oidc schema changes. (#874)

pull/891/head
Jim 5 years ago committed by GitHub
parent f7aad2e0c8
commit 1c744c28ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -669,3 +669,234 @@ set id = null;
assert.Equal(orig.CreateTime, found.CreateTime)
})
}
func TestDomain_wt_url(t *testing.T) {
const (
createTable = `
create table if not exists test_table_wt_url (
id bigint generated always as identity primary key,
url wt_url
);
`
insert = `
insert into test_table_wt_url(url)
values ($1)
returning id;
`
)
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
if _, err := db.Exec(createTable); err != nil {
t.Fatalf("query: \n%s\n error: %s", createTable, err)
}
failTests := []struct {
value string
exception string
}{
{"http://", ""},
{"htt://", "wt_url_invalid_protocol"},
{"ht", "wt_url_invalid_protocol"},
{"http://" + strings.Repeat("a", 4001), "wt_url_too_long"},
}
for _, tt := range failTests {
t.Run(tt.value, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
t.Logf("insert value: %q", tt.value)
_, err := db.Query(insert, tt.value)
if tt.exception != "" {
require.Error(err)
assert.Containsf(err.Error(), tt.exception, "missing %s from err: %s", tt.exception, err.Error())
return
}
require.NoError(err)
})
}
}
func TestDomain_wt_email(t *testing.T) {
const (
createTable = `
create table if not exists test_table_wt_email (
id bigint generated always as identity primary key,
email wt_email
);
`
insert = `
insert into test_table_wt_email(email)
values ($1)
returning id;
`
)
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
if _, err := db.Exec(createTable); err != nil {
t.Fatalf("query: \n%s\n error: %s", createTable, err)
}
failTests := []struct {
value string
exception string
}{
{" ", "wt_email_too_short"},
{"1" + strings.Repeat("1", 320), "wt_email_too_long"},
{"alice@bob.com", ""},
}
for _, tt := range failTests {
t.Run(tt.value, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
t.Logf("insert value: %q", tt.value)
_, err := db.Query(insert, tt.value)
if tt.exception != "" {
require.Error(err)
assert.Containsf(err.Error(), tt.exception, "missing %s from err: %s", tt.exception, err.Error())
return
}
require.NoError(err)
})
}
}
func TestDomain_wt_full_name(t *testing.T) {
const (
createTable = `
create table if not exists test_table_wt_full_name (
id bigint generated always as identity primary key,
full_name wt_full_name
);
`
insert = `
insert into test_table_wt_full_name(full_name)
values ($1)
returning id;
`
)
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
if _, err := db.Exec(createTable); err != nil {
t.Fatalf("query: \n%s\n error: %s", createTable, err)
}
failTests := []struct {
value string
exception string
}{
{" ", "wt_full_name_too_short"},
{"1" + strings.Repeat("1", 512), "wt_full_name_too_long"},
{"alice and bob's dinner", ""},
}
for _, tt := range failTests {
t.Run(tt.value, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
t.Logf("insert value: %q", tt.value)
_, err := db.Query(insert, tt.value)
if tt.exception != "" {
require.Error(err)
assert.Containsf(err.Error(), tt.exception, "missing %s from err: %s", tt.exception, err.Error())
return
}
require.NoError(err)
})
}
}
func TestDomain_wt_name(t *testing.T) {
const (
createTable = `
create table if not exists test_table_wt_name (
id bigint generated always as identity primary key,
name wt_name
);
`
insert = `
insert into test_table_wt_name(name)
values ($1)
returning id;
`
)
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
if _, err := db.Exec(createTable); err != nil {
t.Fatalf("query: \n%s\n error: %s", createTable, err)
}
failTests := []struct {
value string
exception string
}{
{" ", "wt_name_too_short"},
{"1" + strings.Repeat("1", 512), "wt_name_too_long"},
{"alice and bob's dinner", ""},
}
for _, tt := range failTests {
t.Run(tt.value, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
t.Logf("insert value: %q", tt.value)
_, err := db.Query(insert, tt.value)
if tt.exception != "" {
require.Error(err)
assert.Containsf(err.Error(), tt.exception, "missing %s from err: %s", tt.exception, err.Error())
return
}
require.NoError(err)
})
}
}
func TestDomain_wt_description(t *testing.T) {
const (
createTable = `
create table if not exists test_table_wt_description (
id bigint generated always as identity primary key,
description wt_description
);
`
insert = `
insert into test_table_wt_description(description)
values ($1)
returning id;
`
)
conn, _ := TestSetup(t, "postgres")
db := conn.DB()
if _, err := db.Exec(createTable); err != nil {
t.Fatalf("query: \n%s\n error: %s", createTable, err)
}
failTests := []struct {
value string
exception string
}{
{" ", "wt_description_too_short"},
{"1" + strings.Repeat("1", 1024), "wt_description_too_long"},
{"alice and bob's dinner has delicious pancakes", ""},
}
for _, tt := range failTests {
t.Run(tt.value, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
t.Logf("insert value: %q", tt.value)
_, err := db.Query(insert, tt.value)
if tt.exception != "" {
require.Error(err)
assert.Containsf(err.Error(), tt.exception, "missing %s from err: %s", tt.exception, err.Error())
return
}
require.NoError(err)
})
}
}

