Files
threshold/internal/db/schema/migrations/oss/postgres_56_01_test.go
T

186 lines
6.8 KiB
Go

package oss_test
import (
"context"
"crypto/rand"
"testing"
"github.com/hashicorp/boundary/internal/auth/oidc"
"github.com/hashicorp/boundary/internal/auth/password"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/db/schema"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/types/scope"
"github.com/hashicorp/boundary/testing/dbtest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMigrations_DeleteOrphanedAccounts(t *testing.T) {
const (
priorMigration = 55001
currentMigration = 56001
)
t.Parallel()
ctx := context.Background()
dialect := dbtest.Postgres
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
d, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
// migration to the prior migration (before the one we want to test)
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
))
require.NoError(t, err)
_, err = m.ApplyMigrations(ctx)
require.NoError(t, err)
state, err := m.CurrentState(ctx)
require.NoError(t, err)
want := &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: priorMigration,
DatabaseSchemaVersion: priorMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(t, want, state)
// Get a connection
dbType, err := db.StringToDbType(dialect)
require.NoError(t, err)
conn, err := db.Open(ctx, dbType, u)
require.NoError(t, err)
wrapper := db.TestWrapper(t)
rw := db.New(conn)
kmsCache := kms.TestKms(t, conn, wrapper)
err = kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader))
require.NoError(t, err)
// Create the user we will associate accounts with
iamRepo := iam.TestRepo(t, conn, wrapper)
usr, err := iam.NewUser(scope.Global.String())
require.NoError(t, err)
usr, err = iamRepo.CreateUser(ctx, usr)
require.NoError(t, err)
// Create the accounts we will delete and assert their behavior
pwRepo, err := password.NewRepository(rw, rw, kmsCache)
require.NoError(t, err)
pwAm1, err := password.NewAuthMethod(scope.Global.String())
require.NoError(t, err)
pwAm1, err = pwRepo.CreateAuthMethod(ctx, pwAm1)
require.NoError(t, err)
pwAcct1, err := password.NewAccount(pwAm1.GetPublicId(), password.WithLoginName("account1"), password.WithPassword("password"))
require.NoError(t, err)
pwAcct1, err = pwRepo.CreateAccount(ctx, scope.Global.String(), pwAcct1)
require.NoError(t, err)
pwAm2, err := password.NewAuthMethod(scope.Global.String())
require.NoError(t, err)
pwAm2, err = pwRepo.CreateAuthMethod(ctx, pwAm2)
require.NoError(t, err)
pwAcct2, err := password.NewAccount(pwAm2.GetPublicId(), password.WithLoginName("account2"), password.WithPassword("password"))
require.NoError(t, err)
pwAcct2, err = pwRepo.CreateAccount(ctx, scope.Global.String(), pwAcct2)
require.NoError(t, err)
oidcRepo, err := oidc.NewRepository(ctx, rw, rw, kmsCache)
require.NoError(t, err)
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), scope.Global.String(), kms.KeyPurposeDatabase)
oidcAm1 := oidc.TestAuthMethod(t, conn, databaseWrapper, scope.Global.String(), oidc.InactiveState, "alice_rp1",
"my-dogs-name", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://alice1.com")[0]), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://api1.com")[0]))
oidcAcct1, err := oidc.NewAccount(ctx, oidcAm1.GetPublicId(), "oidcAcct1")
require.NoError(t, err)
oidcAcct1, err = oidcRepo.CreateAccount(ctx, scope.Global.String(), oidcAcct1)
require.NoError(t, err)
oidcAm2 := oidc.TestAuthMethod(t, conn, databaseWrapper, scope.Global.String(), oidc.InactiveState, "alice_rp2",
"my-dogs-name", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://alice2.com")[0]), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://api2.com")[0]))
oidcAcct2, err := oidc.NewAccount(ctx, oidcAm2.GetPublicId(), "oidcAcct2")
require.NoError(t, err)
oidcAcct2, err = oidcRepo.CreateAccount(ctx, scope.Global.String(), oidcAcct2)
require.NoError(t, err)
_, err = iamRepo.AddUserAccounts(ctx, usr.GetPublicId(), usr.GetVersion(),
[]string{
pwAcct1.GetPublicId(), pwAcct2.GetPublicId(),
oidcAcct1.GetPublicId(), oidcAcct2.GetPublicId(),
})
require.NoError(t, err)
usr, accts, err := iamRepo.LookupUser(ctx, usr.GetPublicId())
require.NoError(t, err)
assert.ElementsMatch(t, []string{
pwAcct1.GetPublicId(), pwAcct2.GetPublicId(),
oidcAcct1.GetPublicId(), oidcAcct2.GetPublicId(),
}, accts)
_, err = pwRepo.DeleteAccount(ctx, scope.Global.String(), pwAcct1.GetPublicId())
require.NoError(t, err)
_, err = oidcRepo.DeleteAccount(ctx, scope.Global.String(), oidcAcct1.GetPublicId())
require.NoError(t, err)
// pwAcct1 is still listed as an account for this user! oh no!
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
require.NoError(t, err)
assert.ElementsMatch(t, []string{
pwAcct1.GetPublicId(), pwAcct2.GetPublicId(),
oidcAcct1.GetPublicId(), oidcAcct2.GetPublicId(),
}, accts)
// now we're ready for the migration we want to test.
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
))
require.NoError(t, err)
_, err = m.ApplyMigrations(ctx)
require.NoError(t, err)
state, err = m.CurrentState(ctx)
require.NoError(t, err)
want = &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: currentMigration,
DatabaseSchemaVersion: currentMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(t, want, state)
// pwAcct1 is no longer listed as an account for this user. Phew!
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
require.NoError(t, err)
assert.ElementsMatch(t, []string{pwAcct2.GetPublicId(), oidcAcct2.GetPublicId()}, accts)
_, err = pwRepo.DeleteAccount(ctx, scope.Global.String(), pwAcct2.GetPublicId())
require.NoError(t, err)
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
require.NoError(t, err)
assert.ElementsMatch(t, []string{oidcAcct2.GetPublicId()}, accts)
_, err = oidcRepo.DeleteAccount(ctx, scope.Global.String(), oidcAcct2.GetPublicId())
require.NoError(t, err)
// Deleting the account now removes the association with the user
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
require.NoError(t, err)
assert.Empty(t, accts)
}