@@ -40,16 +40,16 @@ import (
40
40
"github.com/gravitational/teleport/lib/services"
41
41
)
42
42
43
- // EncryptionKeyStore provides methods for interacting with encryption keys.
44
- type EncryptionKeyStore interface {
43
+ // KeyStore provides methods for interacting with encryption keys.
44
+ type KeyStore interface {
45
45
NewEncryptionKeyPair (ctx context.Context , purpose cryptosuites.KeyPurpose ) (* types.EncryptionKeyPair , error )
46
46
GetDecrypter (ctx context.Context , keyPair * types.EncryptionKeyPair ) (crypto.Decrypter , error )
47
47
}
48
48
49
49
// ManagerConfig captures all of the dependencies required to instantiate a Manager.
50
50
type ManagerConfig struct {
51
51
Backend services.RecordingEncryption
52
- KeyStore EncryptionKeyStore
52
+ KeyStore KeyStore
53
53
Logger * slog.Logger
54
54
}
55
55
@@ -74,32 +74,30 @@ func NewManager(cfg ManagerConfig) (*Manager, error) {
74
74
}, nil
75
75
}
76
76
77
- // A Manager wraps a services.RecordingEncryption and EncryptionKeyStore in order to provide more complex operations
77
+ // A Manager wraps a services.RecordingEncryption and KeyStore in order to provide more complex operations
78
78
// than the CRUD methods exposed by services.RecordingEncryption. It primarily handles resolving RecordingEncryption
79
79
// state and searching for accessible decryption keys.
80
80
type Manager struct {
81
81
services.RecordingEncryption
82
82
83
83
logger * slog.Logger
84
- keyStore EncryptionKeyStore
84
+ keyStore KeyStore
85
85
}
86
86
87
87
// ensureActiveRecordingEncryption returns the configured RecordingEncryption resource if it exists with active keys. If it does not,
88
88
// then the resource will be created or updated with a new active keypair. The bool return value indicates whether or not
89
89
// a new pair was provisioned.
90
90
func (m * Manager ) ensureActiveRecordingEncryption (ctx context.Context ) (* recordingencryptionv1.RecordingEncryption , bool , error ) {
91
- upsert := m .UpdateRecordingEncryption
91
+ persistFn := m .UpdateRecordingEncryption
92
92
encryption , err := m .GetRecordingEncryption (ctx )
93
93
if err != nil {
94
94
if ! trace .IsNotFound (err ) {
95
95
return encryption , false , trace .Wrap (err )
96
96
}
97
97
encryption = & recordingencryptionv1.RecordingEncryption {
98
- Spec : & recordingencryptionv1.RecordingEncryptionSpec {
99
- ActiveKeys : nil ,
100
- },
98
+ Spec : & recordingencryptionv1.RecordingEncryptionSpec {},
101
99
}
102
- upsert = m .CreateRecordingEncryption
100
+ persistFn = m .CreateRecordingEncryption
103
101
}
104
102
105
103
activeKeys := encryption .GetSpec ().ActiveKeys
@@ -133,7 +131,7 @@ func (m *Manager) ensureActiveRecordingEncryption(ctx context.Context) (*recordi
133
131
},
134
132
}
135
133
encryption .Spec .ActiveKeys = []* recordingencryptionv1.WrappedKey {& wrappedKey }
136
- encryption , err = upsert (ctx , encryption )
134
+ encryption , err = persistFn (ctx , encryption )
137
135
if err != nil {
138
136
return encryption , false , trace .Wrap (err )
139
137
}
@@ -178,13 +176,19 @@ func (m *Manager) getRecordingEncryptionKeyPair(ctx context.Context, keys []*rec
178
176
}
179
177
180
178
// ResolveRecordingEncryption examines the current state of the RescordingEncryption resource and advances it to the
181
- // next state on behalf of the current auth server. When no active recording encryption key pairs exist, the first
182
- // pair will be generated and wrapped using a new key encryption pair generated by the Manager's keystore. When at
183
- // least one active keypair exists but none are accessible to the Manager's keystore, a new key encryption pair will
184
- // be generated and saved without a key encryption key pair. This is an unfulfilled key that some other instance of
185
- // Manager on another auth server will need to fulfill asynchrnously. If at least one active key is accessible ot the
186
- // Manager's keystore, then unfulfilled keys (identified by missing recording encryption key pairs) will be fulfilled
187
- // using their public keys. If there are no unfulfilled keys present, then nothing should be done.
179
+ // next state on behalf of the current auth server.
180
+ //
181
+ // When no active recording encryption key pairs exist, the first pair will be generated and wrapped using a new key
182
+ // encryption pair generated by the Manager's keystore.
183
+ //
184
+ // When at least one active keypair exists but none are accessible to the Manager's keystore, a new key encryption pair
185
+ // will be generated and saved without a key encryption pair. This is an unfulfilled key that some other instance of
186
+ // Manager on another auth server will need to fulfill asynchronously.
187
+ //
188
+ // If at least one active key is accessible to the Manager's keystore, then unfulfilled keys (identified by missing
189
+ // recording encryption key pairs) will be fulfilled using their public key encryption keys.
190
+ //
191
+ // If there are no unfulfilled keys present, then nothing should be done.
188
192
func (m * Manager ) ResolveRecordingEncryption (ctx context.Context ) (* recordingencryptionv1.RecordingEncryption , error ) {
189
193
encryption , generatedKey , err := m .ensureActiveRecordingEncryption (ctx )
190
194
if err != nil {
@@ -308,16 +312,16 @@ func GetAgeEncryptionKeys(keys []*recordingencryptionv1.WrappedKey) iter.Seq[*ty
308
312
}
309
313
}
310
314
311
- // RecordingEncryptionResolver resolves RecordingEncryption state
312
- type RecordingEncryptionResolver interface {
315
+ // Resolver resolves RecordingEncryption state
316
+ type Resolver interface {
313
317
ResolveRecordingEncryption (ctx context.Context ) (* recordingencryptionv1.RecordingEncryption , error )
314
318
}
315
319
316
320
// WatchConfig captures required dependencies for building a RecordingEncryption watcher that
317
321
// automatically resolves state.
318
322
type WatchConfig struct {
319
323
Events types.Events
320
- Resolver RecordingEncryptionResolver
324
+ Resolver Resolver
321
325
ClusterConfig services.ClusterConfiguration
322
326
Logger * slog.Logger
323
327
LockConfig * backend.RunWhileLockedConfig
@@ -327,7 +331,7 @@ type WatchConfig struct {
327
331
// auth server.
328
332
type Watcher struct {
329
333
events types.Events
330
- resolver RecordingEncryptionResolver
334
+ resolver Resolver
331
335
clusterConfig services.ClusterConfiguration
332
336
logger * slog.Logger
333
337
lockConfig * backend.RunWhileLockedConfig
@@ -362,8 +366,14 @@ func NewWatcher(cfg WatchConfig) (*Watcher, error) {
362
366
// This is how auth servers cooperate and ensure there are accessible wrapped keys for each unique keystore
363
367
// configuration in a cluster.
364
368
func (w * Watcher ) Run (ctx context.Context ) (err error ) {
365
- jitter := func () {
366
- <- time .After (retryutils .SeventhJitter (time .Second * 5 ))
369
+ // jitter returns a bool specifiying whether or not execution should continue
370
+ jitter := func () bool {
371
+ select {
372
+ case <- time .After (retryutils .SeventhJitter (time .Second * 5 )):
373
+ return true
374
+ case <- ctx .Done ():
375
+ return false
376
+ }
367
377
}
368
378
369
379
defer func () {
@@ -381,16 +391,20 @@ func (w *Watcher) Run(ctx context.Context) (err error) {
381
391
})
382
392
if err != nil {
383
393
w .logger .ErrorContext (ctx , "failed to create watcher, retrying" , "error" , err )
384
- jitter ()
394
+ if ! jitter () {
395
+ return nil
396
+ }
385
397
continue
386
398
}
399
+ defer watch .Close ()
387
400
388
401
HandleEvents:
389
402
for {
390
403
err := w .handleRecordingEncryptionChange (ctx )
391
404
if err != nil {
392
- w .logger .ErrorContext (ctx , "failed to handle session recording config change" , "error" , err )
393
- jitter ()
405
+ if ! jitter () {
406
+ return nil
407
+ }
394
408
continue
395
409
396
410
}
@@ -406,11 +420,12 @@ func (w *Watcher) Run(ctx context.Context) (err error) {
406
420
}
407
421
408
422
w .logger .ErrorContext (ctx , "watcher failed, retrying" , "error" , err )
409
- jitter ()
423
+ if ! jitter () {
424
+ return nil
425
+ }
410
426
break HandleEvents
411
427
case <- ctx .Done ():
412
- watch .Close ()
413
- return ctx .Err ()
428
+ return nil
414
429
}
415
430
}
416
431
}
0 commit comments