mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-29 17:52:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			203 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) HashiCorp, Inc.
 | |
| // SPDX-License-Identifier: BUSL-1.1
 | |
| 
 | |
| package vault
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"io"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/hashicorp/vault/sdk/logical"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	// ErrBarrierSealed is returned if an operation is performed on
 | |
| 	// a sealed barrier. No operation is expected to succeed before unsealing
 | |
| 	ErrBarrierSealed = errors.New("Vault is sealed")
 | |
| 
 | |
| 	// ErrBarrierAlreadyInit is returned if the barrier is already
 | |
| 	// initialized. This prevents a re-initialization.
 | |
| 	ErrBarrierAlreadyInit = errors.New("Vault is already initialized")
 | |
| 
 | |
| 	// ErrBarrierNotInit is returned if a non-initialized barrier
 | |
| 	// is attempted to be unsealed.
 | |
| 	ErrBarrierNotInit = errors.New("Vault is not initialized")
 | |
| 
 | |
| 	// ErrBarrierInvalidKey is returned if the Unseal key is invalid
 | |
| 	ErrBarrierInvalidKey = errors.New("Unseal failed, invalid key")
 | |
| 
 | |
| 	// ErrPlaintextTooLarge is returned if a plaintext is offered for encryption
 | |
| 	// that is too large to encrypt in memory
 | |
| 	ErrPlaintextTooLarge = errors.New("plaintext value too large")
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	// barrierInitPath is the path used to store our init sentinel file
 | |
| 	barrierInitPath = "barrier/init"
 | |
| 
 | |
| 	// keyringPath is the location of the keyring data. This is encrypted
 | |
| 	// by the root key.
 | |
| 	keyringPath   = "core/keyring"
 | |
| 	keyringPrefix = "core/"
 | |
| 
 | |
| 	// keyringUpgradePrefix is the path used to store keyring update entries.
 | |
| 	// When running in HA mode, the active instance will install the new key
 | |
| 	// and re-write the keyring. For standby instances, they need an upgrade
 | |
| 	// path from key N to N+1. They cannot just use the root key because
 | |
| 	// in the event of a rekey, that root key can no longer decrypt the keyring.
 | |
| 	// When key N+1 is installed, we create an entry at "prefix/N" which uses
 | |
| 	// encryption key N to provide the N+1 key. The standby instances scan
 | |
| 	// for this periodically and refresh their keyring. The upgrade keys
 | |
| 	// are deleted after a few minutes, but this provides enough time for the
 | |
| 	// standby instances to upgrade without causing any disruption.
 | |
| 	keyringUpgradePrefix = "core/upgrade/"
 | |
| 
 | |
| 	// rootKeyPath is the location of the root key. This is encrypted
 | |
| 	// by the latest key in the keyring. This is only used by standby instances
 | |
| 	// to handle the case of a rekey. If the active instance does a rekey,
 | |
| 	// the standby instances can no longer reload the keyring since they
 | |
| 	// have the old root key. This key can be decrypted if you have the
 | |
| 	// keyring to discover the new root key. The new root key is then
 | |
| 	// used to reload the keyring itself.
 | |
| 	rootKeyPath = "core/master"
 | |
| 
 | |
| 	// shamirKekPath is used with Shamir in v1.3+ to store a copy of the
 | |
| 	// unseal key behind the barrier.  As with rootKeyPath this is primarily
 | |
| 	// used by standbys to handle rekeys.  It also comes into play when restoring
 | |
| 	// raft snapshots.
 | |
| 	shamirKekPath = "core/shamir-kek"
 | |
| )
 | |
| 
 | |
| // SecurityBarrier is a critical component of Vault. It is used to wrap
 | |
| // an untrusted physical backend and provide a single point of encryption,
 | |
| // decryption and checksum verification. The goal is to ensure that any
 | |
| // data written to the barrier is confidential and that integrity is preserved.
 | |
| // As a real-world analogy, this is the steel and concrete wrapper around
 | |
| // a Vault. The barrier should only be Unlockable given its key.
 | |