@ -0,0 +1,58 @@
begin;
-- wt_email defines a type for email which must be less than 320 chars and only
-- contain lower case values. The type is defined to allow nulls and not be
-- unique, which can be overriden as needed when used in tables.
create domain wt_email as text
constraint wt_email_too_short
check (length(trim(value)) > 0)
constraint wt_email_too_long
check (length(trim(value)) < 320);
comment on domain wt_email is
'standard column for email addresses';
-- wt_full_name defines a type for a person's full name which must be less than
-- 512 chars. The type is defined to allow nulls and not be unique, which can
-- be overriden as needed when used in tables.
create domain wt_full_name text
constraint wt_full_name_too_short
check (length(trim(value)) > 0)
constraint wt_full_name_too_long
check(length(trim(value)) <= 512); -- gotta pick some upper limit.
comment on domain wt_full_name is
'standard column for the full name of a person';
-- wt_url defines a type for URLs which must be longer that 3 chars and
-- less than 4k chars. It's defined to allow nulls, which can be overriden as
-- needed when used in tables.
create domain wt_url as text
constraint wt_url_too_short
check (length(trim(value)) > 3)
constraint wt_url_too_long
check (length(trim(value)) < 4000)
constraint wt_url_invalid_protocol
check (value ~ 'https?:\/\/*');
comment on domain wt_url is
'standard column for URLs';
-- wt_name defines a type for resource names that must be less than 128 chars.
-- It's defined to allow nulls.
create domain wt_name as text
constraint wt_name_too_short
check (length(trim(value)) > 0)
constraint wt_name_too_long
check (length(trim(value)) < 128);
comment on domain wt_name is
'standard column for resource names';
-- wt_description defines a type for resource descriptionss that must be less
-- than 1024 chars. It's defined to allow nulls.
create domain wt_description as text
constraint wt_description_too_short
check (length(trim(value)) > 0)
constraint wt_description_too_long
check (length(trim(value)) < 1024);
comment on domain wt_description is
'standard column for resource descriptions';
commit;

@ -62,4 +62,4 @@ create trigger
before insert on kms_oidc_key_version
for each row execute procedure kms_version_column('oidc_key_id');
commit;
commit;

@ -0,0 +1,71 @@
begin;
-- auth_oidc_method_state_enum entries define the possible oidc auth method
-- states.
create table auth_oidc_method_state_enm (
name text primary key
constraint only_predefined_oidc_method_states_allowed
check (
name in ('inactive', 'active-private', 'active-public', 'stopping')
)
);
-- populate the values of auth_oidc_method_state_enm
insert into auth_oidc_method_state_enm(name)
values
('inactive'),
('active-private'),
('active-public'),
('stopping');
-- define the immutable fields for auth_oidc_method_state_enm (all of them)
create trigger
immutable_columns
before
update on auth_oidc_method_state_enm
for each row execute procedure immutable_columns('name');
-- auth_oidc_signing_alg entries define the supported oidc auth method
-- signing algorithms.
create table auth_oidc_signing_alg_enm (
name text primary key
constraint only_predefined_auth_oidc_signing_algs_allowed
check (
name in (
'RS256',
'RS384',
'RS512',
'ES256',
'ES384',
'ES512',
'PS256',
'PS384',
'PS512',
'EdDSA')
)
);
-- populate the values of auth_oidc_signing_alg
insert into auth_oidc_signing_alg_enm (name)
values
('RS256'),
('RS384'),
('RS512'),
('ES256'),
('ES384'),
('ES512'),
('PS256'),
('PS384'),
('PS512'),
('EdDSA')
;
-- define the immutable fields for auth_oidc_signing_alg (all of them)
create trigger
immutable_columns
before
update on auth_oidc_signing_alg_enm
for each row execute procedure immutable_columns('name');
commit;

