Claude Skills Guide

Claude Code for ABAC: Attribute-Based Access Control Guide

Attribute-Based Access Control (ABAC) represents a powerful evolution beyond traditional role-based access control (RBAC). Instead of assigning users to fixed roles, ABAC makes access decisions based on attributes of the subject, resource, action, and environment. This flexibility enables fine-grained, context-aware authorization that adapts to complex business requirements. In this guide, you’ll learn how to design and implement ABAC systems using Claude Code to accelerate your development workflow.

Understanding ABAC Fundamentals

ABAC operates on a simple but powerful concept: access decisions are made by evaluating attributes against policies. A policy consists of conditions that, when satisfied, grant or deny access. The four primary attribute categories form the foundation of any ABAC implementation.

Subject attributes describe the entity requesting access. These include user properties such as department, job title, security clearance level, and authentication method. For example, a subject attribute might specify that only users with a “senior” level and “engineering” department can access production databases.

Resource attributes define the object being accessed. File classifications, document sensitivity levels, API endpoint requirements, and data owner information all qualify as resource attributes. A sensitive financial report might require a resource attribute indicating it needs “confidential” classification.

Action attributes specify what the subject wants to do. Common actions include read, write, delete, and execute. Some implementations also support complex actions like “approve” or “delegate” that carry specific business meanings.

Environment attributes capture contextual information about the access attempt. Time of day, geographic location, device type, and network security status all influence access decisions. A user attempting to access sensitive data from an unrecognized location might face additional verification requirements.

Designing ABAC Policies

Effective ABAC policy design requires careful consideration of your organization’s security requirements and business logic. Start by cataloging the attributes available in your system, then build policies that reflect your access control philosophy.

Begin with a policy language that supports expressive conditions. XACML (eXtensible Access Control Markup Language) provides a standardized approach, though many organizations implement custom policy engines using JSON or YAML. Here’s a practical policy structure you might implement:

{
  "policyId": "engineering-prod-access",
  "description": "Grant senior engineers access to production systems during business hours",
  "target": {
    "resource": {
      "type": "api_endpoint",
      "environment": "production"
    }
  },
  "conditions": [
    {
      "subject": {
        "department": "engineering",
        "level": { "operator": "gte", "value": "senior" }
      },
      "environment": {
        "time": {
          "operator": "between",
          "start": "09:00",
          "end": "18:00",
          "timezone": "UTC"
        }
      }
    }
  ],
  "effect": "permit"
}

When designing policies, follow the principle of least privilege by default. Explicitly grant access rather than trying to deny everything. Also consider policy combination algorithms—your system must define how multiple policies interact when they produce different results.

Implementing ABAC with Claude Code

Claude Code can significantly accelerate your ABAC implementation by generating policy structures, creating evaluation engines, and helping you reason through complex authorization scenarios. Here’s how to integrate Claude into your ABAC development workflow.

Start by creating a TypeScript-based ABAC evaluation engine. Claude can help scaffold the core components:

type AttributeValue = string | number | boolean | string[];

interface SubjectAttributes {
  id: string;
  department: string;
  level: string;
  roles: string[];
  clearanceLevel?: number;
}

interface ResourceAttributes {
  id: string;
  type: string;
  classification: string;
  owner: string;
  sensitivity: string;
}

interface ActionAttributes {
  operation: 'read' | 'write' | 'delete' | 'execute';
  target?: string;
}

interface EnvironmentAttributes {
  timestamp: Date;
  ipAddress: string;
  deviceType: 'desktop' | 'mobile' | 'tablet';
  networkSecure: boolean;
  location?: string;
}

interface AccessRequest {
  subject: SubjectAttributes;
  resource: ResourceAttributes;
  action: ActionAttributes;
  environment: EnvironmentAttributes;
}

interface Policy {
  id: string;
  description: string;
  conditions: PolicyCondition[];
  effect: 'permit' | 'deny';
  priority?: number;
}

interface PolicyCondition {
  subject?: Record<string, AttributeValue>;
  resource?: Record<string, AttributeValue>;
  action?: Record<string, AttributeValue>;
  environment?: Record<string, AttributeValue>;
}

The evaluation function processes requests against policies:

class ABACEngine {
  private policies: Policy[];

  constructor(policies: Policy[]) {
    this.policies = policies.sort((a, b) => 
      (b.priority ?? 0) - (a.priority ?? 0)
    );
  }

  evaluate(request: AccessRequest): boolean {
    for (const policy of this.policies) {
      if (this.matchesTarget(request, policy)) {
        if (this.evaluateConditions(request, policy)) {
          return policy.effect === 'permit';
        }
      }
    }
    return false; // Default deny
  }

  private matchesTarget(request: AccessRequest, policy: Policy): boolean {
    // Implement target matching logic
    return true;
  }

  private evaluateConditions(request: AccessRequest, policy: Policy): boolean {
    return policy.conditions.every(condition => {
      return this.checkAttributes(request.subject, condition.subject) &&
             this.checkAttributes(request.resource, condition.resource) &&
             this.checkAttributes(request.action, condition.action) &&
             this.checkAttributes(request.environment, condition.environment);
    });
  }

