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