Skip to content

Policy Evaluation & Fallback Handling

This guide explains how Alien Giraffe evaluates access requests against policies, what happens when a request doesn’t match any policy, and how to configure fallback policies for graceful handling of unmatched requests.

When a user requests access to data, Alien Giraffe follows a structured evaluation process to determine whether to grant or deny access.

The complete evaluation flow includes authentication, policy matching, fallback handling, approval workflows (when required), and final decision with audit logging.

View Complete Flow Diagram →

The flow diagram shows all paths through the evaluation system, including:

  • Primary path: Policy match with optional approval
  • Fallback path: No policy match, fallback evaluation with optional approval
  • Denial points: Authentication failure, policy conditions, approval rejection
  • Audit logging: Complete trail for all outcomes

1. Authentication

  • Verify user identity via SSO/IAM
  • Validate session token
  • Check MFA requirements

2. Context Gathering

  • User identity and team memberships
  • Requested resource and datasets
  • Time of request
  • Network location (IP, VPN status)
  • Stated purpose
  • Requested duration

3. Policy Search Alien Giraffe searches for policies matching the request:

  • Subject match: Does policy apply to this user or their teams?
  • Resource match: Does policy cover the requested data source?
  • Constraint match: Does current time fall within allowed timeframes?
  • Channel match: Does policy allow the requested access method?

4. Policy Evaluation If matching policies are found:

  • Check all constraint conditions (time windows, duration limits)
  • Verify approval requirements (if policy requires approval)
  • Validate context/purpose alignment
  • Calculate final decision (grant/deny/needs-approval)

5. Fallback Handling If no matching policy is found:

  • Check resource-specific fallback policy
  • Check namespace-level fallback policy
  • Check global fallback policy
  • Evaluate fallback conditions (time, context, etc.)
  • Check if fallback requires approval (human-in-the-loop)
  • Apply default deny if no fallback exists

6. Approval Processing (if required) For policies or fallbacks requiring approval:

  • Identify appropriate approvers (manager, data owner, security team)
  • Send approval request with context (user, resource, purpose, duration)
  • Wait for approval decision (with timeout)
  • Escalate if no response within threshold
  • Proceed with grant/deny based on approval outcome

7. Decision & Audit

  • Grant temporary credentials OR deny with reason
  • Log complete audit trail including:
    • Policy or fallback applied
    • Approval flow (if any)
    • Decision rationale
  • Notify relevant parties if configured

Alien Giraffe follows a deny-by-default security model. This means:

  • Access is denied unless explicitly granted by a policy
  • No implicit permissions exist
  • Every access attempt must match a policy or fallback
  • All denials are logged with detailed reasoning

Why deny-by-default?

  • Security: Prevents unauthorized access by default
  • Compliance: Meets regulatory requirements for access control
  • Auditability: Makes all access explicit and traceable
  • Least Privilege: Forces intentional permission grants

Common Scenarios for Non-Matching Requests

Section titled “Common Scenarios for Non-Matching Requests”

New Resources:

  • Database added but no policies created yet
  • Users attempting access before policy deployment

New Users/Teams:

  • New employee without team assignment
  • Team not included in any existing policies

Edge Cases:

  • Request outside defined timeframes
  • Unusual access method not covered by policies
  • Cross-namespace access attempts

Development/Testing:

  • Developers testing new data sources
  • Exploratory data access for new projects

Fallback policies provide graceful handling for requests that don’t match specific policies. They act as a safety net, allowing you to define what happens when no explicit policy applies.

System-wide default for any unmatched request across all resources.

Use cases:

  • Provide read-only access to non-sensitive data
  • Allow self-service request submission
  • Consistent deny messaging with guidance
  • Emergency access during policy gaps

Example: Deny with Helpful Message

apiVersion: v1
kind: FallbackPolicy
metadata:
name: global-fallback-deny
namespace: system
spec:
scope: global
action: deny
message: |
Access denied: No policy matches your request.
To request access:
1. Visit https://access.company.com
2. Submit access request with business justification
3. Your manager will be notified for approval
For urgent access, contact security@company.com
audit:
level: verbose
notify:
- slack: "#security-access-requests"

Example: Allow Read-Only to Development Resources

