Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Define new grants tables #5486

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
90dfb5f
add migration scripts
bosorawis Dec 26, 2024
26d10a7
delete duplicate resources
bosorawis Dec 27, 2024
5bd0a97
fix color persona test setup
bosorawis Dec 27, 2024
d4ed365
fix sqltest setup with new iam_grant
bosorawis Dec 27, 2024
a462705
refactor makefiles for sqltest
bosorawis Dec 27, 2024
7299dd5
feat(db): split up DB migration & add sql tests
elimt Jan 10, 2025
470a463
add timestamp for grant_scope updates
elimt Jan 27, 2025
35ad253
feat: update timestamp for iam_role_global & iam_role_org tables
elimt Jan 27, 2025
63c6b3a
feat: update iam role timestamps
elimt Jan 28, 2025
9e5a155
chore: remove unapplicable comment
elimt Jan 28, 2025
14c6430
add timestamps on create or update to fields
elimt Jan 28, 2025
021f324
revert db/makefile change
elimt Jan 28, 2025
3cad65e
Address PR feedback
elimt Jan 30, 2025
014c09c
- fix comments
elimt Feb 1, 2025
7a7c0df
add test coverage for new migration files
elimt Feb 1, 2025
348dacd
fix: update comments and enforce not null constraint on grant_scope f…
elimt Feb 12, 2025
c263a6f
update sql test grants to use valid grant strings
elimt Feb 12, 2025
3f95ab5
add more test coverage for iam_grant with multiple grant string combi…
elimt Feb 12, 2025
c8193f8
remove not null for primary keys
elimt Feb 19, 2025
d0f4489
fixup! address PR comments
elimt Feb 26, 2025
8a890ba
add more iam_grants test coverage
elimt Feb 26, 2025
3e65df0
update set_resource function to fail when a canonical_grant is malformed
elimt Mar 3, 2025
c3ac100
update case of sql to match other sql files
elimt Mar 3, 2025
907f263
create new wt_canonical_grant domain
elimt Mar 3, 2025
c97fd7f
update wt_canonical_grant comment
elimt Mar 3, 2025
3fdcfa1
address PR feedback on primary key and function name
elimt Mar 4, 2025
d998b2e
fixup! update order of columns to match primary key
elimt Mar 5, 2025
e7d7995
update canonical_grant validation
elimt Mar 6, 2025
89ecf22
remove commented out role
elimt Mar 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ create table iam_role (
);

