mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-29 17:52:32 +00:00 
			
		
		
		
	Vault-18638: add seal reload on SIGHUP (#23571)
* reload seals on SIGHUP * add lock in SetSeals * move lock * use stubmaker and change wrapper finalize call * change finalize logic so that old seals will be finalized after new seals are configured * add changelog * run make fmt * fix fmt * fix panic when reloading seals errors out
This commit is contained in:
		
							
								
								
									
										4
									
								
								changelog/23571.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								changelog/23571.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | ```release-note:feature | ||||||
|  | **Reload seal configuration on SIGHUP**: Seal configuration is reloaded on SIGHUP so that seal configuration can | ||||||
|  | be changed without shutting down vault | ||||||
|  | ``` | ||||||
| @@ -1238,58 +1238,15 @@ func (c *ServerCommand) Run(args []string) int { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
| 	existingSealGenerationInfo, err := vault.PhysicalSealGenInfo(ctx, backend) |  | ||||||
| 	if err != nil { |  | ||||||
| 		c.UI.Error(fmt.Sprintf("Error getting seal generation info: %v", err)) |  | ||||||
| 		return 1 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	hasPartialPaths, err := hasPartiallyWrappedPaths(ctx, backend) | 	setSealResponse, secureRandomReader, err := c.configureSeals(ctx, config, backend, infoKeys, info) | ||||||
| 	if err != nil { |  | ||||||
| 		c.UI.Error(fmt.Sprintf("Cannot determine if there are partially seal wrapped entries in storage: %v", err)) |  | ||||||
| 		return 1 |  | ||||||
| 	} |  | ||||||
| 	setSealResponse, err := setSeal(c, config, infoKeys, info, existingSealGenerationInfo, hasPartialPaths) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		c.UI.Error(err.Error()) | 		c.UI.Error(err.Error()) | ||||||
| 		return 1 | 		return 1 | ||||||
| 	} | 	} | ||||||
| 	if setSealResponse.sealConfigWarning != nil { |  | ||||||
| 		c.UI.Warn(fmt.Sprintf("Warnings during seal configuration: %v", setSealResponse.sealConfigWarning)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for _, seal := range setSealResponse.getCreatedSeals() { | 	currentSeals := setSealResponse.getCreatedSeals() | ||||||
| 		seal := seal // capture range variable | 	defer c.finalizeSeals(ctx, ¤tSeals) | ||||||
| 		// Ensure that the seal finalizer is called, even if using verify-only |  | ||||||
| 		defer func(seal *vault.Seal) { |  | ||||||
| 			err = (*seal).Finalize(ctx) |  | ||||||
| 			if err != nil { |  | ||||||
| 				c.UI.Error(fmt.Sprintf("Error finalizing seals: %v", err)) |  | ||||||
| 			} |  | ||||||
| 		}(seal) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if setSealResponse.barrierSeal == nil { |  | ||||||
| 		c.UI.Error("Could not create barrier seal! Most likely proper Seal configuration information was not set, but no error was generated.") |  | ||||||
| 		return 1 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// prepare a secure random reader for core |  | ||||||
| 	entropyAugLogger := c.logger.Named("entropy-augmentation") |  | ||||||
| 	var entropySources []*configutil.EntropySourcerInfo |  | ||||||
| 	for _, sealWrapper := range setSealResponse.barrierSeal.GetAccess().GetEnabledSealWrappersByPriority() { |  | ||||||
| 		if s, ok := sealWrapper.Wrapper.(entropy.Sourcer); ok { |  | ||||||
| 			entropySources = append(entropySources, &configutil.EntropySourcerInfo{ |  | ||||||
| 				Sourcer: s, |  | ||||||
| 				Name:    sealWrapper.Name, |  | ||||||
| 			}) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	secureRandomReader, err := configutil.CreateSecureRandomReaderFunc(config.SharedConfig, entropySources, entropyAugLogger) |  | ||||||
| 	if err != nil { |  | ||||||
| 		c.UI.Error(err.Error()) |  | ||||||
| 		return 1 |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	coreConfig := createCoreConfig(c, config, backend, configSR, setSealResponse.barrierSeal, setSealResponse.unwrapSeal, metricsHelper, metricSink, secureRandomReader) | 	coreConfig := createCoreConfig(c, config, backend, configSR, setSealResponse.barrierSeal, setSealResponse.unwrapSeal, metricsHelper, metricSink, secureRandomReader) | ||||||
| 	if c.flagDevThreeNode { | 	if c.flagDevThreeNode { | ||||||
| @@ -1680,6 +1637,18 @@ func (c *ServerCommand) Run(args []string) int { | |||||||
| 				c.logger.Warn(cErr.String()) | 				c.logger.Warn(cErr.String()) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			if !cmp.Equal(core.GetCoreConfigInternal().Seals, config.Seals) { | ||||||
|  | 				setSealResponse, err = c.reloadSeals(ctx, core, config) | ||||||
|  | 				if err != nil { | ||||||
|  | 					c.UI.Error(fmt.Errorf("error reloading seal config: %s", err).Error()) | ||||||
|  | 					config.Seals = core.GetCoreConfigInternal().Seals | ||||||
|  | 				} else { | ||||||
|  | 					// finalize the old seals and set the new seals as the current ones | ||||||
|  | 					c.finalizeSeals(ctx, ¤tSeals) | ||||||
|  | 					currentSeals = setSealResponse.getCreatedSeals() | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			core.SetConfig(config) | 			core.SetConfig(config) | ||||||
|  |  | ||||||
| 			// reloading custom response headers to make sure we have | 			// reloading custom response headers to make sure we have | ||||||
| @@ -1836,6 +1805,57 @@ func (c *ServerCommand) Run(args []string) int { | |||||||
| 	return retCode | 	return retCode | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *ServerCommand) configureSeals(ctx context.Context, config *server.Config, backend physical.Backend, infoKeys []string, info map[string]string) (*SetSealResponse, io.Reader, error) { | ||||||
|  | 	existingSealGenerationInfo, err := vault.PhysicalSealGenInfo(ctx, backend) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, nil, fmt.Errorf("Error getting seal generation info: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hasPartialPaths, err := hasPartiallyWrappedPaths(ctx, backend) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, nil, fmt.Errorf("Cannot determine if there are partially seal wrapped entries in storage: %v", err) | ||||||
|  | 	} | ||||||
|  | 	setSealResponse, err := setSeal(c, config, infoKeys, info, existingSealGenerationInfo, hasPartialPaths) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, nil, err | ||||||
|  | 	} | ||||||
|  | 	if setSealResponse.sealConfigWarning != nil { | ||||||
|  | 		c.UI.Warn(fmt.Sprintf("Warnings during seal configuration: %v", setSealResponse.sealConfigWarning)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if setSealResponse.barrierSeal == nil { | ||||||
|  | 		return nil, nil, errors.New("Could not create barrier seal! Most likely proper Seal configuration information was not set, but no error was generated.") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// prepare a secure random reader for core | ||||||
|  | 	entropyAugLogger := c.logger.Named("entropy-augmentation") | ||||||
|  | 	var entropySources []*configutil.EntropySourcerInfo | ||||||
|  | 	for _, sealWrapper := range setSealResponse.barrierSeal.GetAccess().GetEnabledSealWrappersByPriority() { | ||||||
|  | 		if s, ok := sealWrapper.Wrapper.(entropy.Sourcer); ok { | ||||||
|  | 			entropySources = append(entropySources, &configutil.EntropySourcerInfo{ | ||||||
|  | 				Sourcer: s, | ||||||
|  | 				Name:    sealWrapper.Name, | ||||||
|  | 			}) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	secureRandomReader, err := configutil.CreateSecureRandomReaderFunc(config.SharedConfig, entropySources, entropyAugLogger) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return setSealResponse, secureRandomReader, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *ServerCommand) finalizeSeals(ctx context.Context, seals *[]*vault.Seal) { | ||||||
|  | 	for _, seal := range *seals { | ||||||
|  | 		// Ensure that the seal finalizer is called, even if using verify-only | ||||||
|  | 		err := (*seal).Finalize(ctx) | ||||||
|  | 		if err != nil { | ||||||
|  | 			c.UI.Error(fmt.Sprintf("Error finalizing seals: %v", err)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // configureLogging takes the configuration and attempts to parse config values into 'log' friendly configuration values | // configureLogging takes the configuration and attempts to parse config values into 'log' friendly configuration values | ||||||
| // If all goes to plan, a logger is created and setup. | // If all goes to plan, a logger is created and setup. | ||||||
| func (c *ServerCommand) configureLogging(config *server.Config) (hclog.InterceptLogger, error) { | func (c *ServerCommand) configureLogging(config *server.Config) (hclog.InterceptLogger, error) { | ||||||
| @@ -3294,6 +3314,40 @@ func startHttpServers(c *ServerCommand, core *vault.Core, config *server.Config, | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *ServerCommand) reloadSeals(ctx context.Context, core *vault.Core, config *server.Config) (*SetSealResponse, error) { | ||||||
|  | 	if len(config.Seals) == 1 && config.Seals[0].Disabled { | ||||||
|  | 		return nil, errors.New("moving from autoseal to shamir requires seal migration") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if core.SealAccess().BarrierSealConfigType() == vault.SealConfigTypeShamir { | ||||||
|  | 		return nil, errors.New("moving from shamir to autoseal requires seal migration") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	infoKeysReload := make([]string, 0) | ||||||
|  | 	infoReload := make(map[string]string) | ||||||
|  |  | ||||||
|  | 	setSealResponse, secureRandomReader, err := c.configureSeals(ctx, config, core.PhysicalAccess(), infoKeysReload, infoReload) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if setSealResponse.sealConfigError != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = core.SetSeals(setSealResponse.barrierSeal, secureRandomReader) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("error setting seal: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	newGen := setSealResponse.barrierSeal.GetAccess().GetSealGenerationInfo() | ||||||
|  |  | ||||||
|  | 	if err := core.SetPhysicalSealGenInfo(ctx, newGen); err != nil { | ||||||
|  | 		c.logger.Warn("could not update seal information in storage", "err", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return setSealResponse, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func SetStorageMigration(b physical.Backend, active bool) error { | func SetStorageMigration(b physical.Backend, active bool) error { | ||||||
| 	if !active { | 	if !active { | ||||||
| 		return b.Delete(context.Background(), storageMigrationLock) | 		return b.Delete(context.Background(), storageMigrationLock) | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
| package command | package command | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"crypto/tls" | 	"crypto/tls" | ||||||
| 	"crypto/x509" | 	"crypto/x509" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| @@ -21,8 +22,13 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/hashicorp/vault/command/server" | ||||||
|  | 	"github.com/hashicorp/vault/helper/testhelpers/corehelpers" | ||||||
|  | 	"github.com/hashicorp/vault/internalshared/configutil" | ||||||
| 	"github.com/hashicorp/vault/sdk/physical" | 	"github.com/hashicorp/vault/sdk/physical" | ||||||
| 	physInmem "github.com/hashicorp/vault/sdk/physical/inmem" | 	physInmem "github.com/hashicorp/vault/sdk/physical/inmem" | ||||||
|  | 	"github.com/hashicorp/vault/vault" | ||||||
|  | 	"github.com/hashicorp/vault/vault/seal" | ||||||
| 	"github.com/mitchellh/cli" | 	"github.com/mitchellh/cli" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| @@ -400,3 +406,45 @@ func TestConfigureDevTLS(t *testing.T) { | |||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestConfigureSeals(t *testing.T) { | ||||||
|  | 	testConfig := server.Config{SharedConfig: &configutil.SharedConfig{}} | ||||||
|  | 	_, testCommand := testServerCommand(t) | ||||||
|  |  | ||||||
|  | 	logger := corehelpers.NewTestLogger(t) | ||||||
|  | 	backend, err := physInmem.NewInmem(nil, logger) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	testCommand.logger = logger | ||||||
|  |  | ||||||
|  | 	setSealResponse, _, err := testCommand.configureSeals(context.Background(), &testConfig, backend, []string{}, map[string]string{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(setSealResponse.barrierSeal.GetAccess().GetAllSealWrappersByPriority()) != 1 { | ||||||
|  | 		t.Fatalf("expected 1 seal, got %d", len(setSealResponse.barrierSeal.GetAccess().GetAllSealWrappersByPriority())) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if setSealResponse.barrierSeal.BarrierSealConfigType() != vault.SealConfigTypeShamir { | ||||||
|  | 		t.Fatalf("expected shamir seal, got seal type %s", setSealResponse.barrierSeal.BarrierSealConfigType()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestReloadSeals(t *testing.T) { | ||||||
|  | 	testCore := vault.TestCoreWithSeal(t, vault.NewTestSeal(t, &seal.TestSealOpts{StoredKeys: seal.StoredKeysSupportedShamirRoot}), false) | ||||||
|  | 	_, testCommand := testServerCommand(t) | ||||||
|  | 	testConfig := server.Config{SharedConfig: &configutil.SharedConfig{}} | ||||||
|  |  | ||||||
|  | 	_, err := testCommand.reloadSeals(context.Background(), testCore, &testConfig) | ||||||
|  | 	if err == nil { | ||||||
|  | 		t.Fatal("expected error, got nil") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	testConfig = server.Config{SharedConfig: &configutil.SharedConfig{Seals: []*configutil.KMS{{Disabled: true}}}} | ||||||
|  | 	_, err = testCommand.reloadSeals(context.Background(), testCore, &testConfig) | ||||||
|  | 	if err == nil { | ||||||
|  | 		t.Fatal("expected error, got nil") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -4235,6 +4235,49 @@ func (c *Core) Events() *eventbus.EventBus { | |||||||
| 	return c.events | 	return c.events | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Core) SetSeals(barrierSeal Seal, secureRandomReader io.Reader) error { | ||||||
|  | 	ctx, _ := c.GetContext() | ||||||
|  |  | ||||||
|  | 	c.stateLock.Lock() | ||||||
|  | 	defer c.stateLock.Unlock() | ||||||
|  |  | ||||||
|  | 	currentSealBarrierConfig, err := c.SealAccess().BarrierConfig(ctx) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error retrieving barrier config: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	barrierConfigCopy := currentSealBarrierConfig.Clone() | ||||||
|  | 	barrierConfigCopy.Type = barrierSeal.BarrierSealConfigType().String() | ||||||
|  |  | ||||||
|  | 	barrierSeal.SetCore(c) | ||||||
|  |  | ||||||
|  | 	rootKey, err := c.seal.GetStoredKeys(ctx) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(rootKey) < 1 { | ||||||
|  | 		return errors.New("root key not found") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	barrierConfigCopy.Type = barrierSeal.BarrierSealConfigType().String() | ||||||
|  | 	err = barrierSeal.SetBarrierConfig(ctx, barrierConfigCopy) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error setting barrier config for new seal: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = barrierSeal.SetStoredKeys(ctx, rootKey) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("error setting root key in new seal: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c.seal = barrierSeal | ||||||
|  |  | ||||||
|  | 	c.reloadSealsEnt(secureRandomReader, barrierSeal.GetAccess(), c.logger) | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (c *Core) GetWellKnownRedirect(ctx context.Context, path string) (string, error) { | func (c *Core) GetWellKnownRedirect(ctx context.Context, path string) (string, error) { | ||||||
| 	if c.WellKnownRedirects == nil { | 	if c.WellKnownRedirects == nil { | ||||||
| 		return "", nil | 		return "", nil | ||||||
|   | |||||||
| @@ -5,7 +5,13 @@ | |||||||
|  |  | ||||||
| package vault | package vault | ||||||
|  |  | ||||||
| import "context" | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"io" | ||||||
|  |  | ||||||
|  | 	"github.com/hashicorp/go-hclog" | ||||||
|  | 	"github.com/hashicorp/vault/vault/seal" | ||||||
|  | ) | ||||||
|  |  | ||||||
| //go:generate go run github.com/hashicorp/vault/tools/stubmaker | //go:generate go run github.com/hashicorp/vault/tools/stubmaker | ||||||
|  |  | ||||||
| @@ -96,3 +102,6 @@ func (c *Core) entLastRemoteUpstreamWAL() uint64 { | |||||||
| func (c *Core) EntWaitUntilWALShipped(ctx context.Context, index uint64) bool { | func (c *Core) EntWaitUntilWALShipped(ctx context.Context, index uint64) bool { | ||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Core) reloadSealsEnt(secureRandomReader io.Reader, sealAccess seal.Access, logger hclog.Logger) { | ||||||
|  | } | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ import ( | |||||||
| 	"github.com/hashicorp/vault/sdk/logical" | 	"github.com/hashicorp/vault/sdk/logical" | ||||||
| 	"github.com/hashicorp/vault/sdk/physical" | 	"github.com/hashicorp/vault/sdk/physical" | ||||||
| 	"github.com/hashicorp/vault/sdk/physical/inmem" | 	"github.com/hashicorp/vault/sdk/physical/inmem" | ||||||
|  | 	"github.com/hashicorp/vault/vault/seal" | ||||||
| 	"github.com/hashicorp/vault/version" | 	"github.com/hashicorp/vault/version" | ||||||
| 	"github.com/sasha-s/go-deadlock" | 	"github.com/sasha-s/go-deadlock" | ||||||
| ) | ) | ||||||
| @@ -3362,6 +3363,47 @@ func InduceDeadlock(t *testing.T, vaultcore *Core, expected uint32) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestSetSeals(t *testing.T) { | ||||||
|  | 	oldSeal := NewTestSeal(t, &seal.TestSealOpts{ | ||||||
|  | 		StoredKeys:   seal.StoredKeysSupportedGeneric, | ||||||
|  | 		Name:         "old-seal", | ||||||
|  | 		WrapperCount: 1, | ||||||
|  | 		Generation:   1, | ||||||
|  | 	}) | ||||||
|  | 	testCore := TestCoreWithSeal(t, oldSeal, false) | ||||||
|  | 	_, keys, _ := TestCoreInitClusterWrapperSetup(t, testCore, nil) | ||||||
|  | 	for _, key := range keys { | ||||||
|  | 		if _, err := TestCoreUnseal(testCore, key); err != nil { | ||||||
|  | 			t.Fatalf("error unsealing core: %s", err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if testCore.Sealed() { | ||||||
|  | 		t.Fatal("expected core to be unsealed, but it is sealed") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	newSeal := NewTestSeal(t, &seal.TestSealOpts{ | ||||||
|  | 		StoredKeys:   seal.StoredKeysSupportedGeneric, | ||||||
|  | 		Name:         "new-seal", | ||||||
|  | 		WrapperCount: 1, | ||||||
|  | 		Generation:   2, | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	err := testCore.SetSeals(newSeal, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	wrappers := testCore.seal.GetAccess().GetAllSealWrappersByPriority() | ||||||
|  | 	if len(wrappers) != 1 { | ||||||
|  | 		t.Fatalf("expected 1 wrapper in seal access, got %d", len(wrappers)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if wrappers[0].Name != "new-seal-1" { | ||||||
|  | 		t.Fatalf("unexpected seal name: got %s, expected new-seal-1", wrappers[0].Name) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestExpiration_DeadlockDetection(t *testing.T) { | func TestExpiration_DeadlockDetection(t *testing.T) { | ||||||
| 	testCore := TestCore(t) | 	testCore := TestCore(t) | ||||||
| 	testCoreUnsealed(t, testCore) | 	testCoreUnsealed(t, testCore) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Rachel Culpepper
					Rachel Culpepper