diff --git a/examples/advanced-logging/go.mod b/examples/advanced-logging/go.mod index 85eb8e8e..f22c281e 100644 --- a/examples/advanced-logging/go.mod +++ b/examples/advanced-logging/go.mod @@ -5,7 +5,7 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/chimux v1.1.0 github.com/GoCodeAlone/modular/modules/httpclient v0.1.0 github.com/GoCodeAlone/modular/modules/httpserver v0.1.1 diff --git a/examples/feature-flag-proxy/go.mod b/examples/feature-flag-proxy/go.mod index ce6f505d..caf4081f 100644 --- a/examples/feature-flag-proxy/go.mod +++ b/examples/feature-flag-proxy/go.mod @@ -5,7 +5,7 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/chimux v1.1.0 github.com/GoCodeAlone/modular/modules/httpserver v0.1.1 github.com/GoCodeAlone/modular/modules/reverseproxy v1.1.2 diff --git a/examples/health-aware-reverse-proxy/go.mod b/examples/health-aware-reverse-proxy/go.mod index e36ec1bd..8137abec 100644 --- a/examples/health-aware-reverse-proxy/go.mod +++ b/examples/health-aware-reverse-proxy/go.mod @@ -5,7 +5,7 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/chimux v0.0.0-00010101000000-000000000000 github.com/GoCodeAlone/modular/modules/httpserver v0.0.0-00010101000000-000000000000 github.com/GoCodeAlone/modular/modules/reverseproxy v0.0.0-00010101000000-000000000000 diff --git a/examples/http-client/go.mod b/examples/http-client/go.mod index 02273bf3..d44a01d4 100644 --- a/examples/http-client/go.mod +++ b/examples/http-client/go.mod @@ -5,7 +5,7 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/chimux v1.1.0 github.com/GoCodeAlone/modular/modules/httpclient v0.1.0 github.com/GoCodeAlone/modular/modules/httpserver v0.1.1 diff --git a/examples/logmasker-example/go.mod b/examples/logmasker-example/go.mod index e8000006..9cfeecc8 100644 --- a/examples/logmasker-example/go.mod +++ b/examples/logmasker-example/go.mod @@ -3,7 +3,7 @@ module logmasker-example go 1.25 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/logmasker v0.0.0 ) diff --git a/examples/multi-engine-eventbus/go.mod b/examples/multi-engine-eventbus/go.mod index ca572741..fb8dad1b 100644 --- a/examples/multi-engine-eventbus/go.mod +++ b/examples/multi-engine-eventbus/go.mod @@ -5,13 +5,14 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/eventbus v1.7.0 ) require ( github.com/BurntSushi/toml v1.6.0 // indirect github.com/DataDog/datadog-go/v5 v5.4.0 // indirect + github.com/GoCodeAlone/modular/modules/eventbus/v2 v2.5.1 // indirect github.com/IBM/sarama v1.45.2 // indirect github.com/Microsoft/go-winio v0.5.0 // indirect github.com/aws/aws-sdk-go-v2 v1.38.0 // indirect diff --git a/examples/multi-engine-eventbus/go.sum b/examples/multi-engine-eventbus/go.sum index bd3ee7f0..4ce86877 100644 --- a/examples/multi-engine-eventbus/go.sum +++ b/examples/multi-engine-eventbus/go.sum @@ -2,6 +2,8 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DataDog/datadog-go/v5 v5.4.0 h1:Ea3eXUVwrVV28F/fo3Dr3aa+TL/Z7Xi6SUPKW8L99aI= github.com/DataDog/datadog-go/v5 v5.4.0/go.mod h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw= +github.com/GoCodeAlone/modular/modules/eventbus/v2 v2.5.1 h1:GTSJh+QbPj7nuXoiiz53+DPxJ3xw7JPemzBuWg6vKS4= +github.com/GoCodeAlone/modular/modules/eventbus/v2 v2.5.1/go.mod h1:PvgkUxMg2RL/TjKevO3PBTy+RazZX5YXi8IK/Bz1qcw= github.com/IBM/sarama v1.45.2 h1:8m8LcMCu3REcwpa7fCP6v2fuPuzVwXDAM2DOv3CBrKw= github.com/IBM/sarama v1.45.2/go.mod h1:ppaoTcVdGv186/z6MEKsMm70A5fwJfRTpstI37kVn3Y= github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= diff --git a/examples/nats-eventbus/go.mod b/examples/nats-eventbus/go.mod index 0ed7d322..0816901f 100644 --- a/examples/nats-eventbus/go.mod +++ b/examples/nats-eventbus/go.mod @@ -9,13 +9,14 @@ replace github.com/GoCodeAlone/modular => ../../ replace github.com/GoCodeAlone/modular/modules/eventbus => ../../modules/eventbus require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/eventbus v1.7.0 ) require ( github.com/BurntSushi/toml v1.6.0 // indirect github.com/DataDog/datadog-go/v5 v5.4.0 // indirect + github.com/GoCodeAlone/modular/modules/eventbus/v2 v2.5.1 // indirect github.com/IBM/sarama v1.45.2 // indirect github.com/Microsoft/go-winio v0.5.0 // indirect github.com/aws/aws-sdk-go-v2 v1.38.0 // indirect diff --git a/examples/nats-eventbus/go.sum b/examples/nats-eventbus/go.sum index bd3ee7f0..4ce86877 100644 --- a/examples/nats-eventbus/go.sum +++ b/examples/nats-eventbus/go.sum @@ -2,6 +2,8 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DataDog/datadog-go/v5 v5.4.0 h1:Ea3eXUVwrVV28F/fo3Dr3aa+TL/Z7Xi6SUPKW8L99aI= github.com/DataDog/datadog-go/v5 v5.4.0/go.mod h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw= +github.com/GoCodeAlone/modular/modules/eventbus/v2 v2.5.1 h1:GTSJh+QbPj7nuXoiiz53+DPxJ3xw7JPemzBuWg6vKS4= +github.com/GoCodeAlone/modular/modules/eventbus/v2 v2.5.1/go.mod h1:PvgkUxMg2RL/TjKevO3PBTy+RazZX5YXi8IK/Bz1qcw= github.com/IBM/sarama v1.45.2 h1:8m8LcMCu3REcwpa7fCP6v2fuPuzVwXDAM2DOv3CBrKw= github.com/IBM/sarama v1.45.2/go.mod h1:ppaoTcVdGv186/z6MEKsMm70A5fwJfRTpstI37kVn3Y= github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= diff --git a/examples/observer-demo/go.mod b/examples/observer-demo/go.mod index 41825f49..ba497069 100644 --- a/examples/observer-demo/go.mod +++ b/examples/observer-demo/go.mod @@ -9,7 +9,7 @@ replace github.com/GoCodeAlone/modular => ../.. replace github.com/GoCodeAlone/modular/modules/eventlogger => ../../modules/eventlogger require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/eventlogger v0.0.0-00010101000000-000000000000 github.com/cloudevents/sdk-go/v2 v2.16.2 ) diff --git a/examples/observer-pattern/go.mod b/examples/observer-pattern/go.mod index 1a1b51fc..e6b1b958 100644 --- a/examples/observer-pattern/go.mod +++ b/examples/observer-pattern/go.mod @@ -5,7 +5,7 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/eventlogger v0.0.0-00010101000000-000000000000 github.com/cloudevents/sdk-go/v2 v2.16.2 ) diff --git a/examples/reverse-proxy/go.mod b/examples/reverse-proxy/go.mod index 0600e190..4fa492c0 100644 --- a/examples/reverse-proxy/go.mod +++ b/examples/reverse-proxy/go.mod @@ -5,7 +5,7 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/chimux v1.1.0 github.com/GoCodeAlone/modular/modules/httpserver v0.1.1 github.com/GoCodeAlone/modular/modules/reverseproxy v1.1.0 diff --git a/examples/testing-scenarios/go.mod b/examples/testing-scenarios/go.mod index 440db1e8..e65877e7 100644 --- a/examples/testing-scenarios/go.mod +++ b/examples/testing-scenarios/go.mod @@ -5,7 +5,7 @@ go 1.25 toolchain go1.25.0 require ( - github.com/GoCodeAlone/modular v1.11.11 + github.com/GoCodeAlone/modular v1.12.0 github.com/GoCodeAlone/modular/modules/chimux v0.0.0-00010101000000-000000000000 github.com/GoCodeAlone/modular/modules/httpserver v0.0.0-00010101000000-000000000000 github.com/GoCodeAlone/modular/modules/reverseproxy v0.0.0-00010101000000-000000000000 diff --git a/modules/database/AWS_IAM_AUTH.md b/modules/database/AWS_IAM_AUTH.md index dbab11df..eb1a1c88 100644 --- a/modules/database/AWS_IAM_AUTH.md +++ b/modules/database/AWS_IAM_AUTH.md @@ -20,9 +20,9 @@ When AWS IAM authentication is enabled, **any password in the DSN is ignored and ```yaml # All of these DSN formats work identically with IAM auth: -dsn: "postgresql://chimera_app:$TOKEN@host.rds.amazonaws.com:5432/mydb" -dsn: "postgresql://chimera_app:PLACEHOLDER@host.rds.amazonaws.com:5432/mydb" -dsn: "postgresql://chimera_app@host.rds.amazonaws.com:5432/mydb" +dsn: "postgresql://myapp_user:$TOKEN@host.rds.amazonaws.com:5432/mydb" +dsn: "postgresql://myapp_user:PLACEHOLDER@host.rds.amazonaws.com:5432/mydb" +dsn: "postgresql://myapp_user@host.rds.amazonaws.com:5432/mydb" ``` The password portion (`$TOKEN`, `PLACEHOLDER`, or empty) is completely ignored when IAM auth is enabled. @@ -33,7 +33,7 @@ The database username is extracted from the DSN or can be explicitly specified: ```yaml # Option 1: Username in DSN (extracted automatically) -dsn: "postgresql://chimera_app:$TOKEN@host.rds.amazonaws.com:5432/mydb" +dsn: "postgresql://myapp_user:$TOKEN@host.rds.amazonaws.com:5432/mydb" aws_iam_auth: enabled: true region: us-east-1 @@ -43,7 +43,7 @@ dsn: "postgresql://ignored_user:$TOKEN@host.rds.amazonaws.com:5432/mydb" aws_iam_auth: enabled: true region: us-east-1 - db_user: chimera_app # This takes precedence + db_user: myapp_user # This takes precedence ``` ### 3. Token Generation Flow @@ -66,7 +66,7 @@ database: writer: driver: postgres # DSN with $TOKEN placeholder - will be automatically stripped - dsn: "postgresql://chimera_app:$TOKEN@shared-chimera-dev-backend.cluster-xyz.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require" + dsn: "postgresql://myapp_user:$TOKEN@mydb-instance.cluster-xyz.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require" max_open_connections: 25 max_idle_connections: 10 connection_max_lifetime: 1h @@ -82,7 +82,7 @@ database: ```bash export DB_WRITER_DRIVER=postgres -export DB_WRITER_DSN="postgresql://chimera_app:$TOKEN@host.rds.amazonaws.com:5432/mydb?sslmode=require" +export DB_WRITER_DSN="postgresql://myapp_user:$TOKEN@host.rds.amazonaws.com:5432/mydb?sslmode=require" export DB_WRITER_AWS_IAM_AUTH_ENABLED=true export DB_WRITER_AWS_IAM_AUTH_REGION=us-east-1 export DB_WRITER_MAX_OPEN_CONNECTIONS=25 @@ -102,15 +102,15 @@ Create a database user configured for IAM authentication: **PostgreSQL:** ```sql -CREATE USER chimera_app WITH LOGIN; -GRANT rds_iam TO chimera_app; -GRANT ALL PRIVILEGES ON DATABASE chimera_backend TO chimera_app; +CREATE USER myapp_user WITH LOGIN; +GRANT rds_iam TO myapp_user; +GRANT ALL PRIVILEGES ON DATABASE myappdb TO myapp_user; ``` **MySQL:** ```sql -CREATE USER chimera_app IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; -GRANT ALL PRIVILEGES ON chimera_backend.* TO chimera_app@'%'; +CREATE USER myapp_user IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; +GRANT ALL PRIVILEGES ON myappdb.* TO myapp_user@'%'; ``` ### 3. IAM Policy @@ -125,7 +125,7 @@ The AWS principal (user/role) must have `rds-db:connect` permission: "Effect": "Allow", "Action": ["rds-db:connect"], "Resource": [ - "arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/chimera_app" + "arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/myapp_user" ] } ] @@ -135,7 +135,7 @@ The AWS principal (user/role) must have `rds-db:connect` permission: **Finding your Resource ARN:** - Format: `arn:aws:rds-db:REGION:ACCOUNT:dbuser:RESOURCE_ID/DB_USERNAME` - Get RESOURCE_ID from RDS console (cluster identifier starts with `cluster-`) -- Example: `arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-ABC123DEF456/chimera_app` +- Example: `arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-ABC123DEF456/myapp_user` ### 4. AWS Credentials @@ -155,7 +155,7 @@ database: connections: writer: driver: postgres - dsn: "postgresql://myuser:MySecretPassword123@host.rds.amazonaws.com:5432/mydb" + dsn: "postgresql://myuser:MySecretP@ssword@host.rds.amazonaws.com:5432/mydb" ``` ### After (with IAM): @@ -173,18 +173,18 @@ database: **The password portion is completely ignored when IAM auth is enabled.** -## Your Specific Use Case +## Example Use Case -You mentioned passing the DSN as: +Here is a complete example DSN for an RDS Aurora PostgreSQL cluster: ``` -postgresql://chimera_app:$TOKEN@shared-chimera-dev-backend.cluster-cbysgk6e0u2x.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require +postgresql://myapp_user:$TOKEN@mydb-instance.cluster-abc123def456.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require ``` -**This is exactly the correct format!** Here's what happens: +**This is the correct format.** Here's what happens: 1. ✅ The module sees `aws_iam_auth.enabled: true` 2. ✅ The `$TOKEN` placeholder is automatically stripped from the DSN -3. ✅ The username `chimera_app` is extracted and used for IAM authentication +3. ✅ The username `myapp_user` is extracted and used for IAM authentication 4. ✅ AWS credentials are loaded from your environment 5. ✅ An RDS IAM token is generated automatically 6. ✅ The token is refreshed every ~15 minutes automatically @@ -237,10 +237,10 @@ DEBUG Processing DSN for IAM authentication original_dsn_length=142 DEBUG Password stripped from DSN cleaned_dsn_length=128 INFO Extracted RDS endpoint endpoint=mydb.cluster-xyz.us-east-1.rds.amazonaws.com:5432 DEBUG Extracted database configuration database=mydb options_count=1 -DEBUG Extracted username from DSN username=chimera_app -INFO IAM authentication will use database user username=chimera_app +DEBUG Extracted username from DSN username=myapp_user +INFO IAM authentication will use database user username=myapp_user DEBUG Determined database driver configuration driver=pgx port=5432 -INFO Creating AWS RDS credential store endpoint=mydb... region=us-east-1 username=chimera_app +INFO Creating AWS RDS credential store endpoint=mydb... region=us-east-1 username=myapp_user DEBUG AWS RDS credential store created successfully INFO Database connection with AWS IAM authentication configured successfully DEBUG Testing database connection timeout=10s @@ -353,17 +353,17 @@ You can test IAM authentication manually: ```bash # Generate a token TOKEN=$(aws rds generate-db-auth-token \ - --hostname shared-chimera-dev-backend.cluster-xyz.us-east-1.rds.amazonaws.com \ + --hostname mydb-instance.cluster-xyz.us-east-1.rds.amazonaws.com \ --port 5432 \ - --username chimera_app \ + --username myapp_user \ --region us-east-1) # Connect using the token PGPASSWORD=$TOKEN psql \ - -h shared-chimera-dev-backend.cluster-xyz.us-east-1.rds.amazonaws.com \ + -h mydb-instance.cluster-xyz.us-east-1.rds.amazonaws.com \ -p 5432 \ - -U chimera_app \ - -d chimera_backend + -U myapp_user \ + -d myappdb ``` ## Benefits of IAM Authentication diff --git a/modules/database/DIAGNOSTICS.md b/modules/database/DIAGNOSTICS.md index 108cf127..413e8f71 100644 --- a/modules/database/DIAGNOSTICS.md +++ b/modules/database/DIAGNOSTICS.md @@ -114,13 +114,13 @@ ERROR Failed to extract RDS endpoint from DSN **Valid DSN Formats:** ```yaml # URL style with placeholder -dsn: "postgresql://chimera_app:$TOKEN@mydb.us-east-1.rds.amazonaws.com:5432/chimera_backend" +dsn: "postgresql://myapp_user:$TOKEN@mydb.us-east-1.rds.amazonaws.com:5432/myappdb" # URL style without password -dsn: "postgresql://chimera_app@mydb.us-east-1.rds.amazonaws.com:5432/chimera_backend" +dsn: "postgresql://myapp_user@mydb.us-east-1.rds.amazonaws.com:5432/myappdb" # With options -dsn: "postgresql://chimera_app@mydb.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require" +dsn: "postgresql://myapp_user@mydb.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require" ``` **Common Mistakes:** @@ -147,7 +147,7 @@ ERROR Database username not found **Option 1:** Include username in DSN ```yaml # Include username after :// -dsn: "postgresql://chimera_app@mydb.rds.amazonaws.com:5432/mydb" +dsn: "postgresql://myapp_user@mydb.rds.amazonaws.com:5432/mydb" ``` **Option 2:** Specify in config @@ -155,7 +155,7 @@ dsn: "postgresql://chimera_app@mydb.rds.amazonaws.com:5432/mydb" aws_iam_auth: enabled: true region: us-east-1 - db_user: chimera_app # ← Specify username here + db_user: myapp_user # ← Specify username here ``` --- @@ -183,7 +183,7 @@ ERROR Failed to create AWS RDS credential store aws rds generate-db-auth-token \ --hostname mydb.us-east-1.rds.amazonaws.com \ --port 5432 \ - --username chimera_app \ + --username myapp_user \ --region us-east-1 ``` Should output a token string. @@ -209,7 +209,7 @@ ERROR Failed to create AWS RDS credential store **Error Message:** ``` ERROR Database ping failed with IAM authentication - error="pq: password authentication failed for user \"chimera_app\"" + error="pq: password authentication failed for user \"myapp_user\"" timeout=10s possible_causes=["IAM token generation failed", "Database user doesn't have rds_iam role", ...] ``` @@ -223,19 +223,19 @@ This is the most common production error. Follow this systematic diagnostic: -- Connect as master user SELECT rolname, rolcanlogin FROM pg_roles -WHERE rolname = 'chimera_app'; +WHERE rolname = 'myapp_user'; -- Check if user has rds_iam role SELECT r.rolname FROM pg_roles r JOIN pg_auth_members m ON r.oid = m.member WHERE m.roleid = (SELECT oid FROM pg_roles WHERE rolname = 'rds_iam') - AND r.rolname = 'chimera_app'; + AND r.rolname = 'myapp_user'; ``` If the user doesn't have `rds_iam` role: ```sql -GRANT rds_iam TO chimera_app; +GRANT rds_iam TO myapp_user; ``` **MySQL:** @@ -243,15 +243,15 @@ GRANT rds_iam TO chimera_app; -- Check if user exists and uses IAM plugin SELECT user, host, plugin FROM mysql.user -WHERE user = 'chimera_app'; +WHERE user = 'myapp_user'; ``` User should have `plugin = 'AWSAuthenticationPlugin'`. If not: ```sql -CREATE USER chimera_app IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; -GRANT ALL PRIVILEGES ON chimera_backend.* TO chimera_app@'%'; +CREATE USER myapp_user IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; +GRANT ALL PRIVILEGES ON myappdb.* TO myapp_user@'%'; ``` #### Step 2: Verify IAM Policy @@ -266,7 +266,7 @@ Check your IAM policy allows `rds-db:connect`: "Effect": "Allow", "Action": ["rds-db:connect"], "Resource": [ - "arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/chimera_app" + "arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/myapp_user" ] } ] @@ -290,7 +290,7 @@ aws rds describe-db-clusters \ aws iam simulate-principal-policy \ --policy-source-arn arn:aws:iam::123456789012:role/my-role \ --action-names rds-db:connect \ - --resource-arns "arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/chimera_app" + --resource-arns "arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/myapp_user" ``` #### Step 3: Test Manual Connection @@ -301,17 +301,17 @@ Generate a token and try connecting manually: ```bash # Generate token TOKEN=$(aws rds generate-db-auth-token \ - --hostname shared-chimera-dev-backend.cluster-xyz.us-east-1.rds.amazonaws.com \ + --hostname mydb-instance.cluster-xyz.us-east-1.rds.amazonaws.com \ --port 5432 \ - --username chimera_app \ + --username myapp_user \ --region us-east-1) # Try connecting PGPASSWORD=$TOKEN psql \ - -h shared-chimera-dev-backend.cluster-xyz.us-east-1.rds.amazonaws.com \ + -h mydb-instance.cluster-xyz.us-east-1.rds.amazonaws.com \ -p 5432 \ - -U chimera_app \ - -d chimera_backend + -U myapp_user \ + -d myappdb ``` If manual connection works but application doesn't: @@ -429,7 +429,7 @@ aws rds generate-db-auth-token \ --region REGION # Database User Check (PostgreSQL) -psql -h HOST -U master_user -d postgres -c "\du+ chimera_app" +psql -h HOST -U master_user -d postgres -c "\du+ myapp_user" # RDS IAM Status aws rds describe-db-instances \ diff --git a/modules/database/config.go b/modules/database/config.go index d2817fed..37f4de9d 100644 --- a/modules/database/config.go +++ b/modules/database/config.go @@ -67,11 +67,11 @@ type ConnectionConfig struct { // You can include a placeholder like $TOKEN in the DSN for clarity, but it will be removed: // // Example DSN: -// postgresql://chimera_app:$TOKEN@mydb.us-east-1.rds.amazonaws.com:5432/mydb?sslmode=require +// postgresql://myapp_user:$TOKEN@mydb.us-east-1.rds.amazonaws.com:5432/mydb?sslmode=require // // The module will: // 1. Strip the "$TOKEN" placeholder from the DSN -// 2. Extract the username "chimera_app" +// 2. Extract the username "myapp_user" // 3. Use AWS credentials to generate an IAM auth token // 4. Automatically refresh the token before it expires // diff --git a/modules/database/credential_refresh_store.go b/modules/database/credential_refresh_store.go index 5325d60a..0e26d877 100644 --- a/modules/database/credential_refresh_store.go +++ b/modules/database/credential_refresh_store.go @@ -25,7 +25,7 @@ var ( // // AWS IAM Authentication Flow: // 1. Any password/token in the DSN is stripped (including placeholders like $TOKEN) -// 2. Username is extracted from the DSN (e.g., "chimera_app" from postgresql://chimera_app:$TOKEN@host/db) +// 2. Username is extracted from the DSN (e.g., "myapp_user" from postgresql://myapp_user:$TOKEN@host/db) // 3. AWS credentials are loaded from the environment/instance profile/etc. // 4. RDS IAM auth token is automatically generated using AWS credentials // 5. Token is automatically refreshed before expiration @@ -33,11 +33,11 @@ var ( // // This means you can pass a DSN with a placeholder token like: // -// postgresql://chimera_app:$TOKEN@shared-chimera-dev-backend.cluster-xyz.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require +// postgresql://myapp_user:$TOKEN@mydb-instance.cluster-xyz.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require // // And the module will: // - Ignore the "$TOKEN" placeholder -// - Use "chimera_app" as the database username for IAM authentication +// - Use "myapp_user" as the database username for IAM authentication // - Automatically generate and refresh the actual IAM token // // Configuration Requirements: @@ -232,12 +232,12 @@ func configureConnectionPool(db *sql.DB, config ConnectionConfig) { // - The actual IAM token is obtained using AWS credentials and the username extracted from the DSN // // Example DSNs that will have their passwords stripped: -// - postgresql://chimera_app:$TOKEN@host.rds.amazonaws.com:5432/mydb?sslmode=require -// becomes: postgresql://chimera_app@host.rds.amazonaws.com:5432/mydb?sslmode=require +// - postgresql://myapp_user:$TOKEN@host.rds.amazonaws.com:5432/mydb?sslmode=require +// becomes: postgresql://myapp_user@host.rds.amazonaws.com:5432/mydb?sslmode=require // - postgres://user:some_placeholder@host:5432/mydb // becomes: postgres://user@host:5432/mydb // -// The username (e.g., "chimera_app") is preserved and used for IAM authentication. +// The username (e.g., "myapp_user") is preserved and used for IAM authentication. func stripPasswordFromDSN(dsn string) string { if strings.Contains(dsn, "://") { // URL-style DSN (e.g., postgres://user:password@host:port/database) diff --git a/modules/database/credential_refresh_test.go b/modules/database/credential_refresh_test.go index e3e2fd1e..2163b695 100644 --- a/modules/database/credential_refresh_test.go +++ b/modules/database/credential_refresh_test.go @@ -307,8 +307,8 @@ func TestStripPasswordFromDSN(t *testing.T) { }, { name: "URL-style DSN with $TOKEN placeholder", - dsn: "postgresql://chimera_app:$TOKEN@shared-chimera-dev-backend.cluster-cbysgk6e0u2x.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require", - expected: "postgresql://chimera_app@shared-chimera-dev-backend.cluster-cbysgk6e0u2x.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require", + dsn: "postgresql://myapp_user:$TOKEN@mydb-instance.cluster-abc123def456.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require", + expected: "postgresql://myapp_user@mydb-instance.cluster-abc123def456.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require", }, { name: "URL-style DSN without password", @@ -350,8 +350,8 @@ func TestUsernameExtraction_WithTokenPlaceholder(t *testing.T) { }{ { name: "DSN with $TOKEN placeholder", - dsn: "postgresql://chimera_app:$TOKEN@shared-chimera-dev-backend.cluster-cbysgk6e0u2x.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require", - expected: "chimera_app", + dsn: "postgresql://myapp_user:$TOKEN@mydb-instance.cluster-abc123def456.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require", + expected: "myapp_user", }, { name: "DSN with TOKEN placeholder (no $)", diff --git a/modules/database/examples/aws-iam-auth-config.yaml b/modules/database/examples/aws-iam-auth-config.yaml index 3a6bfdf5..95da5b8f 100644 --- a/modules/database/examples/aws-iam-auth-config.yaml +++ b/modules/database/examples/aws-iam-auth-config.yaml @@ -12,15 +12,15 @@ # Prerequisites: # 1. RDS instance must have IAM authentication enabled # 2. Database user must be created with IAM authentication: -# CREATE USER chimera_app WITH LOGIN; -# GRANT rds_iam TO chimera_app; +# CREATE USER myapp_user WITH LOGIN; +# GRANT rds_iam TO myapp_user; # 3. IAM policy must allow rds-db:connect action: # { # "Version": "2012-10-17", # "Statement": [{ # "Effect": "Allow", # "Action": ["rds-db:connect"], -# "Resource": ["arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/chimera_app"] +# "Resource": ["arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-XXXXX/myapp_user"] # }] # } # 4. AWS credentials must be available (environment variables, instance profile, etc.) @@ -33,7 +33,7 @@ database: driver: postgres # DSN with $TOKEN placeholder - the placeholder will be automatically stripped # and replaced with a dynamically generated IAM token - dsn: "postgresql://chimera_app:$TOKEN@shared-chimera-dev-backend.cluster-cbysgk6e0u2x.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require" + dsn: "postgresql://myapp_user:$TOKEN@mydb-instance.cluster-abc123def456.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require" max_open_connections: 25 max_idle_connections: 10 connection_max_lifetime: 1h @@ -42,14 +42,14 @@ database: enabled: true region: us-east-1 # db_user is optional - if not specified, username is extracted from DSN - # db_user: chimera_app + # db_user: myapp_user connection_timeout: 10s # Reader connection with IAM authentication reader: driver: postgres # Alternative format: leave password empty (no placeholder needed) - dsn: "postgresql://chimera_app@shared-chimera-dev-backend-ro.cluster-cbysgk6e0u2x.us-east-1.rds.amazonaws.com:5432/chimera_backend?sslmode=require" + dsn: "postgresql://myapp_user@mydb-instance-ro.cluster-abc123def456.us-east-1.rds.amazonaws.com:5432/myappdb?sslmode=require" max_open_connections: 50 max_idle_connections: 20 connection_max_lifetime: 1h @@ -57,22 +57,22 @@ database: enabled: true region: us-east-1 # Explicitly specify the database user (takes precedence over DSN username) - db_user: chimera_app + db_user: myapp_user # Environment Variable Configuration Alternative: # You can also configure via environment variables: # # export DB_WRITER_DRIVER=postgres -# export DB_WRITER_DSN="postgresql://chimera_app:$TOKEN@host.rds.amazonaws.com:5432/mydb?sslmode=require" +# export DB_WRITER_DSN="postgresql://myapp_user:$TOKEN@host.rds.amazonaws.com:5432/mydb?sslmode=require" # export DB_WRITER_AWS_IAM_AUTH_ENABLED=true # export DB_WRITER_AWS_IAM_AUTH_REGION=us-east-1 # export DB_WRITER_MAX_OPEN_CONNECTIONS=25 # # export DB_READER_DRIVER=postgres -# export DB_READER_DSN="postgresql://chimera_app@host-ro.rds.amazonaws.com:5432/mydb?sslmode=require" +# export DB_READER_DSN="postgresql://myapp_user@host-ro.rds.amazonaws.com:5432/mydb?sslmode=require" # export DB_READER_AWS_IAM_AUTH_ENABLED=true # export DB_READER_AWS_IAM_AUTH_REGION=us-east-1 -# export DB_READER_AWS_IAM_AUTH_DB_USER=chimera_app +# export DB_READER_AWS_IAM_AUTH_DB_USER=myapp_user # How It Works: # 1. The module strips any password from the DSN (including placeholders like $TOKEN)