Skip to content

feat: add support for AWS RDS IAM authentication and update dependencies #3086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

l3ok
Copy link

@l3ok l3ok commented Jun 9, 2025

#3016

AWS RDS IAM Authentication Implementation

Add AWS RDS IAM Authentication Support

This PR introduces AWS RDS IAM authentication support for PostgreSQL connections, enabling secure database access using AWS IAM credentials instead of traditional username/password authentication.

Changes Made

New AWS IAM Utilities (util/aws_iam.go)

Added GetRDSAuthToken function: Generates AWS RDS authentication tokens using IAM credentials

  • Supports custom regions and usernames via function parameters
  • Includes comprehensive debug logging for troubleshooting connection issues
  • Handles AWS credential retrieval and validation through AWS SDK v2
  • Returns generated auth tokens with 15-minute validity for database connections
func GetRDSAuthToken(hostname string, username string, region string) (string, error) {
    hostname, port := ExtractHostPort(hostname, "5432")
    log.Debugf("Generating RDS auth token for %s:%s, user %s in region %s", hostname, port, username, region)

    cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region))
    if err != nil {
        log.Errorf("Failed to load AWS config: %v", err)
        return "", err
    }

    credProvider := cfg.Credentials
    creds, err := credProvider.Retrieve(context.TODO())
    if err != nil {
        log.Errorf("Failed to retrieve AWS credentials: %v", err)
        return "", err
    }

    log.Debugf("AWS credentials retrieved successfully. Access key ID: %s, Provider: %s",
        creds.AccessKeyID[:4]+"...", creds.Source)

    authToken, err := auth.BuildAuthToken(
        context.TODO(),
        hostname+":"+port,
        region,
        username,
        cfg.Credentials,
    )
    if err != nil {
        log.Errorf("Failed to generate RDS auth token: %v", err)
        return "", err
    }

    log.Debugf("Successfully generated RDS auth token (length: %d)", len(authToken))
    return authToken, nil
}

Added ExtractHostPort utility function: Parses host:port strings with PostgreSQL fallback

  • Handles cases where port is omitted from connection strings
  • Defaults to PostgreSQL port (5432) when not specified
  • Supports standard "hostname:port" format parsing
func ExtractHostPort(hostPort string, defaultPort string) (host string, port string) {
    parts := strings.Split(hostPort, ":")
    if len(parts) == 1 {
        return parts[0], defaultPort
    }
    return parts[0], parts[1]
}

Database Configuration Enhancements (util/config.go)

Added PostgreSQL IAM configuration fields:

  • PostgresIAM (bool): Enables/disables IAM authentication mode
  • PostgresIAMRegion (string): Specifies AWS region for RDS authentication

Enhanced GetConnectionString method:

  • Integrates IAM token generation when PostgresIAM is enabled
  • Validates required region configuration before attempting authentication
  • Automatically substitutes generated auth tokens for passwords in connection strings
  • Maintains backward compatibility with traditional password authentication

Database Connection Management (db/sql/SqlDb.go)

Added connection lifecycle management for IAM:

  • Sets ConnMaxLifetime to 14 minutes for IAM-authenticated connections
  • Ensures connections are refreshed before AWS auth tokens expire (15-minute validity)
  • Prevents connection pool from holding expired credentials

Technical Implementation Details

  • AWS SDK Integration: Uses aws-sdk-go-v2 with modern credential providers
  • Security: Supports all AWS credential sources (environment variables, IAM roles, instance profiles, profiles)
  • Error Handling: Comprehensive error handling with detailed logging via logrus
  • Credential Management: Automatic credential retrieval and validation
  • Token Generation: Uses AWS RDS auth.BuildAuthToken for secure token creation

Environment Variables

  • SEMAPHORE_DB_POSTGRES_IAM: Enable IAM authentication (boolean)
  • SEMAPHORE_DB_POSTGRES_IAM_REGION: AWS region for RDS instance (string)

Benefits

  • Enhanced Security: Eliminates need for hard-coded database passwords
  • Simplified Credential Management: Leverages existing AWS IAM infrastructure
  • Audit Trail: Database connections are logged through AWS CloudTrail
  • Automatic Rotation: IAM tokens automatically rotate every 15 minutes
  • Compliance: Supports AWS security best practices and compliance requirements
  • Zero Downtime: Seamless integration with existing connection pooling

Usage Example

{
  "postgres": {
    "host": "mydb.cluster-xyz.us-east-1.rds.amazonaws.com:5432",
    "user": "semaphore_user", 
    "name": "semaphore",
    "postgres_iam": true,
    "postgres_iam_region": "us-east-1"
  },
  "dialect": "postgres"
}

Debugging and Logging

The implementation includes comprehensive debug logging:

  • AWS credential retrieval status
  • Token generation progress
  • Connection endpoint details
  • Generated token metadata (length, without exposing sensitive data)

Error Handling

Robust error handling for common scenarios:

  • AWS credential configuration issues
  • Network connectivity problems
  • Invalid region specifications
  • Token generation failures

This implementation provides a secure foundation for AWS RDS integration while maintaining full backward compatibility with existing password-based configurations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant