1package vault
2
3import (
4	"context"
5	"errors"
6	"io"
7	"time"
8
9	"github.com/hashicorp/vault/sdk/logical"
10)
11
12var (
13	// ErrBarrierSealed is returned if an operation is performed on
14	// a sealed barrier. No operation is expected to succeed before unsealing
15	ErrBarrierSealed = errors.New("Vault is sealed")
16
17	// ErrBarrierAlreadyInit is returned if the barrier is already
18	// initialized. This prevents a re-initialization.
19	ErrBarrierAlreadyInit = errors.New("Vault is already initialized")
20
21	// ErrBarrierNotInit is returned if a non-initialized barrier
22	// is attempted to be unsealed.
23	ErrBarrierNotInit = errors.New("Vault is not initialized")
24
25	// ErrBarrierInvalidKey is returned if the Unseal key is invalid
26	ErrBarrierInvalidKey = errors.New("Unseal failed, invalid key")
27
28	// ErrPlaintextTooLarge is returned if a plaintext is offered for encryption
29	// that is too large to encrypt in memory
30	ErrPlaintextTooLarge = errors.New("plaintext value too large")
31)
32
33const (
34	// barrierInitPath is the path used to store our init sentinel file
35	barrierInitPath = "barrier/init"
36
37	// keyringPath is the location of the keyring data. This is encrypted
38	// by the master key.
39	keyringPath   = "core/keyring"
40	keyringPrefix = "core/"
41
42	// keyringUpgradePrefix is the path used to store keyring update entries.
43	// When running in HA mode, the active instance will install the new key
44	// and re-write the keyring. For standby instances, they need an upgrade
45	// path from key N to N+1. They cannot just use the master key because
46	// in the event of a rekey, that master key can no longer decrypt the keyring.
47	// When key N+1 is installed, we create an entry at "prefix/N" which uses
48	// encryption key N to provide the N+1 key. The standby instances scan
49	// for this periodically and refresh their keyring. The upgrade keys
50	// are deleted after a few minutes, but this provides enough time for the
51	// standby instances to upgrade without causing any disruption.
52	keyringUpgradePrefix = "core/upgrade/"
53
54	// masterKeyPath is the location of the master key. This is encrypted
55	// by the latest key in the keyring. This is only used by standby instances
56	// to handle the case of a rekey. If the active instance does a rekey,
57	// the standby instances can no longer reload the keyring since they
58	// have the old master key. This key can be decrypted if you have the
59	// keyring to discover the new master key. The new master key is then
60	// used to reload the keyring itself.
61	masterKeyPath = "core/master"
62
63	// shamirKekPath is used with Shamir in v1.3+ to store a copy of the
64	// unseal key behind the barrier.  As with masterKeyPath this is primarily
65	// used by standbys to handle rekeys.  It also comes into play when restoring
66	// raft snapshots.
67	shamirKekPath = "core/shamir-kek"
68)
69
70// SecurityBarrier is a critical component of Vault. It is used to wrap
71// an untrusted physical backend and provide a single point of encryption,
72// decryption and checksum verification. The goal is to ensure that any
73// data written to the barrier is confidential and that integrity is preserved.
74// As a real-world analogy, this is the steel and concrete wrapper around
75// a Vault. The barrier should only be Unlockable given its key.
76type SecurityBarrier interface {
77	// Initialized checks if the barrier has been initialized
78	// and has a master key set.
79	Initialized(ctx context.Context) (bool, error)
80
81	// Initialize works only if the barrier has not been initialized
82	// and makes use of the given master key.  When sealKey is provided
83	// it's because we're using a new-style Shamir seal, and masterKey
84	// is to be stored using sealKey to encrypt it.
85	Initialize(ctx context.Context, masterKey []byte, sealKey []byte, random io.Reader) error
86
87	// GenerateKey is used to generate a new key
88	GenerateKey(io.Reader) ([]byte, error)
89
90	// KeyLength is used to sanity check a key
91	KeyLength() (int, int)
92
93	// Sealed checks if the barrier has been unlocked yet. The Barrier
94	// is not expected to be able to perform any CRUD until it is unsealed.
95	Sealed() (bool, error)
96
97	// Unseal is used to provide the master key which permits the barrier
98	// to be unsealed. If the key is not correct, the barrier remains sealed.
99	Unseal(ctx context.Context, key []byte) error
100
101	// VerifyMaster is used to check if the given key matches the master key
102	VerifyMaster(key []byte) error
103
104	// SetMasterKey is used to directly set a new master key. This is used in
105	// replicated scenarios due to the chicken and egg problem of reloading the
106	// keyring from disk before we have the master key to decrypt it.
107	SetMasterKey(key []byte) error
108
109	// ReloadKeyring is used to re-read the underlying keyring.
110	// This is used for HA deployments to ensure the latest keyring
111	// is present in the leader.
112	ReloadKeyring(ctx context.Context) error
113
114	// ReloadMasterKey is used to re-read the underlying masterkey.
115	// This is used for HA deployments to ensure the latest master key
116	// is available for keyring reloading.
117	ReloadMasterKey(ctx context.Context) error
118
119	// Seal is used to re-seal the barrier. This requires the barrier to
120	// be unsealed again to perform any further operations.
121	Seal() error
122
123	// Rotate is used to create a new encryption key. All future writes
124	// should use the new key, while old values should still be decryptable.
125	Rotate(ctx context.Context, reader io.Reader) (uint32, error)
126
127	// CreateUpgrade creates an upgrade path key to the given term from the previous term
128	CreateUpgrade(ctx context.Context, term uint32) error
129
130	// DestroyUpgrade destroys the upgrade path key to the given term
131	DestroyUpgrade(ctx context.Context, term uint32) error
132
133	// CheckUpgrade looks for an upgrade to the current term and installs it
134	CheckUpgrade(ctx context.Context) (bool, uint32, error)
135
136	// ActiveKeyInfo is used to inform details about the active key
137	ActiveKeyInfo() (*KeyInfo, error)
138
139	// RotationConfig returns the auto-rotation config for the barrier key
140	RotationConfig() (KeyRotationConfig, error)
141
142	// SetRotationConfig updates the auto-rotation config for the barrier key
143	SetRotationConfig(ctx context.Context, config KeyRotationConfig) error
144
145	// Rekey is used to change the master key used to protect the keyring
146	Rekey(context.Context, []byte) error
147
148	// For replication we must send over the keyring, so this must be available
149	Keyring() (*Keyring, error)
150
151	// For encryption count shipping, a function which handles updating local encryption counts if the consumer succeeds.
152	// This isolates the barrier code from the replication system
153	ConsumeEncryptionCount(consumer func(int64) error) error
154
155	// Add encryption counts from a remote source (downstream cluster node)
156	AddRemoteEncryptions(encryptions int64)
157
158	// Check whether an automatic rotation is due
159	CheckBarrierAutoRotate(ctx context.Context) (string, error)
160
161	// SecurityBarrier must provide the storage APIs
162	logical.Storage
163
164	// SecurityBarrier must provide the encryption APIs
165	BarrierEncryptor
166}
167
168// BarrierStorage is the storage only interface required for a Barrier.
169type BarrierStorage interface {
170	// Put is used to insert or update an entry
171	Put(ctx context.Context, entry *logical.StorageEntry) error
172
173	// Get is used to fetch an entry
174	Get(ctx context.Context, key string) (*logical.StorageEntry, error)
175
176	// Delete is used to permanently delete an entry
177	Delete(ctx context.Context, key string) error
178
179	// List is used ot list all the keys under a given
180	// prefix, up to the next prefix.
181	List(ctx context.Context, prefix string) ([]string, error)
182}
183
184// BarrierEncryptor is the in memory only interface that does not actually
185// use the underlying barrier. It is used for lower level modules like the
186// Write-Ahead-Log and Merkle index to allow them to use the barrier.
187type BarrierEncryptor interface {
188	Encrypt(ctx context.Context, key string, plaintext []byte) ([]byte, error)
189	Decrypt(ctx context.Context, key string, ciphertext []byte) ([]byte, error)
190}
191
192// KeyInfo is used to convey information about the encryption key
193type KeyInfo struct {
194	Term        int
195	InstallTime time.Time
196	Encryptions int64
197}
198