Skip to content

Security: scttfrdmn/aws-remote-access-patterns

Security

SECURITY.md

Security Analysis: Cross-Account Roles vs Access Keys

This document explains why cross-account roles and temporary credentials are significantly more secure than traditional access keys.

πŸ”’ Security Comparison Overview

Security Aspect Cross-Account Roles Access Keys
Credential Lifetime βœ… Temporary (1 hour default) ❌ Permanent (until manually rotated)
Permission Scope βœ… Least privilege, resource-specific ❌ Often over-privileged
Secret Storage βœ… No long-lived secrets ❌ Permanent secrets in databases
Revocation Speed βœ… Instant (delete CloudFormation stack) ❌ Manual, often forgotten
Audit Trail βœ… Complete CloudTrail logging ❌ Limited visibility
Leak Impact βœ… Minimal (expires quickly) ❌ Full account compromise
Rotation Required βœ… Automatic ❌ Manual process, rarely done

🚨 Access Key Security Problems

1. Long-Lived Credentials

# Access keys never expire unless manually rotated
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE      # Valid forever
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY  # Valid forever

Problems:

  • Keys remain valid indefinitely
  • Often forgotten in configuration files
  • Difficult to track usage and rotate
  • Create permanent attack surface

2. Over-Privileged Permissions

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow", 
    "Action": "*",     # ❌ Often AdminAccess because IAM is complex
    "Resource": "*"    # ❌ Full access to everything
  }]
}

Problems:

  • Users often grant admin access "to be safe"
  • Precise permissions are hard to configure
  • Blast radius of compromise is entire AWS account
  • No resource-level restrictions

3. Secret Sprawl

# These secrets end up everywhere:
- Application configuration files
- Environment variables  
- Container images
- Git repositories (accidentally)
- Log files
- Backup systems
- Developer machines

Problems:

  • Secrets stored in multiple locations
  • Hard to track where credentials are used
  • Accidental exposure in logs/repos
  • Difficult to rotate without breaking things

4. Manual Rotation

# Manual rotation process (rarely done):
1. Generate new access keys
2. Update all applications using old keys
3. Test that everything still works
4. Delete old keys
5. Hope you didn't miss any usage

Problems:

  • Manual process that's rarely executed
  • Risk of breaking applications
  • No automated rotation mechanism
  • Keys often remain active long past needed

βœ… Cross-Account Role Security Benefits

1. Temporary Credentials

// Credentials automatically expire
temporaryCreds, err := client.AssumeRole(ctx, customerID)
// These expire in 1 hour by default
// No permanent secrets anywhere

Benefits:

  • All credentials have expiration times
  • Automatic refresh mechanism
  • Limited blast radius if compromised
  • No permanent secrets to manage

2. Least Privilege Permissions

# Precise, minimal permissions
OngoingPermissions:
  - Sid: "S3DataAccess"
    Effect: "Allow"
    Actions:
      - "s3:GetObject"
      - "s3:PutObject" 
    Resources:
      - "arn:aws:s3:::customer-data-bucket/*"  # Only specific resources

Benefits:

  • Permissions scoped to specific resources
  • Separate setup vs ongoing permissions
  • Easy to audit and understand
  • Follows principle of least privilege

3. No Secret Storage

// No secrets stored in your application
type CustomerCredentials struct {
    RoleARN    string  // Not a secret - can be logged
    ExternalID string  // Not reusable without your AWS account
    // No AccessKey or SecretKey stored anywhere!
}

Benefits:

  • No long-lived secrets in databases
  • External IDs are not reusable
  • Role ARNs are not sensitive information
  • Nothing to leak or compromise

4. Instant Revocation

# Customer can revoke access instantly
aws cloudformation delete-stack --stack-name MyService-Integration
# Done! All access immediately revoked

Benefits:

  • One-command revocation by customer
  • No coordination required with service provider
  • Immediate effect (no propagation delay)
  • Customer maintains full control

🎯 Real-World Attack Scenarios

Access Key Compromise Scenario

1. Developer commits .env file with access keys to GitHub
2. Keys are discovered by automated scanners
3. Attacker uses keys to access AWS account
4. Keys have AdminAccess (common over-permissioning)
5. Entire AWS account is compromised
6. Keys remain valid until manually rotated (often never)
7. Damage: Complete account takeover

Cross-Account Role Compromise Scenario

1. Temporary credentials are somehow leaked
2. Attacker tries to use credentials
3. Credentials have limited scope (only S3 bucket access)
4. Credentials expire in 1 hour
5. No permanent access gained
6. Customer can revoke access by deleting CloudFormation stack
7. Damage: Limited to specific resources for short time

