Add nonce to unseal to allow seeing if the operation has reset (#2276)
This commit is contained in:
parent
0591ba4be8
commit
dd0e44ca10
|
@ -53,6 +53,7 @@ type SealStatusResponse struct {
|
|||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Nonce string `json:"nonce"`
|
||||
Version string `json:"version"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
|
|
|
@ -40,11 +40,13 @@ func (c *StatusCommand) Run(args []string) int {
|
|||
"Key Shares: %d\n"+
|
||||
"Key Threshold: %d\n"+
|
||||
"Unseal Progress: %d\n"+
|
||||
"Unseal Nonce: %v"+
|
||||
"Version: %s",
|
||||
sealStatus.Sealed,
|
||||
sealStatus.N,
|
||||
sealStatus.T,
|
||||
sealStatus.Progress,
|
||||
sealStatus.Nonce,
|
||||
sealStatus.Version)
|
||||
|
||||
if sealStatus.ClusterName != "" && sealStatus.ClusterID != "" {
|
||||
|
|
|
@ -84,11 +84,13 @@ func (c *UnsealCommand) Run(args []string) int {
|
|||
"Sealed: %v\n"+
|
||||
"Key Shares: %d\n"+
|
||||
"Key Threshold: %d\n"+
|
||||
"Unseal Progress: %d",
|
||||
"Unseal Progress: %d\n"+
|
||||
"Unseal Nonce: %v",
|
||||
sealStatus.Sealed,
|
||||
sealStatus.N,
|
||||
sealStatus.T,
|
||||
sealStatus.Progress,
|
||||
sealStatus.Nonce,
|
||||
))
|
||||
|
||||
return 0
|
||||
|
|
|
@ -186,11 +186,14 @@ func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Req
|
|||
clusterID = cluster.ID
|
||||
}
|
||||
|
||||
progress, nonce := core.SecretProgress()
|
||||
|
||||
respondOk(w, &SealStatusResponse{
|
||||
Sealed: sealed,
|
||||
T: sealConfig.SecretThreshold,
|
||||
N: sealConfig.SecretShares,
|
||||
Progress: core.SecretProgress(),
|
||||
Progress: progress,
|
||||
Nonce: nonce,
|
||||
Version: version.GetVersion().VersionNumber(),
|
||||
ClusterName: clusterName,
|
||||
ClusterID: clusterID,
|
||||
|
@ -202,6 +205,7 @@ type SealStatusResponse struct {
|
|||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Nonce string `json:"nonce"`
|
||||
Version string `json:"version"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
|
|
|
@ -29,6 +29,7 @@ func TestSysSealStatus(t *testing.T) {
|
|||
"t": json.Number("1"),
|
||||
"n": json.Number("1"),
|
||||
"progress": json.Number("0"),
|
||||
"nonce": "",
|
||||
}
|
||||
testResponseStatus(t, resp, 200)
|
||||
testResponseBody(t, resp, &actual)
|
||||
|
@ -115,6 +116,7 @@ func TestSysUnseal(t *testing.T) {
|
|||
"t": json.Number("1"),
|
||||
"n": json.Number("1"),
|
||||
"progress": json.Number("0"),
|
||||
"nonce": "",
|
||||
}
|
||||
testResponseStatus(t, resp, 200)
|
||||
testResponseBody(t, resp, &actual)
|
||||
|
@ -189,6 +191,10 @@ func TestSysUnseal_Reset(t *testing.T) {
|
|||
t.Fatalf("expected version information")
|
||||
}
|
||||
expected["version"] = actual["version"]
|
||||
if actual["nonce"] == "" && expected["sealed"].(bool) {
|
||||
t.Fatalf("expected a nonce")
|
||||
}
|
||||
expected["nonce"] = actual["nonce"]
|
||||
if actual["cluster_name"] == nil {
|
||||
delete(expected, "cluster_name")
|
||||
} else {
|
||||
|
@ -221,6 +227,7 @@ func TestSysUnseal_Reset(t *testing.T) {
|
|||
t.Fatalf("expected version information")
|
||||
}
|
||||
expected["version"] = actual["version"]
|
||||
expected["nonce"] = actual["nonce"]
|
||||
if actual["cluster_name"] == nil {
|
||||
delete(expected, "cluster_name")
|
||||
} else {
|
||||
|
|
|
@ -124,6 +124,11 @@ type activeAdvertisement struct {
|
|||
ClusterKeyParams *clusterKeyParams `json:"cluster_key_params,omitempty"`
|
||||
}
|
||||
|
||||
type unlockInformation struct {
|
||||
Parts [][]byte
|
||||
Nonce string
|
||||
}
|
||||
|
||||
// Core is used as the central manager of Vault activity. It is the primary point of
|
||||
// interface for API handlers and is responsible for managing the logical and physical
|
||||
// backends, router, security barrier, and audit trails.
|
||||
|
@ -167,9 +172,8 @@ type Core struct {
|
|||
standbyStopCh chan struct{}
|
||||
manualStepDownCh chan struct{}
|
||||
|
||||
// unlockParts has the keys provided to Unseal until
|
||||
// the threshold number of parts is available.
|
||||
unlockParts [][]byte
|
||||
// unlockInfo has the keys provided to Unseal until the threshold number of parts is available, as well as the operation nonce
|
||||
unlockInfo *unlockInformation
|
||||
|
||||
// generateRootProgress holds the shares until we reach enough
|
||||
// to verify the master key
|
||||
|
@ -735,10 +739,15 @@ func (c *Core) Leader() (isLeader bool, leaderAddr string, err error) {
|
|||
}
|
||||
|
||||
// SecretProgress returns the number of keys provided so far
|
||||
func (c *Core) SecretProgress() int {
|
||||
func (c *Core) SecretProgress() (int, string) {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
return len(c.unlockParts)
|
||||
switch c.unlockInfo {
|
||||
case nil:
|
||||
return 0, ""
|
||||
default:
|
||||
return len(c.unlockInfo.Parts), c.unlockInfo.Nonce
|
||||
}
|
||||
}
|
||||
|
||||
// ResetUnsealProcess removes the current unlock parts from memory, to reset
|
||||
|
@ -749,7 +758,7 @@ func (c *Core) ResetUnsealProcess() {
|
|||
if !c.sealed {
|
||||
return
|
||||
}
|
||||
c.unlockParts = nil
|
||||
c.unlockInfo = nil
|
||||
}
|
||||
|
||||
// Unseal is used to provide one of the key parts to unseal the Vault.
|
||||
|
@ -790,19 +799,29 @@ func (c *Core) Unseal(key []byte) (bool, error) {
|
|||
}
|
||||
|
||||
// Check if we already have this piece
|
||||
for _, existing := range c.unlockParts {
|
||||
if bytes.Equal(existing, key) {
|
||||
return false, nil
|
||||
if c.unlockInfo != nil {
|
||||
for _, existing := range c.unlockInfo.Parts {
|
||||
if bytes.Equal(existing, key) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uuid, err := uuid.GenerateUUID()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
c.unlockInfo = &unlockInformation{
|
||||
Nonce: uuid,
|
||||
}
|
||||
}
|
||||
|
||||
// Store this key
|
||||
c.unlockParts = append(c.unlockParts, key)
|
||||
c.unlockInfo.Parts = append(c.unlockInfo.Parts, key)
|
||||
|
||||
// Check if we don't have enough keys to unlock
|
||||
if len(c.unlockParts) < config.SecretThreshold {
|
||||
if len(c.unlockInfo.Parts) < config.SecretThreshold {
|
||||
if c.logger.IsDebug() {
|
||||
c.logger.Debug("core: cannot unseal, not enough keys", "keys", len(c.unlockParts), "threshold", config.SecretThreshold)
|
||||
c.logger.Debug("core: cannot unseal, not enough keys", "keys", len(c.unlockInfo.Parts), "threshold", config.SecretThreshold, "nonce", c.unlockInfo.Nonce)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
@ -810,11 +829,11 @@ func (c *Core) Unseal(key []byte) (bool, error) {
|
|||
// Recover the master key
|
||||
var masterKey []byte
|
||||
if config.SecretThreshold == 1 {
|
||||
masterKey = c.unlockParts[0]
|
||||
c.unlockParts = nil
|
||||
masterKey = c.unlockInfo.Parts[0]
|
||||
c.unlockInfo = nil
|
||||
} else {
|
||||
masterKey, err = shamir.Combine(c.unlockParts)
|
||||
c.unlockParts = nil
|
||||
masterKey, err = shamir.Combine(c.unlockInfo.Parts)
|
||||
c.unlockInfo = nil
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to compute master key: %v", err)
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ func TestCore_Unseal_MultiShare(t *testing.T) {
|
|||
t.Fatalf("should be sealed")
|
||||
}
|
||||
|
||||
if prog := c.SecretProgress(); prog != 0 {
|
||||
if prog, _ := c.SecretProgress(); prog != 0 {
|
||||
t.Fatalf("bad progress: %d", prog)
|
||||
}
|
||||
|
||||
|
@ -91,14 +91,14 @@ func TestCore_Unseal_MultiShare(t *testing.T) {
|
|||
if !unseal {
|
||||
t.Fatalf("should be unsealed")
|
||||
}
|
||||
if prog := c.SecretProgress(); prog != 0 {
|
||||
if prog, _ := c.SecretProgress(); prog != 0 {
|
||||
t.Fatalf("bad progress: %d", prog)
|
||||
}
|
||||
} else {
|
||||
if unseal {
|
||||
t.Fatalf("should not be unsealed")
|
||||
}
|
||||
if prog := c.SecretProgress(); prog != i+1 {
|
||||
if prog, _ := c.SecretProgress(); prog != i+1 {
|
||||
t.Fatalf("bad progress: %d", prog)
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ func TestCore_Unseal_Single(t *testing.T) {
|
|||
t.Fatalf("should be sealed")
|
||||
}
|
||||
|
||||
if prog := c.SecretProgress(); prog != 0 {
|
||||
if prog, _ := c.SecretProgress(); prog != 0 {
|
||||
t.Fatalf("bad progress: %d", prog)
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ func TestCore_Unseal_Single(t *testing.T) {
|
|||
if !unseal {
|
||||
t.Fatalf("should be unsealed")
|
||||
}
|
||||
if prog := c.SecretProgress(); prog != 0 {
|
||||
if prog, _ := c.SecretProgress(); prog != 0 {
|
||||
t.Fatalf("bad progress: %d", prog)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue