check for unused grants

This commit is contained in:
Michael Hoennig 2024-02-23 12:31:08 +01:00
parent 74071c15db
commit 54cff5ece9

View File

@ -4,6 +4,7 @@ import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacPermissionDefinition;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -17,6 +18,7 @@ import static org.apache.commons.lang3.StringUtils.uncapitalize;
class RolesGrantsAndPermissionsGenerator { class RolesGrantsAndPermissionsGenerator {
private final RbacView rbacDef; private final RbacView rbacDef;
private final Set<RbacView.RbacGrantDefinition> rbacGrants = new HashSet<>();
private final String liquibaseTagPrefix; private final String liquibaseTagPrefix;
private final Class<?> entityClass; private final Class<?> entityClass;
private final String simpleEntityName; private final String simpleEntityName;
@ -25,6 +27,7 @@ class RolesGrantsAndPermissionsGenerator {
RolesGrantsAndPermissionsGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) { RolesGrantsAndPermissionsGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
this.rbacDef = rbacDef; this.rbacDef = rbacDef;
this.rbacGrants.addAll(rbacGrants);
this.liquibaseTagPrefix = liquibaseTagPrefix; this.liquibaseTagPrefix = liquibaseTagPrefix;
entityClass = rbacDef.getEntityAlias().entityClass(); entityClass = rbacDef.getEntityAlias().entityClass();
@ -101,22 +104,26 @@ class RolesGrantsAndPermissionsGenerator {
.replace("%{simpleEntityVarName)", simpleEntityVarName) .replace("%{simpleEntityVarName)", simpleEntityVarName)
.replace("%{roleSuffix}", capitalize(role.roleName()))); .replace("%{roleSuffix}", capitalize(role.roleName())));
final var permissionsForRole = findPermissionsGrantsForRole(rbacDef.getEntityAlias(), role); final var permissionGrantsForRole = findPermissionsGrantsForRole(rbacDef.getEntityAlias(), role);
if (!permissionsForRole.isEmpty()) { if (!permissionGrantsForRole.isEmpty()) {
final var permissionsForRoleInPlPgSql = permissionsForRole.stream() final var permissionsForRoleInPlPgSql = permissionGrantsForRole.stream()
.map(RbacView.RbacGrantDefinition::getPermDef)
.map(RbacPermissionDefinition::getPermission) .map(RbacPermissionDefinition::getPermission)
.map(RbacView.Permission::permission) .map(RbacView.Permission::permission)
.map(p -> "'" + p + "'") .map(p -> "'" + p + "'")
.collect(joining(", ")); .collect(joining(", "));
plPgSql.append(indent(3) + "permissions => array[" + permissionsForRoleInPlPgSql + "],\n"); plPgSql.append(indent(3) + "permissions => array[" + permissionsForRoleInPlPgSql + "],\n");
rbacGrants.removeAll(permissionGrantsForRole);
} }
final var grantsToUsers = findGrantsToUserForRole(rbacDef.getEntityAlias(), role); final var grantsToUsers = findGrantsToUserForRole(rbacDef.getEntityAlias(), role);
if (!grantsToUsers.isEmpty()) { if (!grantsToUsers.isEmpty()) {
final var grantsToUsersPlPgSql = grantsToUsers.stream() final var grantsToUsersPlPgSql = grantsToUsers.stream()
.map(u -> toPlPgSqlReference(u)) .map(RbacView.RbacGrantDefinition::getUserDef)
.map(this::toPlPgSqlReference)
.collect(joining(", ")); .collect(joining(", "));
plPgSql.append(indent(3) + "userUuids => array[" + grantsToUsersPlPgSql + "],\n"); plPgSql.append(indent(3) + "userUuids => array[" + grantsToUsersPlPgSql + "],\n");
rbacGrants.removeAll(grantsToUsers);
} }
final var incomingGrants = findIncomingSuperRolesForRole(rbacDef.getEntityAlias(), role); final var incomingGrants = findIncomingSuperRolesForRole(rbacDef.getEntityAlias(), role);
@ -126,6 +133,7 @@ class RolesGrantsAndPermissionsGenerator {
.map(r -> toPlPgSqlReference(NEW, r)) .map(r -> toPlPgSqlReference(NEW, r))
.collect(joining(", ")); .collect(joining(", "));
plPgSql.append(indent(3) + "incomingSuperRoles => array[" + incomingGrantsInPlPgSql + "],\n"); plPgSql.append(indent(3) + "incomingSuperRoles => array[" + incomingGrantsInPlPgSql + "],\n");
rbacGrants.removeAll(incomingGrants);
} }
final var outgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getEntityAlias(), role); final var outgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getEntityAlias(), role);
@ -135,38 +143,41 @@ class RolesGrantsAndPermissionsGenerator {
.map(r -> toPlPgSqlReference(NEW, r)) .map(r -> toPlPgSqlReference(NEW, r))
.collect(joining(", ")); .collect(joining(", "));
plPgSql.append(indent(3) + "outgoingSubRoles => array[" + outgoingGrantsInPlPgSql + "],\n"); plPgSql.append(indent(3) + "outgoingSubRoles => array[" + outgoingGrantsInPlPgSql + "],\n");
rbacGrants.removeAll(outgoingGrants);
}
if (!rbacGrants.isEmpty()) {
throw new IllegalStateException("unprocessed grants: " + rbacGrants);
} }
chopTail(plPgSql, ",\n"); chopTail(plPgSql, ",\n");
plPgSql.append("\n" + indent(2) + ");\n"); plPgSql.append("\n" + indent(2) + ");\n");
} }
private Set<RbacPermissionDefinition> findPermissionsGrantsForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) { private Set<RbacView.RbacGrantDefinition> findPermissionsGrantsForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role); final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacDef.getGrantDefs().stream() return rbacGrants.stream()
.filter(g -> g.grantType() == ROLE_TO_PERM && g.getSuperRoleDef()==roleDef ) .filter(g -> g.grantType() == ROLE_TO_PERM && g.getSuperRoleDef()==roleDef )
.map(RbacView.RbacGrantDefinition::getPermDef)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
private Set<RbacView.RbacUserReference> findGrantsToUserForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) { private Set<RbacView.RbacGrantDefinition> findGrantsToUserForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role); final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacDef.getGrantDefs().stream() return rbacGrants.stream()
.filter(g -> g.grantType() == USER_TO_ROLE && g.getSubRoleDef() == roleDef ) .filter(g -> g.grantType() == USER_TO_ROLE && g.getSubRoleDef() == roleDef )
.map(RbacView.RbacGrantDefinition::getUserDef)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
private Set<RbacView.RbacGrantDefinition> findIncomingSuperRolesForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) { private Set<RbacView.RbacGrantDefinition> findIncomingSuperRolesForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role); final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacDef.getGrantDefs().stream() return rbacGrants.stream()
.filter(g -> g.grantType() == ROLE_TO_ROLE && g.getSubRoleDef()==roleDef ) .filter(g -> g.grantType() == ROLE_TO_ROLE && g.getSubRoleDef()==roleDef )
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
private Set<RbacView.RbacGrantDefinition> findOutgoingSuperRolesForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) { private Set<RbacView.RbacGrantDefinition> findOutgoingSuperRolesForRole(final RbacView.EntityAlias entityAlias, final RbacView.Role role) {
final var roleDef = rbacDef.findRbacRole(entityAlias, role); final var roleDef = rbacDef.findRbacRole(entityAlias, role);
return rbacDef.getGrantDefs().stream() return rbacGrants.stream()
.filter(g -> g.grantType() == ROLE_TO_ROLE && g.getSuperRoleDef()==roleDef ) .filter(g -> g.grantType() == ROLE_TO_ROLE && g.getSuperRoleDef()==roleDef )
.filter(g -> g.getSubRoleDef().getEntityAlias() != entityAlias) .filter(g -> g.getSubRoleDef().getEntityAlias() != entityAlias)
.collect(Collectors.toSet()); .collect(Collectors.toSet());