| type SecurityBarrier interface {
 | |
| 	// Initialized checks if the barrier has been initialized
 | |
| 	// and has a root key set.
 | |
| 	Initialized(ctx context.Context) (bool, error)
 | |
| 
 | |
| 	// Initialize works only if the barrier has not been initialized
 | |
| 	// and makes use of the given root key.  When sealKey is provided
 | |
| 	// it's because we're using a new-style Shamir seal, and rootKey
 | |
| 	// is to be stored using sealKey to encrypt it.
 | |
| 	Initialize(ctx context.Context, rootKey []byte, sealKey []byte, random io.Reader) error
 | |
| 
 | |
| 	// GenerateKey is used to generate a new key
 | |
| 	GenerateKey(io.Reader) ([]byte, error)
 | |
| 
 | |
| 	// KeyLength is used to sanity check a key
 | |
| 	KeyLength() (int, int)
 | |
| 
 | |
| 	// Sealed checks if the barrier has been unlocked yet. The Barrier
 | |
| 	// is not expected to be able to perform any CRUD until it is unsealed.
 | |
| 	Sealed() (bool, error)
 | |
| 
 | |
| 	// Unseal is used to provide the unseal key which permits the barrier
 | |
| 	// to be unsealed. If the key is not correct, the barrier remains sealed.
 | |
| 	Unseal(ctx context.Context, key []byte) error
 | |
| 
 | |
| 	// VerifyRoot is used to check if the given key matches the root key
 | |
| 	VerifyRoot(key []byte) error
 | |
| 
 | |
| 	// SetRootKey is used to directly set a new root key. This is used in
 | |
| 	// replicated scenarios due to the chicken and egg problem of reloading the
 | |
| 	// keyring from disk before we have the root key to decrypt it.
 | |
| 	SetRootKey(key []byte) error
 | |
| 
 | |
| 	// ReloadKeyring is used to re-read the underlying keyring.
 | |
| 	// This is used for HA deployments to ensure the latest keyring
 | |
| 	// is present in the leader.
 | |
| 	ReloadKeyring(ctx context.Context) error
 | |
| 
 | |
| 	// ReloadRootKey is used to re-read the underlying root key.
 | |
| 	// This is used for HA deployments to ensure the latest root key
 | |
| 	// is available for keyring reloading.
 | |
| 	ReloadRootKey(ctx context.Context) error
 | |
| 
 | |
| 	// Seal is used to re-seal the barrier. This requires the barrier to
 | |
| 	// be unsealed again to perform any further operations.
 | |
| 	Seal() error
 | |
| 
 | |
| 	// Rotate is used to create a new encryption key. All future writes
 | |
| 	// should use the new key, while old values should still be decryptable.
 | |
| 	Rotate(ctx context.Context, reader io.Reader) (uint32, error)
 | |
| 
 | |
| 	// CreateUpgrade creates an upgrade path key to the given term from the previous term
 | |
| 	CreateUpgrade(ctx context.Context, term uint32) error
 | |
| 
 | |
| 	// DestroyUpgrade destroys the upgrade path key to the given term
 | |
| 	DestroyUpgrade(ctx context.Context, term uint32) error
 | |
| 
 | |
| 	// CheckUpgrade looks for an upgrade to the current term and installs it
 | |
| 	CheckUpgrade(ctx context.Context) (bool, uint32, error)
 | |
| 
 | |
| 	// ActiveKeyInfo is used to inform details about the active key
 | |
| 	ActiveKeyInfo() (*KeyInfo, error)
 | |
| 
 | |
| 	// RotationConfig returns the auto-rotation config for the barrier key
 | |
| 	RotationConfig() (KeyRotationConfig, error)
 | |
| 
 | |
| 	// SetRotationConfig updates the auto-rotation config for the barrier key
 | |
| 	SetRotationConfig(ctx context.Context, config KeyRotationConfig) error
 | |
| 
 | |
| 	// Rekey is used to change the master key used to protect the keyring
 | |
| 	Rekey(context.Context, []byte) error
 | |
| 
 | |
| 	// For replication we must send over the keyring, so this must be available
 | |
| 	Keyring() (*Keyring, error)
 | |
| 
 | |
| 	// For encryption count shipping, a function which handles updating local encryption counts if the consumer succeeds.
 | |
| 	// This isolates the barrier code from the replication system
 | |
| 	ConsumeEncryptionCount(consumer func(int64) error) error
 | |
| 
 | |
| 	// Add encryption counts from a remote source (downstream cluster node)
 | |
| 	AddRemoteEncryptions(encryptions int64)
 | |
| 
 | |
| 	// Check whether an automatic rotation is due
 | |
| 	CheckBarrierAutoRotate(ctx context.Context) (string, error)
 | |
| 
 | |
| 	// SecurityBarrier must provide the storage APIs
 | |
| 	logical.Storage
 | |
| 
 | |
| 	// SecurityBarrier must provide the encryption APIs
 | |
| 	BarrierEncryptor
 | |
| 
 | |
| 	DetectDeadlocks() bool
 | |
| }
 | |
| 
 | |
| // BarrierStorage is the storage only interface required for a Barrier.
 | |
| type BarrierStorage interface {
 | |
| 	// Put is used to insert or update an entry
 | |
| 	Put(ctx context.Context, entry *logical.StorageEntry) error
 | |
| 
 | |
| 	// Get is used to fetch an entry
 | |
| 	Get(ctx context.Context, key string) (*logical.StorageEntry, error)
 | |
| 
 | |
| 	// Delete is used to permanently delete an entry
 | |
| 	Delete(ctx context.Context, key string) error
 | |
| 
 | |
| 	// List is used ot list all the keys under a given
 | |
| 	// prefix, up to the next prefix.
 | |
| 	List(ctx context.Context, prefix string) ([]string, error)
 | |
| }
 | |
| 
 | |
| // BarrierEncryptor is the in memory only interface that does not actually
 | |
| // use the underlying barrier. It is used for lower level modules like the
 | |
| // Write-Ahead-Log and Merkle index to allow them to use the barrier.
 | |
| type BarrierEncryptor interface {
 | |
| 	Encrypt(ctx context.Context, key string, plaintext []byte) ([]byte, error)
 | |
| 	Decrypt(ctx context.Context, key string, ciphertext []byte) ([]byte, error)
 | |
| }
 | |
| 
 | |
| // KeyInfo is used to convey information about the encryption key
 | |
| type KeyInfo struct {
 | |
| 	Term        int
 | |
| 	InstallTime time.Time
 | |
| 	Encryptions int64
 | |
| }
 | 