-- Grants are immutable, which is enforced via the trigger below
-- Altered in 100/05_iam_grant.up.sql to add constraint on canonical_grant
create table iam_role_grant (
create_time wt_timestamp,
role_id wt_role_id -- pk
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: BUSL-1.1

begin;

-- Create the enumeration table for the grant scope types for the global iam_role
create table iam_role_global_grant_scope_enm (
name text primary key
constraint only_predefined_scope_types_allowed
check(
name in (
'descendants',
'children',
'individual'
)
)
);
comment on table iam_role_global_grant_scope_enm is
'iam_role_global_grant_scope_enm is an enumeration table for role grant scope types for the iam_role_global table.';

-- Insert the predefined grant scope types for iam_role_global
insert into iam_role_global_grant_scope_enm (name)
values
('descendants'),
('children'),
('individual');

create function insert_role_subtype() returns trigger
as $$
begin
insert into iam_role
(public_id, scope_id)
values
(new.public_id, new.scope_id);
return new;
end;
$$ language plpgsql;
comment on function insert_role_subtype() is
'insert_role_subtype is used to automatically insert a row into the iam_role table '
'whenever a row is inserted into the subtype table';

create function insert_grant_scope_update_time() returns trigger
as $$
begin
if new.grant_scope is distinct from old.grant_scope then
new.grant_scope_update_time = now();
end if;
return new;
end;
$$ language plpgsql;
comment on function insert_grant_scope_update_time() is
'insert_grant_scope_update_time is used to automatically update the grant_scope_update_time '
'of the subtype table whenever the grant_scope column is updated';

create function insert_grant_this_role_scope_update_time() returns trigger
as $$
begin
if new.grant_this_role_scope is distinct from old.grant_this_role_scope then
new.grant_this_role_scope_update_time = now();
end if;
return new;
end;
$$ language plpgsql;
comment on function insert_grant_this_role_scope_update_time() is
'insert_grant_this_role_scope_update_time is used to automatically update the grant_scope_update_time '
'of the subtype table whenever the grant_this_role_scope column is updated';

-- global iam_role must have a scope_id of global.
--
-- grant_this_role_scope indicates if the role can apply its grants to the scope.
-- grant_scope indicates the scope of the grants.
-- grant_scope can be 'descendants', 'children', or 'individual'.
--
-- grant_this_role_scope_update_time and grant_scope_update_time are used to track
-- the last time the grant_this_role_scope and grant_scope columns were updated.
-- This is used to represent the grant scope create_time column from the
-- iam_role_grant_scope table in 83/01_iam_role_grant_scope.up.sql.
-- This matches the representation of the existing create_time field at the
-- role domain layer that indicates when the grant scope was created.
create table iam_role_global (
public_id wt_role_id primary key
constraint iam_role_fkey
references iam_role(public_id)
on delete cascade
on update cascade,
scope_id wt_scope_id not null
constraint iam_scope_global_fkey
references iam_scope_global(scope_id)
on delete cascade
on update cascade,
name text,
description text,
grant_this_role_scope boolean not null default false,
grant_scope text not null
constraint iam_role_global_grant_scope_enm_fkey
references iam_role_global_grant_scope_enm(name)
on delete restrict
on update cascade,
version wt_version,
grant_this_role_scope_update_time wt_timestamp,
grant_scope_update_time wt_timestamp,
create_time wt_timestamp,
update_time wt_timestamp,
constraint iam_role_global_grant_scope_public_id_uq
unique(grant_scope, public_id)
);
comment on table iam_role_global is
'iam_role_global is the subtype table for the global role. grant_this_role_scope_update_time and grant_scope_update_time are used to track the last time the grant_this_role_scope and grant_scope columns were updated.';

create trigger insert_role_subtype before insert on iam_role_global
for each row execute procedure insert_role_subtype();

create trigger insert_grant_scope_update_time before insert on iam_role_global
for each row execute procedure insert_grant_scope_update_time();

create trigger insert_grant_this_role_scope_update_time before insert on iam_role_global
for each row execute procedure insert_grant_this_role_scope_update_time();

create trigger update_iam_role_global_grant_scope_update_time before update on iam_role_global
for each row execute procedure insert_grant_scope_update_time();

create trigger update_iam_role_global_grant_this_role_scope_update_time before update on iam_role_global
for each row execute procedure insert_grant_this_role_scope_update_time();

create trigger default_create_time_column before insert on iam_role_global
for each row execute procedure default_create_time();

create trigger update_time_column before update on iam_role_global
for each row execute procedure update_time_column();

create trigger update_version_column after update on iam_role_global
for each row execute procedure update_version_column();

create trigger immutable_columns before update on iam_role_global
for each row execute procedure immutable_columns('scope_id', 'create_time');

create table iam_role_global_individual_grant_scope (
role_id wt_role_id
constraint iam_role_global_fkey
references iam_role_global(public_id)
on delete cascade
on update cascade,
scope_id wt_scope_id not null
constraint iam_scope_fkey
references iam_scope(public_id)
on delete cascade
on update cascade
constraint scope_id_is_not_global
check(
scope_id != 'global'
),
-- grant_scope is used for constraint checking.
-- This restricts the grant_scope to be 'individual'
-- and since it is also a foreign key to the iam_role_global
-- grant_scope, it ensures that iam_role_global is set to 'individual'
-- if this table is populated for the corresponding role.
grant_scope text not null
constraint only_individual_grant_scope_allowed
check(
grant_scope = 'individual'
),
constraint iam_role_global_grant_scope_fkey
foreign key (role_id, grant_scope)
references iam_role_global(public_id, grant_scope)
on delete cascade
on update cascade,
create_time wt_timestamp,
primary key(role_id, scope_id)
);
comment on table iam_role_global_individual_grant_scope is
'iam_role_global_individual_grant_scope is the subtype table for the global role with grant_scope as individual.';

create trigger default_create_time_column before insert on iam_role_global_individual_grant_scope
for each row execute procedure default_create_time();

create trigger immutable_columns before update on iam_role_global_individual_grant_scope
for each row execute procedure immutable_columns('role_id', 'grant_scope', 'scope_id', 'create_time');

commit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: BUSL-1.1

begin;

-- Create the enumeration table for the grant scope types for the org iam_role
create table iam_role_org_grant_scope_enm (
name text primary key
constraint only_predefined_scope_types_allowed
check(
name in (
'children',
'individual'
)
)
);
comment on table iam_role_org_grant_scope_enm is
'iam_role_org_grant_scope_enm is an enumeration table for role grant scope types for the iam_role_org table.';

-- Insert the predefined grant scope types for iam_role_org
insert into iam_role_org_grant_scope_enm (name)
values
('children'),
('individual');

create table iam_role_org (
public_id wt_role_id primary key
constraint iam_role_fkey
references iam_role(public_id)
on delete cascade
on update cascade,
scope_id wt_scope_id not null
constraint iam_scope_org_fkey
references iam_scope_org(scope_id)
on delete cascade
on update cascade,
name text,
description text,
grant_this_role_scope boolean not null default false,
grant_scope text not null
constraint iam_role_org_grant_scope_enm_fkey
references iam_role_org_grant_scope_enm(name)
on delete restrict
on update cascade,
version wt_version,
grant_this_role_scope_update_time wt_timestamp,
grant_scope_update_time wt_timestamp,
create_time wt_timestamp,
update_time wt_timestamp,
constraint iam_role_org_grant_scope_public_id_uq
unique(grant_scope, public_id)
);
comment on table iam_role_org is
'iam_role_org is a subtype table of the iam_role table. It is used to store roles that are scoped to an org.';

create trigger insert_role_subtype before insert on iam_role_org
for each row execute procedure insert_role_subtype();

create trigger insert_iam_role_org_grant_scope_update_time before insert on iam_role_org
for each row execute procedure insert_grant_scope_update_time();

create trigger insert_iam_role_org_grant_this_role_scope_update_time before insert on iam_role_org
for each row execute procedure insert_grant_this_role_scope_update_time();

create trigger update_iam_role_org_grant_scope_update_time before update on iam_role_org
for each row execute procedure insert_grant_scope_update_time();

create trigger update_iam_role_org_grant_this_role_scope_update_time before update on iam_role_org
for each row execute procedure insert_grant_this_role_scope_update_time();

create trigger default_create_time_column before insert on iam_role_org
for each row execute procedure default_create_time();

create trigger update_time_column before update on iam_role_org
for each row execute procedure update_time_column();

create trigger update_version_column after update on iam_role_org
for each row execute procedure update_version_column();

create trigger immutable_columns before update on iam_role_org
for each row execute procedure immutable_columns('scope_id', 'create_time');

create table iam_role_org_individual_grant_scope (
role_id wt_role_id
constraint iam_role_org_fkey
references iam_role_org(public_id)
on delete cascade
on update cascade,
scope_id wt_scope_id not null
constraint iam_scope_org_scope_id_fkey
references iam_scope_project(scope_id)
on delete cascade
on update cascade,
-- grant_scope is used for constraint checking.
-- This restricts the grant_scope to be 'individual'
-- and since it is also a foreign key to the iam_role_org
-- grant_scope, it ensures that iam_role_org is set to 'individual'
-- if this table is populated for the corresponding role.
grant_scope text not null
constraint only_individual_grant_scope_allowed
check(
grant_scope = 'individual'
),
constraint iam_role_org_grant_scope_fkey
foreign key (role_id, grant_scope)
references iam_role_org(public_id, grant_scope)
on delete cascade
on update cascade,
create_time wt_timestamp,
primary key(role_id, scope_id)
);
comment on table iam_role_org_individual_grant_scope is
'iam_role_global_individual_grant_scope is the subtype table for the org role with grant_scope as individual.';

create trigger default_create_time_column before insert on iam_role_org_individual_grant_scope
for each row execute procedure default_create_time();

create trigger immutable_columns before update on iam_role_org_individual_grant_scope
for each row execute procedure immutable_columns('role_id', 'grant_scope', 'scope_id', 'create_time');

-- ensure the project's parent is the role's scope
create function ensure_project_belongs_to_role_org() returns trigger
as $$
begin
perform
from iam_scope_project
join iam_role_org
on iam_role_org.scope_id = iam_scope_project.parent_id
where iam_scope_project.scope_id = new.scope_id
and iam_role_org.public_id = new.role_id;
if not found then
raise exception 'project scope_id % not found in org', new.scope_id;
end if;
return new;
end;
$$ language plpgsql;
comment on function ensure_project_belongs_to_role_org() is
'ensure_project_belongs_to_role_org ensures the project belongs to the org of the role.';

create trigger ensure_project_belongs_to_role_org before insert or update on iam_role_org_individual_grant_scope
for each row execute procedure ensure_project_belongs_to_role_org();

commit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: BUSL-1.1

begin;

create table iam_role_project (
public_id wt_role_id primary key
constraint iam_role_fkey
references iam_role(public_id)
on delete cascade
on update cascade,
scope_id wt_scope_id not null
constraint iam_scope_project_fkey
references iam_scope_project(scope_id)
on delete cascade
on update cascade,
name text,
description text,
version wt_version,
create_time wt_timestamp,
update_time wt_timestamp
);
comment on table iam_role_project is
'iam_role_project is a subtype table of the iam_role table. It is used to store roles that are scoped to a project.';

create trigger insert_role_subtype before insert on iam_role_project
for each row execute procedure insert_role_subtype();

create trigger default_create_time_column before insert on iam_role_project
for each row execute procedure default_create_time();

create trigger update_time_column before update on iam_role_project
for each row execute procedure update_time_column();

create trigger update_version_column after update on iam_role_project
for each row execute procedure update_version_column();

create trigger immutable_columns before update on iam_role_project
for each row execute procedure immutable_columns('scope_id', 'create_time');

commit;
Loading
Loading