apiVersion: v1
kind: FallbackPolicy
metadata:
name: global-fallback-dev-readonly
namespace: system
spec:
scope: global
action: allow
# Only applies to specific namespaces
namespaceFilter:
include: [development, staging]
exclude: [production]
# Restrictions for fallback access
constraints:
- duration:
max: 1h
default: 30m
- timeframe: business-hours
# Read-only access only
channels:
- name: sql
operation: r
enforcement: strict
# Require purpose documentation
requireContext: true
# Extra auditing for fallback access
audit:
level: verbose
tags: [fallback-access, needs-policy-review]

Fallback policy for specific data sources or resource types.

Use cases:

  • Development databases with permissive defaults
  • Analytics sources allowing broad read access
  • Sandbox environments for experimentation
  • Legacy systems during migration

Example: Per-Resource Fallback

apiVersion: v1
kind: FallbackPolicy
metadata:
name: analytics-db-fallback
namespace: production
spec:
scope: resource
# Applies only to specific resource
resource:
source: analytics-replica
action: allow
# Anyone in analytics teams gets read access
subjects:
- team: data-analysts
- team: data-scientists
- team: business-intelligence
# Read-only, time-limited
constraints:
- timeframe: business-hours
- duration:
max: 4h
default: 2h
channels:
- name: sql
operation: r
# Require purpose
requireContext: true
contextValidation:
allowedContexts: [analytics, reporting, research]
audit:
level: standard
tags: [analytics-fallback]

Example: Namespace-Level Fallback

apiVersion: v1
kind: FallbackPolicy
metadata:
name: development-namespace-fallback
namespace: development
spec:
scope: namespace
action: allow
# Applies to all resources in 'development' namespace
namespaceFilter:
include: [development]
# All engineers get access
subjects:
- team: engineering
constraints:
- timeframe: "*" # 24/7
- duration:
max: 8h
channels:
- name: sql
operation: rw
- name: api
operation: rw
audit:
level: minimal
tags: [dev-fallback]

Combine multiple fallback policies with priority ordering.

Evaluation Order:

  1. Resource-specific fallback - Most specific, highest priority
  2. Namespace-level fallback - Namespace-wide defaults
  3. Global fallback - System-wide catch-all

Example Configuration:

# 1. Resource-specific: Production analytics replica
---
apiVersion: v1
kind: FallbackPolicy
metadata:
name: prod-analytics-replica-fallback
namespace: production
spec:
scope: resource
resource:
source: production-analytics-replica
action: allow
priority: 100 # Highest priority
# ... restrictions ...
# 2. Namespace-level: All production resources
---
apiVersion: v1
kind: FallbackPolicy
metadata:
name: production-namespace-fallback
namespace: production
spec:
scope: namespace
action: deny
priority: 50 # Medium priority
message: "Production access requires explicit policy. Submit request at https://access.company.com"
# 3. Global: System-wide default
---
apiVersion: v1
kind: FallbackPolicy
metadata:
name: global-system-fallback
namespace: system
spec:
scope: global
action: deny
priority: 10 # Lowest priority
message: "No policy found. Contact data-governance@company.com"

Allow users to submit access requests when no policy matches:

apiVersion: v1
kind: FallbackPolicy
metadata:
name: self-service-request-fallback
namespace: system
spec:
scope: global
action: prompt-for-request
# Show user a request form
requestForm:
fields:
- name: purpose
type: textarea
label: "Business justification"
required: true
minLength: 50
- name: duration
type: duration
label: "How long do you need access?"
required: true
options: [1h, 4h, 8h, 24h]
- name: ticket
type: url
label: "Related Jira ticket (optional)"
required: false
approval:
required: true
approvers:
- role: manager
- role: data-owner
timeout: 24h
escalation:
after: 12h
to: [security-team]
# Temporary policy created upon approval
onApproval:
createPolicy: true
policyDuration: requested # Match requested duration
policyExpiry: 30d # Policy auto-expires after 30 days

Conditional Fallback Based on Resource Sensitivity

Section titled “Conditional Fallback Based on Resource Sensitivity”

Different fallback behavior based on data classification:

