diff --git a/api/gen/proto/go/teleport/recordingencryption/v1/recording_encryption.pb.go b/api/gen/proto/go/teleport/recordingencryption/v1/recording_encryption.pb.go index c6118aa023d75..8dc36719a1806 100644 --- a/api/gen/proto/go/teleport/recordingencryption/v1/recording_encryption.pb.go +++ b/api/gen/proto/go/teleport/recordingencryption/v1/recording_encryption.pb.go @@ -37,36 +37,29 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// WrappedKey wraps the private key of a recording encryption key pair using a -// separate asymmetric keypair. -type WrappedKey struct { +// A key pair used with age to wrap and unwrap file keys for session recording encryption. +type KeyPair struct { state protoimpl.MessageState `protogen:"open.v1"` - // RecordingEncryptionPair is the asymmetric keypair used with age to encrypt - // and decrypt filekeys. The private key is encrypted using the KeyEncryptionPair's - // public key and has to be decrypted before recording decryption operations can - // be fulfilled. - RecordingEncryptionPair *types.EncryptionKeyPair `protobuf:"bytes,1,opt,name=recording_encryption_pair,json=recordingEncryptionPair,proto3" json:"recording_encryption_pair,omitempty"` - // KeyEncryptionPair is the asymmetric keypair used to wrap (encrypt) the - // RecordingEncryptionPair's private key. - KeyEncryptionPair *types.EncryptionKeyPair `protobuf:"bytes,2,opt,name=key_encryption_pair,json=keyEncryptionPair,proto3" json:"key_encryption_pair,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *WrappedKey) Reset() { - *x = WrappedKey{} + // A key pair used with age to wrap and unwrap file keys for session recording encryption. + KeyPair *types.EncryptionKeyPair `protobuf:"bytes,1,opt,name=key_pair,json=keyPair,proto3" json:"key_pair,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *KeyPair) Reset() { + *x = KeyPair{} mi := &file_teleport_recordingencryption_v1_recording_encryption_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *WrappedKey) String() string { +func (x *KeyPair) String() string { return protoimpl.X.MessageStringOf(x) } -func (*WrappedKey) ProtoMessage() {} +func (*KeyPair) ProtoMessage() {} -func (x *WrappedKey) ProtoReflect() protoreflect.Message { +func (x *KeyPair) ProtoReflect() protoreflect.Message { mi := &file_teleport_recordingencryption_v1_recording_encryption_proto_msgTypes[0] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -78,21 +71,14 @@ func (x *WrappedKey) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use WrappedKey.ProtoReflect.Descriptor instead. -func (*WrappedKey) Descriptor() ([]byte, []int) { +// Deprecated: Use KeyPair.ProtoReflect.Descriptor instead. +func (*KeyPair) Descriptor() ([]byte, []int) { return file_teleport_recordingencryption_v1_recording_encryption_proto_rawDescGZIP(), []int{0} } -func (x *WrappedKey) GetRecordingEncryptionPair() *types.EncryptionKeyPair { - if x != nil { - return x.RecordingEncryptionPair - } - return nil -} - -func (x *WrappedKey) GetKeyEncryptionPair() *types.EncryptionKeyPair { +func (x *KeyPair) GetKeyPair() *types.EncryptionKeyPair { if x != nil { - return x.KeyEncryptionPair + return x.KeyPair } return nil } @@ -100,13 +86,13 @@ func (x *WrappedKey) GetKeyEncryptionPair() *types.EncryptionKeyPair { // RecordingEncryptionSpec contains the active key set for encrypted session recording. type RecordingEncryptionSpec struct { state protoimpl.MessageState `protogen:"open.v1"` - // AciveKeys is a list of active, wrapped X25519 keypairs. The unique set of RecordingEncryptionPair - // public keys are used as recipients during age encryption of session recordings. This - // allows any active private key to be used during decryption which guards against recordings - // being inaccessible to auth servers waiting for their key to rotate. - ActiveKeys []*WrappedKey `protobuf:"bytes,1,rep,name=active_keys,json=activeKeys,proto3" json:"active_keys,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // A list of active key pairs used for session recording encryption. The unique set of + // active public keys are used as recipients during age encryption. This allows any + // active private key to be used during decryption which guards against recordings being + // inaccessible to auth servers waiting for key rotation. + ActiveKeyPairs []*KeyPair `protobuf:"bytes,2,rep,name=active_key_pairs,json=activeKeyPairs,proto3" json:"active_key_pairs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RecordingEncryptionSpec) Reset() { @@ -139,9 +125,9 @@ func (*RecordingEncryptionSpec) Descriptor() ([]byte, []int) { return file_teleport_recordingencryption_v1_recording_encryption_proto_rawDescGZIP(), []int{1} } -func (x *RecordingEncryptionSpec) GetActiveKeys() []*WrappedKey { +func (x *RecordingEncryptionSpec) GetActiveKeyPairs() []*KeyPair { if x != nil { - return x.ActiveKeys + return x.ActiveKeyPairs } return nil } @@ -272,14 +258,11 @@ var File_teleport_recordingencryption_v1_recording_encryption_proto protoreflect const file_teleport_recordingencryption_v1_recording_encryption_proto_rawDesc = "" + "\n" + - ":teleport/recordingencryption/v1/recording_encryption.proto\x12\x1fteleport.recordingencryption.v1\x1a!teleport/header/v1/metadata.proto\x1a!teleport/legacy/types/types.proto\"\xac\x01\n" + - "\n" + - "WrappedKey\x12T\n" + - "\x19recording_encryption_pair\x18\x01 \x01(\v2\x18.types.EncryptionKeyPairR\x17recordingEncryptionPair\x12H\n" + - "\x13key_encryption_pair\x18\x02 \x01(\v2\x18.types.EncryptionKeyPairR\x11keyEncryptionPair\"g\n" + - "\x17RecordingEncryptionSpec\x12L\n" + - "\vactive_keys\x18\x01 \x03(\v2+.teleport.recordingencryption.v1.WrappedKeyR\n" + - "activeKeys\"\x1b\n" + + ":teleport/recordingencryption/v1/recording_encryption.proto\x12\x1fteleport.recordingencryption.v1\x1a!teleport/header/v1/metadata.proto\x1a!teleport/legacy/types/types.proto\">\n" + + "\aKeyPair\x123\n" + + "\bkey_pair\x18\x01 \x01(\v2\x18.types.EncryptionKeyPairR\akeyPair\"\x80\x01\n" + + "\x17RecordingEncryptionSpec\x12R\n" + + "\x10active_key_pairs\x18\x02 \x03(\v2(.teleport.recordingencryption.v1.KeyPairR\x0eactiveKeyPairsJ\x04\b\x01\x10\x02R\vactive_keys\"\x1b\n" + "\x19RecordingEncryptionStatus\"\xba\x02\n" + "\x13RecordingEncryption\x12\x12\n" + "\x04kind\x18\x01 \x01(\tR\x04kind\x12\x19\n" + @@ -303,7 +286,7 @@ func file_teleport_recordingencryption_v1_recording_encryption_proto_rawDescGZIP var file_teleport_recordingencryption_v1_recording_encryption_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_teleport_recordingencryption_v1_recording_encryption_proto_goTypes = []any{ - (*WrappedKey)(nil), // 0: teleport.recordingencryption.v1.WrappedKey + (*KeyPair)(nil), // 0: teleport.recordingencryption.v1.KeyPair (*RecordingEncryptionSpec)(nil), // 1: teleport.recordingencryption.v1.RecordingEncryptionSpec (*RecordingEncryptionStatus)(nil), // 2: teleport.recordingencryption.v1.RecordingEncryptionStatus (*RecordingEncryption)(nil), // 3: teleport.recordingencryption.v1.RecordingEncryption @@ -311,17 +294,16 @@ var file_teleport_recordingencryption_v1_recording_encryption_proto_goTypes = [] (*v1.Metadata)(nil), // 5: teleport.header.v1.Metadata } var file_teleport_recordingencryption_v1_recording_encryption_proto_depIdxs = []int32{ - 4, // 0: teleport.recordingencryption.v1.WrappedKey.recording_encryption_pair:type_name -> types.EncryptionKeyPair - 4, // 1: teleport.recordingencryption.v1.WrappedKey.key_encryption_pair:type_name -> types.EncryptionKeyPair - 0, // 2: teleport.recordingencryption.v1.RecordingEncryptionSpec.active_keys:type_name -> teleport.recordingencryption.v1.WrappedKey - 5, // 3: teleport.recordingencryption.v1.RecordingEncryption.metadata:type_name -> teleport.header.v1.Metadata - 1, // 4: teleport.recordingencryption.v1.RecordingEncryption.spec:type_name -> teleport.recordingencryption.v1.RecordingEncryptionSpec - 2, // 5: teleport.recordingencryption.v1.RecordingEncryption.status:type_name -> teleport.recordingencryption.v1.RecordingEncryptionStatus - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 4, // 0: teleport.recordingencryption.v1.KeyPair.key_pair:type_name -> types.EncryptionKeyPair + 0, // 1: teleport.recordingencryption.v1.RecordingEncryptionSpec.active_key_pairs:type_name -> teleport.recordingencryption.v1.KeyPair + 5, // 2: teleport.recordingencryption.v1.RecordingEncryption.metadata:type_name -> teleport.header.v1.Metadata + 1, // 3: teleport.recordingencryption.v1.RecordingEncryption.spec:type_name -> teleport.recordingencryption.v1.RecordingEncryptionSpec + 2, // 4: teleport.recordingencryption.v1.RecordingEncryption.status:type_name -> teleport.recordingencryption.v1.RecordingEncryptionStatus + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_teleport_recordingencryption_v1_recording_encryption_proto_init() } diff --git a/api/proto/teleport/legacy/types/types.proto b/api/proto/teleport/legacy/types/types.proto index 8a86be7fa23d2..96e841a87eb93 100644 --- a/api/proto/teleport/legacy/types/types.proto +++ b/api/proto/teleport/legacy/types/types.proto @@ -1269,9 +1269,9 @@ message EncryptionKeyPair { uint32 hash = 4 [(gogoproto.jsontag) = "hash,omitempty"]; } -// AgeEncryptionKey is a Bech32 encoded age X25519 public key. +// A public key to be used as a recipient during age encryption of session recordings. message AgeEncryptionKey { - // PublicKey is a Bech32 encoded age X25519 public key. + // A PEM encoded public key used for key wrapping during age encryption. Expected to be RSA 4096. bytes public_key = 1 [(gogoproto.jsontag) = "public_key"]; } diff --git a/api/proto/teleport/recordingencryption/v1/recording_encryption.proto b/api/proto/teleport/recordingencryption/v1/recording_encryption.proto index 5ee6ef9f0f014..0999f68168e6b 100644 --- a/api/proto/teleport/recordingencryption/v1/recording_encryption.proto +++ b/api/proto/teleport/recordingencryption/v1/recording_encryption.proto @@ -21,26 +21,22 @@ import "teleport/legacy/types/types.proto"; option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/recordingencryption/v1;recordingencryptionv1"; -// WrappedKey wraps the private key of a recording encryption key pair using a -// separate asymmetric keypair. -message WrappedKey { - // RecordingEncryptionPair is the asymmetric keypair used with age to encrypt - // and decrypt filekeys. The private key is encrypted using the KeyEncryptionPair's - // public key and has to be decrypted before recording decryption operations can - // be fulfilled. - types.EncryptionKeyPair recording_encryption_pair = 1; - // KeyEncryptionPair is the asymmetric keypair used to wrap (encrypt) the - // RecordingEncryptionPair's private key. - types.EncryptionKeyPair key_encryption_pair = 2; +// A key pair used with age to wrap and unwrap file keys for session recording encryption. +message KeyPair { + // A key pair used with age to wrap and unwrap file keys for session recording encryption. + types.EncryptionKeyPair key_pair = 1; } // RecordingEncryptionSpec contains the active key set for encrypted session recording. message RecordingEncryptionSpec { - // AciveKeys is a list of active, wrapped X25519 keypairs. The unique set of RecordingEncryptionPair - // public keys are used as recipients during age encryption of session recordings. This - // allows any active private key to be used during decryption which guards against recordings - // being inaccessible to auth servers waiting for their key to rotate. - repeated WrappedKey active_keys = 1; + reserved 1; // active_keys + reserved "active_keys"; + + // A list of active key pairs used for session recording encryption. The unique set of + // active public keys are used as recipients during age encryption. This allows any + // active private key to be used during decryption which guards against recordings being + // inaccessible to auth servers waiting for key rotation. + repeated KeyPair active_key_pairs = 2; } // RecordingEncryptionStatus contains the status of the RecordingEncryption resource. diff --git a/api/types/types.pb.go b/api/types/types.pb.go index cb50f7414baca..bdba3fc9b1c82 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -4413,9 +4413,9 @@ func (m *EncryptionKeyPair) XXX_DiscardUnknown() { var xxx_messageInfo_EncryptionKeyPair proto.InternalMessageInfo -// AgeEncryptionKey is a Bech32 encoded age X25519 public key. +// A public key to be used as a recipient during age encryption of session recordings. type AgeEncryptionKey struct { - // PublicKey is a Bech32 encoded age X25519 public key. + // A PEM encoded public key used for key wrapping during age encryption. Expected to be RSA 4096. PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` diff --git a/docs/pages/reference/terraform-provider/data-sources/session_recording_config.mdx b/docs/pages/reference/terraform-provider/data-sources/session_recording_config.mdx index 7ee2e550a7522..f82e132b02448 100644 --- a/docs/pages/reference/terraform-provider/data-sources/session_recording_config.mdx +++ b/docs/pages/reference/terraform-provider/data-sources/session_recording_config.mdx @@ -89,5 +89,5 @@ Optional: Optional: -- `public_key` (String) PublicKey is a Bech32 encoded age X25519 public key. +- `public_key` (String) A PEM encoded public key used for key wrapping during age encryption. Expected to be RSA 4096. diff --git a/docs/pages/reference/terraform-provider/resources/session_recording_config.mdx b/docs/pages/reference/terraform-provider/resources/session_recording_config.mdx index 30d0a29ca88cd..17e0f9c50339a 100644 --- a/docs/pages/reference/terraform-provider/resources/session_recording_config.mdx +++ b/docs/pages/reference/terraform-provider/resources/session_recording_config.mdx @@ -111,4 +111,4 @@ Optional: Optional: -- `public_key` (String) PublicKey is a Bech32 encoded age X25519 public key. +- `public_key` (String) A PEM encoded public key used for key wrapping during age encryption. Expected to be RSA 4096. diff --git a/integrations/terraform/tfschema/types_terraform.go b/integrations/terraform/tfschema/types_terraform.go index 28b150f390837..ba3ba2840c0d6 100644 --- a/integrations/terraform/tfschema/types_terraform.go +++ b/integrations/terraform/tfschema/types_terraform.go @@ -2157,7 +2157,7 @@ func GenSchemaSessionRecordingConfigV2(ctx context.Context) (github_com_hashicor "status": { Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{"encryption_keys": { Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.ListNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{"public_key": { - Description: "PublicKey is a Bech32 encoded age X25519 public key.", + Description: "A PEM encoded public key used for key wrapping during age encryption. Expected to be RSA 4096.", Optional: true, Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, }}), diff --git a/lib/auth/recordingencryption/manager.go b/lib/auth/recordingencryption/manager.go index d6fa97c453cf7..f05e998ed118e 100644 --- a/lib/auth/recordingencryption/manager.go +++ b/lib/auth/recordingencryption/manager.go @@ -121,7 +121,7 @@ func (m *Manager) CreateSessionRecordingConfig(ctx context.Context, cfg types.Se return err } - _ = cfg.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeys)) + _ = cfg.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeyPairs)) } sessionRecordingConfig, err = m.ClusterConfigurationInternal.CreateSessionRecordingConfig(ctx, cfg) @@ -147,7 +147,7 @@ func (m *Manager) UpdateSessionRecordingConfig(ctx context.Context, cfg types.Se return err } - _ = cfg.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeys)) + _ = cfg.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeyPairs)) } sessionRecordingConfig, err = m.ClusterConfigurationInternal.UpdateSessionRecordingConfig(ctx, cfg) @@ -173,7 +173,7 @@ func (m *Manager) UpsertSessionRecordingConfig(ctx context.Context, cfg types.Se return err } - _ = cfg.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeys)) + _ = cfg.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeyPairs)) } sessionRecordingConfig, err = m.ClusterConfigurationInternal.UpsertSessionRecordingConfig(ctx, cfg) @@ -233,22 +233,22 @@ func (m *Manager) ensureManualEncryptionKeys(manualKeyCfg types.ManualKeyManagem } }) - var encryptionKeys []*recordingencryptionv1.WrappedKey + var encryptionKeys []*recordingencryptionv1.KeyPair for _, decrypter := range activeDecrypters { pubKey, err := keys.MarshalPublicKey(decrypter.Public()) if err != nil { return nil, trace.Wrap(err) } - encryptionKeys = append(encryptionKeys, &recordingencryptionv1.WrappedKey{ - RecordingEncryptionPair: &types.EncryptionKeyPair{ + encryptionKeys = append(encryptionKeys, &recordingencryptionv1.KeyPair{ + KeyPair: &types.EncryptionKeyPair{ PublicKey: pubKey, }, }) } return &recordingencryptionv1.RecordingEncryption{ Spec: &recordingencryptionv1.RecordingEncryptionSpec{ - ActiveKeys: encryptionKeys, + ActiveKeyPairs: encryptionKeys, }, }, nil } @@ -274,12 +274,12 @@ func (m *Manager) ensureRecordingEncryptionKey(ctx context.Context, encryptionCf persistFn = m.RecordingEncryption.CreateRecordingEncryption } - activeKeys := encryption.GetSpec().ActiveKeys - if len(activeKeys) > 0 { - for _, key := range activeKeys { + activePairs := encryption.GetSpec().ActiveKeyPairs + if len(activePairs) > 0 { + for _, pair := range activePairs { // fetch the decrypter to ensure we have access to it - if _, err := m.keyStore.GetDecrypter(ctx, key.RecordingEncryptionPair); err != nil { - fp, _ := fingerprintPEM(key.RecordingEncryptionPair.PublicKey) + if _, err := m.keyStore.GetDecrypter(ctx, pair.KeyPair); err != nil { + fp, _ := fingerprintPEM(pair.KeyPair.PublicKey) m.logger.DebugContext(ctx, "key not accessible", "fingerprint", fp) continue } @@ -295,10 +295,10 @@ func (m *Manager) ensureRecordingEncryptionKey(ctx context.Context, encryptionCf return nil, trace.Wrap(err, "generating wrapping key") } - wrappedKey := recordingencryptionv1.WrappedKey{ - RecordingEncryptionPair: encryptionPair, + wrappedKey := recordingencryptionv1.KeyPair{ + KeyPair: encryptionPair, } - encryption.Spec.ActiveKeys = []*recordingencryptionv1.WrappedKey{&wrappedKey} + encryption.Spec.ActiveKeyPairs = []*recordingencryptionv1.KeyPair{&wrappedKey} encryption, err = persistFn(ctx, encryption) if err != nil { return nil, trace.Wrap(err) @@ -346,13 +346,13 @@ func (m *Manager) UnwrapKey(ctx context.Context, in UnwrapInput) ([]byte, error) } // TODO (eriktate): search rotated keys as well once rotation is implemented - activeKeys := encryption.GetSpec().ActiveKeys - for _, key := range activeKeys { - if key.GetRecordingEncryptionPair() == nil { + activePairs := encryption.GetSpec().ActiveKeyPairs + for _, key := range activePairs { + if key.GetKeyPair() == nil { continue } - activeFP, err := fingerprintPEM(key.RecordingEncryptionPair.PublicKey) + activeFP, err := fingerprintPEM(key.KeyPair.PublicKey) if err != nil { m.logger.ErrorContext(ctx, "failed to fingerprint active public key", "error", err) continue @@ -362,7 +362,7 @@ func (m *Manager) UnwrapKey(ctx context.Context, in UnwrapInput) ([]byte, error) continue } - decrypter, err := m.keyStore.GetDecrypter(ctx, key.RecordingEncryptionPair) + decrypter, err := m.keyStore.GetDecrypter(ctx, key.KeyPair) if err != nil { continue } @@ -487,7 +487,7 @@ func (m *Manager) resolveRecordingEncryption(ctx context.Context, shouldRetryFn return trace.Wrap(err) } - if sessionRecordingConfig.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeys)) { + if sessionRecordingConfig.SetEncryptionKeys(getAgeEncryptionKeys(encryption.GetSpec().ActiveKeyPairs)) { if _, err := m.ClusterConfigurationInternal.UpdateSessionRecordingConfig(ctx, sessionRecordingConfig); err != nil { return trace.Wrap(err) } @@ -507,15 +507,15 @@ func (m *Manager) resolveRecordingEncryption(ctx context.Context, shouldRetryFn // getAgeEncryptionKeys returns an iterator of AgeEncryptionKeys from a list of WrappedKeys. This is for use in // populating the EncryptionKeys field of SessionRecordingConfigStatus. -func getAgeEncryptionKeys(keys []*recordingencryptionv1.WrappedKey) iter.Seq[*types.AgeEncryptionKey] { +func getAgeEncryptionKeys(keys []*recordingencryptionv1.KeyPair) iter.Seq[*types.AgeEncryptionKey] { return func(yield func(*types.AgeEncryptionKey) bool) { for _, key := range keys { - if key.RecordingEncryptionPair == nil { + if key.KeyPair == nil { continue } if !yield(&types.AgeEncryptionKey{ - PublicKey: key.RecordingEncryptionPair.PublicKey, + PublicKey: key.KeyPair.PublicKey, }) { return } diff --git a/lib/auth/recordingencryption/manager_test.go b/lib/auth/recordingencryption/manager_test.go index 2ff377b65fa9b..c49753eddabe7 100644 --- a/lib/auth/recordingencryption/manager_test.go +++ b/lib/auth/recordingencryption/manager_test.go @@ -282,11 +282,11 @@ func TestCreateUpdateSessionRecordingConfig(t *testing.T) { encryption, err := config.Backend.GetRecordingEncryption(ctx) require.NoError(t, err) - activeKeys := encryption.GetSpec().GetActiveKeys() - require.Len(t, activeKeys, 1) - require.NotNil(t, activeKeys[0].RecordingEncryptionPair) - require.NotEmpty(t, activeKeys[0].RecordingEncryptionPair.PrivateKey) - require.NotEmpty(t, activeKeys[0].RecordingEncryptionPair.PublicKey) + activePairs := encryption.GetSpec().GetActiveKeyPairs() + require.Len(t, activePairs, 1) + require.NotNil(t, activePairs[0].KeyPair) + require.NotEmpty(t, activePairs[0].KeyPair.PrivateKey) + require.NotEmpty(t, activePairs[0].KeyPair.PublicKey) // update should change nothing src, err = manager.UpdateSessionRecordingConfig(ctx, src) @@ -296,8 +296,8 @@ func TestCreateUpdateSessionRecordingConfig(t *testing.T) { encryption, err = config.Backend.GetRecordingEncryption(ctx) require.NoError(t, err) - newActiveKeys := encryption.GetSpec().GetActiveKeys() - require.ElementsMatch(t, newActiveKeys, activeKeys) + newActiveKeyPairs := encryption.GetSpec().GetActiveKeyPairs() + require.ElementsMatch(t, newActiveKeyPairs, activePairs) } func TestResolveRecordingEncryption(t *testing.T) { @@ -327,22 +327,22 @@ func TestResolveRecordingEncryption(t *testing.T) { // CASE: service A first evaluation initializes recording encryption resource encryption, src, err := resolve(ctx, service, managerA) require.NoError(t, err) - initialKeys := encryption.GetSpec().GetActiveKeys() + initialKeys := encryption.GetSpec().GetActiveKeyPairs() require.Len(t, initialKeys, 1) require.Len(t, src.GetEncryptionKeys(), 1) key := initialKeys[0] - require.Equal(t, key.RecordingEncryptionPair.PublicKey, src.GetEncryptionKeys()[0].PublicKey) - require.NotNil(t, key.RecordingEncryptionPair) + require.Equal(t, key.KeyPair.PublicKey, src.GetEncryptionKeys()[0].PublicKey) + require.NotNil(t, key.KeyPair) // CASE: service B should have access to the same key encryption, src, err = resolve(ctx, service, managerB) require.NoError(t, err) - activeKeys := encryption.GetSpec().ActiveKeys + activePairs := encryption.GetSpec().ActiveKeyPairs require.Len(t, src.GetEncryptionKeys(), 1) - require.Equal(t, key.RecordingEncryptionPair.PublicKey, src.GetEncryptionKeys()[0].PublicKey) - require.ElementsMatch(t, initialKeys, activeKeys) + require.Equal(t, key.KeyPair.PublicKey, src.GetEncryptionKeys()[0].PublicKey) + require.ElementsMatch(t, initialKeys, activePairs) // service C should error without access to the current key _, _, err = resolve(ctx, service, managerC) @@ -383,13 +383,13 @@ func TestResolveRecordingEncryptionConcurrent(t *testing.T) { encryption, err := service.GetRecordingEncryption(ctx) require.NoError(t, err) - activeKeys := encryption.GetSpec().ActiveKeys + activePairs := encryption.GetSpec().ActiveKeyPairs // each service should share a single active key - require.Len(t, activeKeys, 1) - require.NotNil(t, activeKeys[0].RecordingEncryptionPair) - require.NotEmpty(t, activeKeys[0].RecordingEncryptionPair.PrivateKey) - require.NotEmpty(t, activeKeys[0].RecordingEncryptionPair.PublicKey) - require.Equal(t, types.PrivateKeyType_RAW, activeKeys[0].RecordingEncryptionPair.PrivateKeyType) + require.Len(t, activePairs, 1) + require.NotNil(t, activePairs[0].KeyPair) + require.NotEmpty(t, activePairs[0].KeyPair.PrivateKey) + require.NotEmpty(t, activePairs[0].KeyPair.PublicKey) + require.Equal(t, types.PrivateKeyType_RAW, activePairs[0].KeyPair.PrivateKeyType) } func TestUnwrapKey(t *testing.T) { diff --git a/lib/cache/recording_encryption_test.go b/lib/cache/recording_encryption_test.go index 3a161c0dc8274..1b16e310740da 100644 --- a/lib/cache/recording_encryption_test.go +++ b/lib/cache/recording_encryption_test.go @@ -35,7 +35,7 @@ func newRecordingEncryption() *recordingencryptionv1.RecordingEncryption { Name: types.MetaNameRecordingEncryption, }, Spec: &recordingencryptionv1.RecordingEncryptionSpec{ - ActiveKeys: nil, + ActiveKeyPairs: nil, }, } } diff --git a/lib/services/local/recording_encryption_test.go b/lib/services/local/recording_encryption_test.go index 0f5420f02d1e1..c8ce0fc25466b 100644 --- a/lib/services/local/recording_encryption_test.go +++ b/lib/services/local/recording_encryption_test.go @@ -18,7 +18,6 @@ package local import ( "context" - "crypto" "testing" "github.com/stretchr/testify/require" @@ -39,7 +38,7 @@ func TestRecordingEncryption(t *testing.T) { initialEncryption := pb.RecordingEncryption{ Spec: &pb.RecordingEncryptionSpec{ - ActiveKeys: nil, + ActiveKeyPairs: nil, }, } @@ -53,33 +52,28 @@ func TestRecordingEncryption(t *testing.T) { encryption, err := service.GetRecordingEncryption(ctx) require.NoError(t, err) - require.Empty(t, created.Spec.ActiveKeys) - require.Empty(t, encryption.Spec.ActiveKeys) + require.Empty(t, created.Spec.ActiveKeyPairs) + require.Empty(t, encryption.Spec.ActiveKeyPairs) - encryption.Spec.ActiveKeys = []*pb.WrappedKey{ + encryption.Spec.ActiveKeyPairs = []*pb.KeyPair{ { - RecordingEncryptionPair: &types.EncryptionKeyPair{ + KeyPair: &types.EncryptionKeyPair{ PrivateKey: []byte("recording encryption private"), PublicKey: []byte("recording encryption public"), Hash: 0, }, - KeyEncryptionPair: &types.EncryptionKeyPair{ - PrivateKey: []byte("key encryption private"), - PublicKey: []byte("key encryption public"), - Hash: uint32(crypto.SHA256), - }, }, } updated, err := service.UpdateRecordingEncryption(ctx, encryption) require.NoError(t, err) - require.Len(t, updated.Spec.ActiveKeys, 1) - require.EqualExportedValues(t, encryption.Spec.ActiveKeys[0], updated.Spec.ActiveKeys[0]) + require.Len(t, updated.Spec.ActiveKeyPairs, 1) + require.EqualExportedValues(t, encryption.Spec.ActiveKeyPairs[0], updated.Spec.ActiveKeyPairs[0]) encryption, err = service.GetRecordingEncryption(ctx) require.NoError(t, err) - require.Len(t, encryption.Spec.ActiveKeys, 1) - require.EqualExportedValues(t, updated.Spec.ActiveKeys[0], encryption.Spec.ActiveKeys[0]) + require.Len(t, encryption.Spec.ActiveKeyPairs, 1) + require.EqualExportedValues(t, updated.Spec.ActiveKeyPairs[0], encryption.Spec.ActiveKeyPairs[0]) err = service.DeleteRecordingEncryption(ctx) require.NoError(t, err)