github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/kms/kms.go (about)

     1  // Copyright (c) 2015-2021 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package kms
    19  
    20  import (
    21  	"context"
    22  	"encoding"
    23  	"encoding/json"
    24  
    25  	jsoniter "github.com/json-iterator/go"
    26  	"github.com/minio/kms-go/kes"
    27  )
    28  
    29  // KMS is the generic interface that abstracts over
    30  // different KMS implementations.
    31  type KMS interface {
    32  	// Stat returns the current KMS status.
    33  	Stat(cxt context.Context) (Status, error)
    34  
    35  	// IsLocal returns true if the KMS is a local implementation
    36  	IsLocal() bool
    37  
    38  	// List returns an array of local KMS Names
    39  	List() []kes.KeyInfo
    40  
    41  	// Metrics returns a KMS metric snapshot.
    42  	Metrics(ctx context.Context) (kes.Metric, error)
    43  
    44  	// CreateKey creates a new key at the KMS with the given key ID.
    45  	CreateKey(ctx context.Context, keyID string) error
    46  
    47  	// GenerateKey generates a new data encryption key using the
    48  	// key referenced by the key ID.
    49  	//
    50  	// The KMS may use a default key if the key ID is empty.
    51  	// GenerateKey returns an error if the referenced key does
    52  	// not exist.
    53  	//
    54  	// The context is associated and tied to the generated DEK.
    55  	// The same context must be provided when the generated key
    56  	// should be decrypted. Therefore, it is the callers
    57  	// responsibility to remember the corresponding context for
    58  	// a particular DEK. The context may be nil.
    59  	GenerateKey(ctx context.Context, keyID string, context Context) (DEK, error)
    60  
    61  	// DecryptKey decrypts the ciphertext with the key referenced
    62  	// by the key ID. The context must match the context value
    63  	// used to generate the ciphertext.
    64  	DecryptKey(keyID string, ciphertext []byte, context Context) ([]byte, error)
    65  
    66  	// DecryptAll decrypts all ciphertexts with the key referenced
    67  	// by the key ID. The contexts must match the context value
    68  	// used to generate the ciphertexts.
    69  	DecryptAll(ctx context.Context, keyID string, ciphertext [][]byte, context []Context) ([][]byte, error)
    70  
    71  	// Verify verifies all KMS endpoints and returns the details
    72  	Verify(cxt context.Context) []VerifyResult
    73  }
    74  
    75  // VerifyResult describes the verification result details a KMS endpoint
    76  type VerifyResult struct {
    77  	Endpoint string
    78  	Decrypt  string
    79  	Encrypt  string
    80  	Version  string
    81  	Status   string
    82  }
    83  
    84  // Status describes the current state of a KMS.
    85  type Status struct {
    86  	Name      string   // The name of the KMS
    87  	Endpoints []string // A set of the KMS endpoints
    88  
    89  	// DefaultKey is the key used when no explicit key ID
    90  	// is specified. It is empty if the KMS does not support
    91  	// a default key.
    92  	DefaultKey string
    93  
    94  	// Details provides more details about the KMS endpoint status.
    95  	// including uptime, version and available CPUs.
    96  	// Could be more in future.
    97  	Details kes.State
    98  }
    99  
   100  // DEK is a data encryption key. It consists of a
   101  // plaintext-ciphertext pair and the ID of the key
   102  // used to generate the ciphertext.
   103  //
   104  // The plaintext can be used for cryptographic
   105  // operations - like encrypting some data. The
   106  // ciphertext is the encrypted version of the
   107  // plaintext data and can be stored on untrusted
   108  // storage.
   109  type DEK struct {
   110  	KeyID      string
   111  	Plaintext  []byte
   112  	Ciphertext []byte
   113  }
   114  
   115  var (
   116  	_ encoding.TextMarshaler   = (*DEK)(nil)
   117  	_ encoding.TextUnmarshaler = (*DEK)(nil)
   118  )
   119  
   120  // MarshalText encodes the DEK's key ID and ciphertext
   121  // as JSON.
   122  func (d DEK) MarshalText() ([]byte, error) {
   123  	type JSON struct {
   124  		KeyID      string `json:"keyid"`
   125  		Ciphertext []byte `json:"ciphertext"`
   126  	}
   127  	return json.Marshal(JSON{
   128  		KeyID:      d.KeyID,
   129  		Ciphertext: d.Ciphertext,
   130  	})
   131  }
   132  
   133  // UnmarshalText tries to decode text as JSON representation
   134  // of a DEK and sets DEK's key ID and ciphertext to the
   135  // decoded values.
   136  //
   137  // It sets DEK's plaintext to nil.
   138  func (d *DEK) UnmarshalText(text []byte) error {
   139  	type JSON struct {
   140  		KeyID      string `json:"keyid"`
   141  		Ciphertext []byte `json:"ciphertext"`
   142  	}
   143  	var v JSON
   144  	json := jsoniter.ConfigCompatibleWithStandardLibrary
   145  	if err := json.Unmarshal(text, &v); err != nil {
   146  		return err
   147  	}
   148  	d.KeyID, d.Plaintext, d.Ciphertext = v.KeyID, nil, v.Ciphertext
   149  	return nil
   150  }