Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions IMPLEMENTATION_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# AWS RDS IAM Authentication Implementation Summary
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI slop; remove


## Overview
This implementation adds support for AWS RDS IAM authentication to the Nuts node, allowing secure database connections using temporary IAM tokens instead of static passwords.

## Files Added

### 1. `/storage/rds_iam.go` (Main Implementation)
- `rdsIAMAuthenticator`: Manages IAM token generation and refresh
- `modifyConnectionStringForRDSIAM()`: Modifies connection strings for IAM auth
- `parsePostgresConnectionString()`: Parses PostgreSQL connection strings
- `parseMySQLConnectionString()`: Parses MySQL connection strings
- Token refresh logic with configurable intervals (default: 14 minutes)

### 2. `/storage/rds_iam_test.go` (Unit Tests)
- Tests for connection string parsing
- Tests for token injection
- Tests for authenticator initialization
- All tests passing ✓

### 3. `/storage/RDS_IAM_AUTHENTICATION.md` (Documentation)
- Complete setup guide
- AWS configuration instructions
- Security best practices
- Troubleshooting tips

### 4. `/storage/rds_iam_example_config.yaml` (Example Configuration)
- Ready-to-use configuration examples for PostgreSQL and MySQL
- Commented explanations for each option

## Files Modified

### 1. `/storage/config.go`
- Added `RDSIAMConfig` struct with fields:
- `Enabled`: Enable/disable IAM authentication
- `Region`: AWS region
- `DBUser`: Database username
- `TokenRefreshInterval`: Token refresh interval

### 2. `/storage/engine.go`
- Added `rdsIAMAuth` field to engine struct
- Modified `initSQLDatabase()` to handle RDS IAM authentication
- Added `Start()` method to launch background token refresh
- Added `refreshRDSIAMTokenPeriodically()` for periodic token updates

### 3. `/go.mod` (Dependencies Added)
- `github.com/aws/aws-sdk-go-v2` v1.41.1
- `github.com/aws/aws-sdk-go-v2/config` v1.32.7
- `github.com/aws/aws-sdk-go-v2/feature/rds/auth` v1.6.17
- And related AWS SDK v2 dependencies

## Features

✅ **Automatic Token Management**
- Tokens generated on startup
- Background refresh every 14 minutes (configurable)
- Tokens valid for 15 minutes with 1-minute safety margin

✅ **Database Support**
- PostgreSQL (via `postgres://` connection strings)
- MySQL (via `mysql://` connection strings)

✅ **Security**
- No passwords stored in configuration
- Uses AWS IAM for authentication
- Integrates with AWS credential chain
- Supports EC2 instance profiles

✅ **Configuration**
- Simple YAML configuration
- Optional overrides for user and region
- Backward compatible (disabled by default)

## Usage Example

```yaml
storage:
sql:
connection: "postgres://nutsuser@mydb.us-east-1.rds.amazonaws.com:5432/nuts"
rds_iam:
enabled: true
region: "us-east-1"
db_user: "nutsuser"
```

## Testing

All tests pass:
```
✓ TestParsePostgresConnectionString
✓ TestParseMySQLConnectionString
✓ TestInjectPasswordIntoConnectionString
✓ TestModifyConnectionStringForRDSIAM
✓ TestNewRDSIAMAuthenticator
✓ TestRDSIAMAuthenticator_GetToken
```

## Build Status

✅ Storage package builds successfully
✅ Full project builds successfully
✅ Dependencies cleaned with `go mod tidy`

## AWS Prerequisites

1. **RDS Instance**: IAM authentication enabled
2. **IAM Policy**: `rds-db:connect` permission
3. **Database User**: Created with IAM authentication
4. **AWS Credentials**: Available via environment, instance profile, or config file

## Security Considerations

- Tokens are not logged (only at DEBUG level)
- Connection strings without passwords when IAM enabled
- AWS credentials secured via IAM best practices
- CloudTrail integration for audit logging

## Backward Compatibility

✅ Feature is opt-in (disabled by default)
✅ No breaking changes to existing configurations
✅ Works alongside traditional password authentication
✅ Gracefully handles missing AWS credentials

## Next Steps for Users

