Role-Based Network Access Control
Learn this problemProblem statement
Implement a role-based network access-control system by processing a finite ordered batch of operations.
Entities
- A user may have many roles.
- A role may have many permissions.
- A permission has an identifier, an effect of
ALLOWorDENY, and zero or more required property pairs. - A permission is applicable to a check only when every required key-value pair exactly matches a property supplied by that check. A permission with no required properties is always applicable.
Operations
Each row of operations is one of the following forms:
["CREATE_USER", userId]["CREATE_ROLE", roleId]["CREATE_PERMISSION", permissionId, effect, k, key1, value1, ..., keyk, valuek]["ASSIGN_PERMISSION", roleId, permissionId]["ASSIGN_ROLE", userId, roleId]["CHECK", userId, k, key1, value1, ..., keyk, valuek]
User, role, and permission identifiers are unique when created. Repeating an existing role assignment or permission assignment is an idempotent no-op.
An assignment or check that references an entity that has not been created is invalid: append ERROR to the result and do not mutate any state. All other non-check operations are valid and produce no result.
Access decision
For a valid CHECK, evaluate every applicable permission reachable through all roles assigned to the user:
- If any applicable permission has effect
DENY, appendDENY. - Otherwise, if at least one applicable permission has effect
ALLOW, appendALLOW. - Otherwise, append
DENY.
Return the emitted results in operation order. The judged batch represents one serial history; concurrent updates and distributed replication are outside the returned result contract.
Function
evaluateAccess(operations: String[][]) → String[]Examples
Example 1
operations = [["CREATE_USER","alice"],["CREATE_ROLE","engineer"],["CREATE_PERMISSION","prod-read","ALLOW","1","env","prod"],["ASSIGN_PERMISSION","engineer","prod-read"],["ASSIGN_ROLE","alice","engineer"],["CHECK","alice","1","env","prod"],["CHECK","alice","1","env","dev"]]return = ["ALLOW","DENY"]The permission applies to the first check because env=prod matches, so access is allowed. It does not apply to the second check, so the default decision is DENY.
Example 2
operations = [["CREATE_USER","bob"],["CREATE_ROLE","member"],["CREATE_ROLE","security"],["CREATE_PERMISSION","read-docs","ALLOW","1","resource","docs"],["CREATE_PERMISSION","block-suspended","DENY","2","resource","docs","status","suspended"],["ASSIGN_PERMISSION","member","read-docs"],["ASSIGN_PERMISSION","security","block-suspended"],["ASSIGN_ROLE","bob","member"],["ASSIGN_ROLE","bob","security"],["CHECK","bob","2","resource","docs","status","active"],["CHECK","bob","2","resource","docs","status","suspended"],["CHECK","bob","1","resource","code"]]return = ["ALLOW","DENY","DENY"]The allow applies to active document access. For suspended document access, both permissions apply and the deny wins. No permission applies to the code resource, so access defaults to DENY.
Example 3
operations = [["CREATE_USER","u"],["CREATE_ROLE","r"],["CREATE_PERMISSION","p","ALLOW","0"],["ASSIGN_PERMISSION","r","p"],["ASSIGN_PERMISSION","r","p"],["ASSIGN_ROLE","u","r"],["ASSIGN_ROLE","u","r"],["CHECK","u","0"],["ASSIGN_ROLE","u","missing"],["CHECK","missing","0"]]return = ["ALLOW","ERROR","ERROR"]Duplicate assignments do not change the state. The unconditional allow makes the valid check succeed. The unknown role assignment and unknown user check each emit ERROR.
Constraints
1 <= operations.length <= 10^5.- The total number of strings across all operation rows is at most
2 * 10^5. - Every row has exactly the length required by its operation, and every
kis a valid non-negative integer. - User, role, and permission identifiers are non-empty and unique within their entity type when created.
- Each permission effect is
ALLOWorDENY. - Property keys are unique within one permission or check, and all identifiers, keys, and values are non-null strings.
- Only references to entities that have not yet been created are invalid; operation names and row encodings are otherwise valid.