From 8f8f8854f0702a171f9d0e4ac289c9034fe5c17c Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Sat, 19 Aug 2023 16:37:53 +0200 Subject: [PATCH] update `minio/kes-go` dep to v0.2.0 (#17850) This commit updates the minio/kes-go dependency to v0.2.0 and updates the existing code to work with the new KES APIs. The `SetPolicy` handler got removed since it may not get implemented by KES at all and could not have been used in the past since stateless KES is read-only w.r.t. policies and identities. Signed-off-by: Andreas Auernhammer --- cmd/kms-handlers.go | 96 +++++++++++++++++--------------- cmd/kms-router.go | 1 - go.mod | 2 +- go.sum | 4 +- internal/kms/identity-manager.go | 5 +- internal/kms/kes.go | 91 +++++++++--------------------- internal/kms/key-manager.go | 5 +- internal/kms/policy-manager.go | 8 +-- 8 files changed, 86 insertions(+), 126 deletions(-) diff --git a/cmd/kms-handlers.go b/cmd/kms-handlers.go index eeceef84d..b53e1df05 100644 --- a/cmd/kms-handlers.go +++ b/cmd/kms-handlers.go @@ -20,7 +20,9 @@ package cmd import ( "crypto/subtle" "encoding/json" + "io" "net/http" + "strings" "time" "github.com/minio/kes-go" @@ -258,15 +260,26 @@ func (a kmsAPIHandlers) KMSListKeysHandler(w http.ResponseWriter, r *http.Reques writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrKMSNotConfigured), r.URL) return } - keys, err := manager.ListKeys(ctx, r.Form.Get("pattern")) + keys, err := manager.ListKeys(ctx) if err != nil { writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) return } - values, err := keys.Values(0) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return + + pattern := r.Form.Get("pattern") + if !strings.Contains(pattern, "*") { + pattern += "*" + } + + var values []kes.KeyInfo + for name, err := keys.SeekTo(ctx, pattern); err != io.EOF; name, err = keys.Next(ctx) { + if err != nil { + writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL) + return + } + values = append(values, kes.KeyInfo{ + Name: name, + }) } if res, err := json.Marshal(values); err != nil { writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL) @@ -454,37 +467,6 @@ func (a kmsAPIHandlers) KMSAssignPolicyHandler(w http.ResponseWriter, r *http.Re writeSuccessResponseHeadersOnly(w) } -// KMSSetPolicyHandler - POST /minio/kms/v1/policy/policy?policy= -func (a kmsAPIHandlers) KMSSetPolicyHandler(w http.ResponseWriter, r *http.Request) { - ctx := newContext(r, w, "KMSSetPolicy") - defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) - - objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.KMSSetPolicyAction) - if objectAPI == nil { - return - } - - if GlobalKMS == nil { - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrKMSNotConfigured), r.URL) - return - } - manager, ok := GlobalKMS.(kms.PolicyManager) - if !ok { - writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL) - return - } - var policy kes.Policy - if err := json.NewDecoder(r.Body).Decode(&policy); err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - if err := manager.SetPolicy(ctx, r.Form.Get("policy"), &policy); err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return - } - writeSuccessResponseHeadersOnly(w) -} - // KMSDeletePolicyHandler - DELETE /minio/kms/v1/policy/delete?policy= func (a kmsAPIHandlers) KMSDeletePolicyHandler(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "KMSDeletePolicy") @@ -531,15 +513,26 @@ func (a kmsAPIHandlers) KMSListPoliciesHandler(w http.ResponseWriter, r *http.Re writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL) return } - policies, err := manager.ListPolicies(ctx, r.Form.Get("pattern")) + policies, err := manager.ListPolicies(ctx) if err != nil { writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) return } - values, err := policies.Values(0) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return + + pattern := r.Form.Get("pattern") + if !strings.Contains(pattern, "*") { + pattern += "*" + } + + var values []kes.PolicyInfo + for name, err := policies.SeekTo(ctx, pattern); err != io.EOF; name, err = policies.Next(ctx) { + if err != nil { + writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL) + return + } + values = append(values, kes.PolicyInfo{ + Name: name, + }) } if res, err := json.Marshal(values); err != nil { writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL) @@ -707,15 +700,26 @@ func (a kmsAPIHandlers) KMSListIdentitiesHandler(w http.ResponseWriter, r *http. writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL) return } - identities, err := manager.ListIdentities(ctx, r.Form.Get("pattern")) + identities, err := manager.ListIdentities(ctx) if err != nil { writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) return } - values, err := identities.Values(0) - if err != nil { - writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) - return + + pattern := r.Form.Get("pattern") + if !strings.Contains(pattern, "*") { + pattern += "*" + } + + var values []kes.IdentityInfo + for name, err := identities.SeekTo(ctx, pattern); err != io.EOF; name, err = identities.Next(ctx) { + if err != nil { + writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL) + return + } + values = append(values, kes.IdentityInfo{ + Identity: name, + }) } if res, err := json.Marshal(values); err != nil { writeCustomErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInternalError), err.Error(), r.URL) diff --git a/cmd/kms-router.go b/cmd/kms-router.go index 7d210d95e..98c6c55c1 100644 --- a/cmd/kms-router.go +++ b/cmd/kms-router.go @@ -63,7 +63,6 @@ func registerKMSRouter(router *mux.Router) { kmsRouter.Methods(http.MethodGet).Path(version + "/key/status").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSKeyStatusHandler))) // KMS Policy APIs - kmsRouter.Methods(http.MethodPost).Path(version+"/policy/set").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSSetPolicyHandler))).Queries("policy", "{policy:.*}") kmsRouter.Methods(http.MethodPost).Path(version+"/policy/assign").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSAssignPolicyHandler))).Queries("policy", "{policy:.*}") kmsRouter.Methods(http.MethodGet).Path(version+"/policy/describe").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSDescribePolicyHandler))).Queries("policy", "{policy:.*}") kmsRouter.Methods(http.MethodGet).Path(version+"/policy/get").HandlerFunc(gz(httpTraceAll(kmsAPI.KMSGetPolicyHandler))).Queries("policy", "{policy:.*}") diff --git a/go.mod b/go.mod index 8d7556e2a..a3456de62 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/minio/dnscache v0.1.1 github.com/minio/dperf v0.5.0 github.com/minio/highwayhash v1.0.2 - github.com/minio/kes-go v0.1.0 + github.com/minio/kes-go v0.2.0 github.com/minio/madmin-go/v3 v3.0.11 github.com/minio/minio-go/v7 v7.0.61 github.com/minio/mux v1.9.0 diff --git a/go.sum b/go.sum index 792b75eb3..6efa59168 100644 --- a/go.sum +++ b/go.sum @@ -483,8 +483,8 @@ github.com/minio/filepath v1.0.0 h1:fvkJu1+6X+ECRA6G3+JJETj4QeAYO9sV43I79H8ubDY= github.com/minio/filepath v1.0.0/go.mod h1:/nRZA2ldl5z6jT9/KQuvZcQlxZIMQoFFQPvEXx9T/Bw= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= -github.com/minio/kes-go v0.1.0 h1:h201DyOYP5sTqajkxFGxmXz/kPbT8HQNX1uh3Yx2PFc= -github.com/minio/kes-go v0.1.0/go.mod h1:VorHLaIYis9/MxAHAtXN4d8PUMNKhIxTIlvFt0hBOEo= +github.com/minio/kes-go v0.2.0 h1:HA33arq9s3MErbsj3PAXFVfFo4U4yw7lTKQ5kWFrpCA= +github.com/minio/kes-go v0.2.0/go.mod h1:VorHLaIYis9/MxAHAtXN4d8PUMNKhIxTIlvFt0hBOEo= github.com/minio/madmin-go/v3 v3.0.11 h1:7QrZkgbQ5+qTKGy6Nok2A8OgLAcn/lcMYYuSgiZrgBE= github.com/minio/madmin-go/v3 v3.0.11/go.mod h1:DMXyWO670OXwZNN0v4ZrEodl9oLOcaPJIZhpoHpu7aw= github.com/minio/mc v0.0.0-20230726035150-6b8680a2f7ca h1:y/dJJuWhlVYN9tqBxoHvGCpJ7olVuPa1whg+GS1m1a8= diff --git a/internal/kms/identity-manager.go b/internal/kms/identity-manager.go index 031f0ba77..4c0d7ab84 100644 --- a/internal/kms/identity-manager.go +++ b/internal/kms/identity-manager.go @@ -39,7 +39,6 @@ type IdentityManager interface { // The admin identity cannot be deleted. DeleteIdentity(ctx context.Context, identity string) error - // ListIdentities list all identity metadata that match the specified pattern. - // In particular, the pattern * lists all identity metadata. - ListIdentities(ctx context.Context, pattern string) (*kes.IdentityIterator, error) + // ListIdentities lists all identities. + ListIdentities(ctx context.Context) (*kes.ListIter[kes.Identity], error) } diff --git a/internal/kms/kes.go b/internal/kms/kes.go index 6ff4dfe87..14ee7775f 100644 --- a/internal/kms/kes.go +++ b/internal/kms/kes.go @@ -104,23 +104,10 @@ func NewWithConfig(config Config) (KMS, error) { } client.Endpoints = endpoints - var bulkAvailable bool - _, policy, err := client.DescribeSelf(context.Background()) - if err == nil { - const BulkAPI = "/v1/key/bulk/decrypt/" - for _, allow := range policy.Allow { - if strings.HasPrefix(allow, BulkAPI) { - bulkAvailable = true - break - } - } - } - c := &kesClient{ - client: client, - enclave: client.Enclave(config.Enclave), - defaultKeyID: config.DefaultKeyID, - bulkAvailable: bulkAvailable, + client: client, + enclave: client.Enclave(config.Enclave), + defaultKeyID: config.DefaultKeyID, } go func() { if config.Certificate == nil || config.ReloadCertEvents == nil { @@ -166,11 +153,14 @@ type kesClient struct { defaultKeyID string client *kes.Client enclave *kes.Enclave - - bulkAvailable bool } -var _ KMS = (*kesClient)(nil) // compiler check +var ( // compiler checks + _ KMS = (*kesClient)(nil) + _ KeyManager = (*kesClient)(nil) + _ IdentityManager = (*kesClient)(nil) + _ PolicyManager = (*kesClient)(nil) +) // Stat returns the current KES status containing a // list of KES endpoints and the default key ID. @@ -259,13 +249,14 @@ func (c *kesClient) DeleteKey(ctx context.Context, keyID string) error { return c.enclave.DeleteKey(ctx, keyID) } -// ListKeys List all key names that match the specified pattern. In particular, -// the pattern * lists all keys. -func (c *kesClient) ListKeys(ctx context.Context, pattern string) (*kes.KeyIterator, error) { +// ListKeys returns an iterator over all key names. +func (c *kesClient) ListKeys(ctx context.Context) (*kes.ListIter[string], error) { c.lock.RLock() defer c.lock.RUnlock() - return c.enclave.ListKeys(ctx, pattern) + return &kes.ListIter[string]{ + NextFunc: c.enclave.ListKeys, + }, nil } // GenerateKey generates a new data encryption key using @@ -304,7 +295,9 @@ func (c *kesClient) ImportKey(ctx context.Context, keyID string, bytes []byte) e c.lock.RLock() defer c.lock.RUnlock() - return c.enclave.ImportKey(ctx, keyID, bytes) + return c.enclave.ImportKey(ctx, keyID, &kes.ImportKeyRequest{ + Key: bytes, + }) } // EncryptKey Encrypts and authenticates a (small) plaintext with the cryptographic key @@ -338,30 +331,6 @@ func (c *kesClient) DecryptAll(ctx context.Context, keyID string, ciphertexts [] c.lock.RLock() defer c.lock.RUnlock() - if c.bulkAvailable { - CCPs := make([]kes.CCP, 0, len(ciphertexts)) - for i := range ciphertexts { - bCtx, err := contexts[i].MarshalText() - if err != nil { - return nil, err - } - CCPs = append(CCPs, kes.CCP{ - Ciphertext: ciphertexts[i], - Context: bCtx, - }) - } - - PCPs, err := c.enclave.DecryptAll(ctx, keyID, CCPs...) - if err != nil { - return nil, err - } - plaintexts := make([][]byte, 0, len(PCPs)) - for _, p := range PCPs { - plaintexts = append(plaintexts, p.Plaintext) - } - return plaintexts, nil - } - plaintexts := make([][]byte, 0, len(ciphertexts)) for i := range ciphertexts { ctxBytes, err := contexts[i].MarshalText() @@ -407,21 +376,14 @@ func (c *kesClient) DeletePolicy(ctx context.Context, policy string) error { return c.enclave.DeletePolicy(ctx, policy) } -// ListPolicies list all policy metadata that match the specified pattern. -// In particular, the pattern * lists all policy metadata. -func (c *kesClient) ListPolicies(ctx context.Context, pattern string) (*kes.PolicyIterator, error) { +// ListPolicies returns an iterator over all policy names. +func (c *kesClient) ListPolicies(ctx context.Context) (*kes.ListIter[string], error) { c.lock.RLock() defer c.lock.RUnlock() - return c.enclave.ListPolicies(ctx, pattern) -} - -// SetPolicy creates or updates a policy. -func (c *kesClient) SetPolicy(ctx context.Context, policy string, policyItem *kes.Policy) error { - c.lock.RLock() - defer c.lock.RUnlock() - - return c.enclave.SetPolicy(ctx, policy, policyItem) + return &kes.ListIter[string]{ + NextFunc: c.enclave.ListPolicies, + }, nil } // GetPolicy gets a policy from KMS. @@ -461,13 +423,14 @@ func (c *kesClient) DeleteIdentity(ctx context.Context, identity string) error { return c.enclave.DeleteIdentity(ctx, kes.Identity(identity)) } -// ListIdentities list all identity metadata that match the specified pattern. -// In particular, the pattern * lists all identity metadata. -func (c *kesClient) ListIdentities(ctx context.Context, pattern string) (*kes.IdentityIterator, error) { +// ListPolicies returns an iterator over all identities. +func (c *kesClient) ListIdentities(ctx context.Context) (*kes.ListIter[kes.Identity], error) { c.lock.RLock() defer c.lock.RUnlock() - return c.enclave.ListIdentities(ctx, pattern) + return &kes.ListIter[kes.Identity]{ + NextFunc: c.enclave.ListIdentities, + }, nil } // Verify verifies all KMS endpoints and returns details diff --git a/internal/kms/key-manager.go b/internal/kms/key-manager.go index f02981bb2..dcbc65e2e 100644 --- a/internal/kms/key-manager.go +++ b/internal/kms/key-manager.go @@ -34,9 +34,8 @@ type KeyManager interface { // anymore, and therefore, is lost. DeleteKey(ctx context.Context, keyID string) error - // ListKeys List all key names that match the specified pattern. In particular, - // the pattern * lists all keys. - ListKeys(ctx context.Context, pattern string) (*kes.KeyIterator, error) + // ListKeys lists all key names. + ListKeys(ctx context.Context) (*kes.ListIter[string], error) // ImportKey imports a cryptographic key into the KMS. ImportKey(ctx context.Context, keyID string, bytes []byte) error diff --git a/internal/kms/policy-manager.go b/internal/kms/policy-manager.go index 6e2cbca2a..bf519f8c6 100644 --- a/internal/kms/policy-manager.go +++ b/internal/kms/policy-manager.go @@ -36,15 +36,11 @@ type PolicyManager interface { // Further, an identity cannot assign a policy to itself. AssignPolicy(ctx context.Context, policy, identity string) error - // SetPolicy creates or updates a policy. - SetPolicy(ctx context.Context, policy string, policyItem *kes.Policy) error - // GetPolicy gets a policy from KMS. GetPolicy(ctx context.Context, policy string) (*kes.Policy, error) - // ListPolicies list all policy metadata that match the specified pattern. - // In particular, the pattern * lists all policy metadata. - ListPolicies(ctx context.Context, pattern string) (*kes.PolicyIterator, error) + // ListPolicies lists all policies. + ListPolicies(ctx context.Context) (*kes.ListIter[string], error) // DeletePolicy deletes a policy from KMS. // All identities that have been assigned to this policy will lose all authorization privileges.