Outcome
By the end of this lesson, you will be able to decide when a custom role is justified, design a custom role from the policy table, and avoid the common anti-patterns that turn custom roles into a maintenance burden.
| Prerequisites | M4.1.L1 (policy table) · M4.1.L2 (system roles) |
| Time | 9 minutes |
1. Concept
A custom role is a role that the customer’s Admin assembles from the policy table. It exists alongside the three system roles (Viewer, Editor, Admin) and is invoked when the system roles do not cleanly fit a job function. The system roles cover most role assignments; custom roles cover the rest.
The mechanics are simple: pick policy entities, pick actions for each, save the role, assign to users. The discipline is harder: most custom-role decisions look obvious at the time and obvious-in-retrospect a year later, but the middle six months are where roles accumulate that nobody can explain.
When custom is justified
SIGNAL CUSTOM-WORTHY?─────────────────────────────────────────────────────────────────────"Editor minus one specific action" Yes"Viewer plus billing:view (Viewer lacks it)" Yes"Job function requires unusual combination Yes (audit-log:view + resource:view, nothing else)""Editor but only for one team's resources" No: that's team scoping (L4)"A few engineers do slightly different work" No: system roles"Senior engineers want Admin but won't manage RBAC" No: keep at Editor"Junior engineer should not start/stop resources" No: use the system Viewer roleThe rule of thumb: a custom role is justified when no system role’s policy set is the right answer and a clear, named job function maps to the role. “Roles for Bob and Alice” is a smell; “Compliance Auditor” is a justification.
Custom role examples
"FinOps Analyst" role Policies: resource:view schedule:view, schedule:create, schedule:update recommendation:view, recommendation:update report:view team:view audit-log:view Excludes: cloud-account:create, role:*, user:* (admin functions)
Use: full operational power on cost surface, no RBAC managementSeeing everyone’s audit rows also needs organisation:view; without it, the Audit Logs page shows only the user’s own rows.
"Compliance Auditor" role Policies: audit-log:view resource:view schedule:view organisation:view report:view
Use: forensic visibility across the surface, zero ability to change anything. Common for SOC2/ISO auditors during evidence collection.A junior engineer who should not start or stop resources does not need a custom role. Assign the system Viewer role, and promote to Editor once the new engineer has shown they are ready (usually 30-90 days).
"Cost-spike Responder" role Policies (Editor minus most): resource:view, resource:update (start/stop) schedule:view, schedule:create (emergency-stop schedules) override:view, override:create audit-log:view notification:view Excludes: recommendation:*, role:*, user:*, cloud-account:*
Use: on-call cost responder. Narrow but high-impact subset.As with the FinOps Analyst, add organisation:view if the responder must see everyone’s audit rows; without it, the Audit Logs page shows only their own.
How to design a custom role
A repeatable five-step process:
1. NAME the job-to-be-done "FinOps Analyst", "Compliance Auditor": not "Bob's role"
2. LIST the surfaces the user needs to interact with Map each surface to its policy entity (L1 covered the mapping)
3. PICK actions per entity View only? Create/update? Apply? Delete?
4. EXCLUDE anything not strictly needed Especially: role:*, user:*, cloud-account:*
5. WRITE the role's purpose down where reviewers will find it A role has a name and a policy list, nothing else. Make the name say the job ("Compliance Auditor"), and record who it is for and why these policies in your access-review doc.Step 5 is the most-skipped step and the most-valuable one. Roles nobody wrote a purpose for become “what does this even do?” within two quarters.
When NOT to use custom
CASE DO INSTEAD──────────────────────────────────────────────────────────"Each engineer is slightly different" Use Editor + team scoping"This person needs Admin sometimes" Add a custom role for the specific Admin capability, keep base role at Editor"Engineer wants extra UI shortcuts" That's a feature ask, not a role change"FinOps team has 8 sub-functions" Cluster to 2-3 patterns; resist per-person roles"Need to restrict by resource type" Supported: grant a type-scoped policy such as resource:view:ec2 instead of the broad policyThe proliferation trap
A common failure mode: every team request becomes a new custom role. Six months in, the org has 23 custom roles, 14 of them differ by one policy from another, and no one knows which to use for a new hire.
The fix is role consolidation reviews, typically quarterly:
QUARTERLY ROLE REVIEW (30 minutes): 1. List all custom roles 2. For each, count active assignments 3. Roles with 0 assignments → archive 4. Roles with 1-2 assignments → consolidate if a similar role covers the use case 5. Update the access-review doc entry for each remaining roleA healthy org has 3-5 custom roles + 3 system roles. More than 8 custom roles is a smell.
How ZopNight uses custom roles
The custom-role patterns that come up most often:
PATTERN─────────────────────────────────────────────────────────"Editor minus role:* / user:*""Viewer plus billing:view""FinOps Analyst" variant"DBA / DataOps" variantIf your first custom role matches one of these patterns, start from the closest system role and adjust its policy list.
2. Demo
A team adds a custom “Database Administrator” role:
NEED: DBAs should view database resources and apply specific recs (Multi-AZ migration), but cannot stop/start DBs in production.
CUSTOM ROLE DESIGN: Name: Database Administrator Policies: resource:view recommendation:view recommendation:update audit-log:view schedule:view (so they can see when DBs are scheduled) Excludes: resource:update (cannot start/stop directly) schedule:create / update / delete (cannot schedule DBs)
ASSIGN to 3 DBAs. Save.
ACCESS-REVIEW DOC ENTRY: "DBAs who own database health. Can view database resources and apply DB-specific recommendations. Cannot start/stop instances: that requires the platform-eng Editor role for production safety."The role takes ~5 minutes to design, days to weeks of safety afterward. The written purpose is what makes it auditable in 6 months.
3. Hands-on (6 min)
Identify one job function on your team that does not cleanly fit Viewer / Editor / Admin. Design a custom role for it:
ROLE NAME: __________________
JOB-TO-BE-DONE (one sentence):__________________________________________________________
POLICIES required (list (entity, action) pairs): __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________
EXPLICITLY EXCLUDED (one sentence per exclusion, why): - __________ : because __________ - __________ : because __________
PURPOSE (one paragraph for your access-review doc):____________________________________________________________________________________________________________________If you cannot fill in the JTBD and Purpose, the role is not yet justified.
Do it through MCP. The same task you just did in the console, asked in one sentence.
BEFORE A ZopNight account with one cloud connected. Admin rights in the org, and one team to scope against.ASK "What policies would a read-only role scoped to the platform team need, and what can my own role already do?"CHECK the scope state. The three-state model in L5 is where most role mistakes hide.Tools behind it: list_role_policies (read, Govern), get_my_permissions (read, Introspect). Creating the role can also go through MCP: create_role, update_role and delete_role are Tier 1 Govern writes and need a bound token. Assigning the role to people stays a console action. Connection details are in the MCP integration docs.
4. Knowledge check
Q1
A FinOps Analyst needs all the Editor permissions but cannot manage cloud-account credentials. The best approach:
A. Use the Editor role and simply trust the user never to rotate any of the connected cloud credentials themselves
B. Promote them to the Admin role temporarily whenever it happens to be needed for a particular task
C. Use the Viewer role and grant exceptions on a per-task basis instead, each time one comes up
D. Build a custom role with all Editor policies EXCEPT cloud-account:create, cloud-account:update, and cloud-account:delete
Show answer
Correct: D. “Editor minus specific actions” is the most common custom-role pattern. Trust is not a control; explicit exclusion is.
Q2
A team has 12 custom roles, several differing by only one policy. The most likely root cause:
A. The team genuinely has 12 distinct job functions
B. Over-customization. Each new request became a role
C. The system roles are inadequate
D. Compliance requires per-person roles
Show answer
Correct: B. The fix is quarterly consolidation; cluster similar roles, archive unused ones, get back to 3-5 custom roles. 12 custom roles in a single team is a maintenance burden and an audit problem. Quarterly review with hard consolidation is the corrective.
Q3
Custom role policies are:
A. A separate system from the policy table used by system roles
B. Defined separately for each cloud provider
C. Defined in YAML and deployed with the service
D. Drawn from the same policy table
Show answer
Correct: D. System roles and custom roles share the policy primitives, which means a custom role can be expressed as “system role X plus/minus these specific policies”: useful for documentation. One policy table, shared primitives. Custom roles are subsets/supersets expressed in the same vocabulary.
5. Apply
Build custom roles in Settings → Roles. The policy picker lists every policy, grouped by entity; check the actions you want. Re-read the checked list before saving: it is the role’s whole effect. Then record the role’s purpose in your access-review doc.
Schedule a recurring quarterly role review on your team calendar. Thirty minutes per quarter prevents the proliferation trap.