mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
sse: add support for SSE-KMS bucket configurations (#12295)
This commit adds support for SSE-KMS bucket configurations. Before, the MinIO server did not support SSE-KMS, and therefore, it was not possible to specify an SSE-KMS bucket config. Now, this is possible. For example: ``` mc encrypt set sse-kms some-key <alias>/my-bucket ``` Further, this commit fixes an issue caused by not supporting SSE-KMS bucket configuration and switching to SSE-KMS as default SSE method. Before, the server just checked whether an SSE bucket config was present (not which type of SSE config) and applied the default SSE method (which was switched from SSE-S3 to SSE-KMS). This caused objects to get encrypted with SSE-KMS even though a SSE-S3 bucket config was present. This issue is fixed as a side-effect of this commit. Signed-off-by: Andreas Auernhammer <aead@mail.de>
This commit is contained in:
parent
951acf561c
commit
a1f70b106f
@ -53,7 +53,7 @@ func validateBucketSSEConfig(r io.Reader) (*bucketsse.BucketSSEConfig, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(encConfig.Rules) == 1 && encConfig.Rules[0].DefaultEncryptionAction.Algorithm == bucketsse.AES256 {
|
||||
if len(encConfig.Rules) == 1 {
|
||||
return encConfig, nil
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -47,12 +46,12 @@ func TestValidateBucketSSEConfig(t *testing.T) {
|
||||
<Rule>
|
||||
<ApplyServerSideEncryptionByDefault>
|
||||
<SSEAlgorithm>aws:kms</SSEAlgorithm>
|
||||
<KMSMasterKeyID>arn:aws:kms:us-east-1:1234/5678example</KMSMasterKeyID>
|
||||
<KMSMasterKeyID>my-key</KMSMasterKeyID>
|
||||
</ApplyServerSideEncryptionByDefault>
|
||||
</Rule>
|
||||
</ServerSideEncryptionConfiguration>`,
|
||||
expectedErr: errors.New("Unsupported bucket encryption configuration"),
|
||||
shouldPass: false,
|
||||
expectedErr: nil,
|
||||
shouldPass: true,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -992,12 +992,8 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
||||
var objectEncryptionKey crypto.ObjectKey
|
||||
|
||||
// Check if bucket encryption is enabled
|
||||
if _, err = globalBucketSSEConfigSys.Get(bucket); err == nil || globalAutoEncryption {
|
||||
// This request header needs to be set prior to setting ObjectOptions
|
||||
if !crypto.SSEC.IsRequested(r.Header) {
|
||||
r.Header.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionAES)
|
||||
}
|
||||
}
|
||||
sseConfig, _ := globalBucketSSEConfigSys.Get(bucket)
|
||||
sseConfig.Apply(r.Header, globalAutoEncryption)
|
||||
|
||||
// get gateway encryption options
|
||||
var opts ObjectOptions
|
||||
|
@ -960,11 +960,8 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
||||
}
|
||||
|
||||
// Check if bucket encryption is enabled
|
||||
_, err = globalBucketSSEConfigSys.Get(dstBucket)
|
||||
// This request header needs to be set prior to setting ObjectOptions
|
||||
if (globalAutoEncryption || err == nil) && !crypto.SSEC.IsRequested(r.Header) {
|
||||
r.Header.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionKMS)
|
||||
}
|
||||
sseConfig, _ := globalBucketSSEConfigSys.Get(dstBucket)
|
||||
sseConfig.Apply(r.Header, globalAutoEncryption)
|
||||
|
||||
var srcOpts, dstOpts ObjectOptions
|
||||
srcOpts, err = copySrcOpts(ctx, r, srcBucket, srcObject)
|
||||
@ -1566,11 +1563,8 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
||||
}
|
||||
|
||||
// Check if bucket encryption is enabled
|
||||
_, err = globalBucketSSEConfigSys.Get(bucket)
|
||||
// This request header needs to be set prior to setting ObjectOptions
|
||||
if (globalAutoEncryption || err == nil) && !crypto.SSEC.IsRequested(r.Header) {
|
||||
r.Header.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionKMS)
|
||||
}
|
||||
sseConfig, _ := globalBucketSSEConfigSys.Get(bucket)
|
||||
sseConfig.Apply(r.Header, globalAutoEncryption)
|
||||
|
||||
actualSize := size
|
||||
if objectAPI.IsCompressionSupported() && isCompressible(r.Header, object) && size > 0 {
|
||||
@ -1885,11 +1879,8 @@ func (api objectAPIHandlers) PutObjectExtractHandler(w http.ResponseWriter, r *h
|
||||
}
|
||||
|
||||
// Check if bucket encryption is enabled
|
||||
_, err = globalBucketSSEConfigSys.Get(bucket)
|
||||
// This request header needs to be set prior to setting ObjectOptions
|
||||
if (globalAutoEncryption || err == nil) && !crypto.SSEC.IsRequested(r.Header) {
|
||||
r.Header.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionAES)
|
||||
}
|
||||
sseConfig, _ := globalBucketSSEConfigSys.Get(bucket)
|
||||
sseConfig.Apply(r.Header, globalAutoEncryption)
|
||||
|
||||
retPerms := isPutActionAllowed(ctx, getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction)
|
||||
holdPerms := isPutActionAllowed(ctx, getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction)
|
||||
@ -2076,11 +2067,8 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r
|
||||
}
|
||||
|
||||
// Check if bucket encryption is enabled
|
||||
_, err = globalBucketSSEConfigSys.Get(bucket)
|
||||
// This request header needs to be set prior to setting ObjectOptions
|
||||
if (globalAutoEncryption || err == nil) && !crypto.SSEC.IsRequested(r.Header) {
|
||||
r.Header.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionKMS)
|
||||
}
|
||||
sseConfig, _ := globalBucketSSEConfigSys.Get(bucket)
|
||||
sseConfig.Apply(r.Header, globalAutoEncryption)
|
||||
|
||||
// Validate storage class metadata if present
|
||||
if sc := r.Header.Get(xhttp.AmzStorageClass); sc != "" {
|
||||
|
@ -1201,10 +1201,8 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Check if bucket encryption is enabled
|
||||
_, err = globalBucketSSEConfigSys.Get(bucket)
|
||||
if (globalAutoEncryption || err == nil) && !crypto.SSEC.IsRequested(r.Header) {
|
||||
r.Header.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionKMS)
|
||||
}
|
||||
sseConfig, _ := globalBucketSSEConfigSys.Get(bucket)
|
||||
sseConfig.Apply(r.Header, globalAutoEncryption)
|
||||
|
||||
// Require Content-Length to be set in the request
|
||||
size := r.ContentLength
|
||||
|
@ -21,6 +21,10 @@ import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio/cmd/crypto"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -107,6 +111,49 @@ func ParseBucketSSEConfig(r io.Reader) (*BucketSSEConfig, error) {
|
||||
if config.XMLNS == "" {
|
||||
config.XMLNS = xmlNS
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// Apply applies the SSE bucket configuration on the given HTTP headers and
|
||||
// sets the specified SSE headers.
|
||||
//
|
||||
// Apply does not overwrite any existing SSE headers. Further, it will
|
||||
// set minimal SSE-KMS headers if autoEncrypt is true and the BucketSSEConfig
|
||||
// is nil.
|
||||
func (b *BucketSSEConfig) Apply(headers http.Header, autoEncrypt bool) {
|
||||
if _, ok := crypto.IsRequested(headers); ok {
|
||||
return
|
||||
}
|
||||
if b == nil {
|
||||
if autoEncrypt {
|
||||
headers.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionKMS)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch b.Algorithm() {
|
||||
case xhttp.AmzEncryptionAES:
|
||||
headers.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionAES)
|
||||
case xhttp.AmzEncryptionKMS:
|
||||
headers.Set(xhttp.AmzServerSideEncryption, xhttp.AmzEncryptionKMS)
|
||||
headers.Set(xhttp.AmzServerSideEncryptionKmsID, b.KeyID())
|
||||
}
|
||||
}
|
||||
|
||||
// Algorithm returns the SSE algorithm specified by the SSE configuration.
|
||||
func (b *BucketSSEConfig) Algorithm() SSEAlgorithm {
|
||||
for _, rule := range b.Rules {
|
||||
return rule.DefaultEncryptionAction.Algorithm
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// KeyID returns the KMS key ID specified by the SSE configuration.
|
||||
// If the SSE configuration does not specify SSE-KMS it returns an
|
||||
// empty key ID.
|
||||
func (b *BucketSSEConfig) KeyID() string {
|
||||
for _, rule := range b.Rules {
|
||||
return rule.DefaultEncryptionAction.MasterKeyID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user