fix(db): Reorder migrations (#2688)
Migration numbers need to be consistent between version upgrades. The migrations for the key lifecycle management were merged into v0.11.1 as number 56, but are currently 58 in main. This reorders them down to 56, fixing an issue when migrating from 0.11.1 to main.
This commit is contained in:
1 parent
70a1302cd9
commit
eb113b5c9e
29 files changed
+333
-333
No files matched your search
@@ -18,7 +18,7 @@ create domain wt_scope_id as text
|
||||
check(
|
||||
length(trim(value)) > 10 or value = 'global'
|
||||
);
|
||||
-- Comment fixed in 57/01_fix_comments.up.sql
|
||||
-- Comment fixed in 58/01_fix_comments.up.sql
|
||||
comment on domain wt_scope_id is
|
||||
'"global" or random ID generated with github.com/hashicorp/go-secure-stdlib/base62';
|
||||
|
||||
@@ -26,7 +26,7 @@ create domain wt_user_id as text not null
|
||||
check(
|
||||
length(trim(value)) > 10 or value = 'u_anon' or value = 'u_auth' or value = 'u_recovery'
|
||||
);
|
||||
-- Comment fixed in 57/01_fix_comments.up.sql
|
||||
-- Comment fixed in 58/01_fix_comments.up.sql
|
||||
comment on domain wt_scope_id is
|
||||
'"u_anon", "u_auth", or random ID generated with github.com/hashicorp/go-secure-stdlib/base62';
|
||||
|
||||
@@ -34,7 +34,7 @@ create domain wt_role_id as text not null
|
||||
check(
|
||||
length(trim(value)) > 10
|
||||
);
|
||||
-- Comment fixed in 57/01_fix_comments.up.sql
|
||||
-- Comment fixed in 58/01_fix_comments.up.sql
|
||||
comment on domain wt_scope_id is
|
||||
'Random ID generated with github.com/hashicorp/go-secure-stdlib/base62';
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ begin;
|
||||
comment on function update_last_access_time() is
|
||||
'function used in before update triggers to properly set last_access_time columns';
|
||||
|
||||
-- this trigger is deleted in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is deleted in 56/05_mutable_ciphertext_columns.up.sql
|
||||
create or replace function immutable_auth_token_columns() returns trigger
|
||||
as $$
|
||||
begin
|
||||
|
||||
@@ -190,7 +190,7 @@ begin;
|
||||
create trigger default_create_time_column before insert on credential_vault_token
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
-- this trigger is updated in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is updated in 56/05_mutable_ciphertext_columns.up.sql
|
||||
create trigger immutable_columns before update on credential_vault_token
|
||||
for each row execute procedure immutable_columns('token_hmac', 'token', 'store_id','create_time');
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ begin;
|
||||
|
||||
-- The 'comment on function' statements below are not for the functions in the
|
||||
-- file. They incorrectly override the comments for functions declared in
|
||||
-- 7/01_functions.up.sql. Fixes are contained in 57/01_fix_comments.up.sql.
|
||||
-- 7/01_functions.up.sql. Fixes are contained in 58/01_fix_comments.up.sql.
|
||||
|
||||
create function wt_sub_seconds(sec integer, ts timestamp with time zone) returns timestamp with time zone
|
||||
as $$
|
||||
|
||||
@@ -158,7 +158,7 @@ create table auth_oidc_account (
|
||||
constraint auth_oidc_account_auth_method_id_public_id_uq
|
||||
unique(auth_method_id, public_id)
|
||||
);
|
||||
-- Comment fixed in 57/01_fix_comments.up.sql
|
||||
-- Comment fixed in 58/01_fix_comments.up.sql
|
||||
comment on table auth_oidc_method is
|
||||
'auth_oidc_account entries are subtypes of auth_account and represent an oidc account.';
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ begin;
|
||||
'session_credential is a table where each row contains a credential to be used by '
|
||||
'by a worker when a connection is established for the session_id.';
|
||||
|
||||
-- this trigger is updated in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is updated in 56/05_mutable_ciphertext_columns.up.sql
|
||||
create trigger immutable_columns before update on session_credential
|
||||
for each row execute procedure immutable_columns('session_id', 'credential', 'key_id');
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ create table kms_data_key_version (
|
||||
constraint kms_data_key_version_data_key_id_version_uq
|
||||
unique(data_key_id, version)
|
||||
);
|
||||
-- Comment fixed in 57/01_fix_comments.up.sql
|
||||
-- Comment fixed in 58/01_fix_comments.up.sql
|
||||
comment on table kms_data_key is
|
||||
'kms_data_key_version contains versions of a kms_data_key (dek aka data keys)';
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ create table worker_auth_ca_certificate(
|
||||
comment on table worker_auth_ca_certificate is
|
||||
'worker_auth_ca_certificate is a table where each row represents a root certificate for used for worker authentication.';
|
||||
|
||||
-- this trigger is updated in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is updated in 56/05_mutable_ciphertext_columns.up.sql
|
||||
create trigger immutable_columns before update on worker_auth_ca_certificate
|
||||
for each row execute procedure immutable_columns('serial_number', 'certificate', 'not_valid_before', 'not_valid_after', 'public_key', 'private_key', 'key_id', 'state', 'issuing_ca');
|
||||
|
||||
@@ -102,7 +102,7 @@ create table worker_auth_authorized(
|
||||
comment on table worker_auth_authorized is
|
||||
'worker_auth_authorized is a table where each row represents key and cert data associated with an authorized worker.';
|
||||
|
||||
-- this trigger is updated in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is updated in 56/05_mutable_ciphertext_columns.up.sql
|
||||
create trigger immutable_columns before update on worker_auth_authorized
|
||||
for each row execute procedure immutable_columns('worker_key_identifier', 'worker_id', 'worker_signing_pub_key', 'worker_encryption_pub_key', 'controller_encryption_priv_key', 'key_id', 'nonce');
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ begin;
|
||||
add constraint session_credential_session_id_credential_sha256_uq
|
||||
unique(session_id, credential_sha256);
|
||||
|
||||
-- this trigger is updated in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is updated in 56/05_mutable_ciphertext_columns.up.sql
|
||||
drop trigger immutable_columns on session_credential;
|
||||
create trigger immutable_columns before update on session_credential
|
||||
for each row execute procedure immutable_columns('session_id', 'credential', 'key_id', 'credential_sha256');
|
||||
|
||||
@@ -212,7 +212,7 @@ begin;
|
||||
'No encrypted data is returned. This view can be used to retrieve data which will be returned external to boundary.';
|
||||
|
||||
-- Replaces view from 41/01_worker_filter_vault_cred_store.up.sql
|
||||
-- Recreated in 58/02_add_data_key_foreign_key_references.up.sql
|
||||
-- Recreated in 56/02_add_data_key_foreign_key_references.up.sql
|
||||
create view credential_vault_credential_private as
|
||||
select credential.public_id as public_id,
|
||||
credential.library_id as library_id,
|
||||
|
||||
@@ -71,7 +71,7 @@ begin;
|
||||
|
||||
-- update views
|
||||
drop view host_plugin_catalog_with_secret;
|
||||
-- Recreated in 58/02_add_data_key_foreign_key_references.up.sql
|
||||
-- Recreated in 56/02_add_data_key_foreign_key_references.up.sql
|
||||
create view host_plugin_catalog_with_secret as
|
||||
select
|
||||
hc.public_id,
|
||||
|
||||
@@ -12,7 +12,7 @@ begin;
|
||||
;
|
||||
|
||||
-- Replaces trigger from 01/50_session.up.sql
|
||||
-- Replaced in 58/02_add_data_key_foreign_key_references
|
||||
-- Replaced in 56/02_add_data_key_foreign_key_references
|
||||
create or replace function cancel_session_with_null_fk() returns trigger
|
||||
as $$
|
||||
begin
|
||||
@@ -60,7 +60,7 @@ begin;
|
||||
$$ language plpgsql;
|
||||
|
||||
-- Replaces view from 34/04_views.up.sql
|
||||
-- Replaced in 58/06_add_session_private_key_column
|
||||
-- Replaced in 56/06_add_session_private_key_column
|
||||
drop view session_list;
|
||||
create view session_list as
|
||||
select
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ create table worker_auth_server_led_activation_token(
|
||||
comment on table worker_auth_server_led_activation_token is
|
||||
'worker_auth_server_led_activation_token is a table where each row represents an activation token for a worker. Only one activation token is allowed per worker.';
|
||||
|
||||
-- this trigger is updated in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is updated in 56/05_mutable_ciphertext_columns.up.sql
|
||||
create trigger immutable_columns before update on worker_auth_server_led_activation_token
|
||||
for each row execute procedure immutable_columns('worker_id', 'token_id', 'creation_time_encrypted');
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ begin;
|
||||
drop view credential_vault_library_private;
|
||||
drop view credential_vault_store_private;
|
||||
|
||||
-- Recreated in 58/02_add_data_key_foreign_key_references.up.sql
|
||||
-- Recreated in 56/02_add_data_key_foreign_key_references.up.sql
|
||||
create view credential_vault_token_renewal_revocation as
|
||||
with
|
||||
tokens as (
|
||||
@@ -78,7 +78,7 @@ begin;
|
||||
'If the Vault token has expired this view will return an empty token_hmac and a token_status of ''expired'' '
|
||||
'No encrypted data is returned. This view can be used to retrieve data which will be returned external to boundary.';
|
||||
|
||||
-- Recreated in 58/02_add_data_key_foreign_key_references.up.sql
|
||||
-- Recreated in 56/02_add_data_key_foreign_key_references.up.sql
|
||||
create view credential_vault_store_client as
|
||||
select store.public_id as public_id,
|
||||
store.project_id as project_id,
|
||||
@@ -107,7 +107,7 @@ begin;
|
||||
'The view returns the current token for the store, if the Vault token has expired this view will return an empty token_hmac and a token_status of ''expired'' '
|
||||
'Each row may contain encrypted data. This view should not be used to retrieve data which will be returned external to boundary.';
|
||||
|
||||
-- Recreated in 58/02_add_data_key_foreign_key_references.up.sql
|
||||
-- Recreated in 56/02_add_data_key_foreign_key_references.up.sql
|
||||
create view credential_vault_library_issue_credentials as
|
||||
with
|
||||
password_override (library_id, username_attribute, password_attribute) as (
|
||||
|
||||
@@ -93,7 +93,7 @@ alter table worker_auth_authorized
|
||||
;
|
||||
|
||||
drop trigger immutable_columns on worker_auth_authorized;
|
||||
-- this trigger is updated in 58/05_mutable_ciphertext_columns.up.sql
|
||||
-- this trigger is updated in 56/05_mutable_ciphertext_columns.up.sql
|
||||
create trigger immutable_columns before update on worker_auth_authorized
|
||||
for each row execute function immutable_columns('worker_key_identifier', 'worker_id', 'worker_signing_pub_key',
|
||||
'worker_encryption_pub_key', 'controller_encryption_priv_key', 'key_id', 'nonce', 'create_time');
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-2
@@ -85,7 +85,7 @@ select public_id,
|
||||
'tcp' as type
|
||||
from target_tcp;
|
||||
|
||||
-- Replaces view from 58/06_add_session_private_key_column.up.sql
|
||||
-- Replaces view from 56/06_add_session_private_key_column.up.sql
|
||||
drop view session_list;
|
||||
create view session_list as
|
||||
select
|
||||
@@ -134,4 +134,4 @@ create trigger immutable_columns before update on session
|
||||
for each row execute procedure immutable_columns('public_id', 'certificate', 'expiration_time', 'connection_limit',
|
||||
'create_time', 'endpoint', 'worker_filter', 'egress_worker_filter', 'ingress_worker_filter');
|
||||
|
||||
commit;
|
||||
commit;
|
||||
@@ -42,7 +42,7 @@ drop view oidc_auth_method_with_value_obj;
|
||||
-- value is part of the primary key and unique. This view will make things like
|
||||
-- recursive listing of oidc auth methods fairly straightforward to implement
|
||||
-- for the oidc repo. The view also includes an is_primary_auth_method bool
|
||||
-- Recreated in 58/02_add_data_key_foreign_key_references.up.sql
|
||||
-- Recreated in 56/02_add_data_key_foreign_key_references.up.sql
|
||||
create view oidc_auth_method_with_value_obj as
|
||||
select
|
||||
case when s.primary_auth_method_id is not null then
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
begin;
|
||||
|
||||
-- Comments for the functions below were incorrectly overridden in
|
||||
-- 12/01_timestamp_sub_funcs.up.sql but fixed in 57/01_fix_comments.up.sql.
|
||||
-- 12/01_timestamp_sub_funcs.up.sql but fixed in 58/01_fix_comments.up.sql.
|
||||
|
||||
create function wt_add_seconds(sec integer, ts timestamp with time zone) returns timestamp with time zone
|
||||
as $$
|
||||
|
||||
@@ -2,26 +2,23 @@ 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/authtoken"
|
||||
"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) {
|
||||
func TestMigrations_NewForeignKeys(t *testing.T) {
|
||||
const (
|
||||
priorMigration = 55001
|
||||
currentMigration = 56001
|
||||
priorMigration = 56001
|
||||
currentMigration = 56002
|
||||
)
|
||||
|
||||
t.Parallel()
|
||||
@@ -65,182 +62,19 @@ func TestMigrations_DeleteOrphanedAccounts(t *testing.T) {
|
||||
conn, err := db.Open(ctx, dbType, u)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create project
|
||||
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))
|
||||
err = kmsCache.CreateKeys(ctx, scope.Global.String())
|
||||
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.PublicId = "u_1234567890"
|
||||
num, err := rw.Exec(ctx, `
|
||||
insert into iam_user
|
||||
(public_id, scope_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{usr.PublicId, scope.Global.String()})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
// Create a password account
|
||||
pwam := password.TestAuthMethod(t, conn, "global")
|
||||
password.TestAccount(t, conn, pwam.PublicId, "user", password.WithPassword("password"))
|
||||
|
||||
// Create the accounts we will delete and assert their behavior
|
||||
|
||||
pwAm1, err := password.NewAuthMethod(scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
pwAm1.PublicId = "ampw_1234567890"
|
||||
_, err = rw.DoTx(ctx, 0, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
|
||||
_, err := w.Exec(ctx, `
|
||||
insert into auth_password_argon2_conf
|
||||
(private_id, password_method_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{"arg2conf_1234567890", pwAm1.PublicId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Exec(ctx, `
|
||||
insert into auth_password_method
|
||||
(public_id, password_conf_id, scope_id)
|
||||
values
|
||||
(?, ?, ?)
|
||||
`, []any{pwAm1.PublicId, "arg2conf_1234567890", pwAm1.ScopeId})
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pwAcct1, err := password.NewAccount(pwAm1.GetPublicId(), password.WithLoginName("account1"), password.WithPassword("password"))
|
||||
require.NoError(t, err)
|
||||
pwAcct1.PublicId = "acctpw_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_password_account
|
||||
(public_id, auth_method_id, scope_id, login_name)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{pwAcct1.PublicId, pwAm1.PublicId, pwAm1.ScopeId, pwAcct1.LoginName})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
pwAm2, err := password.NewAuthMethod(scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
pwAm2.PublicId = "ampw_0123456789"
|
||||
_, err = rw.DoTx(ctx, 0, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
|
||||
_, err := w.Exec(ctx, `
|
||||
insert into auth_password_argon2_conf
|
||||
(private_id, password_method_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{"arg2conf_0123456789", pwAm2.PublicId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Exec(ctx, `
|
||||
insert into auth_password_method
|
||||
(public_id, password_conf_id, scope_id)
|
||||
values
|
||||
(?, ?, ?)
|
||||
`, []any{pwAm2.PublicId, "arg2conf_0123456789", pwAm2.ScopeId})
|
||||
return err
|
||||
})
|
||||
pwAcct2, err := password.NewAccount(pwAm2.GetPublicId(), password.WithLoginName("account2"), password.WithPassword("password"))
|
||||
require.NoError(t, err)
|
||||
pwAcct2.PublicId = "acctpw_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_password_account
|
||||
(public_id, auth_method_id, scope_id, login_name)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{pwAcct2.PublicId, pwAm2.PublicId, pwAm2.ScopeId, pwAcct2.LoginName})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
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]))
|
||||
oidcAm1.PublicId = "amoidc_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_method
|
||||
(public_id, scope_id, state, key_id)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{oidcAm1.PublicId, oidcAm1.ScopeId, oidcAm1.OperationalState, oidcAm1.KeyId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
oidcAcct1, err := oidc.NewAccount(ctx, oidcAm1.GetPublicId(), "oidcAcct1")
|
||||
require.NoError(t, err)
|
||||
oidcAcct1.PublicId = "acctoidc_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_account
|
||||
(public_id, auth_method_id, scope_id, issuer, subject)
|
||||
values
|
||||
(?, ?, ?, ?, ?)
|
||||
`, []any{oidcAcct1.PublicId, oidcAm1.PublicId, oidcAm1.ScopeId, oidcAm1.Issuer, oidcAcct1.Subject})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
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]))
|
||||
oidcAm2.PublicId = "amoidc_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_method
|
||||
(public_id, scope_id, state, key_id)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{oidcAm2.PublicId, oidcAm2.ScopeId, oidcAm2.OperationalState, oidcAm2.KeyId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
oidcAcct2, err := oidc.NewAccount(ctx, oidcAm2.GetPublicId(), "oidcAcct2")
|
||||
require.NoError(t, err)
|
||||
oidcAcct2.PublicId = "acctoidc_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_account
|
||||
(public_id, auth_method_id, scope_id, issuer, subject)
|
||||
values
|
||||
(?, ?, ?, ?, ?)
|
||||
`, []any{oidcAcct2.PublicId, oidcAm2.PublicId, oidcAm2.ScopeId, oidcAm2.Issuer, oidcAcct2.Subject})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
update auth_account set
|
||||
iam_user_id=?
|
||||
where
|
||||
public_id in (?, ?, ?, ?)
|
||||
`, []any{
|
||||
usr.PublicId,
|
||||
pwAcct1.PublicId, pwAcct2.PublicId, oidcAcct1.PublicId, oidcAcct2.PublicId,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4, num)
|
||||
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)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_password_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{pwAcct1.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_oidc_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{oidcAcct1.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// 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)
|
||||
// Create an auth token
|
||||
tok := authtoken.TestAuthToken(t, conn, kmsCache, "global")
|
||||
_ = tok
|
||||
|
||||
// now we're ready for the migration we want to test.
|
||||
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
|
||||
@@ -265,31 +99,5 @@ where
|
||||
}
|
||||
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)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_password_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{pwAcct2.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{oidcAcct2.GetPublicId()}, accts)
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_oidc_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{oidcAcct2.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// 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)
|
||||
// As long as there were no errors, the migration succeeded.
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
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 = 56001
|
||||
currentMigration = 57001
|
||||
)
|
||||
|
||||
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.PublicId = "u_1234567890"
|
||||
num, err := rw.Exec(ctx, `
|
||||
insert into iam_user
|
||||
(public_id, scope_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{usr.PublicId, scope.Global.String()})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// Create the accounts we will delete and assert their behavior
|
||||
|
||||
pwAm1, err := password.NewAuthMethod(scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
pwAm1.PublicId = "ampw_1234567890"
|
||||
_, err = rw.DoTx(ctx, 0, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
|
||||
_, err := w.Exec(ctx, `
|
||||
insert into auth_password_argon2_conf
|
||||
(private_id, password_method_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{"arg2conf_1234567890", pwAm1.PublicId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Exec(ctx, `
|
||||
insert into auth_password_method
|
||||
(public_id, password_conf_id, scope_id)
|
||||
values
|
||||
(?, ?, ?)
|
||||
`, []any{pwAm1.PublicId, "arg2conf_1234567890", pwAm1.ScopeId})
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pwAcct1, err := password.NewAccount(pwAm1.GetPublicId(), password.WithLoginName("account1"), password.WithPassword("password"))
|
||||
require.NoError(t, err)
|
||||
pwAcct1.PublicId = "acctpw_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_password_account
|
||||
(public_id, auth_method_id, scope_id, login_name)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{pwAcct1.PublicId, pwAm1.PublicId, pwAm1.ScopeId, pwAcct1.LoginName})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
pwAm2, err := password.NewAuthMethod(scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
pwAm2.PublicId = "ampw_0123456789"
|
||||
_, err = rw.DoTx(ctx, 0, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
|
||||
_, err := w.Exec(ctx, `
|
||||
insert into auth_password_argon2_conf
|
||||
(private_id, password_method_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{"arg2conf_0123456789", pwAm2.PublicId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Exec(ctx, `
|
||||
insert into auth_password_method
|
||||
(public_id, password_conf_id, scope_id)
|
||||
values
|
||||
(?, ?, ?)
|
||||
`, []any{pwAm2.PublicId, "arg2conf_0123456789", pwAm2.ScopeId})
|
||||
return err
|
||||
})
|
||||
pwAcct2, err := password.NewAccount(pwAm2.GetPublicId(), password.WithLoginName("account2"), password.WithPassword("password"))
|
||||
require.NoError(t, err)
|
||||
pwAcct2.PublicId = "acctpw_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_password_account
|
||||
(public_id, auth_method_id, scope_id, login_name)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{pwAcct2.PublicId, pwAm2.PublicId, pwAm2.ScopeId, pwAcct2.LoginName})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
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]))
|
||||
oidcAm1.PublicId = "amoidc_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_method
|
||||
(public_id, scope_id, state, key_id)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{oidcAm1.PublicId, oidcAm1.ScopeId, oidcAm1.OperationalState, oidcAm1.KeyId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
oidcAcct1, err := oidc.NewAccount(ctx, oidcAm1.GetPublicId(), "oidcAcct1")
|
||||
require.NoError(t, err)
|
||||
oidcAcct1.PublicId = "acctoidc_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_account
|
||||
(public_id, auth_method_id, scope_id, issuer, subject)
|
||||
values
|
||||
(?, ?, ?, ?, ?)
|
||||
`, []any{oidcAcct1.PublicId, oidcAm1.PublicId, oidcAm1.ScopeId, oidcAm1.Issuer, oidcAcct1.Subject})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
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]))
|
||||
oidcAm2.PublicId = "amoidc_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_method
|
||||
(public_id, scope_id, state, key_id)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{oidcAm2.PublicId, oidcAm2.ScopeId, oidcAm2.OperationalState, oidcAm2.KeyId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
oidcAcct2, err := oidc.NewAccount(ctx, oidcAm2.GetPublicId(), "oidcAcct2")
|
||||
require.NoError(t, err)
|
||||
oidcAcct2.PublicId = "acctoidc_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_account
|
||||
(public_id, auth_method_id, scope_id, issuer, subject)
|
||||
values
|
||||
(?, ?, ?, ?, ?)
|
||||
`, []any{oidcAcct2.PublicId, oidcAm2.PublicId, oidcAm2.ScopeId, oidcAm2.Issuer, oidcAcct2.Subject})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
update auth_account set
|
||||
iam_user_id=?
|
||||
where
|
||||
public_id in (?, ?, ?, ?)
|
||||
`, []any{
|
||||
usr.PublicId,
|
||||
pwAcct1.PublicId, pwAcct2.PublicId, oidcAcct1.PublicId, oidcAcct2.PublicId,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4, num)
|
||||
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)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_password_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{pwAcct1.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_oidc_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{oidcAcct1.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// 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)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_password_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{pwAcct2.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{oidcAcct2.GetPublicId()}, accts)
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_oidc_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{oidcAcct2.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// 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)
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package oss_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
"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/kms"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/testing/dbtest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMigrations_NewForeignKeys(t *testing.T) {
|
||||
const (
|
||||
priorMigration = 58001
|
||||
currentMigration = 58002
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
// Create project
|
||||
wrapper := db.TestWrapper(t)
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
err = kmsCache.CreateKeys(ctx, scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a password account
|
||||
pwam := password.TestAuthMethod(t, conn, "global")
|
||||
password.TestAccount(t, conn, pwam.PublicId, "user", password.WithPassword("password"))
|
||||
|
||||
// Create an auth token
|
||||
tok := authtoken.TestAuthToken(t, conn, kmsCache, "global")
|
||||
_ = tok
|
||||
|
||||
// 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)
|
||||
|
||||
// As long as there were no errors, the migration succeeded.
|
||||
}
|
||||
Reference in new issue
Block a user