mirror of https://github.com/hashicorp/boundary
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
525 lines
19 KiB
525 lines
19 KiB
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package credentials_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/boundary/api"
|
|
"github.com/hashicorp/boundary/api/credentials"
|
|
"github.com/hashicorp/boundary/api/credentialstores"
|
|
"github.com/hashicorp/boundary/api/hostcatalogs"
|
|
"github.com/hashicorp/boundary/api/hosts"
|
|
"github.com/hashicorp/boundary/api/hostsets"
|
|
"github.com/hashicorp/boundary/api/scopes"
|
|
"github.com/hashicorp/boundary/api/targets"
|
|
"github.com/hashicorp/boundary/globals"
|
|
"github.com/hashicorp/boundary/internal/credential"
|
|
"github.com/hashicorp/boundary/internal/daemon/controller"
|
|
_ "github.com/hashicorp/boundary/internal/daemon/controller/handlers/targets/tcp"
|
|
"github.com/hashicorp/boundary/internal/daemon/worker"
|
|
"github.com/hashicorp/boundary/internal/iam"
|
|
"github.com/hashicorp/boundary/internal/kms"
|
|
"github.com/hashicorp/boundary/internal/server"
|
|
"github.com/hashicorp/boundary/internal/tests/helper"
|
|
"github.com/hashicorp/go-hclog"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/crypto/ssh/testdata"
|
|
)
|
|
|
|
func TestList(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
cs, err := credentialstores.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
|
|
credClient := credentials.NewClient(client)
|
|
|
|
ul, err := credClient.List(tc.Context(), cs.Item.Id)
|
|
require.NoError(err)
|
|
assert.Empty(ul.Items)
|
|
|
|
cred, err := credClient.Create(tc.Context(), credential.UsernamePasswordSubtype.String(), cs.Item.Id,
|
|
credentials.WithName("0"),
|
|
credentials.WithDescription("description"),
|
|
credentials.WithUsernamePasswordCredentialUsername("user"),
|
|
credentials.WithUsernamePasswordCredentialPassword("pass"))
|
|
require.NoError(err)
|
|
|
|
expected := make([]*credentials.Credential, 10)
|
|
expected[0] = cred.Item
|
|
|
|
ul, err = credClient.List(tc.Context(), cs.Item.Id)
|
|
require.NoError(err)
|
|
assert.ElementsMatch(comparableCatalogSlice(expected[:1]), comparableCatalogSlice(ul.Items))
|
|
|
|
for i := 1; i < 10; i++ {
|
|
cred, err := credClient.Create(tc.Context(), credential.UsernamePasswordSubtype.String(), cs.Item.Id,
|
|
credentials.WithName(fmt.Sprintf("%d", i)),
|
|
credentials.WithDescription("description"),
|
|
credentials.WithUsernamePasswordCredentialUsername("user"),
|
|
credentials.WithUsernamePasswordCredentialPassword("pass"))
|
|
require.NoError(err)
|
|
expected[i] = cred.Item
|
|
}
|
|
ul, err = credClient.List(tc.Context(), cs.Item.Id)
|
|
require.NoError(err)
|
|
assert.ElementsMatch(comparableCatalogSlice(expected), comparableCatalogSlice(ul.Items))
|
|
|
|
filterItem := ul.Items[3]
|
|
ul, err = credClient.List(tc.Context(), cs.Item.Id,
|
|
credentials.WithFilter(fmt.Sprintf(`"/item/id"==%q`, filterItem.Id)))
|
|
require.NoError(err)
|
|
assert.Len(ul.Items, 1)
|
|
assert.Equal(filterItem.Id, ul.Items[0].Id)
|
|
}
|
|
|
|
func comparableCatalogSlice(in []*credentials.Credential) []credentials.Credential {
|
|
var filtered []credentials.Credential
|
|
for _, i := range in {
|
|
p := credentials.Credential{
|
|
Id: i.Id,
|
|
Name: i.Name,
|
|
Description: i.Description,
|
|
CreatedTime: i.CreatedTime,
|
|
UpdatedTime: i.UpdatedTime,
|
|
Attributes: i.Attributes,
|
|
}
|
|
filtered = append(filtered, p)
|
|
}
|
|
return filtered
|
|
}
|
|
|
|
func TestCrud(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
cs, err := credentialstores.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
|
|
checkResource := func(step string, c *credentials.Credential, wantedName, wantedUser string, wantVersion uint32) {
|
|
assert.NotNil(c, "returned no resource", step)
|
|
assert.Equal(wantedName, c.Name, step)
|
|
gotUser, ok := c.Attributes["username"]
|
|
require.True(ok)
|
|
assert.Equal(wantedUser, gotUser, step)
|
|
assert.Equal(wantVersion, c.Version)
|
|
}
|
|
credClient := credentials.NewClient(client)
|
|
|
|
cred, err := credClient.Create(tc.Context(), credential.UsernamePasswordSubtype.String(), cs.Item.Id, credentials.WithName("foo"),
|
|
credentials.WithUsernamePasswordCredentialUsername("user"), credentials.WithUsernamePasswordCredentialPassword("pass"))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("create", cred.Item, "foo", "user", 1)
|
|
|
|
cred, err = credClient.Read(tc.Context(), cred.Item.Id)
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("read", cred.Item, "foo", "user", 1)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.WithName("bar"))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "bar", "user", 2)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.WithUsernamePasswordCredentialUsername("newuser"))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "bar", "newuser", 3)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.DefaultName())
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "", "newuser", 4)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version,
|
|
credentials.WithName("newuser"), credentials.WithUsernamePasswordCredentialUsername("neweruser"))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "newuser", "neweruser", 5)
|
|
|
|
_, err = credClient.Delete(tc.Context(), cred.Item.Id)
|
|
assert.NoError(err)
|
|
|
|
_, err = credClient.Delete(tc.Context(), cred.Item.Id)
|
|
require.Error(err)
|
|
apiErr := api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
}
|
|
|
|
func TestCrudSpk(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
cs, err := credentialstores.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
|
|
checkResource := func(step string, c *credentials.Credential, wantedName, wantedUser string, wantVersion uint32) {
|
|
assert.NotNil(c, "returned no resource", step)
|
|
assert.Equal(wantedName, c.Name, step)
|
|
gotUser, ok := c.Attributes["username"]
|
|
require.True(ok)
|
|
assert.Equal(wantedUser, gotUser, step)
|
|
assert.Equal(wantVersion, c.Version)
|
|
}
|
|
credClient := credentials.NewClient(client)
|
|
|
|
spk := string(testdata.PEMBytes["rsa"])
|
|
spkWithPass := string(testdata.PEMEncryptedKeys[0].PEMBytes)
|
|
pass := testdata.PEMEncryptedKeys[0].EncryptionKey
|
|
|
|
cred, err := credClient.Create(tc.Context(), credential.SshPrivateKeySubtype.String(), cs.Item.Id, credentials.WithName("foo"),
|
|
credentials.WithSshPrivateKeyCredentialUsername("user"),
|
|
credentials.WithSshPrivateKeyCredentialPrivateKey(spkWithPass),
|
|
credentials.WithSshPrivateKeyCredentialPrivateKeyPassphrase(pass))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("create", cred.Item, "foo", "user", 1)
|
|
|
|
// Validate passphrase hmac was set and passpharse is not set
|
|
passHmac, ok := cred.GetItem().Attributes["private_key_passphrase_hmac"].(string)
|
|
require.True(ok)
|
|
require.NotNil(passHmac)
|
|
|
|
cred, err = credClient.Read(tc.Context(), cred.Item.Id)
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("read", cred.Item, "foo", "user", 1)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.WithName("bar"))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "bar", "user", 2)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.WithSshPrivateKeyCredentialUsername("newuser"))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "bar", "newuser", 3)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.DefaultName())
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "", "newuser", 4)
|
|
|
|
// Update to non-encrypted key
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.WithSshPrivateKeyCredentialPrivateKey(spk))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "", "newuser", 5)
|
|
|
|
// Validate passphrase hmac is no longer set
|
|
_, ok = cred.GetItem().Attributes["private_key_passphrase_hmac"].(string)
|
|
require.False(ok)
|
|
|
|
_, err = credClient.Delete(tc.Context(), cred.Item.Id)
|
|
assert.NoError(err)
|
|
|
|
_, err = credClient.Delete(tc.Context(), cred.Item.Id)
|
|
require.Error(err)
|
|
apiErr := api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
}
|
|
|
|
func TestCrudJson(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
cs, err := credentialstores.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
|
|
checkResource := func(step string, c *credentials.Credential, wantedName string, wantVersion uint32) {
|
|
assert.NotNil(c, "returned no resource", step)
|
|
assert.Equal(wantedName, c.Name, step)
|
|
assert.Equal(wantVersion, c.Version)
|
|
}
|
|
credClient := credentials.NewClient(client)
|
|
|
|
obj := map[string]any{
|
|
"username": "admin",
|
|
"password": "pass",
|
|
}
|
|
cred, err := credClient.Create(tc.Context(), credential.JsonSubtype.String(), cs.Item.Id, credentials.WithName("foo"), credentials.WithJsonCredentialObject(obj))
|
|
require.NoError(err)
|
|
require.NotNil(cred)
|
|
checkResource("create", cred.Item, "foo", 1)
|
|
|
|
jsonAttributes, err := cred.GetItem().GetJsonAttributes()
|
|
require.NoError(err)
|
|
require.Nil(jsonAttributes.Object)
|
|
require.NotEmpty(jsonAttributes.ObjectHmac)
|
|
|
|
sshAttributes, err := cred.GetItem().GetSshPrivateKeyAttributes()
|
|
require.Error(err)
|
|
require.Nil(sshAttributes)
|
|
|
|
upAttributes, err := cred.GetItem().GetUsernamePasswordAttributes()
|
|
require.Error(err)
|
|
require.Nil(upAttributes)
|
|
|
|
// Validate object hmac was set and object is not set
|
|
originalObjectHmac, ok := cred.GetItem().Attributes["object_hmac"].(string)
|
|
require.True(ok)
|
|
require.NotNil(originalObjectHmac)
|
|
object, ok := cred.GetItem().Attributes["object"].(string)
|
|
require.False(ok)
|
|
require.Empty(object)
|
|
|
|
cred, err = credClient.Read(tc.Context(), cred.Item.Id)
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("read", cred.Item, "foo", 1)
|
|
|
|
// Validate object hmac was set and object is not set
|
|
objectHmac, ok := cred.GetItem().Attributes["object_hmac"].(string)
|
|
require.True(ok)
|
|
require.NotNil(objectHmac)
|
|
object, ok = cred.GetItem().Attributes["object"].(string)
|
|
require.False(ok)
|
|
require.Empty(object)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.WithName("bar"))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "bar", 2)
|
|
|
|
cred, err = credClient.Update(tc.Context(), cred.Item.Id, cred.Item.Version, credentials.WithJsonCredentialObject(map[string]any{
|
|
"username": "not_admin",
|
|
"password": "not_password",
|
|
}))
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
checkResource("update", cred.Item, "bar", 3)
|
|
|
|
// Validate secret hmac was set & is not the same as the original value & secret is not set
|
|
objectHmac, ok = cred.GetItem().Attributes["object_hmac"].(string)
|
|
require.True(ok)
|
|
require.NotNil(objectHmac)
|
|
require.NotEqual(originalObjectHmac, objectHmac)
|
|
object, ok = cred.GetItem().Attributes["secrets"].(string)
|
|
require.False(ok)
|
|
require.Empty(object)
|
|
|
|
_, err = credClient.Delete(tc.Context(), cred.Item.Id)
|
|
assert.NoError(err)
|
|
|
|
_, err = credClient.Delete(tc.Context(), cred.Item.Id)
|
|
require.Error(err)
|
|
apiErr := api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
}
|
|
|
|
func TestErrors(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
tc := controller.NewTestController(t, nil)
|
|
defer tc.Shutdown()
|
|
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
cs, err := credentialstores.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
require.NotNil(cs)
|
|
|
|
c := credentials.NewClient(client)
|
|
|
|
cred, err := c.Create(tc.Context(), credential.UsernamePasswordSubtype.String(), cs.Item.Id, credentials.WithName("foo"),
|
|
credentials.WithUsernamePasswordCredentialUsername("user"), credentials.WithUsernamePasswordCredentialPassword("pass"))
|
|
require.NoError(err)
|
|
require.NotNil(cred)
|
|
|
|
// A malformed id is processed as the id and not a different path to the api.
|
|
_, err = c.Read(tc.Context(), fmt.Sprintf("%s/../", cred.Item.Id))
|
|
require.Error(err)
|
|
apiErr := api.AsServerError(err)
|
|
require.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusBadRequest, apiErr.Response().StatusCode())
|
|
require.Len(apiErr.Details.RequestFields, 1)
|
|
assert.Equal(apiErr.Details.RequestFields[0].Name, "id")
|
|
|
|
// Updating the wrong version should fail.
|
|
_, err = c.Update(tc.Context(), cred.Item.Id, 73, credentials.WithName("anything"))
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
|
|
// Same name
|
|
_, err = c.Create(tc.Context(), credential.UsernamePasswordSubtype.String(), proj.GetPublicId(), credentials.WithName("foo"))
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
|
|
_, err = c.Read(tc.Context(), globals.UsernamePasswordCredentialPrefix+"_doesntexis")
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
|
|
|
_, err = c.Read(tc.Context(), "invalid id")
|
|
require.Error(err)
|
|
apiErr = api.AsServerError(err)
|
|
assert.NotNil(apiErr)
|
|
assert.EqualValues(http.StatusBadRequest, apiErr.Response().StatusCode())
|
|
}
|
|
|
|
// TestUpdateAfterKeyRotation sets up a scenario where a JSON credential
|
|
// is re-encrypted with the newest key version during an update, and checks
|
|
// that the key version ID is tracked correctly. If the key version ID
|
|
// is not updated during the credential update, the data becomes
|
|
// irrecoverable since the encryption key is destroyed.
|
|
func TestUpdateAfterKeyRotation(t *testing.T) {
|
|
require, assert := require.New(t), assert.New(t)
|
|
logger := hclog.New(&hclog.LoggerOptions{
|
|
Level: hclog.Trace,
|
|
})
|
|
|
|
// This prevents us from running tests in parallel.
|
|
server.TestUseCommunityFilterWorkersFn(t)
|
|
|
|
tc := controller.NewTestController(
|
|
t,
|
|
&controller.TestControllerOpts{
|
|
SchedulerRunJobInterval: 100 * time.Millisecond,
|
|
DisableRateLimiting: true,
|
|
},
|
|
)
|
|
ctx := tc.Context()
|
|
client := tc.Client()
|
|
token := tc.Token()
|
|
client.SetToken(token.Token)
|
|
scopesClient := scopes.NewClient(client)
|
|
credsClient := credentials.NewClient(client)
|
|
tgClient := targets.NewClient(client)
|
|
hostClient := hosts.NewClient(client)
|
|
hsClient := hostsets.NewClient(client)
|
|
hcClient := hostcatalogs.NewClient(client)
|
|
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
|
|
|
hc, err := hcClient.Create(ctx, "static", proj.PublicId, hostcatalogs.WithName("my-host-catalog"))
|
|
require.NoError(err)
|
|
host, err := hostClient.Create(ctx, hc.Item.Id, hosts.WithName("my-host"), hosts.WithStaticHostAddress("example.com"))
|
|
require.NoError(err)
|
|
hs, err := hsClient.Create(ctx, hc.Item.Id, hostsets.WithName("my-host-set"))
|
|
require.NoError(err)
|
|
_, err = hsClient.AddHosts(ctx, hs.Item.Id, 1, []string{host.Item.Id})
|
|
require.NoError(err)
|
|
cs, err := credentialstores.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
|
require.NoError(err)
|
|
obj := map[string]any{
|
|
"username": "admin",
|
|
"password": "pass",
|
|
}
|
|
cred, err := credsClient.Create(ctx, credential.JsonSubtype.String(), cs.Item.Id, credentials.WithName("foo"), credentials.WithJsonCredentialObject(obj))
|
|
require.NoError(err)
|
|
targ, err := tgClient.Create(ctx, "tcp", proj.PublicId, targets.WithName("my-target"), targets.WithTcpTargetDefaultPort(22))
|
|
require.NoError(err)
|
|
_, err = tgClient.AddHostSources(ctx, targ.Item.Id, 1, []string{hs.Item.Id})
|
|
require.NoError(err)
|
|
_, err = tgClient.AddCredentialSources(ctx, targ.Item.Id, 2, targets.WithBrokeredCredentialSourceIds([]string{cred.Item.Id}))
|
|
require.NoError(err)
|
|
w := worker.NewTestWorker(t, &worker.TestWorkerOpts{
|
|
InitialUpstreams: tc.ClusterAddrs(),
|
|
Logger: logger.Named("worker"),
|
|
WorkerAuthKms: tc.Config().WorkerAuthKms,
|
|
Name: "worker",
|
|
})
|
|
helper.ExpectWorkers(t, tc, w)
|
|
|
|
// Authorize session, requires decrypting json credential
|
|
_, err = tgClient.AuthorizeSession(ctx, targ.Item.Id)
|
|
require.NoError(err)
|
|
|
|
// Create new key versions
|
|
_, err = scopesClient.RotateKeys(ctx, proj.PublicId, false)
|
|
require.NoError(err)
|
|
|
|
// Update JSON credential, will re-encrypt with new key versions
|
|
obj["password"] = "password"
|
|
_, err = credsClient.Update(ctx, cred.Item.Id, 1, credentials.WithJsonCredentialObject(obj))
|
|
require.NoError(err)
|
|
|
|
// Create new key versions again
|
|
_, err = scopesClient.RotateKeys(ctx, proj.PublicId, false)
|
|
require.NoError(err)
|
|
|
|
keys, err := scopesClient.ListKeys(ctx, proj.PublicId)
|
|
require.NoError(err)
|
|
|
|
var destroyKeyVersion *scopes.KeyVersion
|
|
|
|
for _, key := range keys.Items {
|
|
if key.Purpose == kms.KeyPurposeDatabase.String() {
|
|
// Versions are sorted in descending order, this gets the 2nd version.
|
|
// It is the keyversion that was used to re-encrypt our JSON credential.
|
|
destroyKeyVersion = key.Versions[1]
|
|
break
|
|
}
|
|
}
|
|
|
|
// Destroy the older key version
|
|
result, err := scopesClient.DestroyKeyVersion(ctx, proj.PublicId, destroyKeyVersion.Id)
|
|
require.NoError(err)
|
|
// Should start asynchronous rewrapping of the encrypted JSON credential
|
|
assert.Equal("pending", result.State)
|
|
|
|
ctx, cancel := context.WithTimeout(ctx, 3*time.Minute)
|
|
defer cancel()
|
|
for {
|
|
jobs, err := scopesClient.ListKeyVersionDestructionJobs(ctx, proj.PublicId)
|
|
require.NoError(err)
|
|
if len(jobs.Items) >= 1 {
|
|
break
|
|
}
|
|
select {
|
|
case <-ctx.Done():
|
|
t.Fatalf("Timed out waiting for key version destruction job, got jobs: %#v", jobs.Items)
|
|
break
|
|
case <-time.After(time.Millisecond * 100):
|
|
}
|
|
}
|
|
|
|
// Authorize session, requires decrypting json credential again
|
|
_, err = tgClient.AuthorizeSession(ctx, targ.Item.Id)
|
|
require.NoError(err)
|
|
}
|