diff --git a/docs/how-to/aws-rds-proxy/README.md b/docs/how-to/aws-rds-proxy/README.md new file mode 100644 index 00000000..df983441 --- /dev/null +++ b/docs/how-to/aws-rds-proxy/README.md @@ -0,0 +1,214 @@ +# AWS RDS Proxy Role and Proxy Provisioning + +This document describes the pattern we use to provision the `r-rds-proxy` IAM role and then create an Amazon RDS Proxy that uses that role. + +The goal is to keep the setup simple and repeatable: + +* the `r-rds-proxy` role is created in Terraform +* the SC-DBA SSO permission set is allowed to assume that role +* the RDS Proxy is created with the role ARN and the correct network and authentication settings + +## Related Documents + +* [How To Documents](../README.md) +* [AWS Identity Center (SSO)](../aws-sso/README.md) +* [sc-dba permission set](../../../../infrastructure/global/sso/permissionsets/sc-dba/sc-dba.permissionset.tf) +* [Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) +* [Getting started with RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-setup.html) +* [Configuring IAM authentication for RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-iam-setup.html) +* [Creating a proxy for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-creating.html) +* [Setting up database credentials for RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-secrets-arns.html) +* [Create a role to delegate permissions to an AWS service](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html) + +## Overview + +RDS Proxy sits between your application and your database and manages connection pooling, failover handling, and authentication behavior. + +In this repo, the operational pattern is: + +1. create an IAM role named `r-rds-proxy` +1. attach the permissions required for the proxy workflow +1. allow the `AWSReservedSSO_sc-dba*` role to assume it +1. create the proxy and point it at that role + +The current `sc-dba` permission set already includes the permission required for SSO users to assume the role. See [sc-dba.permissionset.tf](../../../../infrastructure/global/sso/permissionsets/sc-dba/sc-dba.permissionset.tf). + +## Prerequisites + +Before provisioning the role or proxy, make sure you have: + +* access to the Terraform workspace that owns the account and region +* SC-DBA access through AWS Identity Center +* the database target already provisioned or at least planned +* network prerequisites in place, including VPC subnets and security groups for the proxy +* a decision about how the proxy authenticates to the database: + * Secrets Manager credentials + * IAM authentication + * a mixed model, where the proxy uses a secret and the application uses IAM + +For AWS guidance on prerequisites, see [Getting started with RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-setup.html). + +## Create The Role + +The simplest way to provision the role is to keep it in Terraform and let the same stack manage both the trust policy and the inline permissions. + +The existing pattern uses two trust principals: + +* `rds.amazonaws.com`, so the RDS service can assume the role when the proxy needs it +* the SC-DBA Identity Center role, so operators can assume the same role when they administer the proxy and related resources + +An example trust policy looks like this: + +```hcl +data "aws_iam_policy_document" "assume" { + statement { + sid = "STSAssumeRole" + effect = "Allow" + actions = ["sts:AssumeRole"] + principals { + type = "Service" + identifiers = ["rds.amazonaws.com"] + } + } + + statement { + sid = "STSAssumeRoleScDbaSSO" + effect = "Allow" + actions = ["sts:AssumeRole"] + principals { + type = "AWS" + identifiers = [one(data.aws_iam_roles.sc_dba_sso.arns)] + } + } +} +``` + +The role should also have the inline policy bundle it needs for database work. In the current pattern that bundle is `sc-dba-combined`, which combines the database permissions and the Secrets Manager permissions. + +If you are creating the role with the same module pattern used elsewhere in the repo, the shape is: + +```hcl +module "rds-proxy" { + source = "git@github.e.it.census.gov:terraform-modules/aws-iam-role.git?ref=tf-upgrade" + role_name = "rds-proxy" + assume_policy_document = data.aws_iam_policy_document.assume.json + inline_policies = [{ + name = "sc-dba-combined" + policy = data.aws_iam_policy_document.sc-dba-combined.json + }] +} +``` + +### What To Put In The Role Policy + +The policy attached to the role should be as narrow as possible for your use case. + +For this repository’s current `sc-dba` pattern, the policy includes access for: + +* KMS alias lookup and KMS key use for RDS and Secrets Manager +* RDS and Performance Insights read and connect operations +* Secrets Manager secret management operations +* CloudWatch, CloudWatch Logs, CloudTrail, Config, and related operational visibility + +If your deployment only needs a subset of those permissions, split them into smaller policies rather than widening the role further. + +## Allow SSO Users To Assume The Role + +The `sc-dba` permission set must explicitly allow `sts:AssumeRole` on the `r-rds-proxy` role. + +That permission already exists in [sc-dba.permissionset.tf](../../../../infrastructure/global/sso/permissionsets/sc-dba/sc-dba.permissionset.tf). The important part is the IAM resource ARN and the organization guard: + +```hcl +statement { + sid = "STSAssumeRoleRDSProxy" + actions = ["sts:AssumeRole"] + effect = "Allow" + resources = [format("arn:%v:%v:%v:%v:%v", data.aws_arn.current.partition, "iam", "", "*", "role/r-rds-proxy")] + condition { + test = "StringEquals" + variable = "aws:PrincipalOrgID" + values = [data.aws_organizations_organization.org.id] + } +} +``` + +This keeps the role assumable only within the organization and only for the explicitly named role. + +## Create The RDS Proxy + +Once the role exists, create the proxy and pass the role ARN into the proxy resource. + +At a minimum, you need to define: + +* the proxy name +* the target engine family +* the IAM role ARN +* the VPC subnet IDs +* the VPC security group IDs +* the authentication mode for the database backend +* whether TLS is required + +AWS documents the full setup flow in [Creating a proxy for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-creating.html). + +### Authentication Choices + +Use the path that matches your database and security model: + +* **Secrets Manager authentication** if the proxy should use stored database credentials +* **IAM authentication** if you want the proxy and database path to use IAM-based auth +* **mixed or phased setups** if you are migrating from one model to another + +If you are using IAM authentication, review [Configuring IAM authentication for RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-iam-setup.html). + +If you are using Secrets Manager, review [Setting up database credentials for RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-secrets-arns.html). + +### Terraform Example Shape + +The exact resource arguments vary by engine and by whether you are using secrets or IAM auth, but the important part is always the same: the proxy receives the role ARN created above. + +```hcl +resource "aws_db_proxy" "rds_proxy" { + name = "rds-proxy" + engine_family = "POSTGRESQL" + role_arn = aws_iam_role.rds_proxy.arn + vpc_subnet_ids = var.proxy_subnet_ids + vpc_security_group_ids = [aws_security_group.rds_proxy.id] + require_tls = true +} +``` + +When you use Secrets Manager or IAM auth, attach the corresponding `auth` configuration and secret ARN(s) according to the AWS provider documentation and the AWS RDS Proxy guide. + +## Validation + +After provisioning, verify the following: + +* the IAM role exists with the expected trust policy +* the `sc-dba` permission set can assume the role +* the proxy is created in the intended region and VPC +* the proxy can reach the database target subnets and security groups +* the proxy shows as available in the RDS console or via the AWS CLI + +Useful checks: + +```console +aws iam get-role --role-name r-rds-proxy +aws rds describe-db-proxies +aws sts assume-role --role-arn --role-session-name rds-proxy-check +``` + +If the proxy cannot connect, check the trust policy, the secret/KMS permissions, the DB security group rules, and any IAM auth settings on the database side. + +## References + +* [Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) +* [Getting started with RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-setup.html) +* [Configuring IAM authentication for RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-iam-setup.html) +* [Creating a proxy for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-creating.html) +* [Setting up database credentials for RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-secrets-arns.html) +* [IAM role delegation for AWS services](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html) + +# CHANGELOG + +* 1.0.0 -- 2026-07-02 + - initial version