Create Your First Policy
This guide walks you through creating your first access policy from scratch. You’ll learn the policy syntax, test your policy, and deploy it to control data access.
What is a Policy?
Section titled “What is a Policy?”A policy is a declarative rule that defines who can access what data, when, where, and why. Think of it as an access control list (ACL) written in a human-readable format that’s version-controlled alongside your code.
Instead of manually granting database access each time someone needs data, you write the rules once, and Alien Giraffe enforces them automatically.
Policy Structure
Section titled “Policy Structure”Every policy follows a formal access control model with five key components:
- Subjects - Which users or teams need access (e.g.,
team: customer-support) - Resources - Which data sources and datasets they can access (e.g.,
source: production-db,datasets: [customers]) - Constraints - Time windows and duration limits (e.g.,
timeframe: business-hours,duration: 4h) - Channels - Access methods and operations allowed (e.g.,
name: sql,operation: rw) - Context - Purpose or justification (e.g.,
customer-support,incident-response)
Your First Policy
Section titled “Your First Policy”Let’s create a simple policy that grants customer support team access to customer data.
Step 1: Create Policy File
Section titled “Step 1: Create Policy File”Create a file policies/customer-support-access.yaml:
apiVersion: v1kind: Policymetadata: name: customer-support-access namespace: production description: Allow customer support to view customer data during business hours owner: customer-support-lead
spec: # Subjects (who can access) subjects: - team: customer-support
# Resources (what data they can access) resources: - source: production-postgres datasets: - customers - orders - support_tickets
# Constraints (when they can access) constraints: - timeframe: business-hours # 9 AM - 5 PM local time - duration: 4h # Sessions last 4 hours max
# Channels (where they can access from) channels: - name: sql operation: rw - name: web operation: r
# Context (why they need access) context: - customer-support - order-inquiriesStep 2: Validate the Policy
Section titled “Step 2: Validate the Policy”Before deploying, validate your policy:
# Validate syntax and structurea10e policy validate policies/customer-support-access.yaml
# Expected output:# ✓ Syntax valid# ✓ All referenced sources exist# ✓ All referenced teams exist# ✓ Policy ready to applyCompile All Policies and Configurations
Section titled “Compile All Policies and Configurations”When working with multiple policies, you can validate all policies and configurations at once to ensure they can be properly executed and applied:
# Compile and validate all policies in a directorya10e policy compile policies/
# Expected output:# Compiling policies...# ✓ policies/customer-support-access.yaml# ✓ policies/engineering-access.yaml# ✓ policies/analytics-access.yaml## Validating cross-policy dependencies...# ✓ No conflicting policies detected# ✓ All source references valid# ✓ All team references valid# ✓ All time schedules valid## Summary: 3 policies compiled successfully# Compile with verbose output for detailed validationa10e policy compile policies/ --verbose
# Compile specific namespacea10e policy compile policies/production/ --namespace production
# Compile and check for conflictsa10e policy compile policies/ --check-conflicts
# Compile with JSON output for CI/CD integrationa10e policy compile policies/ --output jsonExample compile output with issues:
a10e policy compile policies/
# Expected output with errors:# Compiling policies...# ✓ policies/customer-support-access.yaml# ✗ policies/engineering-access.yaml# Error: Referenced source 'staging-db' does not exist# Line 48: source: staging-db# ✗ policies/analytics-access.yaml# Warning: Team 'legacy-team' has no members# Line 44: team: legacy-team## Validating cross-policy dependencies...# ✗ Policy conflict detected:# - customer-support-access (line 50)# - engineering-access (line 62)# Both grant access to 'customers' dataset with different permissions## Summary: 1 policy compiled, 2 failed# Exit code: 1Step 3: Test the Policy (Dry Run)
Section titled “Step 3: Test the Policy (Dry Run)”Test how the policy would behave without actually deploying it:
# Simulate an access requesta10e policy test customer-support-access \ --user alice@company.com \ --source production-postgres \ --dataset customers \ --dry-run
# Expected output:# ✓ Access would be GRANTED# Reason: User alice@company.com is member of team customer-support# Duration: 4 hours# Channels: sql, web-uiStep 4: Apply the Policy
Section titled “Step 4: Apply the Policy”Deploy the policy to production:
# Apply the policya10e policy apply -f policies/customer-support-access.yaml
# Verify it was createda10e policy list
# View policy detailsa10e policy get customer-support-accessStep 5: Test Real Access
Section titled “Step 5: Test Real Access”Now test that a user can actually access data:
# Request access as a customer support team membera10e access request \ --source production-postgres \ --datasets customers \ --purpose "customer-support" \ --duration 2h
# Expected output:# ✓ Access granted# Session ID: sess-abc123# Expires: 2025-11-18 16:30:00 UTC# Credentials saved to ~/.a10e/credentialsCongratulations! You’ve created and deployed your first policy.
Common Policy Patterns
Section titled “Common Policy Patterns”Pattern 1: Individual User Access
Section titled “Pattern 1: Individual User Access”Grant access to specific users:
spec: subjects: - user: alice@company.com - user: bob@company.com
resources: - source: analytics-db datasets: [reports, dashboards]
constraints: - duration: 8h
channels: - name: sql operation: rwPattern 2: Read-Only Analytics Access
Section titled “Pattern 2: Read-Only Analytics Access”Grant read-only access for analytics work:
metadata: name: analytics-read-access
spec: subjects: - team: data-analysts - team: data-scientists
resources: - source: analytics-replica # Read replica, not production datasets: ["*"] # All datasets permissions: [SELECT] # Read-only
constraints: - timeframe: business-hours - duration: 8h
channels: - name: sql operation: r - name: api operation: r
context: - analytics - reportingPattern 3: Time-Restricted Access
Section titled “Pattern 3: Time-Restricted Access”Limit access to specific time windows:
metadata: name: weekend-maintenance
spec: subjects: - team: sre
resources: - source: production-db datasets: [schema_migrations, system_config]
constraints: - timeframe: days: [saturday, sunday] hours: [2-6] # 2 AM - 6 AM - duration: 4h
channels: - name: sql operation: rw
context: - maintenance - database-upgradesPattern 4: Approval-Required Access
Section titled “Pattern 4: Approval-Required Access”Require manager approval for sensitive data:
metadata: name: pii-access-with-approval
spec: subjects: - team: engineering
resources: - source: production-db datasets: [users_pii, payment_info]
constraints: - duration: 2h
channels: - name: sql operation: rw
context: - debugging - incident-response
approval: required: true approvers: - role: manager - role: data-privacy-officer timeout: 1h # Approval expires after 1 hourPattern 5: Emergency Break-Glass
Section titled “Pattern 5: Emergency Break-Glass”Fast access for critical incidents:
metadata: name: emergency-production-access
spec: subjects: - team: on-call-engineers
resources: - source: production-db datasets: ["*"]
constraints: - timeframe: "*" # 24/7 access - duration: 1h # Short emergency sessions
channels: - name: sql operation: rw
context: - incident-response - outage
mfa: required: true # Require multi-factor auth
audit: level: verbose # Enhanced logging notify: immediate: - slack: "#security-alerts" - email: security@company.comAdvanced Policy Features
Section titled “Advanced Policy Features”Multiple Sources
Section titled “Multiple Sources”Grant access to multiple data sources in one policy:
spec: resources: - source: production-postgres datasets: [customers, orders]
- source: production-redis datasets: [sessions, cache]
- source: data-lake-s3 paths: [/analytics/*, /reports/*]Conditional Access
Section titled “Conditional Access”Apply conditions based on context:
spec: conditions: # Require VPN connection vpnRequired: true
# Restrict to specific IP ranges ipAllowlist: - 203.0.113.0/24 - 198.51.100.42
# Require device compliance deviceCompliance: true
# Time-based conditions timeConditions: - condition: weekend requireApproval: true - condition: after-hours requireMFA: trueData Masking
Section titled “Data Masking”Automatically mask sensitive fields:
spec: resources: - source: production-db datasets: [customers] masking: email: partial # j***@example.com phone: last4 # ***-***-1234 ssn: blocked # Completely blockedSession Extensions
Section titled “Session Extensions”Allow users to extend sessions:
spec: constraints: - duration: 4h maxExtensions: 2 # Can extend twice extensionDuration: 2h # 2 hours each timePolicy Management
Section titled “Policy Management”List Policies
Section titled “List Policies”# List all policiesa10e policy list
# Filter by namespacea10e policy list --namespace production
# Show detailed informationa10e policy list --detailedUpdate a Policy
Section titled “Update a Policy”# Edit the YAML filevim policies/customer-support-access.yaml
# Apply changesa10e policy apply -f policies/customer-support-access.yaml
# Or edit interactivelya10e policy edit customer-support-accessView Policy Usage
Section titled “View Policy Usage”# See who's using this policya10e policy usage customer-support-access
# View access historya10e policy audit customer-support-access --since 7dDelete a Policy
Section titled “Delete a Policy”# Delete a policy (requires confirmation)a10e policy delete customer-support-access
# Force delete without confirmationa10e policy delete customer-support-access --force
# Note: Active sessions are not affected by deletionPolicy Testing
Section titled “Policy Testing”Test Access Scenarios
Section titled “Test Access Scenarios”# Test if a user would be granted accessa10e policy test customer-support-access \ --user alice@company.com \ --source production-postgres \ --dataset customers
# Test with specific contexta10e policy test customer-support-access \ --user bob@company.com \ --source production-postgres \ --dataset customers \ --time "2025-11-18 14:00:00" \ --ip "203.0.113.42"
# Test why access was denieda10e policy test customer-support-access \ --user charlie@company.com \ --explainPolicy Simulation
Section titled “Policy Simulation”Simulate policy behavior over time:
# Simulate policy over a weeka10e policy simulate customer-support-access \ --start "2025-11-18" \ --end "2025-11-25" \ --users alice@company.com,bob@company.com
# Generates report showing:# - When access would be granted/denied# - Duration limits# - Approval requirementsVersion Control Best Practices
Section titled “Version Control Best Practices”Policy Repository Structure
Section titled “Policy Repository Structure”Organize policies in a Git repository:
policies/├── README.md├── production/│ ├── customer-support-access.yaml│ ├── engineering-access.yaml│ └── analytics-access.yaml├── staging/│ └── developer-access.yaml└── development/ └── unrestricted-access.yamlPolicy Review Workflow
Section titled “Policy Review Workflow”-
Create feature branch
Terminal window git checkout -b feature/new-analytics-policy -
Write the policy
Terminal window vim policies/production/analytics-access.yaml -
Validate and test
Terminal window a10e policy validate policies/production/analytics-access.yamla10e policy test analytics-access --dry-run -
Commit and push
Terminal window git add policies/production/analytics-access.yamlgit commit -m "Add analytics team access policy"git push origin feature/new-analytics-policy -
Create pull request
- Request review from security team and data owners
- Include test results in PR description
-
Merge and deploy
Terminal window git checkout maingit merge feature/new-analytics-policya10e policy apply -f policies/production/analytics-access.yaml
CI/CD Integration
Section titled “CI/CD Integration”Automate policy validation in your CI pipeline:
name: Validate Policies
on: [pull_request]
jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3
- name: Install Alien Giraffe CLI run: pip install alien-giraffe
- name: Compile and validate all policies run: | # Compile all policies to validate syntax and cross-policy dependencies a10e policy compile policies/ --check-conflicts --output json > validation-results.json
# Individual policy validation for policy in policies/**/*.yaml; do a10e policy validate $policy done
- name: Test policies run: | for policy in policies/**/*.yaml; do a10e policy test $(basename $policy .yaml) --dry-run done
- name: Upload validation results if: always() uses: actions/upload-artifact@v3 with: name: policy-validation-results path: validation-results.jsonTroubleshooting
Section titled “Troubleshooting”Policy Not Working
Section titled “Policy Not Working”Problem: User access denied despite policy
# Check policy is applieda10e policy get customer-support-access
# Verify user is in the teama10e user get alice@company.com --teams
# Test the specific scenarioa10e policy test customer-support-access \ --user alice@company.com \ --explain
# Check audit logsa10e audit logs --user alice@company.com --since 1hProblem: Policy conflicts
# Check for overlapping policiesa10e policy conflicts customer-support-access
# View policy evaluation ordera10e policy explain \ --user alice@company.com \ --source production-postgresValidation Errors
Section titled “Validation Errors”Problem: “Referenced source does not exist”
# List available sourcesa10e source list
# Fix policy to reference existing source# or create the missing sourceProblem: “Invalid time format”
# Correct time formats:constraints: - timeframe: business-hours # Named range - timeframe: "*" # Always - timeframe: days: [monday, friday] # Specific days hours: [9-17] # Hour range - timeframe: "2025-11-18T09:00:00Z" # Specific timestampBest Practices
Section titled “Best Practices”Start with Least Privilege
Section titled “Start with Least Privilege”Begin restrictive, then expand as needed:
# Start herespec: resources: - source: analytics-replica # Read replica datasets: [public_reports] # Specific dataset permissions: [SELECT] # Read-only
# Not herespec: resources: - source: production-db # Production! datasets: ["*"] # Everything! permissions: ["*"] # All permissions!Use Meaningful Names
Section titled “Use Meaningful Names”Choose descriptive policy names:
- ✅
customer-support-business-hours-access - ✅
engineering-readonly-analytics - ❌
policy-1 - ❌
test-policy
Document Your Policies
Section titled “Document Your Policies”Include clear descriptions:
metadata: description: | Allows customer support team to view customer data during business hours for resolving customer inquiries and support tickets. Approved by: Security Team (2025-11-01) Review date: 2026-11-01Regular Reviews
Section titled “Regular Reviews”Schedule policy audits:
# Review policy usage quarterlya10e policy audit customer-support-access --since 90d
# Identify unused policiesa10e policy unused --since 30d
# Review access patternsa10e policy analytics customer-support-accessNext Steps
Section titled “Next Steps”Now that you have a policy in place:
- Set Up Identity Integration - Connect your identity provider for team management
- Configure Monitoring - Set up audit logging and alerts
- Policies Component Reference - Learn advanced policy features
- Constraints (Just-In-Time Access) - Understand temporary access workflows
For more examples:
- Policy Cookbook - Collection of common policy patterns
- Security Best Practices - Secure your policies
- Compliance Guide - Meet regulatory requirements