@ -0,0 +1,193 @@
begin;
-- auth_oidc_method entries are the current oidc auth methods configured for
-- existing scopes.
create table auth_oidc_method (
public_id wt_public_id
primary key,
scope_id wt_scope_id
not null,
name wt_name,
description wt_description,
create_time wt_timestamp,
update_time wt_timestamp,
version wt_version,
state text not null
references auth_oidc_method_state_enm(name)
on delete restrict
on update cascade,
discovery_url wt_url not null, -- oidc discovery URL without any .well-known component
client_id text not null -- oidc client identifier issued by the oidc provider.
constraint client_id_not_empty
check(length(trim(client_id)) > 0),
client_secret bytea not null, -- encrypted oidc client secret issued by the oidc provider.
key_id wt_private_id not null -- key used to encrypt entries via wrapping wrapper.
references kms_oidc_key_version(private_id)
on delete restrict
on update cascade,
max_age int not null -- the allowable elapsed time in secs since the last time the user was authenticated. zero is allowed and should force the user to be re-authenticated.
constraint max_age_equal_or_greater_than_zero
check(max_age >= 0),
foreign key (scope_id, public_id)
references auth_method (scope_id, public_id)
on delete cascade
on update cascade,
unique(scope_id, name),
unique(scope_id, public_id),
unique(scope_id, discovery_url, client_id) -- a client_id must be unique for a provider within a scope.
);
-- auth_oidc_signing_alg entries are the signing algorithms allowed for an oidc
-- auth method. There must be at least one allowed alg for each oidc auth method.
create table auth_oidc_signing_alg (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
signing_alg_name text
references auth_oidc_signing_alg_enm(name)
on delete restrict
on update cascade,
primary key(oidc_method_id, signing_alg_name)
);
-- auth_oidc_callback_url entries are the callback URLs allowed for a specific
-- oidc auth method. There must be at least one callback url for each oidc auth
-- method.
create table auth_oidc_callback_url (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
callback_url wt_url not null
);
-- auth_oidc_aud_claim entries are the audience claims for a specific oidc auth
-- method. There can be 0 or more for each parent oidc auth method. If an auth
-- method has any aud claims, an ID token must contain one of them to be valid.
create table auth_oidc_aud_claim (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
aud_claim text not null
constraint aud_claim_must_not_be_empty
check(length(trim(aud_claim)) > 0)
constraint aud_claim_must_be_less_than_1024_chars
check(length(trim(aud_claim)) < 1024),
primary key(oidc_method_id, aud_claim)
);
-- auth_oidc_certificate entries are optional PEM encoded x509 certificates.
-- Each entry is a single certificate. An oidc auth method may have 0 or more
-- of these optional x509s. If an auth method has any cert entries, they are
-- used as trust anchors when connecting to the auth method's oidc provider
-- (instead of the host system's cert chain).
create table auth_oidc_certificate (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
certificate bytea not null,
primary key(oidc_method_id, certificate)
);
create table auth_oidc_account (
public_id wt_public_id
primary key,
auth_method_id wt_public_id
not null,
-- NOTE(mgaffney): The scope_id type is not wt_scope_id because the domain
-- check is executed before the insert trigger which retrieves the scope_id
-- causing an insert to fail.
scope_id text not null,
name wt_name,
description wt_description,
create_time wt_timestamp,
update_time wt_timestamp,
version wt_version,
issuer_id wt_url not null, -- case-sensitive URL that maps to an id_token's iss claim
subject_id text not null -- case-senstive string that maps to an id_token's sub claim
constraint subject_id_must_not_be_empty
check (
length(trim(subject_id)) > 0
)
constraint subject_id_must_be_less_than_256_chars
check(
length(trim(subject_id)) <= 255 -- length limit per OIDC spec
),
full_name wt_full_name, -- may be null and maps to an id_token's name claim
email wt_email, -- may be null and maps to the id_token's email claim
foreign key (scope_id, auth_method_id)
references auth_oidc_method (scope_id, public_id)
on delete cascade
on update cascade,
foreign key (scope_id, auth_method_id, public_id)
references auth_account (scope_id, auth_method_id, public_id)
on delete cascade
on update cascade,
unique(auth_method_id, name),
unique(auth_method_id, issuer_id, subject_id), -- subject must be unique for a provider within specific auth method
unique(auth_method_id, public_id)
);
-- auth_oidc_method column triggers
create trigger
insert_auth_method_subtype
before insert on auth_oidc_method
for each row execute procedure insert_auth_method_subtype();
create trigger
update_time_column
before
update on auth_oidc_method
for each row execute procedure update_time_column();
create trigger
immutable_columns
before
update on auth_oidc_method
for each row execute procedure immutable_columns('public_id', 'scope_id', 'create_time');
create trigger
default_create_time_column
before
insert on auth_oidc_method
for each row execute procedure default_create_time();
create trigger
update_version_column
after update on auth_oidc_method
for each row execute procedure update_version_column();
-- auth_oidc_account column triggers
create trigger
update_time_column
before
update on auth_oidc_account
for each row execute procedure update_time_column();
create trigger
immutable_columns
before
update on auth_oidc_account
for each row execute procedure immutable_columns('public_id', 'auth_method_id', 'scope_id', 'create_time', 'issuer_id', 'subject_id');
create trigger
default_create_time_column
before
insert on auth_oidc_account
for each row execute procedure default_create_time();
create trigger
update_version_column
after update on auth_oidc_account
for each row execute procedure update_version_column();
create trigger
insert_auth_account_subtype
before insert on auth_oidc_account
for each row execute procedure insert_auth_account_subtype();
commit;

@ -0,0 +1,31 @@
begin;
-- auth_token_status_enm entries define the possible auth token
-- states.
create table auth_token_status_enm (
name text primary key
constraint only_predefined_auth_token_states_allowed
check (
name in ('auth token pending','token issued', 'authentication failed', 'system error')
)
);
-- populate the values of auth_token_status_enm
insert into auth_token_status_enm(name)
values
('auth token pending'),
('token issued'),
('authentication failed'),
('system error');
-- add the state column with a default to the auth_token table.
alter table auth_token
add column status text
not null
default 'token issued' -- safest default
references auth_token_status_enm(name)
on update cascade
on delete restrict;
commit;

@ -0,0 +1,66 @@
begin;
-- add the account_info_auth_method_id which determines which auth_method is
-- designated as for "account info" in the user's scope.
alter table iam_scope
add column account_info_auth_method_id wt_public_id -- allowed to be null and is mutable of course.
references auth_method(public_id)
on update cascade
on delete set null;
-- establish a compond fk, but there's no cascading of deletes or updates, since
-- we only want to cascade changes to the account_info_auth_method_id portion of
-- the compond fk and that is handled in a separate fk declaration.
alter table iam_scope
add foreign key (public_id, account_info_auth_method_id) references auth_method(scope_id, public_id);
-- iam_user_acct_info provides account info for users by determining which
-- auth_method is designated as for "account info" in the user's scope via the
-- scope's account_info_auth_method_id. Every sub-type of auth_account must be
-- added to this view's union.
create view iam_acct_info as
select
aa.iam_user_id,
oa.subject_id as login_name,
oa.full_name as full_name,
oa.email as email
from
iam_scope s,
auth_account aa,
auth_oidc_account oa
where
aa.public_id = oa.public_id and
aa.auth_method_id = s.account_info_auth_method_id
union
select
aa.iam_user_id,
pa.login_name,
'' as full_name,
'' as email
from
iam_scope s,
auth_account aa,
auth_password_account pa
where
aa.public_id = pa.public_id and
aa.auth_method_id = s.account_info_auth_method_id;
-- iam_user_acct_info provides a simple way to retrieve entries that include
-- both the iam_user fields with an outer join to the user's account info.
create view iam_user_acct_info as
select
u.public_id,
u.scope_id,
u.name,
u.description,
u.create_time,
u.update_time,
u.version,
i.login_name,
i.full_name,
i.email
from
iam_user u
left outer join iam_acct_info i on u.public_id = i.iam_user_id;
commit;

@ -5,7 +5,7 @@ package schema
func init() {
migrationStates["postgres"] = migrationState{
devMigration: true,
binarySchemaVersion: 1082,
binarySchemaVersion: 1086,
upMigrations: map[int][]byte{
1: []byte(`
begin;
@ -4989,6 +4989,67 @@ create table server_tag (
);
commit;
`),
1080: []byte(`
begin;
-- wt_email defines a type for email which must be less than 320 chars and only
-- contain lower case values. The type is defined to allow nulls and not be
-- unique, which can be overriden as needed when used in tables.
create domain wt_email as text
constraint wt_email_too_short
check (length(trim(value)) > 0)
constraint wt_email_too_long
check (length(trim(value)) < 320);
comment on domain wt_email is
'standard column for email addresses';
-- wt_full_name defines a type for a person's full name which must be less than
-- 512 chars. The type is defined to allow nulls and not be unique, which can
-- be overriden as needed when used in tables.
create domain wt_full_name text
constraint wt_full_name_too_short
check (length(trim(value)) > 0)
constraint wt_full_name_too_long
check(length(trim(value)) <= 512); -- gotta pick some upper limit.
comment on domain wt_full_name is
'standard column for the full name of a person';
-- wt_url defines a type for URLs which must be longer that 3 chars and
-- less than 4k chars. It's defined to allow nulls, which can be overriden as
-- needed when used in tables.
create domain wt_url as text
constraint wt_url_too_short
check (length(trim(value)) > 3)
constraint wt_url_too_long
check (length(trim(value)) < 4000)
constraint wt_url_invalid_protocol
check (value ~ 'https?:\/\/*');
comment on domain wt_url is
'standard column for URLs';
-- wt_name defines a type for resource names that must be less than 128 chars.
-- It's defined to allow nulls.
create domain wt_name as text
constraint wt_name_too_short
check (length(trim(value)) > 0)
constraint wt_name_too_long
check (length(trim(value)) < 128);
comment on domain wt_name is
'standard column for resource names';
-- wt_description defines a type for resource descriptionss that must be less
-- than 1024 chars. It's defined to allow nulls.
create domain wt_description as text
constraint wt_description_too_short
check (length(trim(value)) > 0)
constraint wt_description_too_long
check (length(trim(value)) < 1024);
comment on domain wt_description is
'standard column for resource descriptions';
commit;
`),
1082: []byte(`
begin;
@ -5055,6 +5116,378 @@ create trigger
before insert on kms_oidc_key_version
for each row execute procedure kms_version_column('oidc_key_id');
commit;
`),
1083: []byte(`
begin;
-- auth_oidc_method_state_enum entries define the possible oidc auth method
-- states.
create table auth_oidc_method_state_enm (
name text primary key
constraint only_predefined_oidc_method_states_allowed
check (
name in ('inactive', 'active-private', 'active-public', 'stopping')
)
);
-- populate the values of auth_oidc_method_state_enm
insert into auth_oidc_method_state_enm(name)
values
('inactive'),
('active-private'),
('active-public'),
('stopping');
-- define the immutable fields for auth_oidc_method_state_enm (all of them)
create trigger
immutable_columns
before
update on auth_oidc_method_state_enm
for each row execute procedure immutable_columns('name');
-- auth_oidc_signing_alg entries define the supported oidc auth method
-- signing algorithms.
create table auth_oidc_signing_alg_enm (
name text primary key
constraint only_predefined_auth_oidc_signing_algs_allowed
check (
name in (
'RS256',
'RS384',
'RS512',
'ES256',
'ES384',
'ES512',
'PS256',
'PS384',
'PS512',
'EdDSA')
)
);
-- populate the values of auth_oidc_signing_alg
insert into auth_oidc_signing_alg_enm (name)
values
('RS256'),
('RS384'),
('RS512'),
('ES256'),
('ES384'),
('ES512'),
('PS256'),
('PS384'),
('PS512'),
('EdDSA')
;
-- define the immutable fields for auth_oidc_signing_alg (all of them)
create trigger
immutable_columns
before
update on auth_oidc_signing_alg_enm
for each row execute procedure immutable_columns('name');
commit;
`),
1084: []byte(`
begin;
-- auth_oidc_method entries are the current oidc auth methods configured for
-- existing scopes.
create table auth_oidc_method (
public_id wt_public_id
primary key,
scope_id wt_scope_id
not null,
name wt_name,
description wt_description,
create_time wt_timestamp,
update_time wt_timestamp,
version wt_version,
state text not null
references auth_oidc_method_state_enm(name)
on delete restrict
on update cascade,
discovery_url wt_url not null, -- oidc discovery URL without any .well-known component
client_id text not null -- oidc client identifier issued by the oidc provider.
constraint client_id_not_empty
check(length(trim(client_id)) > 0),
client_secret bytea not null, -- encrypted oidc client secret issued by the oidc provider.
key_id wt_private_id not null -- key used to encrypt entries via wrapping wrapper.
references kms_oidc_key_version(private_id)
on delete restrict
on update cascade,
max_age int not null -- the allowable elapsed time in secs since the last time the user was authenticated. zero is allowed and should force the user to be re-authenticated.
constraint max_age_equal_or_greater_than_zero
check(max_age >= 0),
foreign key (scope_id, public_id)
references auth_method (scope_id, public_id)
on delete cascade
on update cascade,
unique(scope_id, name),
unique(scope_id, public_id),
unique(scope_id, discovery_url, client_id) -- a client_id must be unique for a provider within a scope.
);
-- auth_oidc_signing_alg entries are the signing algorithms allowed for an oidc
-- auth method. There must be at least one allowed alg for each oidc auth method.
create table auth_oidc_signing_alg (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
signing_alg_name text
references auth_oidc_signing_alg_enm(name)
on delete restrict
on update cascade,
primary key(oidc_method_id, signing_alg_name)
);
-- auth_oidc_callback_url entries are the callback URLs allowed for a specific
-- oidc auth method. There must be at least one callback url for each oidc auth
-- method.
create table auth_oidc_callback_url (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
callback_url wt_url not null
);
-- auth_oidc_aud_claim entries are the audience claims for a specific oidc auth
-- method. There can be 0 or more for each parent oidc auth method. If an auth
-- method has any aud claims, an ID token must contain one of them to be valid.
create table auth_oidc_aud_claim (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
aud_claim text not null
constraint aud_claim_must_not_be_empty
check(length(trim(aud_claim)) > 0)
constraint aud_claim_must_be_less_than_1024_chars
check(length(trim(aud_claim)) < 1024),
primary key(oidc_method_id, aud_claim)
);
-- auth_oidc_certificate entries are optional PEM encoded x509 certificates.
-- Each entry is a single certificate. An oidc auth method may have 0 or more
-- of these optional x509s. If an auth method has any cert entries, they are
-- used as trust anchors when connecting to the auth method's oidc provider
-- (instead of the host system's cert chain).
create table auth_oidc_certificate (
oidc_method_id wt_public_id
references auth_oidc_method(public_id)
on delete cascade
on update cascade,
certificate bytea not null,
primary key(oidc_method_id, certificate)
);
create table auth_oidc_account (
public_id wt_public_id
primary key,
auth_method_id wt_public_id
not null,
-- NOTE(mgaffney): The scope_id type is not wt_scope_id because the domain
-- check is executed before the insert trigger which retrieves the scope_id
-- causing an insert to fail.
scope_id text not null,
name wt_name,
description wt_description,
create_time wt_timestamp,
update_time wt_timestamp,
version wt_version,
issuer_id wt_url not null, -- case-sensitive URL that maps to an id_token's iss claim
subject_id text not null -- case-senstive string that maps to an id_token's sub claim
constraint subject_id_must_not_be_empty
check (
length(trim(subject_id)) > 0
)
constraint subject_id_must_be_less_than_256_chars
check(
length(trim(subject_id)) <= 255 -- length limit per OIDC spec
),
full_name wt_full_name, -- may be null and maps to an id_token's name claim
email wt_email, -- may be null and maps to the id_token's email claim
foreign key (scope_id, auth_method_id)
references auth_oidc_method (scope_id, public_id)
on delete cascade
on update cascade,
foreign key (scope_id, auth_method_id, public_id)
references auth_account (scope_id, auth_method_id, public_id)
on delete cascade
on update cascade,
unique(auth_method_id, name),
unique(auth_method_id, issuer_id, subject_id), -- subject must be unique for a provider within specific auth method
unique(auth_method_id, public_id)
);
-- auth_oidc_method column triggers
create trigger
insert_auth_method_subtype
before insert on auth_oidc_method
for each row execute procedure insert_auth_method_subtype();
create trigger
update_time_column
before
update on auth_oidc_method
for each row execute procedure update_time_column();
create trigger
immutable_columns
before
update on auth_oidc_method
for each row execute procedure immutable_columns('public_id', 'scope_id', 'create_time');
create trigger
default_create_time_column
before
insert on auth_oidc_method
for each row execute procedure default_create_time();
create trigger
update_version_column
after update on auth_oidc_method
for each row execute procedure update_version_column();
-- auth_oidc_account column triggers
create trigger
update_time_column
before
update on auth_oidc_account
for each row execute procedure update_time_column();
create trigger
immutable_columns
before
update on auth_oidc_account
for each row execute procedure immutable_columns('public_id', 'auth_method_id', 'scope_id', 'create_time', 'issuer_id', 'subject_id');
create trigger
default_create_time_column
before
insert on auth_oidc_account
for each row execute procedure default_create_time();
create trigger
update_version_column
after update on auth_oidc_account
for each row execute procedure update_version_column();
create trigger
insert_auth_account_subtype
before insert on auth_oidc_account
for each row execute procedure insert_auth_account_subtype();
commit;
`),
1085: []byte(`
begin;
-- auth_token_status_enm entries define the possible auth token
-- states.
create table auth_token_status_enm (
name text primary key
constraint only_predefined_auth_token_states_allowed
check (
name in ('auth token pending','token issued', 'authentication failed', 'system error')
)
);
-- populate the values of auth_token_status_enm
insert into auth_token_status_enm(name)
values
('auth token pending'),
('token issued'),
('authentication failed'),
('system error');
-- add the state column with a default to the auth_token table.
alter table auth_token
add column status text
not null
default 'token issued' -- safest default
references auth_token_status_enm(name)
on update cascade
on delete restrict;
commit;
`),
1086: []byte(`
begin;
-- add the account_info_auth_method_id which determines which auth_method is
-- designated as for "account info" in the user's scope.
alter table iam_scope
add column account_info_auth_method_id wt_public_id -- allowed to be null and is mutable of course.
references auth_method(public_id)
on update cascade
on delete set null;
-- establish a compond fk, but there's no cascading of deletes or updates, since
-- we only want to cascade changes to the account_info_auth_method_id portion of
-- the compond fk and that is handled in a separate fk declaration.
alter table iam_scope
add foreign key (public_id, account_info_auth_method_id) references auth_method(scope_id, public_id);
-- iam_user_acct_info provides account info for users by determining which
-- auth_method is designated as for "account info" in the user's scope via the
-- scope's account_info_auth_method_id. Every sub-type of auth_account must be
-- added to this view's union.
create view iam_acct_info as
select
aa.iam_user_id,
oa.subject_id as login_name,
oa.full_name as full_name,
oa.email as email
from
iam_scope s,
auth_account aa,
auth_oidc_account oa
where
aa.public_id = oa.public_id and
aa.auth_method_id = s.account_info_auth_method_id
union
select
aa.iam_user_id,
pa.login_name,
'' as full_name,
'' as email
from
iam_scope s,
auth_account aa,
auth_password_account pa
where
aa.public_id = pa.public_id and
aa.auth_method_id = s.account_info_auth_method_id;
-- iam_user_acct_info provides a simple way to retrieve entries that include
-- both the iam_user fields with an outer join to the user's account info.
create view iam_user_acct_info as
select
u.public_id,
u.scope_id,
u.name,
u.description,
u.create_time,
u.update_time,
u.version,
i.login_name,
i.full_name,
i.email
from
iam_user u
left outer join iam_acct_info i on u.public_id = i.iam_user_id;
commit;
`),
},

Loading…
Cancel
Save