Added endpoint and versions attributes to KMS details (#17350)

Now it would list details of all KMS instances with additional
attributes `endpoint` and `version`. In the case of k8s-based
deployment the list would consist of a single entry.

Signed-off-by: Shubhendu Ram Tripathi <shubhendu@minio.io>
This commit is contained in:
Shubhendu 2023-07-13 12:20:38 +05:30 committed by GitHub
parent f80b6926d3
commit 9b9871cfbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 6 deletions

View file

@ -1868,8 +1868,6 @@ func getPoolsInfo(ctx context.Context, allDisks []madmin.Disk) (map[int]map[int]
}
func getServerInfo(ctx context.Context, poolsInfoEnabled bool, r *http.Request) madmin.InfoMessage {
kmsStat := fetchKMSStatus()
ldap := madmin.LDAP{}
if globalIAMSys.LDAPConfig.Enabled() {
ldapConn, err := globalIAMSys.LDAPConfig.LDAP.Connect()
@ -1949,7 +1947,8 @@ func getServerInfo(ctx context.Context, poolsInfoEnabled bool, r *http.Request)
domain := globalDomainNames
services := madmin.Services{
KMS: kmsStat,
KMS: fetchKMSStatus(),
KMSStatus: fetchKMSStatusV2(ctx),
LDAP: ldap,
Logger: log,
Audit: audit,
@ -2569,6 +2568,28 @@ func fetchKMSStatus() madmin.KMS {
return kmsStat
}
// fetchKMSStatusV2 fetches KMS-related status information for all instances
func fetchKMSStatusV2(ctx context.Context) []madmin.KMS {
if GlobalKMS == nil {
return []madmin.KMS{}
}
results := GlobalKMS.Verify(ctx)
stats := []madmin.KMS{}
for _, result := range results {
stats = append(stats, madmin.KMS{
Status: result.Status,
Endpoint: result.Endpoint,
Encrypt: result.Encrypt,
Decrypt: result.Decrypt,
Version: result.Version,
})
}
return stats
}
// fetchLoggerDetails return log info
func fetchLoggerInfo() ([]madmin.Logger, []madmin.Audit) {
var loggerInfo []madmin.Logger

2
go.mod
View file

@ -49,7 +49,7 @@ require (
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/madmin-go/v3 v3.0.5
github.com/minio/madmin-go/v3 v3.0.6
github.com/minio/minio-go/v7 v7.0.59
github.com/minio/mux v1.9.0
github.com/minio/pkg v1.7.5

4
go.sum
View file

@ -483,8 +483,8 @@ github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA
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/madmin-go/v3 v3.0.5 h1:ynWTsnszHnQVJWRL2OE4ysCvCNG0uHgdTvJpdLazf9c=
github.com/minio/madmin-go/v3 v3.0.5/go.mod h1:lPrMoc1aeiIWmmrxBthkDqzMPQwC/Lu9ByuyM2wenJk=
github.com/minio/madmin-go/v3 v3.0.6 h1:rlU0UCwRhi/bI5R9Pg5df88ddqFNFA5mpmxScAanQCA=
github.com/minio/madmin-go/v3 v3.0.6/go.mod h1:lPrMoc1aeiIWmmrxBthkDqzMPQwC/Lu9ByuyM2wenJk=
github.com/minio/mc v0.0.0-20230706154612-72958227ad65 h1:27INveRWSp7yAEy4szNp15DOA2dyOwnxTGt/p0JuTh4=
github.com/minio/mc v0.0.0-20230706154612-72958227ad65/go.mod h1:41ndsUBIAA/dRjOQ/0KY4d8vI70gDiKeMo1zusOQRWk=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=

View file

@ -20,9 +20,11 @@ package kms
import (
"bytes"
"context"
"crypto/subtle"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"strings"
"sync"
@ -467,3 +469,51 @@ func (c *kesClient) ListIdentities(ctx context.Context, pattern string) (*kes.Id
return c.enclave.ListIdentities(ctx, pattern)
}
// Verify verifies all KMS endpoints and returns details
func (c *kesClient) Verify(ctx context.Context) []VerifyResult {
c.lock.RLock()
defer c.lock.RUnlock()
results := []VerifyResult{}
kmsContext := Context{"MinIO admin API": "ServerInfoHandler"} // Context for a test key operation
for _, endpoint := range c.client.Endpoints {
client := kes.Client{
Endpoints: []string{endpoint},
HTTPClient: c.client.HTTPClient,
}
// 1. Get stats for the KES instance
state, err := client.Status(ctx)
if err != nil {
results = append(results, VerifyResult{Status: "offline", Endpoint: endpoint})
continue
}
// 2. Generate a new key using the KMS.
kmsCtx, err := kmsContext.MarshalText()
if err != nil {
results = append(results, VerifyResult{Status: "offline", Endpoint: endpoint})
continue
}
result := VerifyResult{Status: "online", Endpoint: endpoint, Version: state.Version}
key, err := client.GenerateKey(ctx, env.Get(EnvKESKeyName, ""), kmsCtx)
if err != nil {
result.Encrypt = fmt.Sprintf("Encryption failed: %v", err)
} else {
result.Encrypt = "success"
}
// 3. Verify that we can indeed decrypt the (encrypted) key
decryptedKey, err := client.Decrypt(ctx, env.Get(EnvKESKeyName, ""), key.Ciphertext, kmsCtx)
switch {
case err != nil:
result.Decrypt = fmt.Sprintf("Decryption failed: %v", err)
case subtle.ConstantTimeCompare(key.Plaintext, decryptedKey) != 1:
result.Decrypt = "Decryption failed: decrypted key does not match generated key"
default:
result.Decrypt = "success"
}
results = append(results, result)
}
return results
}

View file

@ -67,6 +67,18 @@ type KMS interface {
// by the key ID. The contexts must match the context value
// used to generate the ciphertexts.
DecryptAll(ctx context.Context, keyID string, ciphertext [][]byte, context []Context) ([][]byte, error)
// Verify verifies all KMS endpoints and returns the details
Verify(cxt context.Context) []VerifyResult
}
// VerifyResult describes the verification result details a KMS endpoint
type VerifyResult struct {
Endpoint string
Decrypt string
Encrypt string
Version string
Status string
}
// Status describes the current state of a KMS.

View file

@ -303,6 +303,13 @@ func (kms secretKey) DecryptAll(_ context.Context, keyID string, ciphertexts [][
return plaintexts, nil
}
// Verify verifies all KMS endpoints and returns details
func (kms secretKey) Verify(cxt context.Context) []VerifyResult {
return []VerifyResult{
{Endpoint: "self"},
}
}
type encryptedKey struct {
Algorithm string `json:"aead"`
IV []byte `json:"iv"`