implement insert trigger if no explicit grant rule is specified

This commit is contained in:
Michael Hoennig 2024-03-07 12:26:07 +01:00
parent 20de9ba7a4
commit b37e8044b2
6 changed files with 81 additions and 23 deletions

View File

@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.rbac.rbacdef;
import java.util.Optional;
import java.util.stream.Stream;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT;
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE;
@ -95,11 +96,7 @@ public class InsertTriggerGenerator {
}
private void generateInsertCheckTrigger(final StringWriter plPgSql) {
rbacDef.getGrantDefs().stream()
.filter(g -> g.isToCreate() && g.grantType() == PERM_TO_ROLE &&
g.getPermDef().getPermission() == INSERT )
.forEach(g -> {
plPgSql.writeLn("""
plPgSql.writeLn("""
/**
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}.
*/
@ -107,24 +104,51 @@ public class InsertTriggerGenerator {
returns trigger
language plpgsql as $$
begin
raise exception 'insert into ${rawSubTable} not allowed for current subjects %', currentSubjectsUuids();
raise exception 'insert into ${rawSubTable} not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger ${rawSubTable}_insert_permission_check_tg
before insert on ${rawSubTable}
for each row
when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
execute procedure ${rawSubTable}_insert_permission_missing_tf();
""",
with("rawSubTable", g.getPermDef().entityAlias.getRawTableName()),
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName() ));
});
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
getOptionalInsertGrant().ifPresentOrElse(g -> {
plPgSql.writeLn("""
create trigger ${rawSubTable}_insert_permission_check_tg
before insert on ${rawSubTable}
for each row
when ( not hasInsertPermission(NEW.${referenceColumn}, 'INSERT', '${rawSubTable}') )
execute procedure ${rawSubTable}_insert_permission_missing_tf();
""",
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName() ));
},
() -> {
plPgSql.writeLn("""
create trigger ${rawSubTable}_insert_permission_check_tg
before insert on ${rawSubTable}
for each row
-- As there is no explicit INSERT grant specified for this table,
-- only global admins are allowed to insert any rows.
when ( not isGlobalAdmin() )
execute procedure ${rawSubTable}_insert_permission_missing_tf();
""",
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
});
}
private Stream<RbacView.RbacGrantDefinition> getInsertGrants() {
return rbacDef.getGrantDefs().stream()
.filter(g -> g.grantType() == PERM_TO_ROLE)
.filter(g -> g.getPermDef().toCreate && g.getPermDef().getPermission() == INSERT);
}
private Optional<RbacView.RbacGrantDefinition> getOptionalInsertGrant() {
return getInsertGrants()
.reduce((x, y) -> {
throw new IllegalStateException("only a single INSERT permission grant allowed");
});
}
private Optional<RbacView.RbacRoleDefinition> getOptionalInsertSuperRole() {
return rbacDef.getGrantDefs().stream()
.filter(g -> g.grantType() == PERM_TO_ROLE)
.filter(g -> g.getPermDef().toCreate && g.getPermDef().getPermission() == INSERT)
return getInsertGrants()
.map(RbacView.RbacGrantDefinition::getSuperRoleDef)
.reduce((x, y) -> {
throw new IllegalStateException("only a single INSERT permission grant allowed");

View File

@ -334,6 +334,7 @@ class RolesGrantsAndPermissionsGenerator {
.map(RbacPermissionDefinition::getPermission)
.map(RbacView.Permission::permission)
.map(p -> "'" + p + "'")
.sorted()
.toList();
plPgSql.indented(() ->
plPgSql.writeLn("permissions => array[" + joinArrayElements(arrayElements, 3) + "],\n"));

View File

@ -22,6 +22,19 @@ grant select on global to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--//
-- ============================================================================
--changeset rbac-global-IS-GLOBAL-ADMIN:1 endDelimiter:--//
-- ------------------------------------------------------------------
create or replace function isGlobalAdmin()
returns boolean
language plpgsql as $$
begin
return isGranted(currentSubjectsUuids(), findRoleId(globalAdmin()));
end; $$;
--//
-- ============================================================================
--changeset rbac-global-HAS-GLOBAL-PERMISSION:1 endDelimiter:--//
-- ------------------------------------------------------------------

View File

@ -1,5 +1,5 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-06T15:40:13.239729250.
-- This code generated was by RbacViewPostgresGenerator at 2024-03-07T12:25:36.376742633.
-- ============================================================================
@ -80,6 +80,25 @@ execute procedure insertTriggerForTestCustomer_tf();
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Checks if the user or assumed roles are allowed to insert a row to test_customer.
*/
create or replace function test_customer_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception 'insert into test_customer not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger test_customer_insert_permission_check_tg
before insert on test_customer
for each row
-- As there is no explicit INSERT grant specified for this table,
-- only global admins are allowed to insert any rows.
when ( not isGlobalAdmin() )
execute procedure test_customer_insert_permission_missing_tf();
--//
-- ============================================================================

View File

@ -1,5 +1,5 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-06T15:40:13.277446553.
-- This code generated was by RbacViewPostgresGenerator at 2024-03-07T12:25:36.422351715.
-- ============================================================================
@ -194,7 +194,8 @@ create or replace function test_package_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception 'insert into test_package not allowed for current subjects %', currentSubjectsUuids();
raise exception 'insert into test_package not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger test_package_insert_permission_check_tg

View File

@ -74,7 +74,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest {
// then
result.assertExceptionWithRootCauseMessage(
PersistenceException.class,
"add-customer not permitted for test_customer#xxx.admin");
"ERROR: insert into test_customer not allowed for current subjects {test_customer#xxx.admin}");
}
@Test
@ -92,7 +92,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest {
// then
result.assertExceptionWithRootCauseMessage(
PersistenceException.class,
"add-customer not permitted for customer-admin@xxx.example.com");
"ERROR: insert into test_customer not allowed for current subjects {customer-admin@xxx.example.com}");
}