@@ -23,6 +23,7 @@ import (
23
23
"crypto/sha256"
24
24
"encoding/hex"
25
25
"errors"
26
+ "iter"
26
27
"log/slog"
27
28
"slices"
28
29
@@ -45,19 +46,21 @@ type KeyStore interface {
45
46
46
47
// ManagerConfig captures all of the dependencies required to instantiate a Manager.
47
48
type ManagerConfig struct {
48
- Backend services.RecordingEncryption
49
- KeyStore KeyStore
50
- Logger * slog.Logger
51
- LockConfig backend.RunWhileLockedConfig
49
+ Backend services.RecordingEncryption
50
+ ClusterConfig services.ClusterConfigurationInternal
51
+ KeyStore KeyStore
52
+ Logger * slog.Logger
53
+ LockConfig backend.RunWhileLockedConfig
52
54
}
53
55
54
56
// NewManager returns a new Manager using the given ManagerConfig.
55
57
func NewManager (cfg ManagerConfig ) (* Manager , error ) {
56
- if cfg .Backend == nil {
58
+ switch {
59
+ case cfg .Backend == nil :
57
60
return nil , trace .BadParameter ("backend is required" )
58
- }
59
-
60
- if cfg .KeyStore == nil {
61
+ case cfg . ClusterConfig == nil :
62
+ return nil , trace . BadParameter ( "cluster config is required" )
63
+ case cfg .KeyStore == nil :
61
64
return nil , trace .BadParameter ("key store is required" )
62
65
}
63
66
@@ -66,10 +69,12 @@ func NewManager(cfg ManagerConfig) (*Manager, error) {
66
69
}
67
70
68
71
return & Manager {
69
- RecordingEncryption : cfg .Backend ,
70
- keyStore : cfg .KeyStore ,
71
- lockConfig : cfg .LockConfig ,
72
- logger : cfg .Logger ,
72
+ RecordingEncryption : cfg .Backend ,
73
+ ClusterConfigurationInternal : cfg .ClusterConfig ,
74
+
75
+ keyStore : cfg .KeyStore ,
76
+ lockConfig : cfg .LockConfig ,
77
+ logger : cfg .Logger ,
73
78
}, nil
74
79
}
75
80
@@ -78,10 +83,12 @@ func NewManager(cfg ManagerConfig) (*Manager, error) {
78
83
// state and searching for accessible decryption keys.
79
84
type Manager struct {
80
85
services.RecordingEncryption
86
+ services.ClusterConfigurationInternal
81
87
82
- logger * slog.Logger
83
- lockConfig backend.RunWhileLockedConfig
84
- keyStore KeyStore
88
+ logger * slog.Logger
89
+ lockConfig backend.RunWhileLockedConfig
90
+ keyStore KeyStore
91
+ sessionRecordingConfig types.SessionRecordingConfig
85
92
}
86
93
87
94
// ensureActiveRecordingEncryption returns the configured RecordingEncryption resource if it exists with active keys. If it does not,
@@ -189,15 +196,31 @@ func (m *Manager) getRecordingEncryptionKeyPair(ctx context.Context, keys []*rec
189
196
// recording encryption key pairs) will be fulfilled using their public key encryption keys.
190
197
//
191
198
// If there are no unfulfilled keys present, then nothing should be done.
192
- func (m * Manager ) ResolveRecordingEncryption (ctx context.Context , postProcessFn func (context. Context , * recordingencryptionv1. RecordingEncryption ) error ) (encryption * recordingencryptionv1.RecordingEncryption , err error ) {
199
+ func (m * Manager ) ResolveRecordingEncryption (ctx context.Context ) (encryption * recordingencryptionv1.RecordingEncryption , err error ) {
193
200
err = backend .RunWhileLocked (ctx , m .lockConfig , func (ctx context.Context ) error {
201
+ if m .sessionRecordingConfig == nil {
202
+ m .sessionRecordingConfig , err = m .GetSessionRecordingConfig (ctx )
203
+ if err != nil {
204
+ return trace .Wrap (err )
205
+ }
206
+ }
207
+
208
+ if ! m .sessionRecordingConfig .GetEncrypted () {
209
+ m .logger .DebugContext (ctx , "session recording encryption disabled, skip resolving keys" )
210
+ return nil
211
+ }
212
+
194
213
encryption , err = m .resolveRecordingEncryption (ctx )
195
214
if err != nil {
196
215
return err
197
216
}
198
- if postProcessFn != nil {
199
- return postProcessFn (ctx , encryption )
217
+
218
+ if m .sessionRecordingConfig .SetEncryptionKeys (getAgeEncryptionKeys (encryption .GetSpec ().ActiveKeys )) {
219
+ if _ , err := m .UpdateSessionRecordingConfig (ctx , m .sessionRecordingConfig ); err != nil {
220
+ return trace .Wrap (err )
221
+ }
200
222
}
223
+
201
224
return nil
202
225
})
203
226
return encryption , trace .Wrap (err )
@@ -311,3 +334,21 @@ func (m *Manager) FindDecryptionKey(ctx context.Context, publicKeys ...[]byte) (
311
334
312
335
return nil , trace .NotFound ("no accessible decryption key found" )
313
336
}
337
+
338
+ // getAgeEncryptionKeys returns an iterator of AgeEncryptionKeys from a list of WrappedKeys. This is for use in
339
+ // populating the EncryptionKeys field of SessionRecordingConfigStatus.
340
+ func getAgeEncryptionKeys (keys []* recordingencryptionv1.WrappedKey ) iter.Seq [* types.AgeEncryptionKey ] {
341
+ return func (yield func (* types.AgeEncryptionKey ) bool ) {
342
+ for _ , key := range keys {
343
+ if key .RecordingEncryptionPair == nil {
344
+ continue
345
+ }
346
+
347
+ if ! yield (& types.AgeEncryptionKey {
348
+ PublicKey : key .RecordingEncryptionPair .PublicKey ,
349
+ }) {
350
+ return
351
+ }
352
+ }
353
+ }
354
+ }
0 commit comments