apiVersion: v1
kind: FallbackPolicy
metadata:
name: conditional-fallback-by-sensitivity
namespace: system
spec:
scope: global
# Rules evaluated in order
rules:
# High sensitivity: Strict deny
- condition: resource.classification.criticality == "critical"
action: deny
message: "Critical data requires explicit policy and manager approval"
notify:
- slack: "#security-critical-access-attempts"
- email: security@company.com
# Medium sensitivity: Require approval
- condition: resource.classification.criticality == "high"
action: prompt-for-request
approval:
required: true
approvers: [manager, data-owner]
# Low sensitivity: Auto-approve with limits
- condition: resource.classification.criticality in ["medium", "low"]
action: allow
constraints:
- duration:
max: 2h
- timeframe: business-hours
channels:
- name: sql
operation: r
audit:
level: verbose
# Default: Deny
- condition: true
action: deny
# Development: Permissive fallback
---
apiVersion: v1
kind: FallbackPolicy
metadata:
name: dev-permissive-fallback
namespace: development
spec:
scope: namespace
action: allow
subjects:
- team: engineering
- team: qa
constraints:
- duration:
max: 8h
channels:
- name: sql
operation: rw
- name: api
operation: rw
audit:
level: minimal
# Production: Strict deny with request flow
---
apiVersion: v1
kind: FallbackPolicy
metadata:
name: prod-strict-fallback
namespace: production
spec:
scope: namespace
action: deny
message: |
Production access denied: No matching policy.
This is production data - access requires:
1. Explicit policy approval
2. Manager sign-off
3. Business justification
Submit request: https://access.company.com
Emergency access: contact security@company.com
audit:
level: verbose
notify:
immediate:
- slack: "#security-prod-access-denied"

When evaluating an access request, Alien Giraffe follows this matching logic:

1. Exact Policy Match

  • Subject + Resource + Constraints + Channels all match
  • Multiple policies may match - most specific wins
  • Policies are evaluated in priority order

2. Partial Policy Match

  • Some fields match, others don’t
  • Request is denied with specific reason
  • Example: Right user, wrong time window

3. No Policy Match

  • No policy matches the request
  • Fallback policies are evaluated
  • Follows fallback priority order

Policy Priority (highest to lowest):

  1. Explicit deny policies - Always evaluated first
  2. User-specific policies - Individual user grants
  3. Team-based policies - Team membership grants
  4. Resource-specific fallbacks - Per-resource defaults
  5. Namespace fallbacks - Namespace-wide defaults
  6. Global fallback - System-wide default
  7. Default deny - Built-in final denial

Priority Field:

metadata:
priority: 100 # Higher number = higher priority

Check which policy was applied:

Terminal window
# Explain why user has/doesn't have access
a10e policy explain \
--user alice@company.com \
--source production-postgres \
--datasets customers
# Output:
# ✓ Access granted via policy: customer-support-access
# Priority: 75
# Match reason: User is member of team 'customer-support'
# Constraints: Must access during business-hours (currently met)
# Duration limit: 4h
# Approval: Not required
Terminal window
# Test hypothetical request
a10e policy test \
--user bob@company.com \
--source analytics-db \
--time "2025-11-20 03:00"
# Output:
# ✗ Access denied
# Reason: No policy matches request
# Fallback applied: global-fallback-deny
# Evaluation details:
# - No policies match user 'bob@company.com'
# - Time 03:00 is outside business-hours for all policies
# - Global fallback policy denied with message: [...]

View policy evaluation logs:

Terminal window
# View recent policy evaluations
a10e audit logs --event policy_evaluation --since 1h
# Filter by user
a10e audit logs --event policy_evaluation --user alice@company.com
# See fallback usage
a10e audit logs --tag fallback-access --since 24h

Analyze policy coverage:

Terminal window
# See which resources lack specific policies
a10e policy coverage
# Output:
# Resource: production-postgres
# Policies: 3
# Fallback: production-namespace-fallback
# Coverage: 85% (engineering, support, sre teams)
#
# Resource: analytics-replica
# Policies: 1
# Fallback: analytics-db-fallback
# Coverage: 100% (via fallback)
#
# Resource: new-database
# Policies: 0
# Fallback: global-fallback-deny
# Coverage: 0% (no specific policies)
# ⚠ Warning: No specific policies defined

When to Use Global vs Resource-Targeted Fallbacks

Section titled “When to Use Global vs Resource-Targeted Fallbacks”

