Skip to content

Adding manual encryption key management for encrypted recordings#56920

Merged
eriktate merged 1 commit intomasterfrom
eriktate/manual-encryption-keys
Aug 5, 2025
Merged

Adding manual encryption key management for encrypted recordings#56920
eriktate merged 1 commit intomasterfrom
eriktate/manual-encryption-keys

Conversation

@eriktate
Copy link
Copy Markdown
Contributor

@eriktate eriktate commented Jul 17, 2025

This PR adds configurations for manual management of session recording encryption keys. This works by accepting an active and rotated list of KeyLabels which designate which keystore a key can be found in and an identifying label. For HSM systems this is a label that that might identify multiple keys, but for KMS systems this will be an ID, ARN, or fully qualified version name of a specific key.

Once an auth server knows how to find the keys, it will search for them in its configured keystore (configurable with ca_key_params), save the public keys to the session_recording_config resource to enable encryption, and cache the associated crypto.Decrypter for future replay. When in manual management mode, Teleport will make no attempt at provisioning or rotating recording encryption keys.

Comment thread api/types/enum.go Outdated
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.

I added these helpers because I noticed that most of the enum types with custom unmarshalers were doing essentially the same thing. For now these are only used by PrivateKeyType since that's the only one I'm modifying for this PR, but I might do a separate PR that updates the other enum types to use this unless I get feedback against implementing this generically.