  private checkAttributes(
    actual: Record<string, AttributeValue>,
    expected?: Record<string, AttributeValue>
  ): boolean {
    if (!expected) return true;
    
    for (const [key, expectedValue] of Object.entries(expected)) {
      const actualValue = actual[key];
      if (!this.compareValues(actualValue, expectedValue)) {
        return false;
      }
    }
    return true;
  }

  private compareValues(actual: AttributeValue, expected: AttributeValue): boolean {
    if (typeof expected === 'object' && 'operator' in expected) {
      const { operator, value, ...rest } = expected as any;
      switch (operator) {
        case 'eq': return actual === value;
        case 'neq': return actual !== value;
        case 'gte': return (actual as number) >= value;
        case 'lte': return (actual as number) <= value;
        case 'in': return (value as string[]).includes(actual as string);
        case 'contains': return (actual as string[]).includes(value);
        default: return false;
      }
    }
    return actual === expected;
  }
}

Real-World ABAC Patterns

Several common patterns emerge in enterprise ABAC implementations. Understanding these patterns helps you design more effective authorization systems.

The time-based access pattern restricts operations to specific hours. A policy might allow managers to approve expense reports only during business hours, preventing after-hours approvals that could indicate fraud. Combine time conditions with subject attributes to create exceptions for on-call staff.

The conditional delegation pattern allows authorized users to temporarily grant access to others. A project manager might delegate document review permissions to a team member during vacation. Delegation policies typically include expiration times and scope limitations.

The risk-adaptive access pattern adjusts requirements based on detected risk factors. Access attempts from new devices, unusual locations, or abnormal access patterns might trigger additional verification. This pattern integrates well with fraud detection systems.

The resource hierarchy pattern applies policies based on organizational structure. Access to a parent resource might cascade to child resources, or you might enforce stricter controls at deeper levels. This pattern helps maintain consistent security across complex resource trees.

Testing ABAC Policies

Comprehensive testing ensures your ABAC implementation correctly enforces access controls. Use Claude Code to generate test cases covering both positive and negative scenarios.

describe('ABAC Engine', () => {
  const policies: Policy[] = [
    {
      id: 'senior-eng-prod',
      description: 'Senior engineers access production',
      conditions: [
        {
          subject: { department: 'engineering', level: 'senior' },
          resource: { environment: 'production' },
          action: { operation: 'read' }
        }
      ],
      effect: 'permit'
    }
  ];

  const engine = new ABACEngine(policies);

  it('permits senior engineer to read production data', () => {
    const request: AccessRequest = {
      subject: { id: 'user1', department: 'engineering', level: 'senior', roles: ['engineer'] },
      resource: { id: 'api', type: 'service', classification: 'internal', owner: 'platform', sensitivity: 'medium', environment: 'production' },
      action: { operation: 'read' },
      environment: { timestamp: new Date(), ipAddress: '10.0.0.1', deviceType: 'desktop', networkSecure: true }
    };
    
    expect(engine.evaluate(request)).toBe(true);
  });

  it('denies junior engineer access to production', () => {
    const request: AccessRequest = {
      subject: { id: 'user2', department: 'engineering', level: 'junior', roles: ['engineer'] },
      resource: { id: 'api', type: 'service', classification: 'internal', owner: 'platform', sensitivity: 'medium', environment: 'production' },
      action: { operation: 'read' },
      environment: { timestamp: new Date(), ipAddress: '10.0.0.1', deviceType: 'desktop', networkSecure: true }
    };
    
    expect(engine.evaluate(request)).toBe(false);
  });
});

Best Practices for ABAC Implementation

Implementing ABAC successfully requires attention to both technical and organizational factors. Follow these best practices to avoid common pitfalls.

Maintain clear documentation of all attributes and policies. As your system grows, understanding what each policy controls becomes crucial. Use descriptive names and include rationale comments for complex conditions.

Implement a policy administration interface that separates policy management from policy evaluation. This separation enables authorized administrators to modify access rules without deploying code changes.

Plan for policy conflicts explicitly. Define how your system handles contradictory policies through priority levels, combination algorithms, or explicit conflict resolution rules.

Monitor access decisions for anomalies. Unusual patterns might indicate misconfigured policies or attempted security breaches. Log sufficient detail to investigate issues while avoiding unnecessary personal data retention.

Consider performance implications of complex policy evaluation. Cache attribute values when appropriate, and design policies to short-circuit evaluation when possible.

Conclusion

Attribute-Based Access Control provides the flexibility modern applications need to implement sophisticated authorization logic. By understanding the fundamental concepts—subject, resource, action, and environment attributes—you can design policies that accurately reflect your organization’s security requirements. Claude Code accelerates ABAC implementation by generating core engine code, creating policy structures, and helping you reason through complex authorization scenarios. Start with simple policies, test thoroughly, and iteratively add complexity as your requirements evolve.

Built by theluckystrike — More at zovo.one