c87d34d1a4
* Seal migration after unsealing * Refactor migration fields migrationInformation in core * Perform seal migration as part of postUnseal * Remove the sleep logic * Use proper seal in the unseal function * Fix migration from Auto to Shamir * Fix the recovery config missing issue * Address the non-ha migration case * Fix the multi cluster case * Avoid re-running seal migration * Run the post migration code in new leaders * Fix the issue of wrong recovery being set * Address review feedback * Add more complete testing coverage for seal migrations. (#8247) * Add more complete testing coverage for seal migrations. Also remove VAULT_ACC gate from some tests that just depend on docker, cleanup dangling recovery config in storage after migration, and fix a call in adjustCoreForSealMigration that seems broken. * Fix the issue of wrong recovery key being set * Adapt tests to work with multiple cores. * Add missing line to disable raft join. Co-authored-by: Vishal Nayak <vishalnayak@users.noreply.github.com> * Fix all known issues * Remove warning * Review feedback. * Revert my previous change that broke raft tests. We'll need to come back and at least comment this once we better understand why it's needed. * Don't allow migration between same types for now * Disable auto to auto tests for now since it uses migration between same types which is not allowed * Update vault/core.go Co-Authored-By: Brian Kassouf <briankassouf@users.noreply.github.com> * Add migration logs * Address review comments * Add the recovery config check back * Skip a few steps if migration is already done * Return from waitForLeadership if migration fails Co-authored-by: ncabatoff <nick.cabatoff@gmail.com> Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com>
189 lines
4.3 KiB
Go
189 lines
4.3 KiB
Go
package seal_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/go-uuid"
|
|
"github.com/hashicorp/vault/api"
|
|
"github.com/hashicorp/vault/command/server/seal"
|
|
"github.com/ory/dockertest"
|
|
)
|
|
|
|
func TestTransitWrapper_Lifecycle(t *testing.T) {
|
|
cleanup, retAddress, token, mountPath, keyName, _ := prepareTestContainer(t)
|
|
defer cleanup()
|
|
|
|
wrapperConfig := map[string]string{
|
|
"address": retAddress,
|
|
"token": token,
|
|
"mount_path": mountPath,
|
|
"key_name": keyName,
|
|
}
|
|
|
|
s, _, err := seal.GetTransitKMSFunc(nil, wrapperConfig)
|
|
if err != nil {
|
|
t.Fatalf("error setting wrapper config: %v", err)
|
|
}
|
|
|
|
// Test Encrypt and Decrypt calls
|
|
input := []byte("foo")
|
|
swi, err := s.Encrypt(context.Background(), input, nil)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err.Error())
|
|
}
|
|
|
|
pt, err := s.Decrypt(context.Background(), swi, nil)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err.Error())
|
|
}
|
|
|
|
if !reflect.DeepEqual(input, pt) {
|
|
t.Fatalf("expected %s, got %s", input, pt)
|
|
}
|
|
}
|
|
|
|
func TestTransitSeal_TokenRenewal(t *testing.T) {
|
|
cleanup, retAddress, token, mountPath, keyName, tlsConfig := prepareTestContainer(t)
|
|
defer cleanup()
|
|
|
|
clientConfig := &api.Config{
|
|
Address: retAddress,
|
|
}
|
|
if err := clientConfig.ConfigureTLS(tlsConfig); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
remoteClient, err := api.NewClient(clientConfig)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
remoteClient.SetToken(token)
|
|
|
|
req := &api.TokenCreateRequest{
|
|
Period: "5s",
|
|
}
|
|
rsp, err := remoteClient.Auth().Token().Create(req)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
wrapperConfig := map[string]string{
|
|
"address": retAddress,
|
|
"token": rsp.Auth.ClientToken,
|
|
"mount_path": mountPath,
|
|
"key_name": keyName,
|
|
}
|
|
s, _, err := seal.GetTransitKMSFunc(nil, wrapperConfig)
|
|
if err != nil {
|
|
t.Fatalf("error setting wrapper config: %v", err)
|
|
}
|
|
|
|
time.Sleep(7 * time.Second)
|
|
|
|
// Test Encrypt and Decrypt calls
|
|
input := []byte("foo")
|
|
swi, err := s.Encrypt(context.Background(), input, nil)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err.Error())
|
|
}
|
|
|
|
pt, err := s.Decrypt(context.Background(), swi, nil)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err.Error())
|
|
}
|
|
|
|
if !reflect.DeepEqual(input, pt) {
|
|
t.Fatalf("expected %s, got %s", input, pt)
|
|
}
|
|
}
|
|
|
|
func prepareTestContainer(t *testing.T) (cleanup func(), retAddress, token, mountPath, keyName string, tlsConfig *api.TLSConfig) {
|
|
testToken, err := uuid.GenerateUUID()
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
testMountPath, err := uuid.GenerateUUID()
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
testKeyName, err := uuid.GenerateUUID()
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
pool, err := dockertest.NewPool("")
|
|
if err != nil {
|
|
t.Fatalf("Failed to connect to docker: %s", err)
|
|
}
|
|
|
|
dockerOptions := &dockertest.RunOptions{
|
|
Repository: "vault",
|
|
Tag: "latest",
|
|
Cmd: []string{"server", "-log-level=trace", "-dev", fmt.Sprintf("-dev-root-token-id=%s", testToken),
|
|
"-dev-listen-address=0.0.0.0:8200"},
|
|
}
|
|
resource, err := pool.RunWithOptions(dockerOptions)
|
|
if err != nil {
|
|
t.Fatalf("Could not start local Vault docker container: %s", err)
|
|
}
|
|
|
|
cleanup = func() {
|
|
var err error
|
|
for i := 0; i < 10; i++ {
|
|
err = pool.Purge(resource)
|
|
if err == nil {
|
|
return
|
|
}
|
|
time.Sleep(1 * time.Second)
|
|
}
|
|
|
|
if strings.Contains(err.Error(), "No such container") {
|
|
return
|
|
}
|
|
t.Fatalf("Failed to cleanup local container: %s", err)
|
|
}
|
|
|
|
retAddress = fmt.Sprintf("http://127.0.0.1:%s", resource.GetPort("8200/tcp"))
|
|
tlsConfig = &api.TLSConfig{
|
|
Insecure: true,
|
|
}
|
|
|
|
// exponential backoff-retry
|
|
if err = pool.Retry(func() error {
|
|
vaultConfig := api.DefaultConfig()
|
|
vaultConfig.Address = retAddress
|
|
if err := vaultConfig.ConfigureTLS(tlsConfig); err != nil {
|
|
return err
|
|
}
|
|
vault, err := api.NewClient(vaultConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
vault.SetToken(testToken)
|
|
|
|
// Set up transit
|
|
if err := vault.Sys().Mount(testMountPath, &api.MountInput{
|
|
Type: "transit",
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create default aesgcm key
|
|
if _, err := vault.Logical().Write(path.Join(testMountPath, "keys", testKeyName), map[string]interface{}{}); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Could not connect to vault: %s", err)
|
|
}
|
|
return cleanup, retAddress, testToken, testMountPath, testKeyName, tlsConfig
|
|
}
|