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.
423 lines
15 KiB
423 lines
15 KiB
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
|
|
constraint auth_oidc_method_state_enm_fkey
|
|
references auth_oidc_method_state_enm(name)
|
|
on delete restrict
|
|
on update cascade,
|
|
disable_discovered_config_validation bool not null default false,
|
|
api_url wt_url, -- an address prefix at which the boundary api is reachable.
|
|
issuer wt_url,
|
|
client_id text -- oidc client identifier issued by the oidc provider.
|
|
constraint client_id_not_empty
|
|
check(length(trim(client_id)) > 0),
|
|
client_secret bytea, -- encrypted oidc client secret issued by the oidc provider.
|
|
client_secret_hmac text
|
|
constraint client_secret_hmac_not_empty
|
|
check(length(trim(client_secret_hmac)) > 0),
|
|
key_id wt_private_id not null -- key used to encrypt entries via wrapping wrapper.
|
|
constraint kms_database_key_version_fkey
|
|
references kms_database_key_version(private_id)
|
|
on delete restrict
|
|
on update cascade,
|
|
constraint key_id_not_empty
|
|
check(length(trim(key_id)) > 0),
|
|
max_age int -- the allowable elapsed time in secs since the last time the user was authenticated. A value -1 basically forces the IdP to re-authenticate the End-User. Zero is not a valid value.
|
|
constraint max_age_not_equal_zero
|
|
check(max_age != 0)
|
|
constraint max_age_not_less_then_negative_one
|
|
check(max_age >= -1),
|
|
constraint auth_method_fkey
|
|
foreign key (scope_id, public_id)
|
|
references auth_method (scope_id, public_id)
|
|
on delete cascade
|
|
on update cascade,
|
|
constraint auth_oidc_method_scope_id_name_uq
|
|
unique(scope_id, name),
|
|
constraint auth_oidc_method_scope_id_public_id_uq
|
|
unique(scope_id, public_id),
|
|
constraint auth_oidc_method_scope_id_issuer_client_id_unique
|
|
unique(scope_id, issuer, client_id) -- a client_id must be unique for a provider within a scope.
|
|
);
|
|
comment on table auth_oidc_method is
|
|
'auth_oidc_method entries are the current oidc auth methods configured for existing scopes.';
|
|
|
|
-- 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 (
|
|
create_time wt_timestamp,
|
|
oidc_method_id wt_public_id
|
|
constraint auth_oidc_method_fkey
|
|
references auth_oidc_method(public_id)
|
|
on delete cascade
|
|
on update cascade,
|
|
signing_alg_name text
|
|
constraint auth_oidc_signing_alg_enm_fkey
|
|
references auth_oidc_signing_alg_enm(name)
|
|
on delete restrict
|
|
on update cascade,
|
|
primary key(oidc_method_id, signing_alg_name)
|
|
);
|
|
comment on table auth_oidc_signing_alg is
|
|
'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';
|
|
|
|
-- 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 (
|
|
create_time wt_timestamp,
|
|
oidc_method_id wt_public_id
|
|
constraint auth_oidc_method_fkey
|
|
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)
|
|
);
|
|
comment on table auth_oidc_aud_claim is
|
|
'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.';
|
|
|
|
|
|
-- 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 (
|
|
create_time wt_timestamp,
|
|
oidc_method_id wt_public_id
|
|
constraint auth_oidc_method_fkey
|
|
references auth_oidc_method(public_id)
|
|
on delete cascade
|
|
on update cascade,
|
|
certificate bytea not null,
|
|
primary key(oidc_method_id, certificate)
|
|
);
|
|
comment on table auth_oidc_certificate is
|
|
'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 methods oidc provider (instead of the host system cert chain)';
|
|
|
|
|
|
-- auth_oidc_account entries are subtypes of auth_account and represent an
|
|
-- oidc account.
|
|
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 wt_url not null, -- case-sensitive URL that maps to an id_token's iss claim,
|
|
subject text not null -- case-sensitive string that maps to an id_token's sub claim
|
|
constraint subject_must_not_be_empty
|
|
check (
|
|
length(trim(subject)) > 0
|
|
)
|
|
constraint subject_must_be_less_than_256_chars
|
|
check(
|
|
length(trim(subject)) <= 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
|
|
constraint auth_oidc_method_fkey
|
|
foreign key (scope_id, auth_method_id)
|
|
references auth_oidc_method (scope_id, public_id)
|
|
on delete cascade
|
|
on update cascade,
|
|
constraint auth_account_fkey
|
|
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,
|
|
constraint auth_oidc_account_auth_method_id_name_uq
|
|
unique(auth_method_id, name),
|
|
-- ###############################################################
|
|
-- any change to this constraints name must be aligned with the
|
|
-- acctUpsertQuery const in internal/auth/oidc/query.go
|
|
-- ###############################################################
|
|
constraint auth_oidc_account_auth_method_id_issuer_subject_uq
|
|
unique(auth_method_id, issuer, subject), -- subject must be unique for a provider within specific auth method
|
|
constraint auth_oidc_account_auth_method_id_public_id_uq
|
|
unique(auth_method_id, public_id)
|
|
);
|
|
comment on table auth_oidc_method is
|
|
'auth_oidc_account entries are subtypes of auth_account and represent an oidc account.';
|
|
|
|
-- 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();
|
|
|
|
-- active_auth_oidc_method_must_be_complete() defines a function to be used in
|
|
-- a "before update" trigger for auth_oidc_method entries. Its intent: prevent
|
|
-- incomplete oidc methods from transitioning out of the "inactive" state.
|
|
create or replace function
|
|
active_auth_oidc_method_must_be_complete()
|
|
returns trigger
|
|
as $$
|
|
begin
|
|
-- validate signing alg
|
|
if old.state = 'inactive' and new.state != 'inactive' then
|
|
perform
|
|
from
|
|
auth_oidc_method am
|
|
join auth_oidc_signing_alg alg on am.public_id = alg.oidc_method_id
|
|
where
|
|
new.public_id = am.public_id;
|
|
if not found then
|
|
raise exception 'an incomplete oidc auth method must remain inactive';
|
|
end if;
|
|
-- validate issuer
|
|
case
|
|
when new.issuer != old.issuer then
|
|
if length(trim(new.issuer)) = 0 then
|
|
raise exception 'empty issuer: an incomplete oidc auth method must remain inactive';
|
|
end if;
|
|
when new.issuer = old.issuer then
|
|
if length(trim(old.issuer)) = 0 then
|
|
raise exception 'empty issuer: an incomplete oidc auth method must remain inactive';
|
|
end if;
|
|
else
|
|
end case;
|
|
-- validate client_id
|
|
case
|
|
when new.client_id != old.client_id then
|
|
if length(trim(new.client_id)) = 0 then
|
|
raise exception 'empty client_id: an incomplete oidc auth method must remain inactive';
|
|
end if;
|
|
when new.client_id = old.client_id then
|
|
if length(trim(old.client_id)) = 0 then
|
|
raise exception 'empty client_id: an incomplete oidc auth method must remain inactive';
|
|
end if;
|
|
else
|
|
end case;
|
|
-- validate client_secret
|
|
case
|
|
when new.client_secret != old.client_secret then
|
|
if length(new.client_secret) = 0 then
|
|
raise exception 'empty client_secret: an incomplete oidc auth method must remain inactive';
|
|
end if;
|
|
when new.client_secret = old.client_secret then
|
|
if length(old.client_secret) = 0 then
|
|
raise exception 'empty client_secret: an incomplete oidc auth method must remain inactive';
|
|
end if;
|
|
else
|
|
end case;
|
|
|
|
|
|
end if;
|
|
return new;
|
|
end;
|
|
$$ language plpgsql;
|
|
comment on function active_auth_oidc_method_must_be_complete() is
|
|
'active_auth_oidc_method_must_be_complete() will raise an error if the oidc auth method is not complete';
|
|
|
|
create trigger
|
|
update_active_auth_oidc_method_must_be_complete
|
|
before
|
|
update on auth_oidc_method
|
|
for each row execute procedure active_auth_oidc_method_must_be_complete();
|
|
|
|
-- new_auth_oidc_method_must_be_inactive() defines a function to be used in
|
|
-- a "before insert" trigger for auth_oidc_method entries. Its intent:
|
|
-- only allow "inactive" auth methods to be inserted. Why? there's no way
|
|
-- you can insert an entry that's anything but incomplete, since we have a
|
|
-- chicken/egg problem: you need the auth method id to create the required
|
|
-- signing algs value objects.
|
|
create or replace function
|
|
new_auth_oidc_method_must_be_inactive()
|
|
returns trigger
|
|
as $$
|
|
begin
|
|
if new.state != 'inactive' then
|
|
raise exception 'an incomplete oidc method must be inactive';
|
|
end if;
|
|
end;
|
|
$$ language plpgsql;
|
|
comment on function new_auth_oidc_method_must_be_inactive() is
|
|
'new_auth_oidc_method_must_be_inactive ensures that new incomplete oidc auth methods must remain inactive';
|
|
|
|
create trigger
|
|
new_auth_oidc_method_must_be_inactive
|
|
before
|
|
insert on auth_oidc_method
|
|
for each row execute procedure active_auth_oidc_method_must_be_complete();
|
|
|
|
-- 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', 'subject');
|
|
|
|
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();
|
|
|
|
|
|
-- insert_auth_oidc_account_subtype is intended as a before insert
|
|
-- trigger on auth_oidc_account. Its purpose is to insert a base
|
|
-- auth_account for new oidc accounts. It's a bit different than the
|
|
-- standard trigger for this, because it will have conflicting PKs
|
|
-- and we just want to "do nothing" on those conflicts, deferring the
|
|
-- raising on an error to insert into the auth_oidc_account table.
|
|
-- this is all necessary because of we're using predictable public ids
|
|
-- for oidc accounts.
|
|
create or replace function
|
|
insert_auth_oidc_account_subtype()
|
|
returns trigger
|
|
as $$
|
|
begin
|
|
select auth_method.scope_id
|
|
into new.scope_id
|
|
from auth_method
|
|
where auth_method.public_id = new.auth_method_id;
|
|
|
|
insert into auth_account
|
|
(public_id, auth_method_id, scope_id)
|
|
values
|
|
(new.public_id, new.auth_method_id, new.scope_id)
|
|
on conflict do nothing;
|
|
|
|
return new;
|
|
end;
|
|
$$ language plpgsql;
|
|
|
|
create trigger
|
|
insert_auth_oidc_account_subtype
|
|
before insert on auth_oidc_account
|
|
for each row execute procedure insert_auth_oidc_account_subtype();
|
|
|
|
-- triggers for auth_oidc_method children tables: auth_oidc_aud_claim,
|
|
-- auth_oidc_certificate, auth_oidc_signing_alg
|
|
|
|
|
|
-- on_delete_active_auth_oidc_method_must_be_complete() defines a function
|
|
-- to be used in an "after delete" trigger for auth_oidc_signing_alg
|
|
-- Its intent: prevent deletes that would result in an "active" oidc
|
|
-- auth method which is incomplete.
|
|
create or replace function
|
|
on_delete_active_auth_oidc_method_must_be_complete()
|
|
returns trigger
|
|
as $$
|
|
declare am_state text;
|
|
declare alg_cnt int;
|
|
begin
|
|
select
|
|
am.state,
|
|
count(alg.oidc_method_id) as alg_cnt
|
|
from
|
|
auth_oidc_method am
|
|
left outer join auth_oidc_signing_alg alg on am.public_id = alg.oidc_method_id
|
|
where
|
|
new.oidc_method_id = am.public_id
|
|
group by am.public_id
|
|
into am_state, alg_cnt;
|
|
|
|
if not found then
|
|
return new; -- auth method was deleted, so we're done
|
|
end if;
|
|
|
|
if am_state != inactive then
|
|
case
|
|
when alg_cnt = 0 then
|
|
raise exception 'delete would have resulted in an incomplete active oidc auth method with no signing algorithms';
|
|
end case;
|
|
end if;
|
|
|
|
return new;
|
|
end;
|
|
$$ language plpgsql;
|
|
comment on function on_delete_active_auth_oidc_method_must_be_complete() is
|
|
'on_delete_active_auth_oidc_method_must_be_complete() will raise an error if the oidc auth method is not complete after a delete on algs';
|
|
|
|
create trigger
|
|
default_create_time_column
|
|
before
|
|
insert on auth_oidc_aud_claim
|
|
for each row execute procedure default_create_time();
|
|
|
|
create trigger
|
|
default_create_time_column
|
|
before
|
|
insert on auth_oidc_certificate
|
|
for each row execute procedure default_create_time();
|
|
|
|
create trigger
|
|
default_create_time_column
|
|
before
|
|
insert on auth_oidc_signing_alg
|
|
for each row execute procedure default_create_time();
|
|
|
|
create trigger
|
|
on_delete_active_auth_oidc_method_must_be_complete
|
|
after
|
|
delete on auth_oidc_signing_alg
|
|
for each row execute procedure on_delete_active_auth_oidc_method_must_be_complete();
|
|
|
|
insert into oplog_ticket (name, version)
|
|
values
|
|
('auth_oidc_method', 1), -- auth method is the root aggregate itself and all of its value objects.
|
|
('auth_oidc_account', 1);
|
|
|
|
commit;
|