diff --git a/app/services/encryption/contextless_kms_client.rb b/app/services/encryption/contextless_kms_client.rb index 392f9d0e34c..1e16eab8159 100644 --- a/app/services/encryption/contextless_kms_client.rb +++ b/app/services/encryption/contextless_kms_client.rb @@ -19,13 +19,23 @@ class ContextlessKmsClient }.freeze def encrypt(plaintext, log_context: nil) - KmsLogger.log(:encrypt, key_id: IdentityConfig.store.aws_kms_key_id, log_context: log_context) + KmsLogger.log( + action: :encrypt, + timestamp: Time.zone.now, + key_id: IdentityConfig.store.aws_kms_key_id, + log_context: log_context, + ) return encrypt_kms(plaintext) if FeatureManagement.use_kms? encrypt_local(plaintext) end def decrypt(ciphertext, log_context: nil) - KmsLogger.log(:decrypt, key_id: IdentityConfig.store.aws_kms_key_id, log_context: log_context) + KmsLogger.log( + action: :decrypt, + timestamp: Time.zone.now, + key_id: IdentityConfig.store.aws_kms_key_id, + log_context: log_context, + ) return decrypt_kms(ciphertext) if use_kms?(ciphertext) decrypt_local(ciphertext) end diff --git a/app/services/encryption/kms_client.rb b/app/services/encryption/kms_client.rb index 55d44d24cd5..1c4189281f6 100644 --- a/app/services/encryption/kms_client.rb +++ b/app/services/encryption/kms_client.rb @@ -32,7 +32,12 @@ def initialize(kms_key_id: IdentityConfig.store.aws_kms_key_id) end def encrypt(plaintext, encryption_context) - KmsLogger.log(:encrypt, context: encryption_context, key_id: kms_key_id) + KmsLogger.log( + action: :encrypt, + timestamp: Time.zone.now, + context: encryption_context, + key_id: kms_key_id, + ) return encrypt_kms(plaintext, encryption_context) if FeatureManagement.use_kms? encrypt_local(plaintext, encryption_context) end @@ -41,7 +46,12 @@ def decrypt(ciphertext, encryption_context) if self.class.looks_like_contextless?(ciphertext) return decrypt_contextless_kms(ciphertext, encryption_context) end - KmsLogger.log(:decrypt, context: encryption_context, key_id: kms_key_id) + KmsLogger.log( + action: :decrypt, + timestamp: Time.zone.now, + context: encryption_context, + key_id: kms_key_id, + ) return decrypt_kms(ciphertext, encryption_context) if use_kms?(ciphertext) decrypt_local(ciphertext, encryption_context) end diff --git a/app/services/encryption/kms_logger.rb b/app/services/encryption/kms_logger.rb index 9824a4ef9ff..c45d0b3c27d 100644 --- a/app/services/encryption/kms_logger.rb +++ b/app/services/encryption/kms_logger.rb @@ -2,9 +2,10 @@ module Encryption class KmsLogger - def self.log(action, key_id:, context: nil, log_context: nil) + def self.log(action:, timestamp:, key_id:, context: nil, log_context: nil) output = { kms: { + timestamp: timestamp, action: action, encryption_context: context, log_context: log_context, diff --git a/spec/services/encryption/contextless_kms_client_spec.rb b/spec/services/encryption/contextless_kms_client_spec.rb index 1fe0da64319..d776a2fea63 100644 --- a/spec/services/encryption/contextless_kms_client_spec.rb +++ b/spec/services/encryption/contextless_kms_client_spec.rb @@ -4,6 +4,11 @@ let(:password_pepper) { '1' * 32 } let(:local_plaintext) { 'local plaintext' } let(:local_ciphertext) { 'local ciphertext' } + let(:log_timestamp) { Time.utc(2025, 2, 28, 15, 30, 1) } + + around do |example| + freeze_time { example.run } + end before do stub_const( @@ -149,7 +154,8 @@ it 'logs the encryption' do expect(Encryption::KmsLogger).to receive(:log).with( - :encrypt, + action: :encrypt, + timestamp: Time.zone.now, log_context: { context: 'abc' }, key_id: IdentityConfig.store.aws_kms_key_id, ) @@ -185,7 +191,8 @@ it 'logs the decryption' do expect(Encryption::KmsLogger).to receive(:log).with( - :decrypt, + action: :decrypt, + timestamp: Time.zone.now, log_context: { context: 'abc' }, key_id: IdentityConfig.store.aws_kms_key_id, ) diff --git a/spec/services/encryption/kms_client_spec.rb b/spec/services/encryption/kms_client_spec.rb index 59f70b19c51..4b4a46e94a5 100644 --- a/spec/services/encryption/kms_client_spec.rb +++ b/spec/services/encryption/kms_client_spec.rb @@ -1,6 +1,10 @@ require 'rails_helper' RSpec.describe Encryption::KmsClient do + around do |example| + freeze_time { example.run } + end + before do stub_const( 'Encryption::KmsClient::KMS_CLIENT_POOL', @@ -40,6 +44,7 @@ let(:key_id) { 'key1' } let(:plaintext) { 'a' * 3000 + 'b' * 3000 + 'c' * 3000 } let(:encryption_context) { { 'context' => 'attribute-bundle', 'user_id' => '123-abc-456-def' } } + let(:log_timestamp) { Time.utc(2025, 2, 28, 15, 30, 1) } let(:local_encryption_key) do OpenSSL::HMAC.digest( @@ -112,7 +117,8 @@ it 'logs the context' do expect(Encryption::KmsLogger).to receive(:log).with( - :encrypt, + action: :encrypt, + timestamp: Time.zone.now, context: encryption_context, key_id: subject.kms_key_id, ) @@ -168,7 +174,8 @@ it 'logs the context' do expect(Encryption::KmsLogger).to receive(:log).with( - :decrypt, + action: :decrypt, + timestamp: Time.zone.now, context: encryption_context, key_id: subject.kms_key_id, ) diff --git a/spec/services/encryption/kms_logger_spec.rb b/spec/services/encryption/kms_logger_spec.rb index bf1acaf12f1..51c85549d02 100644 --- a/spec/services/encryption/kms_logger_spec.rb +++ b/spec/services/encryption/kms_logger_spec.rb @@ -2,10 +2,13 @@ RSpec.describe Encryption::KmsLogger do describe '.log' do + let(:log_timestamp) { Time.utc(2025, 2, 28, 15, 30, 1) } + context 'with a context' do it 'logs the context' do log = { kms: { + timestamp: log_timestamp, action: 'encrypt', encryption_context: { context: 'pii-encryption', user_uuid: '1234-abc' }, log_context: 'log_context', @@ -17,10 +20,11 @@ expect(described_class.logger).to receive(:info).with(log) described_class.log( - :encrypt, + action: :encrypt, context: { context: 'pii-encryption', user_uuid: '1234-abc' }, log_context: 'log_context', key_id: 'super-duper-aws-kms-key-id', + timestamp: log_timestamp, ) end end @@ -29,6 +33,7 @@ it 'logs that an encryption happened without a context' do log = { kms: { + timestamp: log_timestamp, action: 'decrypt', encryption_context: nil, log_context: nil, @@ -39,7 +44,11 @@ expect(described_class.logger).to receive(:info).with(log) - described_class.log(:decrypt, key_id: 'super-duper-aws-kms-key-id') + described_class.log( + action: :decrypt, + timestamp: log_timestamp, + key_id: 'super-duper-aws-kms-key-id', + ) end end end