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