πŸ” Audit and Compliance Benefits

CloudTrail Integration

{
  "eventTime": "2025-01-15T10:30:00Z",
  "eventName": "AssumeRole",
  "userIdentity": {
    "type": "AssumedRole",
    "principalId": "AIDACKCEVSQ6C2EXAMPLE:MyService-acme-corp-1673771400",
    "arn": "arn:aws:sts::123456789012:assumed-role/MyService-CrossAccount/MyService-acme-corp-1673771400"
  },
  "sourceIPAddress": "203.0.113.12",
  "resources": [{
    "ARN": "arn:aws:iam::123456789012:role/MyService-CrossAccount",
    "accountId": "123456789012"
  }]
}

Benefits:

  • Every role assumption logged
  • Clear attribution to specific service/customer
  • Detailed resource access logging
  • Integration with compliance tools

Permission Boundaries

# Built-in permission boundaries
MaxSessionDuration: 3600  # 1 hour maximum
Condition:
  StringEquals:
    "sts:ExternalId": "unique-customer-id"  # Only your service can assume
  IpAddress:
    "aws:SourceIp": "203.0.113.0/24"       # Optional IP restrictions

Benefits:

  • Session duration limits
  • IP address restrictions possible
  • MFA requirements supported
  • Integration with AWS Organizations SCPs

πŸ“Š Industry Adoption

Major SaaS providers using cross-account roles:

  • Datadog: Monitoring and observability
  • Coiled: Data science platform
  • Snowflake: Data warehouse
  • Databricks: Analytics platform
  • New Relic: Application monitoring
  • Sumo Logic: Log analytics

Why they switched:

  1. Better security posture
  2. Easier customer onboarding
  3. Compliance requirements
  4. Reduced support burden
  5. Customer demand for better security

πŸ›‘οΈ Implementation Security Best Practices

1. External ID Generation

// Use cryptographically secure random generation
func generateExternalID(customerID string) string {
    randomBytes := make([]byte, 16)
    if _, err := rand.Read(randomBytes); err != nil {
        // Never use predictable fallbacks in production
        panic("Failed to generate secure external ID")
    }
    return fmt.Sprintf("%s-%s-%s", serviceName, customerID, hex.EncodeToString(randomBytes))
}

2. Permission Validation

// Always test role assumptions during setup
func (c *Client) CompleteSetup(ctx context.Context, req *SetupCompleteRequest) error {
    // Test that we can actually assume the role
    if err := c.validateRoleAccess(ctx, req.RoleARN, req.ExternalID); err != nil {
        return fmt.Errorf("role validation failed: %w", err)
    }
    // ... store only after validation
}

3. Credential Caching

// Cache credentials but respect expiration
func (c *Client) AssumeRole(ctx context.Context, customerID string) (aws.Config, error) {
    if cached := c.cache.Get(customerID); cached != nil {
        if time.Now().Before(cached.ExpiresAt.Add(-5*time.Minute)) { // 5min buffer
            return cached.Config, nil
        }
    }
    // ... assume role and cache result
}

πŸŽ“ Migration Guide

From Access Keys to Cross-Account Roles

  1. Phase 1: Implement cross-account support

    // Add cross-account client alongside existing access key support
    crossAccountClient, _ := crossaccount.New(config)
  2. Phase 2: Customer migration

    // Support both methods during transition
    if customer.HasCrossAccountRole {
        return crossAccountClient.AssumeRole(ctx, customerID)
    } else {
        return legacyAccessKeyAuth(customer.AccessKey, customer.SecretKey)
    }
  3. Phase 3: Deprecate access keys

    // Gradually migrate customers and sunset access key support
    if customer.UsingAccessKeys && time.Since(customer.CreatedAt) > 90*24*time.Hour {
        log.Warn("Customer still using deprecated access keys")
        // Send migration reminder
    }

πŸ“ˆ Business Benefits

Reduced Support Burden

  • No more "my access keys stopped working" tickets
  • No manual rotation coordination with customers
  • Automatic credential refresh eliminates expiration issues

Better Customer Trust

  • Customers maintain control over access
  • Transparent permission model
  • Follows AWS security best practices
  • Easy to audit and demonstrate compliance

Competitive Advantage

  • Modern, enterprise-grade security model
  • Easier procurement process for enterprise customers
  • Differentiator against competitors using access keys

Bottom Line: Cross-account roles provide significantly better security, user experience, and operational benefits compared to traditional access keys. The initial implementation effort pays dividends in reduced security risk, better customer satisfaction, and lower operational overhead.

There aren’t any published security advisories