# encoding: utf-8 require "logstash/filters/base" require "logstash/namespace" # This filter parses a source and apply a cipher or decipher before # storing it in the target. # class LogStash::Filters::Cipher < LogStash::Filters::Base config_name "cipher" # The field to perform filter # # Example, to use the @message field (default) : # [source,ruby] # filter { cipher { source => "message" } } config :source, :validate => :string, :default => "message" # The name of the container to put the result # # Example, to place the result into crypt : # [source,ruby] # filter { cipher { target => "crypt" } } config :target, :validate => :string, :default => "message" # Do we have to perform a `base64` decode or encode? # # If we are decrypting, `base64` decode will be done before. # If we are encrypting, `base64` will be done after. # config :base64, :validate => :boolean, :default => true # The key to use config :key, :validate => :string # The key size to pad # # It depends of the cipher algorythm.I your key don't need # padding, don't set this parameter # # Example, for AES-256, we must have 32 char long key # [source,ruby] # filter { cipher { key_size => 32 } # config :key_size, :validate => :number, :default => 32 # The character used to pad the key config :key_pad, :default => "\0" # The cipher algorythm # # A list of supported algorithms can be obtained by # [source,ruby] # puts OpenSSL::Cipher.ciphers config :algorithm, :validate => :string, :required => true # Encrypting or decrypting some data # # Valid values are encrypt or decrypt config :mode, :validate => :string, :required => true # Cypher padding to use. Enables or disables padding. # # By default encryption operations are padded using standard block padding # and the padding is checked and removed when decrypting. If the pad # parameter is zero then no padding is performed, the total amount of data # encrypted or decrypted must then be a multiple of the block size or an # error will occur. # # See EVP_CIPHER_CTX_set_padding for further information. # # We are using Openssl jRuby which uses default padding to PKCS5Padding # If you want to change it, set this parameter. If you want to disable # it, Set this parameter to 0 # [source,ruby] # filter { cipher { padding => 0 }} config :cipher_padding, :validate => :string # The initialization vector to use # # The cipher modes CBC, CFB, OFB and CTR all need an "initialization # vector", or short, IV. ECB mode is the only mode that does not require # an IV, but there is almost no legitimate use case for this mode # because of the fact that it does not sufficiently hide plaintext patterns. config :iv, :validate => :string def register require 'base64' if @base64 init_cipher end # def register def filter(event) return unless filter?(event) #If decrypt or encrypt fails, we keep it it intact. begin #@logger.debug("Event to filter", :event => event) data = event[@source] if @mode == "decrypt" data = Base64.decode64(data) if @base64 == true end result = @cipher.update(data) + @cipher.final if @mode == "encrypt" data = Base64.encode64(data) if @base64 == true end rescue => e @logger.warn("Exception catch on cipher filter", :event => event, :error => e) else event[@target]= result #Is it necessary to add 'if !result.nil?' ? exception have been already catched. #In doubt, I keep it. filter_matched(event) if !result.nil? #Too much bad result can be a problem, reinit cipher prevent this. init_cipher end end # def filter def init_cipher @cipher = OpenSSL::Cipher.new(@algorithm) if @mode == "encrypt" @cipher.encrypt elsif @mode == "decrypt" @cipher.decrypt else @logger.error("Invalid cipher mode. Valid values are \"encrypt\" or \"decrypt\"", :mode => @mode) raise "Bad configuration, aborting." end if @key.length != @key_size @logger.debug("key length is " + @key.length.to_s + ", padding it to " + @key_size.to_s + " with '" + @key_pad.to_s + "'") @key = @key[0,@key_size].ljust(@key_size,@key_pad) end @cipher.key = @key @cipher.iv = @iv if @iv @cipher.padding = @cipher_padding if @cipher_padding @logger.debug("Cipher initialisation done", :mode => @mode, :key => @key, :iv => @iv, :cipher_padding => @cipher_padding) end # def init_cipher end # class LogStash::Filters::Cipher