1. Enable IAM authentication on RDS instance
2. Create IAM policy with `rds-db:connect` permission
3. Create database user for IAM authentication
4. Configure Nuts node with RDS IAM settings
5. Ensure AWS credentials are available
6. Start the node and verify connection

## Implementation Notes

- Token refresh runs in background goroutine
- Refresh interval prevents token expiry
- Error handling for AWS API failures
- Clean shutdown of refresh goroutine
- Thread-safe token updates
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ The following options can be configured on the server:
storage.session.redis.sentinel.username Username for authenticating to Redis Sentinels.
storage.session.redis.tls.truststorefile PEM file containing the trusted CA certificate(s) for authenticating remote Redis session servers. Can only be used when connecting over TLS (use 'rediss://' as scheme in address).
storage.sql.connection Connection string for the SQL database. If not set it, defaults to a SQLite database stored inside the configured data directory. Note: using SQLite is not recommended in production environments. If using SQLite anyways, remember to enable foreign keys ('_foreign_keys=on') and the write-ahead-log ('_journal_mode=WAL').
storage.sql.rdsiam.enabled false Enable AWS RDS IAM authentication for the SQL database connection. When enabled, the node will use temporary IAM tokens instead of passwords. Requires the connection string to be a PostgreSQL or MySQL RDS endpoint without a password.
storage.sql.rdsiam.region AWS region where the RDS instance is located (e.g., 'us-east-1). Required when RDS IAM authentication is enabled.
storage.sql.rdsiam.dbuser Database username for IAM authentication. If not specified, the username from the connection string will be used. The database user must be created with IAM authentication enabled.
storage.sql.rdsiam.tokenrefreshinterval 14m0s Interval at which to refresh the IAM authentication token. RDS tokens are valid for 15 minutes, so the default is 14 minutes to ensure tokens are refreshed before expiry. Specified as Golang duration (e.g. 10m, 1h).
**policy**
policy.directory ./config/policy Directory to read policy files from. Policy files are JSON files that contain a scope to PresentationDefinition mapping.
======================================== =================================================================================================================================================================================================================================================================================================================================================================================================================================================================== ============================================================================================================================================================================================================================================================================================================================================
Expand Down
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ require (
)

require (
github.com/aws/aws-sdk-go-v2/config v1.32.7
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.6.17
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
github.com/daangn/minimemcached v1.2.0
github.com/eko/gocache/lib/v4 v4.2.3
Expand All @@ -219,6 +221,19 @@ require (
)

require (
github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.19.7 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect
github.com/aws/smithy-go v1.24.0 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
Expand Down
30 changes: 30 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,36 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7D
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/avast/retry-go/v4 v4.7.0 h1:yjDs35SlGvKwRNSykujfjdMxMhMQQM0TnIjJaHB+Zio=
github.com/avast/retry-go/v4 v4.7.0/go.mod h1:ZMPDa3sY2bKgpLtap9JRUgk2yTAba7cgiFhqxY2Sg6Q=
github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU=
github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
github.com/aws/aws-sdk-go-v2/config v1.32.7 h1:vxUyWGUwmkQ2g19n7JY/9YL8MfAIl7bTesIUykECXmY=
github.com/aws/aws-sdk-go-v2/config v1.32.7/go.mod h1:2/Qm5vKUU/r7Y+zUk/Ptt2MDAEKAfUtKc1+3U1Mo3oY=
github.com/aws/aws-sdk-go-v2/credentials v1.19.7 h1:tHK47VqqtJxOymRrNtUXN5SP/zUTvZKeLx4tH6PGQc8=
github.com/aws/aws-sdk-go-v2/credentials v1.19.7/go.mod h1:qOZk8sPDrxhf+4Wf4oT2urYJrYt3RejHSzgAquYeppw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.6.17 h1:BTFAHrUqHRo9KRVXojX/uU/ht9tyYH2TN0NfPiyLfqA=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.6.17/go.mod h1:8Xhnm3tJUGk9ernojWk4VOgEsPhDkeNOrY+IVRL6eqY=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 h1:v6EiMvhEYBoHABfbGB4alOYmCIrcgyPPiBE1wZAEbqk=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.9/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 h1:gd84Omyu9JLriJVCbGApcLzVR3XtmC4ZDPcAI6Ftvds=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ=
github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk=
github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down
Loading