mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
* Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License. Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUS-1.1 * Fix test that expected exact offset on hcl file --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Sarah Thompson <sthompson@hashicorp.com> Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com>
201 lines
7.9 KiB
Go
201 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
|
|
}
|
|
|
|
// 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
|
|
}
|