diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go
index 923bcef04..30f484d8b 100644
--- a/cmd/admin-handlers.go
+++ b/cmd/admin-handlers.go
@@ -37,9 +37,9 @@ import (
"time"
"github.com/gorilla/mux"
+ "github.com/minio/kes"
"github.com/minio/madmin-go"
"github.com/minio/minio/cmd/config"
- "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/cmd/logger/message/log"
@@ -1003,7 +1003,7 @@ func toAdminAPIErr(ctx context.Context, err error) APIError {
Description: err.Error(),
HTTPStatusCode: http.StatusServiceUnavailable,
}
- case errors.Is(err, crypto.ErrKESKeyExists):
+ case errors.Is(err, kes.ErrKeyExists):
apiErr = APIError{
Code: "XMinioKMSKeyExists",
Description: err.Error(),
diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go
index 34097daf3..651eed362 100644
--- a/cmd/bucket-handlers.go
+++ b/cmd/bucket-handlers.go
@@ -50,6 +50,7 @@ import (
"github.com/minio/minio/pkg/handlers"
"github.com/minio/minio/pkg/hash"
iampolicy "github.com/minio/minio/pkg/iam/policy"
+ "github.com/minio/minio/pkg/kms"
"github.com/minio/minio/pkg/sync/errgroup"
)
@@ -1015,7 +1016,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
reader io.Reader
keyID string
key []byte
- kmsCtx crypto.Context
+ kmsCtx kms.Context
)
kind, _ := crypto.IsRequested(formValues)
switch kind {
diff --git a/cmd/bucket-metadata-sys.go b/cmd/bucket-metadata-sys.go
index 2cae5ecfa..dc5894bcf 100644
--- a/cmd/bucket-metadata-sys.go
+++ b/cmd/bucket-metadata-sys.go
@@ -26,7 +26,6 @@ import (
"github.com/minio/madmin-go"
"github.com/minio/minio-go/v7/pkg/tags"
- "github.com/minio/minio/cmd/crypto"
"github.com/minio/minio/cmd/logger"
bucketsse "github.com/minio/minio/pkg/bucket/encryption"
"github.com/minio/minio/pkg/bucket/lifecycle"
@@ -35,6 +34,7 @@ import (
"github.com/minio/minio/pkg/bucket/replication"
"github.com/minio/minio/pkg/bucket/versioning"
"github.com/minio/minio/pkg/event"
+ "github.com/minio/minio/pkg/kms"
"github.com/minio/minio/pkg/sync/errgroup"
)
@@ -170,7 +170,7 @@ func (sys *BucketMetadataSys) Update(bucket string, configFile string, configDat
}
meta.ReplicationConfigXML = configData
case bucketTargetsFile:
- meta.BucketTargetsConfigJSON, meta.BucketTargetsConfigMetaJSON, err = encryptBucketMetadata(meta.Name, configData, crypto.Context{
+ meta.BucketTargetsConfigJSON, meta.BucketTargetsConfigMetaJSON, err = encryptBucketMetadata(meta.Name, configData, kms.Context{
bucket: meta.Name,
bucketTargetsFile: bucketTargetsFile,
})
diff --git a/cmd/bucket-targets.go b/cmd/bucket-targets.go
index deb37e57a..15cba3704 100644
--- a/cmd/bucket-targets.go
+++ b/cmd/bucket-targets.go
@@ -33,6 +33,7 @@ import (
"github.com/minio/minio/cmd/crypto"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/bucket/versioning"
+ "github.com/minio/minio/pkg/kms"
)
const (
@@ -390,7 +391,7 @@ func parseBucketTargetConfig(bucket string, cdata, cmetadata []byte) (*madmin.Bu
return nil, err
}
if crypto.S3.IsEncrypted(meta) {
- if data, err = decryptBucketMetadata(cdata, bucket, meta, crypto.Context{
+ if data, err = decryptBucketMetadata(cdata, bucket, meta, kms.Context{
bucket: bucket,
bucketTargetsFile: bucketTargetsFile,
}); err != nil {
diff --git a/cmd/common-main.go b/cmd/common-main.go
index 83baad223..95d93f6a1 100644
--- a/cmd/common-main.go
+++ b/cmd/common-main.go
@@ -40,12 +40,12 @@ import (
"github.com/minio/cli"
"github.com/minio/minio-go/v7/pkg/set"
"github.com/minio/minio/cmd/config"
- "github.com/minio/minio/cmd/crypto"
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/certs"
"github.com/minio/minio/pkg/console"
+ "github.com/minio/minio/pkg/ellipses"
"github.com/minio/minio/pkg/env"
"github.com/minio/minio/pkg/handlers"
"github.com/minio/minio/pkg/kms"
@@ -361,18 +361,37 @@ func handleCommonEnvVars() {
}
}
if env.IsSet(config.EnvKESEndpoint) {
- kesEndpoints, err := crypto.ParseKESEndpoints(env.Get(config.EnvKESEndpoint, ""))
- if err != nil {
- logger.Fatal(err, "Unable to parse the KES endpoints inherited from the shell environment")
+ var endpoints []string
+ for _, endpoint := range strings.Split(env.Get(config.EnvKESEndpoint, ""), ",") {
+ if strings.TrimSpace(endpoint) == "" {
+ continue
+ }
+ if !ellipses.HasEllipses(endpoint) {
+ endpoints = append(endpoints, endpoint)
+ continue
+ }
+ patterns, err := ellipses.FindEllipsesPatterns(endpoint)
+ if err != nil {
+ logger.Fatal(err, fmt.Sprintf("Invalid KES endpoint %q", endpoint))
+ }
+ for _, lbls := range patterns.Expand() {
+ endpoints = append(endpoints, strings.Join(lbls, ""))
+ }
}
- KMS, err := crypto.NewKes(crypto.KesConfig{
- Enabled: true,
- Endpoint: kesEndpoints,
+ certificate, err := tls.LoadX509KeyPair(env.Get(config.EnvKESClientCert, ""), env.Get(config.EnvKESClientKey, ""))
+ if err != nil {
+ logger.Fatal(err, "Unable to load KES client certificate as specified by the shell environment")
+ }
+ rootCAs, err := certs.GetRootCAs(env.Get(config.EnvKESServerCA, globalCertsCADir.Get()))
+ if err != nil {
+ logger.Fatal(err, fmt.Sprintf("Unable to load X.509 root CAs for KES from %q", env.Get(config.EnvKESServerCA, globalCertsCADir.Get())))
+ }
+
+ KMS, err := kms.NewWithConfig(kms.Config{
+ Endpoints: endpoints,
DefaultKeyID: env.Get(config.EnvKESKeyName, ""),
- CertFile: env.Get(config.EnvKESClientCert, ""),
- KeyFile: env.Get(config.EnvKESClientKey, ""),
- CAPath: env.Get(config.EnvKESServerCA, globalCertsCADir.Get()),
- Transport: newCustomHTTPTransportWithHTTP2(&tls.Config{RootCAs: globalRootCAs}, defaultDialTimeout)(),
+ Certificate: certificate,
+ RootCAs: rootCAs,
})
if err != nil {
logger.Fatal(err, "Unable to initialize a connection to KES as specified by the shell environment")
diff --git a/cmd/crypto/kms.go b/cmd/crypto/auto-encryption.go
similarity index 53%
rename from cmd/crypto/kms.go
rename to cmd/crypto/auto-encryption.go
index d78fe9a84..103011ca7 100644
--- a/cmd/crypto/kms.go
+++ b/cmd/crypto/auto-encryption.go
@@ -18,15 +18,23 @@
package crypto
import (
- "github.com/minio/minio/pkg/kms"
+ "github.com/minio/minio/cmd/config"
+ "github.com/minio/minio/pkg/env"
)
-// Context is a list of key-value pairs cryptographically
-// associated with a certain object.
-type Context = kms.Context
+const (
+ // EnvKMSAutoEncryption is the environment variable used to en/disable
+ // SSE-S3 auto-encryption. SSE-S3 auto-encryption, if enabled,
+ // requires a valid KMS configuration and turns any non-SSE-C
+ // request into an SSE-S3 request.
+ // If present EnvAutoEncryption must be either "on" or "off".
+ EnvKMSAutoEncryption = "MINIO_KMS_AUTO_ENCRYPTION"
+)
-// KMS represents an active and authenticted connection
-// to a Key-Management-Service. It supports generating
-// data key generation and unsealing of KMS-generated
-// data keys.
-type KMS = kms.KMS
+// LookupAutoEncryption returns true if and only if
+// the MINIO_KMS_AUTO_ENCRYPTION env. variable is
+// set to "on".
+func LookupAutoEncryption() bool {
+ auto, _ := config.ParseBool(env.Get(EnvKMSAutoEncryption, config.EnableOff))
+ return auto
+}
diff --git a/cmd/crypto/config.go b/cmd/crypto/config.go
deleted file mode 100644
index a1f30f0f2..000000000
--- a/cmd/crypto/config.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package crypto
-
-import (
- "math/rand"
- "strings"
-
- "github.com/minio/minio/cmd/config"
- "github.com/minio/minio/pkg/ellipses"
- "github.com/minio/minio/pkg/env"
- xnet "github.com/minio/minio/pkg/net"
-)
-
-const (
- // EnvKMSAutoEncryption is the environment variable used to en/disable
- // SSE-S3 auto-encryption. SSE-S3 auto-encryption, if enabled,
- // requires a valid KMS configuration and turns any non-SSE-C
- // request into an SSE-S3 request.
- // If present EnvAutoEncryption must be either "on" or "off".
- EnvKMSAutoEncryption = "MINIO_KMS_AUTO_ENCRYPTION"
-)
-
-// ParseKESEndpoints parses the given endpoint string and
-// returns a list of valid endpoint URLs. The order of the
-// returned endpoints is randomized.
-func ParseKESEndpoints(endpointStr string) ([]string, error) {
- var rawEndpoints []string
- for _, endpoint := range strings.Split(endpointStr, ",") {
- if strings.TrimSpace(endpoint) == "" {
- continue
- }
- if !ellipses.HasEllipses(endpoint) {
- rawEndpoints = append(rawEndpoints, endpoint)
- continue
- }
- pattern, err := ellipses.FindEllipsesPatterns(endpoint)
- if err != nil {
- return nil, Errorf("Invalid KES endpoint %q: %v", endpointStr, err)
- }
- for _, p := range pattern {
- rawEndpoints = append(rawEndpoints, p.Expand()...)
- }
- }
- if len(rawEndpoints) == 0 {
- return nil, Errorf("Invalid KES endpoint %q", endpointStr)
- }
-
- var (
- randNum = rand.Intn(len(rawEndpoints))
- endpoints = make([]string, len(rawEndpoints))
- )
- for i, endpoint := range rawEndpoints {
- endpoint, err := xnet.ParseHTTPURL(endpoint)
- if err != nil {
- return nil, Errorf("Invalid KES endpoint %q: %v", endpointStr, err)
- }
- endpoints[(randNum+i)%len(rawEndpoints)] = endpoint.String()
- }
- return endpoints, nil
-}
-
-// LookupAutoEncryption returns true if and only if
-// the MINIO_KMS_AUTO_ENCRYPTION env. variable is
-// set to "on".
-func LookupAutoEncryption() bool {
- auto, _ := config.ParseBool(env.Get(EnvKMSAutoEncryption, config.EnableOff))
- return auto
-}
diff --git a/cmd/crypto/help.go b/cmd/crypto/help.go
deleted file mode 100644
index 9fde078bd..000000000
--- a/cmd/crypto/help.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package crypto
diff --git a/cmd/crypto/json.go b/cmd/crypto/json.go
deleted file mode 100644
index 0faf56bfe..000000000
--- a/cmd/crypto/json.go
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (c) 2015-2021 MinIO, Inc.
-//
-// This file is part of MinIO Object Storage stack
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-package crypto
-
-import (
- "bytes"
- "unicode/utf8"
-)
-
-// Adapted from Go stdlib.
-
-var hexTable = "0123456789abcdef"
-
-// EscapeStringJSON will escape a string for JSON and write it to dst.
-func EscapeStringJSON(dst *bytes.Buffer, s string) {
- start := 0
- for i := 0; i < len(s); {
- if b := s[i]; b < utf8.RuneSelf {
- if htmlSafeSet[b] {
- i++
- continue
- }
- if start < i {
- dst.WriteString(s[start:i])
- }
- dst.WriteByte('\\')
- switch b {
- case '\\', '"':
- dst.WriteByte(b)
- case '\n':
- dst.WriteByte('n')
- case '\r':
- dst.WriteByte('r')
- case '\t':
- dst.WriteByte('t')
- default:
- // This encodes bytes < 0x20 except for \t, \n and \r.
- // If escapeHTML is set, it also escapes <, >, and &
- // because they can lead to security holes when
- // user-controlled strings are rendered into JSON
- // and served to some browsers.
- dst.WriteString(`u00`)
- dst.WriteByte(hexTable[b>>4])
- dst.WriteByte(hexTable[b&0xF])
- }
- i++
- start = i
- continue
- }
- c, size := utf8.DecodeRuneInString(s[i:])
- if c == utf8.RuneError && size == 1 {
- if start < i {
- dst.WriteString(s[start:i])
- }
- dst.WriteString(`\ufffd`)
- i += size
- start = i
- continue
- }
- // U+2028 is LINE SEPARATOR.
- // U+2029 is PARAGRAPH SEPARATOR.
- // They are both technically valid characters in JSON strings,
- // but don't work in JSONP, which has to be evaluated as JavaScript,
- // and can lead to security holes there. It is valid JSON to
- // escape them, so we do so unconditionally.
- // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
- if c == '\u2028' || c == '\u2029' {
- if start < i {
- dst.WriteString(s[start:i])
- }
- dst.WriteString(`\u202`)
- dst.WriteByte(hexTable[c&0xF])
- i += size
- start = i
- continue
- }
- i += size
- }
- if start < len(s) {
- dst.WriteString(s[start:])
- }
-}
-
-// htmlSafeSet holds the value true if the ASCII character with the given
-// array position can be safely represented inside a JSON string, embedded
-// inside of HTML