Skip to content

Adding support for rotating session recording encryption keys#57577

Merged
eriktate merged 1 commit intomasterfrom
eriktate/rotating-encryption-keys
Aug 26, 2025
Merged

Adding support for rotating session recording encryption keys#57577
eriktate merged 1 commit intomasterfrom
eriktate/rotating-encryption-keys

Conversation

@eriktate
Copy link
Copy Markdown
Contributor

@eriktate eriktate commented Aug 5, 2025

This PR adds new methods to the recordingencryption.Manager for handling key rotations in a way that ensures the RecordingEncryption and SessionRecordingConfig resources remain in sync. The necessary changes for tctl will be in a future PR, but the RPC endpoints making the functionality available are included here.

@eriktate eriktate changed the base branch from master to eriktate/rotated-keys-resource August 5, 2025 21:12
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Aug 5, 2025

Amplify deployment status

Branch Commit Job ID Status Preview Updated (UTC)
eriktate/rotating-encryption-keys e125ded 44 ✅SUCCEED eriktate-rotating-encryption-keys 2025-08-26 20:51:59

@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch from 63d66c5 to 508e290 Compare August 5, 2025 21:23
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from e57457c to c4a6221 Compare August 5, 2025 21:24
@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch from 508e290 to 54a4224 Compare August 6, 2025 14:27
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from c4a6221 to 4bf69d4 Compare August 6, 2025 14:27
@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch from 54a4224 to 4d2c853 Compare August 6, 2025 20:42
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 4bf69d4 to b558c6f Compare August 7, 2025 23:18
@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch 2 times, most recently from aab1fbd to 4760315 Compare August 11, 2025 19:19
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from b558c6f to 9975ad2 Compare August 11, 2025 19:23
@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch from 4760315 to 6b4df30 Compare August 12, 2025 16:09
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch 2 times, most recently from dfcb23e to 08205b8 Compare August 12, 2025 19:47
@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch from 6b4df30 to f9dc21c Compare August 12, 2025 19:47
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 08205b8 to 0bbff95 Compare August 12, 2025 20:08
@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch from f9dc21c to 3efc234 Compare August 13, 2025 18:22
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch 2 times, most recently from cfd8a0d to f82758a Compare August 13, 2025 19:41
@eriktate eriktate added the no-changelog Indicates that a PR does not require a changelog entry label Aug 13, 2025
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from f82758a to ad69faf Compare August 13, 2025 20:05
@eriktate eriktate force-pushed the eriktate/rotated-keys-resource branch 2 times, most recently from 9f2fc98 to b609982 Compare August 14, 2025 17:57
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch 2 times, most recently from feb25d0 to 37eeb59 Compare August 14, 2025 18:42
Base automatically changed from eriktate/rotated-keys-resource to master August 14, 2025 18:51
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 9a4027f to b5a6e71 Compare August 19, 2025 21:01
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from b5a6e71 to 0216b77 Compare August 20, 2025 19:19
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 4c4f4f8 to dc622f3 Compare August 20, 2025 20:40
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 81c0b43 to 94a2ae6 Compare August 21, 2025 15:52
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 94a2ae6 to 94498db Compare August 21, 2025 16:17
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 94498db to 775f225 Compare August 22, 2025 19:35
Comment thread lib/auth/recordingencryption/manager.go Outdated
Comment thread lib/auth/recordingencryption/manager_test.go Outdated
Comment thread lib/auth/recordingencryption/manager.go Outdated
Comment thread lib/auth/recordingencryption/manager.go Outdated
Comment thread lib/auth/recordingencryption/manager.go Outdated
Comment thread lib/auth/recordingencryption/manager.go Outdated
Comment thread lib/auth/recordingencryption/manager.go Outdated
Comment thread lib/auth/recordingencryption/manager.go Outdated
Comment thread lib/auth/recordingencryption/manager.go Outdated
// resolveAllSessionRecordingConfigs coordinates all updates to the [SessionRecordingConfig] or [RecordingEncryption]
// resources and ensures that both are in a valid state with respect to eachother. If either resource is nil when
// calling this function, they will be fetched from the backend.
func (m *Manager) resolveAllSessionRecordingConfigs(ctx context.Context, in resolveSessionRecordingInput) (types.SessionRecordingConfig, *recordingencryptionv1.RecordingEncryption, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this function a bit hard to grok. There's a lot going on, callers can modify it's behavior by passing in different resolveSessionRecordingInput fields. It seems like this exists to have a unified location for holding the backend lock and acting accordingly for each use case, but I'm wondering if the unification is causing things to be more complex than it needs to be.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's partly to keep everything in the same backend lock and partly because there's a lot of overlap between the different cases. I did notice I was never providing both a SessionRecordingConfig and a RecordingEncryption to a single call of resolveAllSessionRecordingConfigs, so I split it into two functions. modifySessionRecordingConfig handles explicit modifications of the SessionRecordingConfig and modifyRecordingEncryption handles explicit modifications of the RecordingEncryption. It's not a huge change, but I think it helps a bit with the readability

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better! Thank you for taking another look at this.

@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 775f225 to 9c09e0e Compare August 25, 2025 15:19
@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from 6c56f27 to 447add2 Compare August 25, 2025 17:15
@eriktate eriktate requested a review from rosstimothy August 25, 2025 17:16
Comment thread lib/auth/recordingencryption/manager.go Outdated
}

if len(rotatedDecrypters) == 0 && len(rotatedLabels) > 0 {
m.logger.WarnContext(ctx, "no accessible keys found for manual_key_management.rotated_keys")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens in this state? Maybe add a comment explaining why it's okay to proceed and possibly update the log message to indicate what needs to be done if any action is required, and what this means for the health of the cluster?

Copy link
Copy Markdown
Contributor Author

@eriktate eriktate Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments here, but this would prevent replay of historical recordings that were encrypted using any of the missing rotated keys. I don't treat this as a catastrophic error because we've already confirmed there's a valid active key at this point, and so there's no destructive harm in allowing the auth service to continue. Assuming the issue is fixed, the impacted recordings would just become playable again.

Comment thread lib/auth/recordingencryption/manager.go Outdated
// will be provisioned. An error is returned if an active key is found but is not accessible.
func (m *Manager) resolveRecordingEncryption(ctx context.Context, sessionRecordingCfg types.SessionRecordingConfig, encryption *recordingencryptionv1.RecordingEncryption) (*recordingencryptionv1.RecordingEncryption, error) {
if !sessionRecordingCfg.GetEncrypted() {
return nil, nil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is return nil,nil safe? If this is expected we should at least document the behavior. However, I'm fairly certain that this would result in a panic here, if not in the other places this function is called as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is expected and it should be safe because GetSpec()and GetActiveKeyPairs both have nil checks. I can return a pointer to a zero-value RecordingEncryption instead, but I think the nil is a better signal that there's no RecordingEncryption to work with.

Copy link
Copy Markdown
Contributor

@rosstimothy rosstimothy Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's clarify in the function docs the expected contract of the function since nil, nil is not a common return in Go.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comment and also opted to return the given encryption argument instead of just nil. It's still possible for the return to be nil, nil, but only if the function was called with a nil to begin with

@eriktate eriktate force-pushed the eriktate/rotating-encryption-keys branch from e24a4ff to d17e49f Compare August 25, 2025 20:47
checking access to manual keys before persisting and init
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold-for-18.2 no-changelog Indicates that a PR does not require a changelog entry size/md

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants