算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
backend-authorization【设计与创意】Use this skill when the user says 'authorization', 'access control', 'RBAC', 'ABAC', 'ReBAC', 'permissions', 'role', 'policy', 'Casbin', 'Cerbos', 'permission delegation', 'temporary access', 'break glass', 'super admin', 'JIT elevation', 'role hierarchy', or when designing or implementing authorization for any backend application. This skill covers:…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Design and implement authorization that is correct, auditable, and maintainable. Every protected resource must have an explicit access decision. Authorization rules live in code or policy, never in the developer's head.
How many resource types need access control?
├── < 10 → Flat RBAC (simple role-permission map)
└── >= 10 → Do roles map well to resources?
├── Yes → Does every user fit a single role?
│ ├── Yes → Hierarchical RBAC (roles + inheritance)
│ └── No → RBAC + ABAC hybrid (roles for coarse, attributes for exceptions)
└── No → Does access depend on relationships between entities?
├── Yes → ReBAC (Zanzibar-style relationship tuples)
└── No → ABAC (attribute-based policies for maximal flexibility)
Regulatory requirements (SoD, audit)?
├── Yes → Constrained RBAC with SoD enforcement
└── No → Standard RBAC or ABAC
Multi-tenant?
├── Yes → RBAC + scope-based authorization (org/department/team isolation)
└── No → Single-tenant RBAC or ABAC
Existing policy engine in stack?
├── Yes → Leverage existing engine
└── No → Cloud-native / K8s?
├── Yes → OPA (sidecar deployment, Rego policies, K8s admission control)
└── No → Need GUI for non-devs to manage policies?
├── Yes → Permit.io (SaaS, visual policy editor)
└── No → Multi-language support critical?
├── Yes → Casbin (libraries for 10+ languages, in-app)
└── No → Fine-grained, human-readable policies?
├── Yes → Cerbos (YAML policies, sidecar)
└── No → ReBAC at massive scale?
└── AuthZed / SpiceDB (Zanzibar, gRPC API)
Emergency scenario (production outage)?
├── Yes → Break-glass protocol: MFA required, 30 min expiry, security team notified
└── No → Need temporary elevated permissions?
├── Yes → JIT elevation: request + approval, time-bound, auto-expire
└── No → Need to delegate permissions?
└── Delegation: delegator-scoped, time-bound, non-cascading
Exact user phrases: "authorization", "access control", "RBAC", "ABAC", "ReBAC", "permissions", "role", "policy engine", "Casbin", "Cerbos", "Permit.io", "OPA", "permission delegation", "temporary access", "break glass", "super admin", "master admin", "JIT elevation", "role hierarchy", "permission model", "least privilege", "separation of duties", "I want to restrict access".
Authorization architecture document: model selection, role tree, permission matrix, policy structure, integration plan.
Model: {RBAC|ABAC|ReBAC|Hybrid}
Role Tree: {top-level roles, hierarchy depth}
Granularity: {coarse|fine|mixed}
Policy Engine: {native|Casbin|OPA|Cerbos}
Admin Pattern: {flat|hierarchical|break-glass}
Testing: {matrix|regression|fuzzing}
Authorization architecture: 25 lines maximum.
Map every resource and action in the system:
| Resource | Actions | Conditions |
|---|---|---|
| Invoice | create, read, update, delete, approve | own dept only, business hours |
| User | read, update, deactivate | same org level |
| Workspace | create, read, update, delete, invite | quota limits |
| Report | generate, export, schedule | premium tier only |
Collect:
| Model | Granularity | Complexity | Scale | Best For |
|---|---|---|---|---|
| ACL | Per-resource | Low | Small | Simple file sharing |
| RBAC (Core) | Role-level | Low | Large | Enterprise apps, orgs with clear roles |
| RBAC (Hierarchical) | Role-level + inheritance | Medium | Large | Multi-level orgs, subsidiaries |
| RBAC (Constrained) | Role + SoD | Medium | Large | Regulated industries |
| ABAC | Attribute-level | High | Very large | Multi-tenant, document-level, context-aware |
| ReBAC | Relationship-level | High | Very large | Collaboration, social, hierarchical data |
Decision matrix:
Define permission levels and granularity:
Global (SaaS-wide)
└── Organization (company)
└── Workspace (project/team)
└── Resource (document, record, asset)
└── Field (specific column/attribute)
Coarse-grained permissions (RBAC level):
workspace.read, workspace.write, workspace.deleteeditor can workspace.read + workspace.writeFine-grained permissions (ABAC level):
document.read where document.department == user.departmentinvoice.approve where amount < 10000 && user.role == 'manager'Permission types:
| Type | Example | Enforcement |
|---|---|---|
| Functional | report.export | UI hide + API guard |
| Data | read own records only | Query filter + row-level security |
| Field | view salary column | GraphQL field resolver |
| Environmental | approve during business hours | Policy condition |
| Administrative | deactivate user | Admin guard + audit |
// Role-to-permission mapping (source of truth)
const PERMISSIONS = {
admin: ['*'],
manager: ['workspace.*', 'report.*', 'user.read', 'user.invite'],
editor: ['workspace.read', 'workspace.write', 'document.*'],
viewer: ['workspace.read', 'document.read'],
guest: ['document.read']
};
// Authorization check
function authorize(user, action, resource) {
const role = user.role;
const permissions = PERMISSIONS[role];
if (!permissions) return false;
if (permissions.includes('*')) return true;
return permissions.some(p =>
p === `${resource}.${action}` ||
p === `${resource}.*` ||
p === `*.${action}` ||
p === '*'
);
}
Rules:
{resource}.{action} format with wildcard support.Role hierarchy with inheritance:
super-admin (everything, cross-org)
└── org-admin (everything within one org)
└── manager (inherits manager perms + department scope)
└── lead (inherits lead perms + team scope)
└── member (basic perms)
// Role hierarchy with inherited permissions
const ROLE_HIERARCHY = {
'super-admin': { parent: null, scope: 'global' },
'org-admin': { parent: 'super-admin' | 'org-admin' | 'manager' | 'lead' | null, scope: 'org' },
'manager': { parent: 'org-admin', scope: 'department' },
'lead': { parent: 'manager', scope: 'team' },
'member': { parent: 'lead', scope: 'self' }
};
function getEffectivePermissions(role) {
let perms = new Set(PERMISSIONS[role] || []);
let current = ROLE_HIERARCHY[role];
while (current?.parent) {
const parentPerms = PERMISSIONS[current.parent] || [];
parentPerms.forEach(p => perms.add(p));
current = ROLE_HIERARCHY[current.parent];
}
return [...perms];
}
Separation of Duties (SoD):
// Static SoD — mutually exclusive roles
const SOD_STATIC = {
'purchase-approver': ['purchase-requester', 'purchase-receiver'],
'auditor': ['accountant', 'treasurer']
};
// Dynamic SoD — cannot act on same resource
function checkDynamicSoD(userId, action, resourceId) {
const history = getRecentActions(userId, resourceId);
if (action === 'approve' && history.includes('submit')) {
return false; // Cannot approve your own submission
}
return true;
}
Scope-based authorization for multi-org:
function authorizeScoped(user, action, resource, resourceOrgId) {
const roleInfo = ROLE_HIERARCHY[user.role];
if (!roleInfo) return false;
// Scope check
switch (roleInfo.scope) {
case 'global': return true; // super-admin sees everything
case 'org': return user.orgId === resourceOrgId;
case 'department': return user.deptId === getResourceDept(resourceOrgId);
case 'team': return user.teamId === getResourceTeam(resourceOrgId);
case 'self': return user.id === getResourceOwner(resourceOrgId);
default: return false;
}
}
For when role-level is too coarse:
// ABAC policy rule
const POLICY = {
"effect": "deny",
"target": {
"resource": "invoice",
"action": "approve"
},
"condition": {
"all": [
{ "subject.role": { "neq": "admin" } },
{ "resource.amount": { "gt": 10000 } },
{ "subject.department": { "neq": "resource.department" } }
]
}
};
// ABAC evaluation engine
function evaluateABAC(subject, resource, action, env, policies) {
for (const policy of policies) {
if (matchesTarget(policy.target, resource, action)) {
if (evaluateConditions(policy.condition, { subject, resource, env })) {
return policy.effect === 'allow';
}
}
}
return false; // default deny
}
Attribute sources:
| Attribute Type | Examples | Source |
|---|---|---|
| Subject | role, department, clearance, location | JWT token / User DB |
| Resource | owner, department, classification, tier | Resource DB |
| Action | read, write, approve, delete | Request path + method |
| Environment | time, IP, device trust, risk score | Request context |
JIT (Just-In-Time) elevation:
// Elevation request
async function elevateRole(userId, targetRole, reason, durationMinutes) {
if (!canRequestElevation(userId, targetRole)) {
throw new Error('Elevation not permitted');
}
const approval = await requestApproval(userId, targetRole, reason);
if (!approval.approved) {
throw new Error('Elevation denied');
}
// Create time-bound elevation
await createElevation({
userId,
elevatedRole: targetRole,
expiresAt: Date.now() + durationMinutes * 60_000,
reason,
approvedBy: approval.approvedBy,
auditId: crypto.randomUUID()
});
// Log audit event
await logSecurityEvent('role_elevation', {
userId, targetRole, reason, durationMinutes, approvedBy: approval.approvedBy
});
}
Permission delegation:
async function delegatePermission(delegatorId, delegateId, actions, resourceScope, expiresAt) {
// Verify delegator owns the resource scope
if (!ownsScope(delegatorId, resourceScope)) {
throw new Error('Cannot delegate what you do not own');
}
await createDelegation({
delegatorId, delegateId, actions, resourceScope, expiresAt,
revoked: false
});
}
// Check including delegation
function authorizeWithDelegation(user, action, resource) {
return (
authorize(user, action, resource) ||
hasDelegatedPermission(user.id, action, resource)
);
}
Break-glass (emergency access):
async function breakGlassAccess(userId, resourceId, reason) {
// Must have break-glass capability
if (!userHasCapability(userId, 'break-glass')) {
throw new Error('User not authorized for break-glass');
}
// Create time-limited emergency session
const session = await createEmergencySession({
userId,
resourceId,
reason,
accessLevel: 'admin',
expiresAt: Date.now() + 30 * 60_000, // 30 minutes
multiFactorRequired: true
});
// Notify security team immediately
await notifySecurityTeam('BREAK_GLASS_ACTIVATED', {
userId, resourceId, reason, sessionId: session.id
});
// Log everything
await logSecurityEvent('break_glass', {
userId, resourceId, reason, sessionId: session.id
});
return session;
}
Admin role patterns:
| Pattern | Access | Use Case |
|---|---|---|
| Super Admin | Unrestricted, cross-system | Platform-wide emergency, initial setup |
| Org Admin | Full within one org unit | Subsidiary administration |
| System Admin | Infrastructure only | DevOps, deployments |
| Audit Admin | Read-only + audit log | Compliance, investigations |
| Support Admin | User management + read | Customer support |
| Billing Admin | Finance + subscriptions | Billing operations |
| Delegated Admin | Scoped subset of admin | Department leads managing their team |
| Engine | Language | Model | Deployment | Best For |
|---|---|---|---|---|
| Casbin | Go, Node.js, Python, Java, .NET, Rust | PERM metamodel | In-app library | RBAC/ABAC/ACL in any language |
| OPA/Rego | Rego | Declarative policies | Sidecar/bundle | Cloud-native, K8s, multi-service |
| Cerbos | YAML | Resource policies | Sidecar/Docker | Fine-grained, user-friendly |
| Permit.io | Python, Node.js, Go, REST | RBAC/ABAC/ReBAC | SaaS/self-hosted | Rapid deployment, GUI policy editor |
| AuthZed/SpiceDB | Zanzibar | Relationship tuples | gRPC API | ReBAC at scale |
Casbin example (Node.js):
const { newEnforcer } = require('casbin');
// model.conf (RBAC with hierarchy)
// [request_definition]
// r = sub, obj, act
// [policy_definition]
// p = sub, obj, act
// [role_definition]
// g = _, _
// g2 = _, _
// [matchers]
// m = g(r.sub, p.sub) || g2(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
const enforcer = await newEnforcer('model.conf', 'policy.csv');
const allowed = await enforcer.enforce('alice', 'invoice:123', 'approve');
OPA example (Rego):
package authz
default allow = false
# RBAC rules
allow {
user_has_role(input.user_id, "admin")
}
allow {
role := user_role(input.user_id)
permission := data.permissions[role][_]
permission.resource == input.resource
permission.action == input.action
}
user_has_role(user_id, role) {
data.roles[user_id] == role
}
user_role(user_id) := data.roles[user_id]
Permission matrix testing:
// Test every role against every resource+action
const TEST_MATRIX = [
{ role: 'admin', actions: ['*'], expected: 'allow' },
{ role: 'manager', actions: ['workspace.*', 'report.*'], expected: 'allow' },
{ role: 'manager', actions: ['workspace.delete'], expected: 'deny' },
{ role: 'editor', actions: ['workspace.read', 'doc.write'], expected: 'allow' },
{ role: 'editor', actions: ['workspace.delete'], expected: 'deny' },
{ role: 'viewer', actions: ['workspace.write'], expected: 'deny' },
];
test('authorization matrix', () => {
for (const { role, actions, expected } of TEST_MATRIX) {
for (const action of actions) {
const result = authorize({ role }, action, 'workspace');
expect(result).toBe(expected);
}
}
});
Negative testing:
Audit requirements:
Regression testing for policy changes:
if (user.id === 'admin-user'). Fix → Never reference specific users — use roles and attributes.*.* grants access to everything. Fix → Be explicit. Use wildcards only for true admin roles.default_decision timeout. Cerbos: configure evaluation deadline.| Engine | P50 (simple) | P50 (complex) | P99 (complex) |
|---|---|---|---|
| In-app (Casbin) | ~0.05ms | ~0.5ms | ~2ms |
| Sidecar (OPA) | ~0.5ms | ~5ms | ~20ms |
| Sidecar (Cerbos) | ~1ms | ~3ms | ~15ms |
| Network (SpiceDB) | ~5ms | ~15ms | ~50ms |
| SaaS (Permit.io) | ~15ms | ~30ms | ~100ms |
-- Row-Level Security (RLS) in PostgreSQL
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.current_tenant_id'));
CREATE POLICY user_scope ON documents
USING (
owner_id = current_setting('app.current_user_id')
OR current_setting('app.current_role') = 'admin'
);
-- Always set session context at auth middleware
SELECT set_config('app.current_user_id', $1, false),
set_config('app.current_role', $2, false),
set_config('app.current_tenant_id', $3, false);
Express middleware with policy engine:
function authorizeMiddleware(action, resourceType) {
return async (req, res, next) => {
const decision = await policyEngine.check({
subject: { id: req.user.id, role: req.user.role, department: req.user.dept },
resource: { type: resourceType, id: req.params.id, ...resourceMeta(req) },
action,
env: { time: new Date(), ip: req.ip }
});
if (!decision.allowed) {
throw new ForbiddenError(decision.reason || 'Access denied');
}
// Attach decision metadata for downstream enforcement
req.authz = { decision, scope: decision.scope };
next();
};
}
FastAPI dependency injection:
from fastapi import Depends, HTTPException
async def require_permission(action: str, resource: str):
async def dependency(user: dict = Depends(get_current_user)):
allowed = await authz_client.check({
"subject": user,
"action": action,
"resource": resource
})
if not allowed:
raise HTTPException(status_code=403, detail="Access denied")
return user
return dependency
@app.get("/invoices/{invoice_id}")
async def get_invoice(
invoice_id: str,
user: dict = Depends(require_permission("read", "invoice"))
):
return await invoice_service.get(invoice_id, user)
ASP.NET Core policy-based auth:
public class InvoiceAuthorizationHandler : AuthorizationHandler<InvoiceRequirement, Invoice>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
InvoiceRequirement requirement,
Invoice resource)
{
var userDept = context.User.FindFirst("department")?.Value;
if (userDept == resource.Department)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
// Registration
services.AddAuthorization(options => {
options.AddPolicy("InvoiceAccess", policy =>
policy.Requirements.Add(new InvoiceRequirement()));
});
Go HTTP middleware:
func Authorize(engine *casbin.Enforcer) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value("user").(*User)
resource := r.URL.Path
action := r.Method
allowed, err := engine.Enforce(user.Role, resource, action)
if err != nil || !allowed {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
}
No artifact produced unless requested. Next skill: authentication (frontend) — implement login UI, route guards, token storage for the auth system. Next skill: multi-tenancy — combine authorization with tenant isolation for SaaS apps. Next skill: api-security — apply authorization to API endpoints with rate limiting and WAF. Carry forward: authorization model, role tree, permission matrix, policy engine choice.