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