Module: Sidekiq::EncryptedArgs

Defined in:
lib/sidekiq/encrypted_args.rb,
lib/sidekiq/encrypted_args/version.rb,
lib/sidekiq/encrypted_args/client_middleware.rb,
lib/sidekiq/encrypted_args/server_middleware.rb

Overview

Provides middleware for encrypting sensitive arguments in Sidekiq jobs.

This module allows you to specify which job arguments should be encrypted in Redis to protect sensitive information like API keys, passwords, or personally identifiable information.

Defined Under Namespace

Classes: ClientMiddleware, InvalidSecretError, ServerMiddleware

Constant Summary collapse

VERSION =
File.read(File.join(__dir__, "..", "..", "..", "VERSION")).chomp.freeze

Class Method Summary collapse

Class Method Details

.configure!(secret: nil) ⇒ Object

Add the client and server middleware to the default Sidekiq middleware chains. If you need to ensure the order of where the middleware is added, you can forgo this method and add it yourself.

This method prepends client middleware and appends server middleware.

Examples:

Basic configuration

Sidekiq::EncryptedArgs.configure!(secret: "your_secret_key")

Configuration using environment variable

ENV['SIDEKIQ_ENCRYPTED_ARGS_SECRET'] = "your_secret_key"
Sidekiq::EncryptedArgs.configure!

Parameters:

  • secret (String) (defaults to: nil)

    optionally set the secret here. See secret=



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/sidekiq/encrypted_args.rb', line 59

def configure!(secret: nil)
  self.secret = secret unless secret.nil?

  Sidekiq.configure_client do |config|
    config.client_middleware do |chain|
      chain.prepend Sidekiq::EncryptedArgs::ClientMiddleware
    end
  end

  Sidekiq.configure_server do |config|
    config.server_middleware do |chain|
      chain.add Sidekiq::EncryptedArgs::ServerMiddleware
    end
    config.client_middleware do |chain|
      chain.prepend Sidekiq::EncryptedArgs::ClientMiddleware
    end
  end
end

.decrypt(encrypted_data) ⇒ Object

Decrypt data

an unencrypted string, then the string itself will be returned.

Examples:

Decrypting an encrypted value

EncryptedArgs.decrypt("encrypted_string") #=> "original_value"

Handling unencrypted data

EncryptedArgs.decrypt("unencrypted_string") #=> "unencrypted_string"

Parameters:

  • encrypted_data (String)

    Data that was previously encrypted. If the value passed in is

Returns:

  • (Object)


113
114
115
116
117
# File 'lib/sidekiq/encrypted_args.rb', line 113

def decrypt(encrypted_data)
  return encrypted_data unless SecretKeys::Encryptor.encrypted?(encrypted_data)
  json = decrypt_string(encrypted_data)
  JSON.parse(json)
end

.encrypt(data) ⇒ String

Encrypt a value.

Examples:

Encrypting a simple value

EncryptedArgs.encrypt("secret_value") #=> "encrypted_string"

Encrypting complex data

EncryptedArgs.encrypt({api_key: "secret", user_id: 123}) #=> "encrypted_string"

Parameters:

  • data (#to_json, Object)

    Data to encrypt. You can pass any JSON compatible data types or structures.

Returns:

  • (String)


89
90
91
92
93
94
95
96
97
98
99
# File 'lib/sidekiq/encrypted_args.rb', line 89

def encrypt(data)
  return nil if data.nil?

  json = (data.respond_to?(:to_json) ? data.to_json : JSON.generate(data))
  encrypted = encrypt_string(json)
  if encrypted == json
    data
  else
    encrypted
  end
end

.encrypted?(value) ⇒ Boolean

Check if a value is encrypted.

Returns:

  • (Boolean)


122
123
124
# File 'lib/sidekiq/encrypted_args.rb', line 122

def encrypted?(value)
  SecretKeys::Encryptor.encrypted?(value)
end

.encrypted_args_option(worker_class, job) ⇒ Object

Private helper method to get the encrypted args option from an options hash. The value of this option can be ‘true` or an array indicating if each positional argument should be encrypted, or a hash with keys for the argument position and true as the value.



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/sidekiq/encrypted_args.rb', line 131

def encrypted_args_option(worker_class, job)
  option = job["encrypted_args"]
  return nil if option.nil?
  return [] if option == false

  indexes = []
  if option == true
    job["args"].size.times { |i| indexes << i }
  elsif option.is_a?(Hash)
    raise ArgumentError.new("Hash-based argument encryption is no longer supported.")
  else
    array_type = nil
    Array(option).each_with_index do |val, position|
      current_type = nil
      if val.is_a?(Integer)
        indexes << val
        current_type = :integer
      elsif val.is_a?(Symbol) || val.is_a?(String)
        worker_class = constantize(worker_class) if worker_class.is_a?(String)
        position = perform_method_parameter_index(worker_class, val)
        indexes << position if position
        current_type = :symbol
      else
        raise ArgumentError.new("Encrypted args must be specified as integers or symbols.")
      end

      if array_type && current_type
        raise ArgumentError.new("Encrypted args cannot mix integers and symbols.")
      else
        array_type ||= current_type
      end
    end
  end
  indexes
end

.secret=(value) ⇒ void

This method returns an undefined value.

Set the secret key used for encrypting arguments. If this is not set, the value will be loaded from the ‘SIDEKIQ_ENCRYPTED_ARGS_SECRET` environment variable. If that value is not set, arguments will not be encrypted.

You can set multiple secrets by passing an array if you need to roll your secrets. The left most value in the array will be used as the encryption secret, but all the values will be tried when decrypting. That way if you have scheduled jobs that were encrypted with a different secret, you can still make it available when decrypting the arguments when the job gets run. If you are using the environment variable, separate the keys with spaces.

Examples:

Setting a single secret

Sidekiq::EncryptedArgs.secret = "your_secret_key"

Rolling secrets (multiple keys for backward compatibility)

Sidekiq::EncryptedArgs.secret = ["new_secret", "old_secret", "older_secret"]

Parameters:

  • value (String, Array<String>)

    One or more secrets to use for encrypting arguments.



41
42
43
# File 'lib/sidekiq/encrypted_args.rb', line 41

def secret=(value)
  @encryptors = make_encryptors(value)
end