Use Global Fallbacks for:

  • Consistent security messaging across all resources
  • Organization-wide access request workflows
  • Default deny-by-default enforcement
  • Emergency contact information

Use Resource-Targeted Fallbacks for:

  • Development/staging environments with relaxed access
  • Analytics databases allowing broad read access
  • Sandbox resources for experimentation
  • Legacy systems during policy migration
  • Resources with unique access patterns

Use Namespace Fallbacks for:

  • Environment-based policies (dev/staging/prod)
  • Team-specific namespaces
  • Organizational unit separation

Principle of Least Privilege:

# Good: Restrictive fallback
constraints:
- duration:
max: 1h # Short duration
- timeframe: business-hours
channels:
- name: sql
operation: r # Read-only
# Bad: Overly permissive fallback
constraints:
- duration:
max: 24h # Too long
- timeframe: "*" # Always allowed
channels:
- name: sql
operation: rw # Write access

Audit Everything:

# Always use verbose auditing for fallback access
audit:
level: verbose
tags: [fallback-access, needs-policy-review]
notify:
- slack: "#security-fallback-usage"
Terminal window
# Weekly review of fallback access
a10e audit search --tag fallback-access --since 7d
# Identify resources needing explicit policies
a10e policy coverage --show-fallback-only
# Top users hitting fallback policies
a10e audit aggregate \
--event policy_evaluation \
--filter "outcome=fallback" \
--group-by user \
--since 30d
apiVersion: v1
kind: FallbackPolicy
metadata:
name: migration-temporary-fallback
namespace: production
spec:
scope: resource
resource:
source: legacy-database
action: allow
# Auto-expire fallback policy
expiry: 2025-12-31T23:59:59Z
# Warn users this is temporary
message: |
⚠ Temporary migration access granted.
This fallback expires 2025-12-31.
Explicit policies required before expiration.
audit:
level: verbose
tags: [migration, temporary-fallback]
notify:
weekly-summary:
- email: data-governance@company.com

Problem: User denied access, no matching policy found.

Debug steps:

Terminal window
# 1. Check user's team memberships
a10e subject describe alice@company.com
# 2. See which policies exist for the resource
a10e policy list --source production-postgres
# 3. Explain why access was denied
a10e policy explain \
--user alice@company.com \
--source production-postgres \
--verbose
# 4. Check if fallback policy exists
a10e policy list --type fallback --namespace production

Solutions:

  • Create explicit policy for user/team + resource
  • Update fallback policy to allow this access pattern
  • Add user to team that has access

Problem: Expected fallback to allow access, but request was denied.

Debug steps:

Terminal window
# Check fallback policy configuration
a10e policy describe global-fallback-deny
# Verify fallback scope and filters
a10e policy test-fallback \
--policy global-fallback-deny \
--user alice@company.com \
--source production-postgres
# Check evaluation order
a10e policy explain \
--user alice@company.com \
--source production-postgres \
--show-evaluation-order

Common issues:

  • Fallback namespaceFilter excludes the resource
  • Fallback subjects doesn’t include user
  • Higher-priority explicit deny policy blocks fallback
  • Fallback constraints not met (time window, etc.)

Problem: High volume of fallback policy usage indicates missing explicit policies.

Analysis:

Terminal window
# Identify gaps in policy coverage
a10e policy coverage --show-gaps
# Top resources accessed via fallback
a10e audit aggregate \
--event policy_evaluation \
--filter "policyType=fallback" \
--group-by resource \
--since 30d \
--top 10
# Users most affected by policy gaps
a10e audit aggregate \
--event policy_evaluation \
--filter "policyType=fallback" \
--group-by user \
--since 30d

Resolution:

  • Create explicit policies for frequently accessed resources
  • Review fallback usage reports weekly
  • Set alerts for high fallback usage rates

Problem: Fallback grants broader access than intended.

Mitigation:

# Add strict constraints to fallback
spec:
constraints:
- duration:
max: 30m # Very short sessions
- timeframe: business-hours
# Require explicit purpose
requireContext: true
contextValidation:
minLength: 50
allowedContexts: [specific, purposes, only]
# Alert on every use
audit:
level: verbose
notify:
immediate:
- slack: "#security-fallback-alerts"