mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-05 12:26:34 +02:00
Update rekey methods to indicate proper error codes in responses
This commit is contained in:
parent
9b796f1aca
commit
cfd087b155
@ -169,31 +169,35 @@ func (c *Sys) RekeyDeleteRecoveryBackup() error {
|
||||
}
|
||||
|
||||
type RekeyInitRequest struct {
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
StoredShares int `json:"stored_shares"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
Backup bool
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
StoredShares int `json:"stored_shares"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
Backup bool
|
||||
RequireVerification bool `json:"require_verification"`
|
||||
}
|
||||
|
||||
type RekeyStatusResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Started bool `json:"started"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Required int `json:"required"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool `json:"backup"`
|
||||
Nonce string `json:"nonce"`
|
||||
Started bool `json:"started"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Required int `json:"required"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool `json:"backup"`
|
||||
VerificationRequired bool `json:"verification_required"`
|
||||
}
|
||||
|
||||
type RekeyUpdateResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Complete bool `json:"complete"`
|
||||
Keys []string `json:"keys"`
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool `json:"backup"`
|
||||
Nonce string `json:"nonce"`
|
||||
Complete bool `json:"complete"`
|
||||
Keys []string `json:"keys"`
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool `json:"backup"`
|
||||
VerificationRequired bool `json:"verification_required"`
|
||||
VerificationNonce string `json:"verification_nonce,omitempty"`
|
||||
}
|
||||
|
||||
type RekeyRetrieveResponse struct {
|
||||
@ -201,3 +205,15 @@ type RekeyRetrieveResponse struct {
|
||||
Keys map[string][]string `json:"keys"`
|
||||
KeysB64 map[string][]string `json:"keys_base64"`
|
||||
}
|
||||
|
||||
type RekeyVerificationStatusResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
}
|
||||
|
||||
type RekeyVerificationUpdateResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Complete bool `json:"complete"`
|
||||
}
|
||||
|
||||
38
api/sys_rekey_ext_test.go
Normal file
38
api/sys_rekey_ext_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package api_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
vaulthttp "github.com/hashicorp/vault/http"
|
||||
"github.com/hashicorp/vault/vault"
|
||||
)
|
||||
|
||||
func TestSysRekey_Verification(t *testing.T) {
|
||||
cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
|
||||
HandlerFunc: vaulthttp.Handler,
|
||||
})
|
||||
cluster.Start()
|
||||
defer cluster.Cleanup()
|
||||
|
||||
vault.TestWaitActive(t, cluster.Cores[0].Core)
|
||||
client := cluster.Cores[0].Client
|
||||
|
||||
vault.DefaultSealPretendsToAllowRecoveryKeys = true
|
||||
vault.DefaultSealPretendsToAllowStoredShares = true
|
||||
status, err := client.Sys().RekeyInit(&api.RekeyInitRequest{
|
||||
StoredShares: 1,
|
||||
RequireVerification: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if status == nil {
|
||||
t.Fatal("empty status")
|
||||
}
|
||||
|
||||
/*
|
||||
cluster.EnsureCoresSealed(t)
|
||||
cluster.UnsealCores(t)
|
||||
*/
|
||||
}
|
||||
@ -47,9 +47,9 @@ func handleSysRekeyInit(core *vault.Core, recovery bool) http.Handler {
|
||||
}
|
||||
|
||||
func handleSysRekeyInitGet(ctx context.Context, core *vault.Core, recovery bool, w http.ResponseWriter, r *http.Request) {
|
||||
barrierConfig, err := core.SealAccess().BarrierConfig(ctx)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
barrierConfig, barrierConfErr := core.SealAccess().BarrierConfig(ctx)
|
||||
if barrierConfErr != nil {
|
||||
respondError(w, http.StatusInternalServerError, barrierConfErr)
|
||||
return
|
||||
}
|
||||
if barrierConfig == nil {
|
||||
@ -60,20 +60,20 @@ func handleSysRekeyInitGet(ctx context.Context, core *vault.Core, recovery bool,
|
||||
// Get the rekey configuration
|
||||
rekeyConf, err := core.RekeyConfig(recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the progress
|
||||
progress, err := core.RekeyProgress(recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
sealThreshold, err := core.RekeyThreshold(ctx, recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ func handleSysRekeyInitPut(ctx context.Context, core *vault.Core, recovery bool,
|
||||
VerificationRequired: req.RequireVerification,
|
||||
}, recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ func handleSysRekeyInitPut(ctx context.Context, core *vault.Core, recovery bool,
|
||||
func handleSysRekeyInitDelete(core *vault.Core, recovery bool, w http.ResponseWriter, r *http.Request) {
|
||||
err := core.RekeyCancel(recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
respondOk(w, nil)
|
||||
@ -203,9 +203,9 @@ func handleSysRekeyUpdate(core *vault.Core, recovery bool) http.Handler {
|
||||
defer cancel()
|
||||
|
||||
// Use the key to make progress on rekey
|
||||
result, err := core.RekeyUpdate(ctx, key, req.Nonce, recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, err)
|
||||
result, rekeyErr := core.RekeyUpdate(ctx, key, req.Nonce, recovery)
|
||||
if rekeyErr != nil {
|
||||
respondError(w, rekeyErr.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -269,9 +269,9 @@ func handleSysRekeyVerify(core *vault.Core, recovery bool) http.Handler {
|
||||
}
|
||||
|
||||
func handleSysRekeyVerifyGet(ctx context.Context, core *vault.Core, recovery bool, w http.ResponseWriter, r *http.Request) {
|
||||
barrierConfig, err := core.SealAccess().BarrierConfig(ctx)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
barrierConfig, barrierConfErr := core.SealAccess().BarrierConfig(ctx)
|
||||
if barrierConfErr != nil {
|
||||
respondError(w, http.StatusInternalServerError, barrierConfErr)
|
||||
return
|
||||
}
|
||||
if barrierConfig == nil {
|
||||
@ -282,7 +282,7 @@ func handleSysRekeyVerifyGet(ctx context.Context, core *vault.Core, recovery boo
|
||||
// Get the rekey configuration
|
||||
rekeyConf, err := core.RekeyConfig(recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
if rekeyConf == nil {
|
||||
@ -293,7 +293,7 @@ func handleSysRekeyVerifyGet(ctx context.Context, core *vault.Core, recovery boo
|
||||
// Get the progress
|
||||
progress, err := core.RekeyVerifyProgress(recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -310,7 +310,7 @@ func handleSysRekeyVerifyGet(ctx context.Context, core *vault.Core, recovery boo
|
||||
func handleSysRekeyVerifyDelete(core *vault.Core, recovery bool, w http.ResponseWriter, r *http.Request) {
|
||||
err := core.RekeyVerifyRestart(recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
respondError(w, err.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -354,9 +354,9 @@ func handleSysRekeyVerifyPut(ctx context.Context, core *vault.Core, recovery boo
|
||||
defer cancel()
|
||||
|
||||
// Use the key to make progress on rekey
|
||||
result, err := core.RekeyVerify(ctx, key, recovery)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, err)
|
||||
result, rekeyErr := core.RekeyVerify(ctx, key, recovery)
|
||||
if rekeyErr != nil {
|
||||
respondError(w, rekeyErr.Code(), err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
258
vault/rekey.go
258
vault/rekey.go
@ -6,14 +6,15 @@ import (
|
||||
"crypto/subtle"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/vault/helper/consts"
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/helper/pgpkeys"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/physical"
|
||||
"github.com/hashicorp/vault/shamir"
|
||||
)
|
||||
@ -56,14 +57,14 @@ type RekeyBackup struct {
|
||||
// the recovery key threshold, depending on whether rekey is being
|
||||
// performed on the recovery key, or whether the seal supports
|
||||
// recovery keys.
|
||||
func (c *Core) RekeyThreshold(ctx context.Context, recovery bool) (int, error) {
|
||||
func (c *Core) RekeyThreshold(ctx context.Context, recovery bool) (int, logical.HTTPCodedError) {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return 0, consts.ErrSealed
|
||||
return 0, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return 0, consts.ErrStandby
|
||||
return 0, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.RLock()
|
||||
@ -80,21 +81,24 @@ func (c *Core) RekeyThreshold(ctx context.Context, recovery bool) (int, error) {
|
||||
config, err = c.seal.BarrierConfig(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("unable to look up config: {{err}}", err).Error())
|
||||
}
|
||||
if config == nil {
|
||||
return 0, logical.CodedError(http.StatusBadRequest, ErrNotInit.Error())
|
||||
}
|
||||
|
||||
return config.SecretThreshold, nil
|
||||
}
|
||||
|
||||
// RekeyProgress is used to return the rekey progress (num shares).
|
||||
func (c *Core) RekeyProgress(recovery bool) (int, error) {
|
||||
func (c *Core) RekeyProgress(recovery bool) (int, logical.HTTPCodedError) {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return 0, consts.ErrSealed
|
||||
return 0, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return 0, consts.ErrStandby
|
||||
return 0, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.RLock()
|
||||
@ -108,14 +112,14 @@ func (c *Core) RekeyProgress(recovery bool) (int, error) {
|
||||
|
||||
// RekeyVerifyProgress is used to return the rekey progress (num shares) during
|
||||
// verification.
|
||||
func (c *Core) RekeyVerifyProgress(recovery bool) (int, error) {
|
||||
func (c *Core) RekeyVerifyProgress(recovery bool) (int, logical.HTTPCodedError) {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return 0, consts.ErrSealed
|
||||
return 0, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return 0, consts.ErrStandby
|
||||
return 0, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.RLock()
|
||||
@ -128,14 +132,14 @@ func (c *Core) RekeyVerifyProgress(recovery bool) (int, error) {
|
||||
}
|
||||
|
||||
// RekeyConfig is used to read the rekey configuration
|
||||
func (c *Core) RekeyConfig(recovery bool) (*SealConfig, error) {
|
||||
func (c *Core) RekeyConfig(recovery bool) (*SealConfig, logical.HTTPCodedError) {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return nil, consts.ErrSealed
|
||||
return nil, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return nil, consts.ErrStandby
|
||||
return nil, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -158,7 +162,7 @@ func (c *Core) RekeyConfig(recovery bool) (*SealConfig, error) {
|
||||
|
||||
// RekeyInit will either initialize the rekey of barrier or recovery key.
|
||||
// recovery determines whether this is a rekey on the barrier or recovery key.
|
||||
func (c *Core) RekeyInit(config *SealConfig, recovery bool) error {
|
||||
func (c *Core) RekeyInit(config *SealConfig, recovery bool) logical.HTTPCodedError {
|
||||
if recovery {
|
||||
return c.RecoveryRekeyInit(config)
|
||||
}
|
||||
@ -166,39 +170,39 @@ func (c *Core) RekeyInit(config *SealConfig, recovery bool) error {
|
||||
}
|
||||
|
||||
// BarrierRekeyInit is used to initialize the rekey settings for the barrier key
|
||||
func (c *Core) BarrierRekeyInit(config *SealConfig) error {
|
||||
func (c *Core) BarrierRekeyInit(config *SealConfig) logical.HTTPCodedError {
|
||||
if config.StoredShares > 0 {
|
||||
if !c.seal.StoredKeysSupported() {
|
||||
return fmt.Errorf("storing keys not supported by barrier seal")
|
||||
return logical.CodedError(http.StatusBadRequest, "storing keys not supported by barrier seal")
|
||||
}
|
||||
if len(config.PGPKeys) > 0 {
|
||||
return fmt.Errorf("PGP key encryption not supported when using stored keys")
|
||||
return logical.CodedError(http.StatusBadRequest, "PGP key encryption not supported when using stored keys")
|
||||
}
|
||||
if config.Backup {
|
||||
return fmt.Errorf("key backup not supported when using stored keys")
|
||||
return logical.CodedError(http.StatusBadRequest, "key backup not supported when using stored keys")
|
||||
}
|
||||
}
|
||||
|
||||
if c.seal.RecoveryKeySupported() && c.seal.RecoveryType() == config.Type {
|
||||
c.logger.Debug("using recovery seal configuration to rekey barrier key")
|
||||
if config.VerificationRequired {
|
||||
return fmt.Errorf("requiring verification not supported when rekeying the barrier key with recovery keys")
|
||||
return logical.CodedError(http.StatusBadRequest, "requiring verification not supported when rekeying the barrier key with recovery keys")
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the seal configuration is valid
|
||||
if err := config.Validate(); err != nil {
|
||||
c.logger.Error("invalid rekey seal configuration", "error", err)
|
||||
return errwrap.Wrapf("invalid rekey seal configuration: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("invalid rekey seal configuration: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return consts.ErrSealed
|
||||
return logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return consts.ErrStandby
|
||||
return logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -206,7 +210,7 @@ func (c *Core) BarrierRekeyInit(config *SealConfig) error {
|
||||
|
||||
// Prevent multiple concurrent re-keys
|
||||
if c.barrierRekeyConfig != nil {
|
||||
return fmt.Errorf("rekey already in progress")
|
||||
return logical.CodedError(http.StatusBadRequest, "rekey already in progress")
|
||||
}
|
||||
|
||||
// Copy the configuration
|
||||
@ -216,7 +220,7 @@ func (c *Core) BarrierRekeyInit(config *SealConfig) error {
|
||||
nonce, err := uuid.GenerateUUID()
|
||||
if err != nil {
|
||||
c.barrierRekeyConfig = nil
|
||||
return err
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("error generating nonce for procedure: {{err}}", err).Error())
|
||||
}
|
||||
c.barrierRekeyConfig.Nonce = nonce
|
||||
|
||||
@ -227,28 +231,28 @@ func (c *Core) BarrierRekeyInit(config *SealConfig) error {
|
||||
}
|
||||
|
||||
// RecoveryRekeyInit is used to initialize the rekey settings for the recovery key
|
||||
func (c *Core) RecoveryRekeyInit(config *SealConfig) error {
|
||||
func (c *Core) RecoveryRekeyInit(config *SealConfig) logical.HTTPCodedError {
|
||||
if config.StoredShares > 0 {
|
||||
return fmt.Errorf("stored shares not supported by recovery key")
|
||||
return logical.CodedError(http.StatusBadRequest, "stored shares not supported by recovery key")
|
||||
}
|
||||
|
||||
// Check if the seal configuration is valid
|
||||
if err := config.Validate(); err != nil {
|
||||
c.logger.Error("invalid recovery configuration", "error", err)
|
||||
return errwrap.Wrapf("invalid recovery configuration: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("invalid recovery configuration: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
if !c.seal.RecoveryKeySupported() {
|
||||
return fmt.Errorf("recovery keys not supported")
|
||||
return logical.CodedError(http.StatusBadRequest, "recovery keys not supported")
|
||||
}
|
||||
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return consts.ErrSealed
|
||||
return logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return consts.ErrStandby
|
||||
return logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -256,7 +260,7 @@ func (c *Core) RecoveryRekeyInit(config *SealConfig) error {
|
||||
|
||||
// Prevent multiple concurrent re-keys
|
||||
if c.recoveryRekeyConfig != nil {
|
||||
return fmt.Errorf("rekey already in progress")
|
||||
return logical.CodedError(http.StatusBadRequest, "rekey already in progress")
|
||||
}
|
||||
|
||||
// Copy the configuration
|
||||
@ -266,7 +270,7 @@ func (c *Core) RecoveryRekeyInit(config *SealConfig) error {
|
||||
nonce, err := uuid.GenerateUUID()
|
||||
if err != nil {
|
||||
c.recoveryRekeyConfig = nil
|
||||
return err
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("error generating nonce for procedure: {{err}}", err).Error())
|
||||
}
|
||||
c.recoveryRekeyConfig.Nonce = nonce
|
||||
|
||||
@ -277,7 +281,7 @@ func (c *Core) RecoveryRekeyInit(config *SealConfig) error {
|
||||
}
|
||||
|
||||
// RekeyUpdate is used to provide a new key part for the barrier or recovery key.
|
||||
func (c *Core) RekeyUpdate(ctx context.Context, key []byte, nonce string, recovery bool) (*RekeyResult, error) {
|
||||
func (c *Core) RekeyUpdate(ctx context.Context, key []byte, nonce string, recovery bool) (*RekeyResult, logical.HTTPCodedError) {
|
||||
if recovery {
|
||||
return c.RecoveryRekeyUpdate(ctx, key, nonce)
|
||||
}
|
||||
@ -289,25 +293,25 @@ func (c *Core) RekeyUpdate(ctx context.Context, key []byte, nonce string, recove
|
||||
// key.
|
||||
//
|
||||
// N.B.: If recovery keys are used to rekey, the new barrier key shares are not returned.
|
||||
func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string) (*RekeyResult, error) {
|
||||
func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string) (*RekeyResult, logical.HTTPCodedError) {
|
||||
// Ensure we are already unsealed
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return nil, consts.ErrSealed
|
||||
return nil, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return nil, consts.ErrStandby
|
||||
return nil, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
// Verify the key length
|
||||
min, max := c.barrier.KeyLength()
|
||||
max += shamir.ShareOverhead
|
||||
if len(key) < min {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is shorter than minimum %d bytes", min)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is shorter than minimum %d bytes", min))
|
||||
}
|
||||
if len(key) > max {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is longer than maximum %d bytes", max)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is longer than maximum %d bytes", max))
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -324,27 +328,26 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
existingConfig, err = c.seal.BarrierConfig(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to fetch existing config: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
// Ensure the barrier is initialized
|
||||
if existingConfig == nil {
|
||||
return nil, ErrNotInit
|
||||
return nil, logical.CodedError(http.StatusBadRequest, ErrNotInit.Error())
|
||||
}
|
||||
|
||||
// Ensure a rekey is in progress
|
||||
if c.barrierRekeyConfig == nil {
|
||||
return nil, fmt.Errorf("no barrier rekey in progress")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "no barrier rekey in progress")
|
||||
}
|
||||
|
||||
if nonce != c.barrierRekeyConfig.Nonce {
|
||||
return nil, fmt.Errorf("incorrect nonce supplied; nonce for this rekey operation is %q", c.barrierRekeyConfig.Nonce)
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("incorrect nonce supplied; nonce for this rekey operation is %q", c.barrierRekeyConfig.Nonce))
|
||||
}
|
||||
|
||||
// Check if we already have this piece
|
||||
for _, existing := range c.barrierRekeyProgress {
|
||||
if subtle.ConstantTimeCompare(existing, key) == 1 {
|
||||
return nil, fmt.Errorf("given key has already been provided during this generation operation")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "given key has already been provided during this generation operation")
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,19 +374,19 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
} else {
|
||||
recoveredKey, err = shamir.Combine(c.barrierRekeyProgress)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to compute master key: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to compute master key: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
if useRecovery {
|
||||
if err := c.seal.VerifyRecoveryKey(ctx, recoveredKey); err != nil {
|
||||
c.logger.Error("rekey aborted, recovery key verification failed", "error", err)
|
||||
return nil, err
|
||||
c.logger.Error("rekey recovery key verification failed", "error", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("recovery key verification failed: {{err}}", err).Error())
|
||||
}
|
||||
} else {
|
||||
if err := c.barrier.VerifyMaster(recoveredKey); err != nil {
|
||||
c.logger.Error("rekey aborted, master key verification failed", "error", err)
|
||||
return nil, err
|
||||
c.logger.Error("master key verification failed", "error", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("master key verification failed: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,7 +394,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
newMasterKey, err := c.barrier.GenerateKey()
|
||||
if err != nil {
|
||||
c.logger.Error("failed to generate master key", "error", err)
|
||||
return nil, errwrap.Wrapf("master key generation failed: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("master key generation failed: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
results := &RekeyResult{
|
||||
@ -406,7 +409,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
shares, err := shamir.Split(newMasterKey, c.barrierRekeyConfig.SecretShares, c.barrierRekeyConfig.SecretThreshold)
|
||||
if err != nil {
|
||||
c.logger.Error("failed to generate shares", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to generate shares: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to generate shares: {{err}}", err).Error())
|
||||
}
|
||||
results.SecretShares = shares
|
||||
}
|
||||
@ -429,7 +432,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
}
|
||||
results.PGPFingerprints, results.SecretShares, err = pgpkeys.EncryptShares(hexEncodedShares, c.barrierRekeyConfig.PGPKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to encrypt shares: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
// If backup is enabled, store backup info in vault.coreBarrierUnsealKeysBackupPath
|
||||
@ -451,7 +454,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
buf, err := json.Marshal(backupVals)
|
||||
if err != nil {
|
||||
c.logger.Error("failed to marshal unseal key backup", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to marshal unseal key backup: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to marshal unseal key backup: {{err}}", err).Error())
|
||||
}
|
||||
pe := &physical.Entry{
|
||||
Key: coreBarrierUnsealKeysBackupPath,
|
||||
@ -459,7 +462,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
}
|
||||
if err = c.physical.Put(ctx, pe); err != nil {
|
||||
c.logger.Error("failed to save unseal key backup", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to save unseal key backup: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to save unseal key backup: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -467,7 +470,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
if keysToStore != nil {
|
||||
if err := c.seal.SetStoredKeys(ctx, keysToStore); err != nil {
|
||||
c.logger.Error("failed to store keys", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to store keys: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to store keys: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,7 +479,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
nonce, err := uuid.GenerateUUID()
|
||||
if err != nil {
|
||||
c.barrierRekeyConfig = nil
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to generate verification nonce: {{err}}", err).Error())
|
||||
}
|
||||
c.barrierRekeyConfig.VerificationNonce = nonce
|
||||
c.barrierRekeyConfig.VerificationKey = newMasterKey
|
||||
@ -487,18 +490,18 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
}
|
||||
|
||||
if err := c.performBarrierRekey(ctx, newMasterKey); err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to perform barrier rekey: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
c.barrierRekeyConfig = nil
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (c *Core) performBarrierRekey(ctx context.Context, newMasterKey []byte) error {
|
||||
func (c *Core) performBarrierRekey(ctx context.Context, newMasterKey []byte) logical.HTTPCodedError {
|
||||
// Rekey the barrier
|
||||
if err := c.barrier.Rekey(ctx, newMasterKey); err != nil {
|
||||
c.logger.Error("failed to rekey barrier", "error", err)
|
||||
return errwrap.Wrapf("failed to rekey barrier: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to rekey barrier: {{err}}", err).Error())
|
||||
}
|
||||
if c.logger.IsInfo() {
|
||||
c.logger.Info("security barrier rekeyed", "shares", c.barrierRekeyConfig.SecretShares, "threshold", c.barrierRekeyConfig.SecretThreshold)
|
||||
@ -508,7 +511,7 @@ func (c *Core) performBarrierRekey(ctx context.Context, newMasterKey []byte) err
|
||||
|
||||
if err := c.seal.SetBarrierConfig(ctx, c.barrierRekeyConfig); err != nil {
|
||||
c.logger.Error("error saving rekey seal configuration", "error", err)
|
||||
return errwrap.Wrapf("failed to save rekey seal configuration: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to save rekey seal configuration: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
// Write to the canary path, which will force a synchronous truing during
|
||||
@ -518,32 +521,32 @@ func (c *Core) performBarrierRekey(ctx context.Context, newMasterKey []byte) err
|
||||
Value: []byte(c.barrierRekeyConfig.Nonce),
|
||||
}); err != nil {
|
||||
c.logger.Error("error saving keyring canary", "error", err)
|
||||
return errwrap.Wrapf("failed to save keyring canary: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to save keyring canary: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecoveryRekeyUpdate is used to provide a new key part
|
||||
func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string) (*RekeyResult, error) {
|
||||
func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string) (*RekeyResult, logical.HTTPCodedError) {
|
||||
// Ensure we are already unsealed
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return nil, consts.ErrSealed
|
||||
return nil, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return nil, consts.ErrStandby
|
||||
return nil, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
// Verify the key length
|
||||
min, max := c.barrier.KeyLength()
|
||||
max += shamir.ShareOverhead
|
||||
if len(key) < min {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is shorter than minimum %d bytes", min)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is shorter than minimum %d bytes", min))
|
||||
}
|
||||
if len(key) > max {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is longer than maximum %d bytes", max)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is longer than maximum %d bytes", max))
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -552,27 +555,26 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
// Get the seal configuration
|
||||
existingConfig, err := c.seal.RecoveryConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to fetch existing recovery config: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
// Ensure the seal is initialized
|
||||
if existingConfig == nil {
|
||||
return nil, ErrNotInit
|
||||
return nil, logical.CodedError(http.StatusBadRequest, ErrNotInit.Error())
|
||||
}
|
||||
|
||||
// Ensure a rekey is in progress
|
||||
if c.recoveryRekeyConfig == nil {
|
||||
return nil, fmt.Errorf("no recovery rekey in progress")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "no recovery rekey in progress")
|
||||
}
|
||||
|
||||
if nonce != c.recoveryRekeyConfig.Nonce {
|
||||
return nil, fmt.Errorf("incorrect nonce supplied; nonce for this rekey operation is %q", c.recoveryRekeyConfig.Nonce)
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("incorrect nonce supplied; nonce for this rekey operation is %q", c.recoveryRekeyConfig.Nonce))
|
||||
}
|
||||
|
||||
// Check if we already have this piece
|
||||
for _, existing := range c.recoveryRekeyProgress {
|
||||
if subtle.ConstantTimeCompare(existing, key) == 1 {
|
||||
return nil, fmt.Errorf("given key has already been provided during this rekey operation")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "given key has already been provided during this rekey operation")
|
||||
}
|
||||
}
|
||||
|
||||
@ -599,21 +601,21 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
} else {
|
||||
recoveryKey, err = shamir.Combine(c.recoveryRekeyProgress)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to compute recovery key: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to compute recovery key: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the recovery key
|
||||
if err := c.seal.VerifyRecoveryKey(ctx, recoveryKey); err != nil {
|
||||
c.logger.Error("rekey aborted, recovery key verification failed", "error", err)
|
||||
return nil, err
|
||||
c.logger.Error("recovery key verification failed", "error", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("recovery key verification failed: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
// Generate a new master key
|
||||
newMasterKey, err := c.barrier.GenerateKey()
|
||||
if err != nil {
|
||||
c.logger.Error("failed to generate recovery key", "error", err)
|
||||
return nil, errwrap.Wrapf("recovery key generation failed: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("recovery key generation failed: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
// Return the master key if only a single key part is used
|
||||
@ -628,7 +630,7 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
shares, err := shamir.Split(newMasterKey, c.recoveryRekeyConfig.SecretShares, c.recoveryRekeyConfig.SecretThreshold)
|
||||
if err != nil {
|
||||
c.logger.Error("failed to generate shares", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to generate shares: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to generate shares: {{err}}", err).Error())
|
||||
}
|
||||
results.SecretShares = shares
|
||||
}
|
||||
@ -640,7 +642,7 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
}
|
||||
results.PGPFingerprints, results.SecretShares, err = pgpkeys.EncryptShares(hexEncodedShares, c.recoveryRekeyConfig.PGPKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to encrypt shares: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
if c.recoveryRekeyConfig.Backup {
|
||||
@ -661,7 +663,7 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
buf, err := json.Marshal(backupVals)
|
||||
if err != nil {
|
||||
c.logger.Error("failed to marshal recovery key backup", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to marshal recovery key backup: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to marshal recovery key backup: {{err}}", err).Error())
|
||||
}
|
||||
pe := &physical.Entry{
|
||||
Key: coreRecoveryUnsealKeysBackupPath,
|
||||
@ -669,7 +671,7 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
}
|
||||
if err = c.physical.Put(ctx, pe); err != nil {
|
||||
c.logger.Error("failed to save unseal key backup", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to save unseal key backup: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to save unseal key backup: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -680,7 +682,7 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
nonce, err := uuid.GenerateUUID()
|
||||
if err != nil {
|
||||
c.recoveryRekeyConfig = nil
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to generate verification nonce: {{err}}", err).Error())
|
||||
}
|
||||
c.recoveryRekeyConfig.VerificationNonce = nonce
|
||||
c.recoveryRekeyConfig.VerificationKey = newMasterKey
|
||||
@ -691,24 +693,24 @@ func (c *Core) RecoveryRekeyUpdate(ctx context.Context, key []byte, nonce string
|
||||
}
|
||||
|
||||
if err := c.performRecoveryRekey(ctx, newMasterKey); err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to perform recovery rekey: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
c.recoveryRekeyConfig = nil
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (c *Core) performRecoveryRekey(ctx context.Context, newMasterKey []byte) error {
|
||||
func (c *Core) performRecoveryRekey(ctx context.Context, newMasterKey []byte) logical.HTTPCodedError {
|
||||
if err := c.seal.SetRecoveryKey(ctx, newMasterKey); err != nil {
|
||||
c.logger.Error("failed to set recovery key", "error", err)
|
||||
return errwrap.Wrapf("failed to set recovery key: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to set recovery key: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
c.recoveryRekeyConfig.VerificationKey = nil
|
||||
|
||||
if err := c.seal.SetRecoveryConfig(ctx, c.recoveryRekeyConfig); err != nil {
|
||||
c.logger.Error("error saving rekey seal configuration", "error", err)
|
||||
return errwrap.Wrapf("failed to save rekey seal configuration: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to save rekey seal configuration: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
// Write to the canary path, which will force a synchronous truing during
|
||||
@ -718,38 +720,38 @@ func (c *Core) performRecoveryRekey(ctx context.Context, newMasterKey []byte) er
|
||||
Value: []byte(c.recoveryRekeyConfig.Nonce),
|
||||
}); err != nil {
|
||||
c.logger.Error("error saving keyring canary", "error", err)
|
||||
return errwrap.Wrapf("failed to save keyring canary: {{err}}", err)
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to save keyring canary: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Core) RekeyVerify(ctx context.Context, key []byte, recovery bool) (*RekeyVerifyResult, error) {
|
||||
func (c *Core) RekeyVerify(ctx context.Context, key []byte, recovery bool) (*RekeyVerifyResult, logical.HTTPCodedError) {
|
||||
if recovery {
|
||||
return c.RecoveryRekeyVerify(ctx, key)
|
||||
}
|
||||
return c.BarrierRekeyVerify(ctx, key)
|
||||
}
|
||||
|
||||
func (c *Core) BarrierRekeyVerify(ctx context.Context, key []byte) (*RekeyVerifyResult, error) {
|
||||
func (c *Core) BarrierRekeyVerify(ctx context.Context, key []byte) (*RekeyVerifyResult, logical.HTTPCodedError) {
|
||||
// Ensure we are already unsealed
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return nil, consts.ErrSealed
|
||||
return nil, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return nil, consts.ErrStandby
|
||||
return nil, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
// Verify the key length
|
||||
min, max := c.barrier.KeyLength()
|
||||
max += shamir.ShareOverhead
|
||||
if len(key) < min {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is shorter than minimum %d bytes", min)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is shorter than minimum %d bytes", min))
|
||||
}
|
||||
if len(key) > max {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is longer than maximum %d bytes", max)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is longer than maximum %d bytes", max))
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -757,13 +759,13 @@ func (c *Core) BarrierRekeyVerify(ctx context.Context, key []byte) (*RekeyVerify
|
||||
|
||||
// Ensure a rekey is in progress
|
||||
if c.barrierRekeyConfig == nil {
|
||||
return nil, fmt.Errorf("no barrier rekey in progress")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "no barrier rekey in progress")
|
||||
}
|
||||
|
||||
// Check if we already have this piece
|
||||
for _, existing := range c.barrierRekeyVerifyProgress {
|
||||
if subtle.ConstantTimeCompare(existing, key) == 1 {
|
||||
return nil, fmt.Errorf("given key has already been provided during this verify operation")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "given key has already been provided during this verify operation")
|
||||
}
|
||||
}
|
||||
|
||||
@ -797,17 +799,17 @@ func (c *Core) BarrierRekeyVerify(ctx context.Context, key []byte) (*RekeyVerify
|
||||
} else {
|
||||
recoveredKey, err = shamir.Combine(c.barrierRekeyVerifyProgress)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to compute master key for verification: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to compute master key for verification: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
if subtle.ConstantTimeCompare(recoveredKey, c.barrierRekeyConfig.VerificationKey) != 1 {
|
||||
c.logger.Error("rekey verification failed")
|
||||
return nil, errors.New("rekey verification failed")
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("verification for barrier rekey failed: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
if err := c.performBarrierRekey(ctx, recoveredKey); err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to perform barrier rekey: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
res := &RekeyVerifyResult{
|
||||
@ -818,25 +820,25 @@ func (c *Core) BarrierRekeyVerify(ctx context.Context, key []byte) (*RekeyVerify
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Core) RecoveryRekeyVerify(ctx context.Context, key []byte) (*RekeyVerifyResult, error) {
|
||||
func (c *Core) RecoveryRekeyVerify(ctx context.Context, key []byte) (*RekeyVerifyResult, logical.HTTPCodedError) {
|
||||
// Ensure we are already unsealed
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return nil, consts.ErrSealed
|
||||
return nil, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return nil, consts.ErrStandby
|
||||
return nil, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
// Verify the key length
|
||||
min, max := c.barrier.KeyLength()
|
||||
max += shamir.ShareOverhead
|
||||
if len(key) < min {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is shorter than minimum %d bytes", min)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is shorter than minimum %d bytes", min))
|
||||
}
|
||||
if len(key) > max {
|
||||
return nil, &ErrInvalidKey{fmt.Sprintf("key is longer than maximum %d bytes", max)}
|
||||
return nil, logical.CodedError(http.StatusBadRequest, fmt.Sprintf("key is longer than maximum %d bytes", max))
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -844,13 +846,13 @@ func (c *Core) RecoveryRekeyVerify(ctx context.Context, key []byte) (*RekeyVerif
|
||||
|
||||
// Ensure a rekey is in progress
|
||||
if c.recoveryRekeyConfig == nil {
|
||||
return nil, fmt.Errorf("no recovery rekey in progress")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "no recovery rekey in progress")
|
||||
}
|
||||
|
||||
// Check if we already have this piece
|
||||
for _, existing := range c.recoveryRekeyVerifyProgress {
|
||||
if subtle.ConstantTimeCompare(existing, key) == 1 {
|
||||
return nil, fmt.Errorf("given key has already been provided during this verify operation")
|
||||
return nil, logical.CodedError(http.StatusBadRequest, "given key has already been provided during this verify operation")
|
||||
}
|
||||
}
|
||||
|
||||
@ -884,18 +886,18 @@ func (c *Core) RecoveryRekeyVerify(ctx context.Context, key []byte) (*RekeyVerif
|
||||
} else {
|
||||
recoveryKey, err = shamir.Combine(c.recoveryRekeyVerifyProgress)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to compute recovery key: {{err}}", err)
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to compute recovery key: {{err}}", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the recovery key
|
||||
if subtle.ConstantTimeCompare(recoveryKey, c.recoveryRekeyConfig.VerificationKey) != 1 {
|
||||
c.logger.Error("rekey verification failed", "error", err)
|
||||
return nil, errors.New("rekey verification failed")
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("verification for recovery rekey failed: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
if err := c.performRecoveryRekey(ctx, recoveryKey); err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("failed to perform recovery key rekey: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
res := &RekeyVerifyResult{
|
||||
@ -907,14 +909,14 @@ func (c *Core) RecoveryRekeyVerify(ctx context.Context, key []byte) (*RekeyVerif
|
||||
}
|
||||
|
||||
// RekeyCancel is used to cancel an in-progress rekey
|
||||
func (c *Core) RekeyCancel(recovery bool) error {
|
||||
func (c *Core) RekeyCancel(recovery bool) logical.HTTPCodedError {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return consts.ErrSealed
|
||||
return logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return consts.ErrStandby
|
||||
return logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -932,14 +934,14 @@ func (c *Core) RekeyCancel(recovery bool) error {
|
||||
}
|
||||
|
||||
// RekeyVerifyCancel is used to start the verification process over
|
||||
func (c *Core) RekeyVerifyRestart(recovery bool) error {
|
||||
func (c *Core) RekeyVerifyRestart(recovery bool) logical.HTTPCodedError {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return consts.ErrSealed
|
||||
return logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return consts.ErrStandby
|
||||
return logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
@ -967,14 +969,14 @@ func (c *Core) RekeyVerifyRestart(recovery bool) error {
|
||||
|
||||
// RekeyRetrieveBackup is used to retrieve any backed-up PGP-encrypted unseal
|
||||
// keys
|
||||
func (c *Core) RekeyRetrieveBackup(ctx context.Context, recovery bool) (*RekeyBackup, error) {
|
||||
func (c *Core) RekeyRetrieveBackup(ctx context.Context, recovery bool) (*RekeyBackup, logical.HTTPCodedError) {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return nil, consts.ErrSealed
|
||||
return nil, logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return nil, consts.ErrStandby
|
||||
return nil, logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.RLock()
|
||||
@ -988,7 +990,7 @@ func (c *Core) RekeyRetrieveBackup(ctx context.Context, recovery bool) (*RekeyBa
|
||||
entry, err = c.physical.Get(ctx, coreBarrierUnsealKeysBackupPath)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("error getting keys from backup: {{err}}", err).Error())
|
||||
}
|
||||
if entry == nil {
|
||||
return nil, nil
|
||||
@ -997,28 +999,36 @@ func (c *Core) RekeyRetrieveBackup(ctx context.Context, recovery bool) (*RekeyBa
|
||||
ret := &RekeyBackup{}
|
||||
err = jsonutil.DecodeJSON(entry.Value, ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("error decoding backup keys: {{err}}", err).Error())
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// RekeyDeleteBackup is used to delete any backed-up PGP-encrypted unseal keys
|
||||
func (c *Core) RekeyDeleteBackup(ctx context.Context, recovery bool) error {
|
||||
func (c *Core) RekeyDeleteBackup(ctx context.Context, recovery bool) logical.HTTPCodedError {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
if c.sealed {
|
||||
return consts.ErrSealed
|
||||
return logical.CodedError(http.StatusServiceUnavailable, consts.ErrSealed.Error())
|
||||
}
|
||||
if c.standby {
|
||||
return consts.ErrStandby
|
||||
return logical.CodedError(http.StatusBadRequest, consts.ErrStandby.Error())
|
||||
}
|
||||
|
||||
c.rekeyLock.Lock()
|
||||
defer c.rekeyLock.Unlock()
|
||||
|
||||
if recovery {
|
||||
return c.physical.Delete(ctx, coreRecoveryUnsealKeysBackupPath)
|
||||
err := c.physical.Delete(ctx, coreRecoveryUnsealKeysBackupPath)
|
||||
if err != nil {
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("error deleting backup keys: {{err}}", err).Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return c.physical.Delete(ctx, coreBarrierUnsealKeysBackupPath)
|
||||
err := c.physical.Delete(ctx, coreBarrierUnsealKeysBackupPath)
|
||||
if err != nil {
|
||||
return logical.CodedError(http.StatusInternalServerError, errwrap.Wrapf("error deleting backup keys: {{err}}", err).Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -86,6 +86,11 @@ type Seal interface {
|
||||
VerifyRecoveryKey(context.Context, []byte) error
|
||||
}
|
||||
|
||||
var (
|
||||
DefaultSealPretendsToAllowRecoveryKeys bool
|
||||
DefaultSealPretendsToAllowStoredShares bool
|
||||
)
|
||||
|
||||
type defaultSeal struct {
|
||||
config atomic.Value
|
||||
core *Core
|
||||
@ -121,11 +126,11 @@ func (d *defaultSeal) BarrierType() string {
|
||||
}
|
||||
|
||||
func (d *defaultSeal) StoredKeysSupported() bool {
|
||||
return false
|
||||
return DefaultSealPretendsToAllowStoredShares
|
||||
}
|
||||
|
||||
func (d *defaultSeal) RecoveryKeySupported() bool {
|
||||
return false
|
||||
return DefaultSealPretendsToAllowRecoveryKeys
|
||||
}
|
||||
|
||||
func (d *defaultSeal) SetStoredKeys(ctx context.Context, keys [][]byte) error {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user