Enforce auth_account to iam_user plus iam_scope constraints (#137)

This commit is contained in:
Michael Gaffney authored and GitHub committed 2020-06-21 13:16:03 -04:00
1 parent 0a0d37668d
commit 1023c90729
6 files changed
+198 -109

No files matched your search

+29 -8
View File
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/hashicorp/watchtower/internal/db"
"github.com/hashicorp/watchtower/internal/iam"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -12,12 +13,15 @@ func TestDB_AuthMethodIDTrigger(t *testing.T) {
const (
createTable = `
create table if not exists test_auth_method (
auth_method_id wt_public_id primary key
auth_method_id wt_public_id primary key,
iam_scope_id wt_public_id not null references iam_scope(public_id)
);
`
insert = `
insert into test_auth_method (auth_method_id)
values ($1);
insert into test_auth_method
(auth_method_id, iam_scope_id)
values
($1, $2);
`
addTriggers = `
create trigger
@@ -55,8 +59,10 @@ select count(*) from test_auth_method where auth_method_id = $1;
_, err = db.Exec(addTriggers)
require.NoError(err)
org, _ := iam.TestScopes(t, conn)
id := "l1Ocw0TpHn800CekIxIXlmQqRDgFDfYl"
_, err = db.Query(insert, id)
_, err = db.Query(insert, id, org.GetPublicId())
require.NoError(err)
var count int
@@ -75,12 +81,16 @@ func TestDB_AuthAccountIDTrigger(t *testing.T) {
const (
createTable = `
create table if not exists test_auth_account (
auth_account_id wt_public_id primary key
auth_account_id wt_public_id primary key,
auth_method_id wt_public_id not null,
iam_scope_id wt_public_id not null
);
`
insert = `
insert into test_auth_account (auth_account_id)
values ($1);
insert into test_auth_account
(auth_account_id, auth_method_id, iam_scope_id)
values
($1, $2, $3);
`
addTriggers = `
create trigger
@@ -94,6 +104,12 @@ select count(*) from auth_account where auth_account_id = $1;
`
testTableQuery = `
select count(*) from test_auth_account where auth_account_id = $1;
`
insertAuthMethod = `
insert into auth_method
(auth_method_id, iam_scope_id)
values
($1, $2);
`
)
@@ -118,8 +134,13 @@ select count(*) from test_auth_account where auth_account_id = $1;
_, err = db.Exec(addTriggers)
require.NoError(err)
org, _ := iam.TestScopes(t, conn)
meth_id := "31Ocw0TpHn800CekIxIXlmQqRDgFDfYl"
_, err = db.Query(insertAuthMethod, meth_id, org.GetPublicId())
require.NoError(err)
id := "l1Ocw0TpHn800CekIxIXlmQqRDgFDfYl"
_, err = db.Query(insert, id)
_, err = db.Query(insert, id, meth_id, org.GetPublicId())
require.NoError(err)
var count int
+95 -61
View File
@@ -330,66 +330,6 @@ insert on db_test_rental
commit;
`),
},
"migrations/04_auth.down.sql": {
name: "04_auth.down.sql",
bytes: []byte(`
begin;
drop function insert_auth_account_subtype;
drop function insert_auth_method_subtype;
drop table auth_account cascade;
drop table auth_method cascade;
commit;
`),
},
"migrations/04_auth.up.sql": {
name: "04_auth.up.sql",
bytes: []byte(`
begin;
-- base table for auth methods
create table auth_method (
auth_method_id wt_public_id primary key
);
-- base table for auth accounts
create table auth_account (
auth_account_id wt_public_id primary key
);
create or replace function
insert_auth_method_subtype()
returns trigger
as $$
begin
insert into auth_method (auth_method_id)
values
(new.auth_method_id);
return new;
end;
$$ language plpgsql;
create or replace function
insert_auth_account_subtype()
returns trigger
as $$
begin
insert into auth_account (auth_account_id)
values
(new.auth_account_id);
return new;
end;
$$ language plpgsql;
commit;
`),
},
"migrations/06_iam.down.sql": {
@@ -568,7 +508,12 @@ create table iam_user (
description text,
scope_id wt_public_id not null references iam_scope_organization(scope_id) on delete cascade on update cascade,
unique(name, scope_id),
disabled boolean not null default false
disabled boolean not null default false,
-- The order of columns is important for performance. See:
-- https://dba.stackexchange.com/questions/58970/enforcing-constraints-two-tables-away/58972#58972
-- https://dba.stackexchange.com/questions/27481/is-a-composite-index-also-good-for-queries-on-the-first-field
unique(scope_id, public_id)
);
create trigger
@@ -646,6 +591,95 @@ insert on iam_group
commit;
`),
},
"migrations/07_auth.down.sql": {
name: "07_auth.down.sql",
bytes: []byte(`
begin;
drop function insert_auth_account_subtype;
drop function insert_auth_method_subtype;
drop table auth_account cascade;
drop table auth_method cascade;
commit;
`),
},
"migrations/07_auth.up.sql": {
name: "07_auth.up.sql",
bytes: []byte(`
begin;
-- Design influenced by:
-- https://dba.stackexchange.com/questions/58970/enforcing-constraints-two-tables-away/58972#58972
--
-- iam_scope ←───── auth_method
-- ↑ ↑
-- iam_user ←───── auth_account
-- base table for auth methods
create table auth_method (
auth_method_id wt_public_id primary key,
iam_scope_id wt_public_id not null
references iam_scope(public_id)
on delete cascade
on update cascade,
-- The order of columns is important for performance. See:
-- https://dba.stackexchange.com/questions/58970/enforcing-constraints-two-tables-away/58972#58972
-- https://dba.stackexchange.com/questions/27481/is-a-composite-index-also-good-for-queries-on-the-first-field
unique(iam_scope_id, auth_method_id)
);
-- base table for auth accounts
create table auth_account (
auth_account_id wt_public_id primary key,
auth_method_id wt_public_id not null,
iam_scope_id wt_public_id not null,
iam_user_id wt_public_id,
foreign key (iam_scope_id, auth_method_id)
references auth_method (iam_scope_id, auth_method_id)
on delete cascade
on update cascade,
foreign key (iam_scope_id, iam_user_id)
references iam_user (scope_id, public_id)
on delete set null
on update cascade
);
create or replace function
insert_auth_method_subtype()
returns trigger
as $$
begin
insert into auth_method
(auth_method_id, iam_scope_id)
values
(new.auth_method_id, new.iam_scope_id);
return new;
end;
$$ language plpgsql;
create or replace function
insert_auth_account_subtype()
returns trigger
as $$
begin
insert into auth_account
(auth_account_id, auth_method_id, iam_scope_id)
values
(new.auth_account_id, new.auth_method_id, new.iam_scope_id);
return new;
end;
$$ language plpgsql;
commit;
`),
},
"migrations/10_static_host.down.sql": {
@@ -1,39 +0,0 @@
begin;
-- base table for auth methods
create table auth_method (
auth_method_id wt_public_id primary key
);
-- base table for auth accounts
create table auth_account (
auth_account_id wt_public_id primary key
);
create or replace function
insert_auth_method_subtype()
returns trigger
as $$
begin
insert into auth_method (auth_method_id)
values
(new.auth_method_id);
return new;
end;
$$ language plpgsql;
create or replace function
insert_auth_account_subtype()
returns trigger
as $$
begin
insert into auth_account (auth_account_id)
values
(new.auth_account_id);
return new;
end;
$$ language plpgsql;
commit;
@@ -149,7 +149,12 @@ create table iam_user (
description text,
scope_id wt_public_id not null references iam_scope_organization(scope_id) on delete cascade on update cascade,
unique(name, scope_id),
disabled boolean not null default false
disabled boolean not null default false,
-- The order of columns is important for performance. See:
-- https://dba.stackexchange.com/questions/58970/enforcing-constraints-two-tables-away/58972#58972
-- https://dba.stackexchange.com/questions/27481/is-a-composite-index-also-good-for-queries-on-the-first-field
unique(scope_id, public_id)
);
create trigger
@@ -0,0 +1,68 @@
begin;
-- Design influenced by:
-- https://dba.stackexchange.com/questions/58970/enforcing-constraints-two-tables-away/58972#58972
--
-- iam_scope ←───── auth_method
-- ↑ ↑
-- iam_user ←───── auth_account
-- base table for auth methods
create table auth_method (
auth_method_id wt_public_id primary key,
iam_scope_id wt_public_id not null
references iam_scope(public_id)
on delete cascade
on update cascade,
-- The order of columns is important for performance. See:
-- https://dba.stackexchange.com/questions/58970/enforcing-constraints-two-tables-away/58972#58972
-- https://dba.stackexchange.com/questions/27481/is-a-composite-index-also-good-for-queries-on-the-first-field
unique(iam_scope_id, auth_method_id)
);
-- base table for auth accounts
create table auth_account (
auth_account_id wt_public_id primary key,
auth_method_id wt_public_id not null,
iam_scope_id wt_public_id not null,
iam_user_id wt_public_id,
foreign key (iam_scope_id, auth_method_id)
references auth_method (iam_scope_id, auth_method_id)
on delete cascade
on update cascade,
foreign key (iam_scope_id, iam_user_id)
references iam_user (scope_id, public_id)
on delete set null
on update cascade
);
create or replace function
insert_auth_method_subtype()
returns trigger
as $$
begin
insert into auth_method
(auth_method_id, iam_scope_id)
values
(new.auth_method_id, new.iam_scope_id);
return new;
end;
$$ language plpgsql;
create or replace function
insert_auth_account_subtype()
returns trigger
as $$
begin
insert into auth_account
(auth_account_id, auth_method_id, iam_scope_id)
values
(new.auth_account_id, new.auth_method_id, new.iam_scope_id);
return new;
end;
$$ language plpgsql;
commit;