Add unit tests for seal backend health check (#22779)

* make Healthy bool consistent and add unit tests

* fix formatting

* fix missing import
This commit is contained in:
Rachel Culpepper
2023-09-08 13:19:05 -04:00
committed by GitHub
parent b6e8cb3a4c
commit 886ea0e094
3 changed files with 133 additions and 1 deletions

View File

@@ -5051,6 +5051,7 @@ func (c *Core) GetSealBackendStatus(ctx context.Context) (*SealBackendStatusResp
Healthy: true,
},
}
r.Healthy = true
}
return &r, nil
}

View File

@@ -7,6 +7,7 @@ import (
"context"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"net/http"
@@ -21,6 +22,8 @@ import (
"github.com/fatih/structs"
"github.com/go-test/deep"
"github.com/hashicorp/go-hclog"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
aeadwrapper "github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2"
semver "github.com/hashicorp/go-version"
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
"github.com/hashicorp/vault/helper/builtinplugins"
@@ -30,6 +33,7 @@ import (
"github.com/hashicorp/vault/helper/random"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/helper/versions"
"github.com/hashicorp/vault/internalshared/configutil"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/compressutil"
"github.com/hashicorp/vault/sdk/helper/consts"
@@ -38,8 +42,10 @@ import (
"github.com/hashicorp/vault/sdk/helper/pluginutil"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/vault/seal"
"github.com/hashicorp/vault/version"
"github.com/mitchellh/mapstructure"
"github.com/stretchr/testify/require"
)
func TestSystemConfigCORS(t *testing.T) {
@@ -6110,6 +6116,131 @@ func TestSystemBackend_pluginRuntimeCRUD(t *testing.T) {
}
}
func TestGetSealBackendStatus(t *testing.T) {
testCases := []struct {
name string
sealOpts seal.TestSealOpts
expectHealthy bool
}{
{
name: "healthy-autoseal",
sealOpts: seal.TestSealOpts{
StoredKeys: seal.StoredKeysSupportedGeneric,
Name: "autoseal-test",
WrapperCount: 1,
Generation: 1,
},
expectHealthy: true,
},
{
name: "unhealthy-autoseal",
sealOpts: seal.TestSealOpts{
StoredKeys: seal.StoredKeysSupportedGeneric,
Name: "autoseal-test",
WrapperCount: 1,
Generation: 1,
},
expectHealthy: false,
},
}
ctx := context.Background()
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
testAccess, wrappers := seal.NewTestSeal(&tt.sealOpts)
c := TestCoreWithSeal(t, NewAutoSeal(testAccess), false)
_, keys, _ := TestCoreInitClusterWrapperSetup(t, c, nil)
for _, key := range keys {
_, err := TestCoreUnseal(c, key)
require.NoError(t, err)
}
if c.Sealed() {
t.Fatal("vault is sealed")
}
if !tt.expectHealthy {
// set encryption error and perform encryption to mark seal unhealthy
wrappers[0].SetEncryptError(errors.New("test error encrypting"))
_, errs := c.seal.GetAccess().Encrypt(context.Background(), []byte("test-plaintext"))
if len(errs) == 0 {
t.Fatalf("expected error on encryption, but got none")
}
}
resp, err := c.GetSealBackendStatus(ctx)
require.NoError(t, err)
if resp.Healthy && !tt.expectHealthy {
t.Fatal("expected seal to be unhealthy, but status was healthy")
} else if !resp.Healthy && tt.expectHealthy {
t.Fatal("expected seal to be healthy, but status was unhealthy")
}
if !tt.expectHealthy && resp.UnhealthySince == "" {
t.Fatal("missing UnhealthySince field in response with unhealthy seal")
}
if len(resp.Backends) == 0 {
t.Fatal("Backend list in response was empty")
}
if !tt.expectHealthy && resp.Backends[0].Healthy {
t.Fatal("expected seal to be unhealthy, received healthy status")
} else if tt.expectHealthy && !resp.Backends[0].Healthy {
t.Fatal("expected seal to be healthy, received unhealthy status")
}
if !tt.expectHealthy && resp.Backends[0].UnhealthySince == "" {
t.Fatal("missing UnhealthySince field in unhealthy seal")
}
})
}
shamirSeal := NewDefaultSeal(seal.NewAccess(nil,
&seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{{Type: wrapping.WrapperTypeShamir.String()}},
},
[]*seal.SealWrapper{
{
Wrapper: aeadwrapper.NewShamirWrapper(),
SealConfigType: wrapping.WrapperTypeShamir.String(),
Priority: 1,
},
},
))
c := TestCoreWithSeal(t, shamirSeal, false)
keys, _, _ := TestCoreInitClusterWrapperSetup(t, c, nil)
for _, key := range keys {
_, err := TestCoreUnseal(c, key)
require.NoError(t, err)
}
if c.Sealed() {
t.Fatal("vault is sealed")
}
resp, err := c.GetSealBackendStatus(ctx)
require.NoError(t, err)
if !resp.Healthy {
t.Fatal("expected healthy seal, got unhealthy")
}
if len(resp.Backends) != 1 {
t.Fatalf("expected response Backends to contain one seal, got %d", len(resp.Backends))
}
if !resp.Backends[0].Healthy {
t.Fatal("expected healthy seal, got unhealthy")
}
}
func TestSystemBackend_pluginRuntime_CannotDeleteRuntimeWithReferencingPlugins(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("Currently plugincontainer only supports linux")

View File

@@ -66,7 +66,7 @@ func NewAutoSeal(lowLevel seal.Access) *autoSeal {
func (d *autoSeal) Healthy() bool {
d.hcLock.RLock()
defer d.hcLock.RUnlock()
return d.allSealsHealthy
return d.Access.AllSealWrappersHealthy()
}
func (d *autoSeal) SealWrapable() bool {