Class: ActiveCipherStorage::Providers::AwsKmsProvider
- Includes:
- KeyUtils
- Defined in:
- lib/active_cipher_storage/providers/aws_kms_provider.rb
Constant Summary collapse
- PROVIDER_ID =
"aws_kms"
Instance Method Summary collapse
- #decrypt_data_key(encrypted_key) ⇒ Object
- #generate_data_key ⇒ Object
-
#initialize(key_id: nil, region: nil, encryption_context: {}, client: nil) ⇒ AwsKmsProvider
constructor
A new instance of AwsKmsProvider.
- #key_id ⇒ Object
- #provider_id ⇒ Object
-
#rotate_data_key(encrypted_key, destination_key_id: nil) ⇒ Object
Uses KMS ReEncrypt — the plaintext DEK never leaves KMS.
-
#wrap_data_key(plaintext_dek) ⇒ Object
Encrypts an existing plaintext DEK using KMS Encrypt.
Constructor Details
#initialize(key_id: nil, region: nil, encryption_context: {}, client: nil) ⇒ AwsKmsProvider
Returns a new instance of AwsKmsProvider.
8 9 10 11 12 13 14 15 16 |
# File 'lib/active_cipher_storage/providers/aws_kms_provider.rb', line 8 def initialize(key_id: nil, region: nil, encryption_context: {}, client: nil) @key_id = key_id || ENV.fetch("AWS_KMS_KEY_ID") { raise Errors::ProviderError, "AwsKmsProvider requires :key_id or AWS_KMS_KEY_ID env var" } @region = region @encryption_context = encryption_context || {} @client_override = client end |
Instance Method Details
#decrypt_data_key(encrypted_key) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/active_cipher_storage/providers/aws_kms_provider.rb', line 35 def decrypt_data_key(encrypted_key) resp = kms_client.decrypt( ciphertext_blob: encrypted_key, encryption_context: @encryption_context ) resp.plaintext.dup rescue Aws::KMS::Errors::InvalidCiphertextException, Aws::KMS::Errors::IncorrectKeyException => e raise Errors::KeyManagementError, "KMS Decrypt failed — wrong key or tampered DEK: #{e.}" rescue Aws::KMS::Errors::ServiceError => e raise Errors::KeyManagementError, "KMS Decrypt failed: #{e.}" ensure resp&.plaintext&.then { |k| zero_bytes!(k) } end |
#generate_data_key ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/active_cipher_storage/providers/aws_kms_provider.rb', line 21 def generate_data_key resp = kms_client.generate_data_key( key_id: @key_id, key_spec: "AES_256", encryption_context: @encryption_context ) { plaintext_key: resp.plaintext.dup, encrypted_key: resp.ciphertext_blob.dup } rescue Aws::KMS::Errors::ServiceError => e raise Errors::KeyManagementError, "KMS GenerateDataKey failed: #{e.}" ensure # AWS SDK may retain a reference to resp.plaintext; zero our copy too. resp&.plaintext&.then { |k| zero_bytes!(k) } end |
#key_id ⇒ Object
19 |
# File 'lib/active_cipher_storage/providers/aws_kms_provider.rb', line 19 def key_id = @key_id |
#provider_id ⇒ Object
18 |
# File 'lib/active_cipher_storage/providers/aws_kms_provider.rb', line 18 def provider_id = PROVIDER_ID |
#rotate_data_key(encrypted_key, destination_key_id: nil) ⇒ Object
Uses KMS ReEncrypt — the plaintext DEK never leaves KMS.
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/active_cipher_storage/providers/aws_kms_provider.rb', line 66 def rotate_data_key(encrypted_key, destination_key_id: nil) resp = kms_client.re_encrypt( ciphertext_blob: encrypted_key, source_encryption_context: @encryption_context, destination_key_id: destination_key_id || @key_id, destination_encryption_context: @encryption_context ) resp.ciphertext_blob.dup rescue Aws::KMS::Errors::ServiceError => e raise Errors::KeyManagementError, "KMS ReEncrypt failed: #{e.}" end |
#wrap_data_key(plaintext_dek) ⇒ Object
Encrypts an existing plaintext DEK using KMS Encrypt. Prefer rotate_data_key (ReEncrypt) when both old and new providers are AWS KMS, because ReEncrypt keeps the plaintext DEK entirely within KMS.
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/active_cipher_storage/providers/aws_kms_provider.rb', line 54 def wrap_data_key(plaintext_dek) resp = kms_client.encrypt( key_id: @key_id, plaintext: plaintext_dek, encryption_context: @encryption_context ) resp.ciphertext_blob.dup rescue Aws::KMS::Errors::ServiceError => e raise Errors::KeyManagementError, "KMS Encrypt failed: #{e.}" end |