class Aws::S3::EncryptionV2::Client
Attributes
@return [S3::Client]
@return [Symbol<:metadata, :instruction_file>]
@return [String] When {#envelope_location} is `:instruction_file`,
the envelope is stored in the object with the object key suffixed by this string.
@return [KeyProvider, nil] Returns `nil` if you are using
AWS Key Management Service (KMS).
@return [Boolean] If true the provided KMS key_id will not be used
during decrypt, allowing decryption with the key_id from the object.
@return [Symbol] Determines the support for reading objects written
using older key wrap or content encryption schemas.
Public Class Methods
Creates a new encryption client. You must configure all of the following:
-
a key or key provider - The key provided also determines the key wrapping schema(s) supported for both encryption and decryption.
-
`key_wrap_schema` - The key wrapping schema. It must match the type of key configured.
-
`content_encryption_schema` - The only supported value currently is `:aes_gcm_no_padding`
More options will be added in future releases.
-
`security_profile` - Determines the support for reading objects written
using older key wrap or content encryption schemas. If you need to read legacy objects encrypted by an existing V1 Client, then set this to `:v2_and_legacy`. Otherwise, set it to `:v2`
To configure the key you must provide one of the following set of options:
-
`:encryption_key`
-
`:kms_key_id`
-
`:key_provider`
You may also pass any other options accepted by `Client#initialize`.
@option options [S3::Client] :client A basic S3
client that is used
to make api calls. If a `:client` is not provided, a new {S3::Client} will be constructed.
@option options [OpenSSL::PKey::RSA, String] :encryption_key The master
key to use for encrypting/decrypting all objects.
@option options [String] :kms_key_id When you provide a `:kms_key_id`,
then AWS Key Management Service (KMS) will be used to manage the object encryption keys. By default a {KMS::Client} will be constructed for KMS API calls. Alternatively, you can provide your own via `:kms_client`. To only support decryption/reads, you may provide `:allow_decrypt_with_any_cmk` which will use the implicit CMK associated with the data during reads but will not allow you to encrypt/write objects with this client.
@option options [#key_for] :key_provider Any object that responds
to `#key_for`. This method should accept a materials description JSON document string and return return an encryption key.
@option options [required, Symbol] :key_wrap_schema The Key wrapping
schema to be used. It must match the type of key configured. Must be one of the following: * :kms_context (Must provide kms_key_id) * :aes_gcm (Must provide an AES (string) key) * :rsa_oaep_sha1 (Must provide an RSA key)
@option options [required, Symbol] :content_encryption_schema
Must be one of the following: * :aes_gcm_no_padding
@option options [Required, Symbol] :security_profile
Determines the support for reading objects written using older key wrap or content encryption schemas. Must be one of the following: * :v2 - Reads of legacy (v1) objects are NOT allowed * :v2_and_legacy - Enables reading of legacy (V1) schemas.
@option options [Symbol] :envelope_location (:metadata) Where to
store the envelope encryption keys. By default, the envelope is stored with the encrypted object. If you pass `:instruction_file`, then the envelope is stored in a separate object in Amazon S3.
@option options [String] :instruction_file_suffix ('.instruction')
When `:envelope_location` is `:instruction_file` then the instruction file uses the object key with this suffix appended.
@option options [KMS::Client] :kms_client A default {KMS::Client}
is constructed when using KMS to manage encryption keys.
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 310 def initialize(options = {}) validate_params(options) @client = extract_client(options) @cipher_provider = cipher_provider(options) @envelope_location = extract_location(options) @instruction_file_suffix = extract_suffix(options) @kms_allow_decrypt_with_any_cmk = options[:kms_key_id] == :kms_allow_decrypt_with_any_cmk @security_profile = extract_security_profile(options) end
Public Instance Methods
Gets an object from Amazon S3
, decrypting data locally. See {S3::Client#get_object} for documentation on accepted request parameters. Warning: If you provide a block to get_object
or set the request parameter :response_target to a Proc, then read the entire object to the end before you start using the decrypted data. This is to verify that the object has not been modified since it was encrypted.
@option options [Symbol] :security_profile
Determines the support for reading objects written using older key wrap or content encryption schemas. Overrides the value set on client construction if provided. Must be one of the following: * :v2 - Reads of legacy (v1) objects are NOT allowed * :v2_and_legacy - Enables reading of legacy (V1) schemas.
@option params [String] :instruction_file_suffix The suffix
used to find the instruction file containing the encryption envelope. You should not set this option when the envelope is stored in the object metadata. Defaults to {#instruction_file_suffix}.
@option params [Hash] :kms_encryption_context Additional encryption
context to use with KMS. Applies only when KMS is used.
@option options [Boolean] :kms_allow_decrypt_with_any_cmk (false)
By default the KMS CMK ID (kms_key_id) will be used during decrypt and will fail if there is a mismatch. Setting this to true will use the implicit CMK associated with the data.
@option (see S3::Client#get_object
) @return (see S3::Client#get_object
) @see S3::Client#get_object
@note The `:range` request parameter is not supported.
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 398 def get_object(params = {}, &block) if params[:range] raise NotImplementedError, '#get_object with :range not supported' end envelope_location, instruction_file_suffix = envelope_options(params) kms_encryption_context = params.delete(:kms_encryption_context) kms_any_cmk_mode = kms_any_cmk_mode(params) security_profile = security_profile_from_params(params) req = @client.build_request(:get_object, params) req.handlers.add(DecryptHandler) req.context[:encryption] = { cipher_provider: @cipher_provider, envelope_location: envelope_location, instruction_file_suffix: instruction_file_suffix, kms_encryption_context: kms_encryption_context, kms_allow_decrypt_with_any_cmk: kms_any_cmk_mode, security_profile: security_profile } req.send_request(target: block) end
Uploads an object to Amazon S3
, encrypting data client-side. See {S3::Client#put_object} for documentation on accepted request parameters. @option params [Hash] :kms_encryption_context Additional encryption
context to use with KMS. Applies only when KMS is used. In order to decrypt the object you will need to provide the identical :kms_encryption_context to `get_object`.
@option (see S3::Client#put_object
) @return (see S3::Client#put_object
) @see S3::Client#put_object
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 354 def put_object(params = {}) kms_encryption_context = params.delete(:kms_encryption_context) req = @client.build_request(:put_object, params) req.handlers.add(EncryptHandler, priority: 95) req.context[:encryption] = { cipher_provider: @cipher_provider, envelope_location: @envelope_location, instruction_file_suffix: @instruction_file_suffix, kms_encryption_context: kms_encryption_context } req.send_request end
Private Instance Methods
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 465 def cipher_provider(options) if options[:kms_key_id] KmsCipherProvider.new( kms_key_id: options[:kms_key_id], kms_client: kms_client(options), key_wrap_schema: options[:key_wrap_schema], content_encryption_schema: options[:content_encryption_schema] ) else @key_provider = extract_key_provider(options) DefaultCipherProvider.new( key_provider: @key_provider, key_wrap_schema: options[:key_wrap_schema], content_encryption_schema: options[:content_encryption_schema] ) end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 494 def envelope_options(params) location = params.delete(:envelope_location) || @envelope_location suffix = params.delete(:instruction_file_suffix) if suffix [:instruction_file, suffix] else [location, @instruction_file_suffix] end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 442 def extract_client(options) options[:client] || begin options = options.dup options.delete(:kms_key_id) options.delete(:kms_client) options.delete(:key_provider) options.delete(:encryption_key) options.delete(:envelope_location) options.delete(:instruction_file_suffix) REQUIRED_PARAMS.each { |p| options.delete(p) } S3::Client.new(options) end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 483 def extract_key_provider(options) if options[:key_provider] options[:key_provider] elsif options[:encryption_key] DefaultKeyProvider.new(options) else msg = 'you must pass a :kms_key_id, :key_provider, or :encryption_key' raise ArgumentError, msg end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 504 def extract_location(options) location = options[:envelope_location] || :metadata if [:metadata, :instruction_file].include?(location) location else msg = ':envelope_location must be :metadata or :instruction_file '\ "got #{location.inspect}" raise ArgumentError, msg end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 533 def extract_security_profile(options) validate_security_profile(options[:security_profile]) end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 515 def extract_suffix(options) suffix = options[:instruction_file_suffix] || '.instruction' if suffix.is_a? String suffix else msg = ':instruction_file_suffix must be a String' raise ArgumentError, msg end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 525 def kms_any_cmk_mode(params) if !params[:kms_allow_decrypt_with_any_cmk].nil? params.delete(:kms_allow_decrypt_with_any_cmk) else @kms_allow_decrypt_with_any_cmk end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 456 def kms_client(options) options[:kms_client] || begin KMS::Client.new( region: @client.config.region, credentials: @client.config.credentials, ) end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 537 def security_profile_from_params(params) security_profile = if !params[:security_profile].nil? params.delete(:security_profile) else @security_profile end validate_security_profile(security_profile) end
Validate required parameters exist and don't conflict. The cek_alg and wrap_alg are passed on to the CipherProviders and further validated there
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 425 def validate_params(options) unless (missing_params = REQUIRED_PARAMS - options.keys).empty? raise ArgumentError, "Missing required parameter(s): "\ "#{missing_params.map{ |s| ":#{s}" }.join(', ')}" end wrap_alg = options[:key_wrap_schema] # validate that the wrap alg matches the type of key given case wrap_alg when :kms_context unless options[:kms_key_id] raise ArgumentError, 'You must provide :kms_key_id to use :kms_context' end end end
# File lib/aws-sdk-s3/encryptionV2/client.rb, line 547 def validate_security_profile(security_profile) unless SUPPORTED_SECURITY_PROFILES.include? security_profile raise ArgumentError, "Unsupported security profile: :#{security_profile}. " \ "Please provide one of: #{SUPPORTED_SECURITY_PROFILES.map { |s| ":#{s}" }.join(', ')}" end if security_profile == :v2_and_legacy && !@warned_about_legacy @warned_about_legacy = true warn( 'The S3 Encryption Client is configured to read encrypted objects ' \ "with legacy encryption modes. If you don't have objects " \ 'encrypted with these legacy modes, you should disable support ' \ 'for them to enhance security.' ) end security_profile end