mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-01 21:52:02 +08:00
Add support for configurable KMS CMK keys for S3 SSE (#8354)
This commit is contained in:
@@ -349,6 +349,9 @@ const (
|
||||
// DisableServerSideEncryption is an optional switch to opt out of SSE in case the provider does not support it
|
||||
DisableServerSideEncryption = "disablesse"
|
||||
|
||||
// SSEKMSKey is an optional switch to use an KMS CMK key for S3 SSE.
|
||||
SSEKMSKey = "sse_kms_key"
|
||||
|
||||
// SchemeFile is a local disk file storage
|
||||
SchemeFile = "file"
|
||||
|
||||
|
||||
@@ -215,6 +215,119 @@ These optional `GET` parameters control how Teleport interacts with an S3 endpoi
|
||||
- `endpoint=mys3.example.com` - connect to a custom S3 endpoint.
|
||||
- `insecure=true` - set to `true` or `false`. If `true`, TLS will be disabled.
|
||||
- `disablesse=true` - set to `true` or `false`. If `true`, S3 server-side encryption will be disabled. If `false`, aws:kms (Key Management Service) will be used for server-side encryption. Other SSE types are not supported at this time.
|
||||
- `sse_kms_key=kms_key_id` - If set to a valid AWS KMS CMK key ID all objects uploaded to S3 will be encrypted with this key. Details can be found below.
|
||||
|
||||
### S3 Server Side Encryption
|
||||
|
||||
Teleport supports using a custom AWS KMS Customer Managed Key for encrypting objects uploaded to S3.
|
||||
This allows you to restrict who can read objects like session recordings separately from those that have read
|
||||
access to a bucket by restricting key access.
|
||||
|
||||
The `sse_kms_key` parameter above can be set to any valid KMS CMK ID corresponding to a symmetric standard spec KMS key.
|
||||
Example template KMS key policies are provided below for common usage cases. IAM users do not have access to any
|
||||
key by default. Permissions have to be explicitly granted in the policy.
|
||||
|
||||
#### Encryption/Decryption
|
||||
|
||||
This policy allows an IAM user to encrypt and decrypt objects.
|
||||
This allows a cluster auth to write and play back session recordings.
|
||||
|
||||
Replace `[iam-key-admin-arn]` with the IAM ARN of the user(s) that should have
|
||||
administrative key access and `[auth-node-iam-arn]` with the IAM ARN
|
||||
of the user the Teleport auth nodes are using.
|
||||
|
||||
```json
|
||||
{
|
||||
"Id": "Teleport Encryption and Decryption",
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Teleport CMK Admin",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "[iam-key-admin-arn]"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Teleport CMK Auth",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "[auth-node-iam-arn]"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Encryption/Decryption with separate clusters
|
||||
|
||||
This policy allows specifying separate IAM users for encryption and decryption.
|
||||
This can be used to set up a multi cluster configuration where the main cluster
|
||||
cannot play back session recordings but only write them.
|
||||
A separate cluster authenticating as a different IAM user with decryption access
|
||||
can be used for playing back the session recordings.
|
||||
|
||||
Replace `[iam-key-admin-arn]` with the IAM ARN of the user(s) that should have
|
||||
administrative key access, `[iam-node-write-arn]` with the IAM ARN of the user the
|
||||
main write-only cluster auth nodes are using and `[iam-node-read-arn]` with the
|
||||
IAM ARN of the user used by the read-only cluster.
|
||||
|
||||
For this to work the second cluster has to be connected to the same audit log as the main cluster.
|
||||
This is needed to detect session recordings.
|
||||
|
||||
```json
|
||||
{
|
||||
"Id": "Teleport Separate Encryption and Decryption",
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Teleport CMK Admin",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "[iam-key-admin-arn]"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Teleport CMK Auth Encrypt",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "[auth-node-write-arn]"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Teleport CMK Auth Decrypt",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "[auth-node-read-arn]"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Decrypt",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## DynamoDB
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ type Config struct {
|
||||
Session *awssession.Session
|
||||
// Credentials if supplied are used in tests
|
||||
Credentials *credentials.Credentials
|
||||
// SSEKMSKey specifies the optional custom CMK used for KMS SSE.
|
||||
SSEKMSKey string
|
||||
}
|
||||
|
||||
// SetFromURL sets values on the Config from the supplied URI
|
||||
@@ -83,6 +85,9 @@ func (s *Config) SetFromURL(in *url.URL, inRegion string) error {
|
||||
}
|
||||
s.DisableServerSideEncryption = disableServerSideEncryption
|
||||
}
|
||||
if val := in.Query().Get(teleport.SSEKMSKey); val != "" {
|
||||
s.SSEKMSKey = val
|
||||
}
|
||||
s.Region = region
|
||||
s.Bucket = in.Host
|
||||
s.Path = in.Path
|
||||
@@ -176,6 +181,10 @@ func (h *Handler) Upload(ctx context.Context, sessionID session.ID, reader io.Re
|
||||
}
|
||||
if !h.Config.DisableServerSideEncryption {
|
||||
uploadInput.ServerSideEncryption = aws.String(s3.ServerSideEncryptionAwsKms)
|
||||
|
||||
if h.Config.SSEKMSKey != "" {
|
||||
uploadInput.SSEKMSKeyId = aws.String(h.Config.SSEKMSKey)
|
||||
}
|
||||
}
|
||||
_, err = h.uploader.UploadWithContext(ctx, uploadInput)
|
||||
if err != nil {
|
||||
@@ -202,6 +211,7 @@ func (h *Handler) Download(ctx context.Context, sessionID session.ID, writer io.
|
||||
Key: aws.String(h.path(sessionID)),
|
||||
VersionId: aws.String(versionID),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return ConvertS3Error(err)
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ func (h *Handler) CreateUpload(ctx context.Context, sessionID session.ID) (*even
|
||||
}
|
||||
if !h.Config.DisableServerSideEncryption {
|
||||
input.ServerSideEncryption = aws.String(s3.ServerSideEncryptionAwsKms)
|
||||
|
||||
if h.Config.SSEKMSKey != "" {
|
||||
input.SSEKMSKeyId = aws.String(h.Config.SSEKMSKey)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := h.client.CreateMultipartUploadWithContext(ctx, input)
|
||||
@@ -75,6 +79,7 @@ func (h *Handler) UploadPart(ctx context.Context, upload events.StreamUpload, pa
|
||||
Body: partBody,
|
||||
PartNumber: aws.Int64(partNumber),
|
||||
}
|
||||
|
||||
resp, err := h.client.UploadPartWithContext(ctx, params)
|
||||
if err != nil {
|
||||
return nil, ConvertS3Error(err)
|
||||
|
||||
Reference in New Issue
Block a user