@eriktate eriktate force-pushed the eriktate/rsa-recording-encryption branch from 65d37b1 to 4c6f773 Compare July 21, 2025 21:24
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch 2 times, most recently from 72bfb2a to e6cde62 Compare July 21, 2025 22:02
Comment on lines +229 to +232
shouldUpdate := len(addedKeys) > 0 && (keysChanged || len(existingKeys) != len(addedKeys))
if !shouldUpdate {
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.

This was previously failing to remove keys after rotation

@eriktate eriktate marked this pull request as ready for review July 21, 2025 22:06
@github-actions github-actions Bot requested review from nklaassen and rudream July 21, 2025 22:06
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from e6cde62 to 03952e5 Compare July 21, 2025 22:10
@eriktate eriktate force-pushed the eriktate/rsa-recording-encryption branch from 4c6f773 to cd87b3e Compare July 21, 2025 22:11
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 03952e5 to 11aec2a Compare July 21, 2025 22:12
@eriktate eriktate force-pushed the eriktate/rsa-recording-encryption branch from cd87b3e to 6044e3f Compare July 22, 2025 19:59
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 24ea8a4 to cd09a43 Compare July 22, 2025 20:00
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jul 22, 2025

Amplify deployment status

Branch Commit Job ID Status Preview Updated (UTC)
eriktate/manual-encryption-keys 2c98b5d 18 ✅SUCCEED eriktate-manual-encryption-keys 2025-08-05 21:09:51

@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 29da268 to 3f8ea79 Compare July 22, 2025 22:15
@eriktate eriktate force-pushed the eriktate/rsa-recording-encryption branch from 17e0aab to ced2f23 Compare July 23, 2025 13:00
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 3f8ea79 to 6c7edeb Compare July 23, 2025 13:02
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 6c7edeb to 174da72 Compare July 23, 2025 13:25
@eriktate eriktate added the no-changelog Indicates that a PR does not require a changelog entry label Jul 23, 2025
Base automatically changed from eriktate/rsa-recording-encryption to master July 23, 2025 15:43
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 174da72 to 836f806 Compare July 25, 2025 13:21
Comment thread api/types/sessionrecording.go Outdated
Comment thread api/types/sessionrecording.go
Comment thread api/proto/teleport/legacy/types/types.proto Outdated
Comment thread lib/auth/keystore/gcp_kms.go Outdated

func (s *kmsKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) {
resp, err := doGCPRequest(s.ctx, s.g, s.g.kmsClient.AsymmetricDecrypt, &kmspb.AsymmetricDecryptRequest{
resp, err := doGCPRequest(context.Background(), s.g, s.g.kmsClient.AsymmetricDecrypt, &kmspb.AsymmetricDecryptRequest{
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.

How come this was changed to a background context?

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.

I meant to come back around and fix this. The embedded context in kmsKey was causing cache issues because it only had a request lifetime when the keys were fetched during asession_recording_config update. I added a context to the Manager struct to be used for this so any cached key context has at least the same lifetime as the manager itself.

Comment thread lib/config/fileconf.go Outdated
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 72c8635 to 72afacd Compare July 28, 2025 22:34
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 7739cfa to 6f668f3 Compare July 29, 2025 20:02
@eriktate
Copy link
Copy Markdown
Contributor Author

Do you intend on following up in another PR to prevent manual key management from being enabled for Cloud?

I do and you can find it here.

Should we validate the KeyLabel types prior to persisting the SessionRecordingEncryptionConfig?

Most definitely, should be in the latest commit 👍

@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 6f668f3 to 27e5b9c Compare July 29, 2025 20:32
return nil, trace.AccessDenied("this request can be only executed by an auth server")
}

if err := cfg.CheckAndSetDefaults(); err != 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.

What do you think about adding a services.ValidateSessionRecordingConfig function similar to services.ValidateAuthPreference which can also be home to the cloud and fips checks from your future PR instead of performing a CheckAndSetDefaults in the gRPC layer?

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.

Yeah I wasn't totally sure about using CheckAndSetDefaults for this. Adding a new validation func to services makes sense to me 👍

@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from d114b67 to 3d01dd2 Compare July 30, 2025 19:48
@eriktate
Copy link
Copy Markdown
Contributor Author

@nklaassen @rudream friendly ping!

)

// ValidateSessionRecordingConfig checks that the state of a [SessionRecordingConfig] meets constraints.
func ValidateSessionRecordingConfig(cfg types.SessionRecordingConfig) 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.

Suggestion: add some test coverage for this

@public-teleport-github-review-bot public-teleport-github-review-bot Bot removed the request for review from rudream July 31, 2025 15:57
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 3d01dd2 to 0372b0a Compare August 5, 2025 20:03
@eriktate eriktate force-pushed the eriktate/manual-encryption-keys branch from 0372b0a to 2c98b5d Compare August 5, 2025 20:59
@eriktate eriktate enabled auto-merge August 5, 2025 21:02
@eriktate eriktate added this pull request to the merge queue Aug 5, 2025
Merged via the queue into master with commit 8eb5aca Aug 5, 2025
44 checks passed
@eriktate eriktate deleted the eriktate/manual-encryption-keys branch August 5, 2025 21:42
eriktate added a commit that referenced this pull request Aug 15, 2025
eriktate added a commit that referenced this pull request Aug 27, 2025
eriktate added a commit that referenced this pull request Sep 2, 2025
eriktate added a commit that referenced this pull request Sep 2, 2025
eriktate added a commit that referenced this pull request Sep 2, 2025
eriktate added a commit that referenced this pull request Sep 3, 2025
github-merge-queue Bot pushed a commit that referenced this pull request Sep 3, 2025
* adding support for encryption/decryption keys to keystore manager (#54428, #55652)

* adds new protos for resources related to encrypted session recordings and updates the existing SessionRecordingConfig protos to include a Status (#54780)

* adding local service implementation for recording encryption resources (#54816)

* adding Manager for RecordingEncryption resources that handles shared ops more complex than CRUD (#55078)

* Adding session recording plugin for `age` (#55120)

* adding Manager for RecordingEncryption resources that handles shared ops more complex than CRUD

* adding age plugin wrapping default X25519 Identity/Recipient implementation with hooks to more efficiently lookup private keys given their respective public key

* Adding recording encryption and playback for `sync` modes (#54901)

* adding cache for RecordingEncryption (#55857)

* adding recording_encryption service protos (#55121)

* adding async recording encryption with gRPC multipart uploader (#55859)

* adding file configuration for encrypted session recording (#56200)

* Switching recording encryption to unwrap keys using direct keystore RSA decryption (#56776)

* adding manual key management config (#56920)

* updating protos for recording encryption (#57055)

* Add missing handling for recording encryption configs and keys (#57279)

* updating protos for recording encryption

* changing labels for encryption keys to prevent automatic cleanup, adjusting pkcs11 host UUID check to allow for key sharing of encryption keys, preventing cloud tenants from enabling manual key management, preventing use of recording encryption in FIPS mode

* adding new protos for rotated keys and the local service for interacting (#57576)

with them

* Switching encryption keys from PEM to ASN.1 DER encoding (#58137)

* using pregenerated RSA4096 key for keystore tests because generation is too slow (#58138)

* extending precomputed RSA keys to support 4096-bit keys (#58251)

* adding rotation process to Manager and exposing with new RPCs and (#57577)

* adding rotation sub commands for recording encryption keys and fixing (#57780)

broken session_recording_config when using fileconf

* using more reliable method of validating key bit length
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog Indicates that a PR does not require a changelog entry size/lg

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants