Compare commits

...

37 commits

Author SHA1 Message Date
semantic-release-bot
cf3a8f41f6 chore(release): version 4.2.1 [skip ci]
## [4.2.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v4.2.0...v4.2.1) (2025-10-21)

### Bug Fixes

* Update CI workflow versions to latest ([#40](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/40)) ([5deff22](5deff22cf4))
2025-10-21 09:10:15 +00:00
Bryant Biggs
5deff22cf4
fix: Update CI workflow versions to latest (#40) 2025-10-21 11:09:40 +02:00
semantic-release-bot
c0b0204344 chore(release): version 4.2.0 [skip ci]
## [4.2.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v4.1.0...v4.2.0) (2025-10-14)

### Features

* Support `default_auth_scheme` ([#39](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/39)) ([c2073a0](c2073a031c))
2025-10-14 13:10:34 +00:00
Melissa Greenbaum
c2073a031c
feat: Support default_auth_scheme (#39) 2025-10-14 08:10:07 -05:00
semantic-release-bot
c65b5f03a7 chore(release): version 4.1.0 [skip ci]
## [4.1.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v4.0.0...v4.1.0) (2025-10-01)

### Features

* Add Terragrunt wrappers ([#38](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/38)) ([33b43c7](33b43c72ab))
2025-10-01 14:13:37 +00:00
flora-five
33b43c72ab
feat: Add Terragrunt wrappers (#38) 2025-10-01 09:13:12 -05:00
semantic-release-bot
3cd004baa3 chore(release): version 4.0.0 [skip ci]
## [4.0.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.2.1...v4.0.0) (2025-09-16)

### ⚠ BREAKING CHANGES

* Upgrade AWS provider and min required Terraform version to `6.0` and `1.5.7` respectively (#34)

### Features

* Upgrade AWS provider and min required Terraform version to `6.0` and `1.5.7` respectively ([#34](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/34)) ([47c0fca](47c0fcad4b))
2025-09-16 14:29:24 +00:00
mrobinson1022
47c0fcad4b
feat!: Upgrade AWS provider and min required Terraform version to 6.0 and 1.5.7 respectively (#34)
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
2025-09-16 09:28:55 -05:00
semantic-release-bot
e8ffe8f2f1 chore(release): version 3.2.1 [skip ci]
## [3.2.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.2.0...v3.2.1) (2025-05-22)

### Bug Fixes

* Correct service principal to rds.amazonaws.com (incl China) ([#32](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/32)) ([bbbf50c](bbbf50ce87))
2025-05-22 09:51:36 +00:00
vladislav-orlovskiy
bbbf50ce87
fix: Correct service principal to rds.amazonaws.com (incl China) (#32)
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
Co-authored-by: Anton Babenko <anton@antonbabenko.com>
2025-05-22 11:51:06 +02:00
semantic-release-bot
99df7e3913 chore(release): version 3.2.0 [skip ci]
## [3.2.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.1.1...v3.2.0) (2024-11-19)

### Features

* Add CloudWatch log group name to outputs ([#28](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/28)) ([0fc0e19](0fc0e19e64))

### Bug Fixes

* Update CI workflow versions to latest ([#27](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/27)) ([b6f22be](b6f22becf6))
2024-11-19 19:29:43 +00:00
Kevin Kortum
0fc0e19e64
feat: Add CloudWatch log group name to outputs (#28)
* feat: adds cloudwatch group name to module outputs

* test: align tests with the new output
2024-11-19 13:29:15 -06:00
Bryant Biggs
b6f22becf6
fix: Update CI workflow versions to latest (#27) 2024-10-11 18:25:27 +02:00
semantic-release-bot
56a832c60d chore(release): version 3.1.1 [skip ci]
## [3.1.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.1.0...v3.1.1) (2024-03-06)

### Bug Fixes

* Update CI workflow versions to remove deprecated runtime warnings ([#26](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/26)) ([a31a810](a31a81097b))
2024-03-06 19:15:03 +00:00
Bryant Biggs
a31a81097b
fix: Update CI workflow versions to remove deprecated runtime warnings (#26) 2024-03-06 11:14:39 -08:00
semantic-release-bot
67116fc717 chore(release): version 3.1.0 [skip ci]
## [3.1.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.0.0...v3.1.0) (2023-08-30)

### Features

* Add IAM role output ([#22](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/22)) ([d18ae45](d18ae45d9e))
2023-08-30 23:59:54 +00:00
Matt McLane
d18ae45d9e
feat: Add IAM role output (#22)
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
2023-08-30 19:59:28 -04:00
Akihiro YAMAZAKI
4e5c8068b9
chore: Fix broken links to examples (#21) 2023-06-27 13:19:28 +02:00
semantic-release-bot
cb79f9c5dc chore(release): version 3.0.0 [skip ci]
## [3.0.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v2.1.2...v3.0.0) (2023-06-09)

### ⚠ BREAKING CHANGES

* Increase Terraform and AWS provider minimum supported versions; update `auth` configuration schema (#17)

### Features

* Increase Terraform and AWS provider minimum supported versions; update `auth` configuration schema ([#17](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/17)) ([cc39e9d](cc39e9d029))
2023-06-09 11:31:21 +00:00
jatalocks
cc39e9d029
feat!: Increase Terraform and AWS provider minimum supported versions; update auth configuration schema (#17)
Co-authored-by: Orest Kapko <orest.kapko@welltech.com>
Co-authored-by: Amitai Getzler <amitai.getzler@explorium.ai>
Co-authored-by: Orest Kapko <kapko2311@gmail.com>
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
Co-authored-by: Anton Babenko <anton@antonbabenko.com>
2023-06-09 07:30:52 -04:00
Pål-Magnus Slåtto
5d1c5e67ea
chore: Upgrade CI workflows to use non-deprecated runtimes (#15) 2023-01-24 13:44:33 -08:00
semantic-release-bot
8670cc32f3 chore(release): version 2.1.2 [skip ci]
### [2.1.2](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v2.1.1...v2.1.2) (2022-10-27)

### Bug Fixes

* Update CI configuration files to use latest version ([#13](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/13)) ([2e11175](2e111751a3))
2022-10-27 19:09:02 +00:00
Bryant Biggs
2e111751a3
fix: Update CI configuration files to use latest version (#13) 2022-10-27 21:08:36 +02:00
semantic-release-bot
8d5c48782d chore(release): version 2.1.1 [skip ci]
### [2.1.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v2.1.0...v2.1.1) (2022-08-10)

### Bug Fixes

* Disable endpoint creation when setting `create_proxy = false` ([#12](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/12)) ([26724ab](26724abef9))
* Update documentation to remove prior notice and deprecated workflow ([#9](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/9)) ([8c1720c](8c1720cee3))
2022-08-10 18:35:22 +00:00
Gavin Williams
26724abef9
fix: Disable endpoint creation when setting create_proxy = false (#12)
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
2022-08-10 14:34:48 -04:00
Bryant Biggs
8c1720cee3
fix: Update documentation to remove prior notice and deprecated workflow (#9) 2022-04-21 09:56:38 +02:00
semantic-release-bot
6506401d6f chore(release): version 2.1.0 [skip ci]
## [2.1.0](https://github.com/clowdhaus/terraform-aws-rds-proxy/compare/v2.0.1...v2.1.0) (2022-04-20)

### Features

* Repo has moved to [terraform-aws-modules](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy) organization ([ec9c760](ec9c76000e))
2022-04-20 22:50:21 +00:00
Bryant Biggs
ec9c76000e feat: Repo has moved to [terraform-aws-modules](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy) organization 2022-04-20 18:48:34 -04:00
Bryant Biggs
2f5444105f chore: update reference in README documentation 2021-11-17 08:08:07 -05:00
Bryant Biggs
affe754727 fix: remove un-used variables and update linting checks to ensure this is catched in the future 2021-11-17 08:04:41 -05:00
Bryant Biggs
9c80ff9ac5
chore: update examples and CI workflows (#7) 2021-11-03 13:58:02 -04:00
Bryant Biggs
9af356bced chore: update README link to svg 2021-09-19 13:17:39 -04:00
Bryant Biggs
4bbca899ca
chore: update examples for security best practices and Bridgecrew monitoring (#6) 2021-09-19 12:41:40 -04:00
Bryant Biggs
3550f1bd9c BREAKING CHANGE: add new resource aws_db_proxy_endpoint for generating proxy endpoints from a dynamic map of inputs (#5) 2021-05-08 17:41:06 -04:00
Bryant Biggs
2ff25454fe chore: update documentation using latest version of terraform_docs 2021-03-27 18:35:03 -04:00
Bryant Biggs
9bd94bdf43 chore: update pre-commit hook version and update docs via terraform_docs 2021-03-02 18:01:44 -05:00
Bryant Biggs
947bc1f6c5 chore: add CODEOWNERS file 2021-03-02 18:00:25 -05:00
57 changed files with 2265 additions and 1941 deletions

View file

@ -1,76 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at contact@clowd.haus. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

21
.github/workflows/lock.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: 'Lock Threads'
on:
schedule:
- cron: '50 1 * * *'
jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-comment: >
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
issue-inactive-days: '30'
pr-comment: >
I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
pr-inactive-days: '30'

52
.github/workflows/pr-title.yml vendored Normal file
View file

@ -0,0 +1,52 @@
name: 'Validate PR title'
on:
pull_request_target:
types:
- opened
- edited
- synchronize
jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
steps:
# Please look up the latest version from
# https://github.com/amannn/action-semantic-pull-request/releases
- uses: amannn/action-semantic-pull-request@v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# Configure which types are allowed.
# Default: https://github.com/commitizen/conventional-commit-types
types: |
fix
feat
docs
ci
chore
# Configure that a scope must always be provided.
requireScope: false
# Configure additional validation for the subject based on a regex.
# This example ensures the subject starts with an uppercase character.
subjectPattern: ^[A-Z].+$
# If `subjectPattern` is configured, you can use this property to override
# the default error message that is shown when the pattern doesn't match.
# The variables `subject` and `title` can be used within the message.
subjectPatternError: |
The subject "{subject}" found in the pull request title "{title}"
didn't match the configured pattern. Please ensure that the subject
starts with an uppercase character.
# For work-in-progress PRs you can typically use draft pull requests
# from Github. However, private repositories on the free plan don't have
# this option and therefore this action allows you to opt-in to using the
# special "[WIP]" prefix to indicate this state. This will avoid the
# validation of the PR title and the pull request checks remain pending.
# Note that a second check will be reported if this is enabled.
wip: true
# When using "Squash and merge" on a PR with only one commit, GitHub
# will suggest using that commit message instead of the PR title for the
# merge commit, and it's easy to commit this by mistake. Enable this option
# to also validate the commit message for one commit PRs.
validateSingleCommit: false

168
.github/workflows/pre-commit.yml vendored Normal file
View file

@ -0,0 +1,168 @@
name: Pre-Commit
on:
pull_request:
branches:
- main
- master
env:
TERRAFORM_DOCS_VERSION: v0.20.0
TFLINT_VERSION: v0.59.1
jobs:
collectInputs:
name: Collect workflow inputs
runs-on: ubuntu-latest
outputs:
directories: ${{ steps.dirs.outputs.directories }}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Get root directories
id: dirs
uses: clowdhaus/terraform-composite-actions/directories@v1.14.0
preCommitMinVersions:
name: Min TF pre-commit
needs: collectInputs
runs-on: ubuntu-latest
strategy:
matrix:
directory: ${{ fromJson(needs.collectInputs.outputs.directories) }}
steps:
- name: Install rmz
uses: jaxxstorm/action-install-gh-release@v2.1.0
with:
repo: SUPERCILEX/fuc
asset-name: x86_64-unknown-linux-gnu-rmz
rename-to: rmz
chmod: 0755
extension-matching: disable
# https://github.com/orgs/community/discussions/25678#discussioncomment-5242449
- name: Delete unnecessary files
run: |
formatByteCount() { echo $(numfmt --to=iec-i --suffix=B --padding=7 $1'000'); }
getAvailableSpace() { echo $(df -a $1 | awk 'NR > 1 {avail+=$4} END {print avail}'); }
BEFORE=$(getAvailableSpace)
ln -s /opt/hostedtoolcache/SUPERCILEX/x86_64-unknown-linux-gnu-rmz/latest/linux-x64/rmz /usr/local/bin/rmz
rmz -f /opt/hostedtoolcache/CodeQL &
rmz -f /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk &
rmz -f /opt/hostedtoolcache/PyPy &
rmz -f /opt/hostedtoolcache/Ruby &
rmz -f /opt/hostedtoolcache/go &
wait
AFTER=$(getAvailableSpace)
SAVED=$((AFTER-BEFORE))
echo "=> Saved $(formatByteCount $SAVED)"
- name: Checkout
uses: actions/checkout@v5
- name: Terraform min/max versions
id: minMax
uses: clowdhaus/terraform-min-max@v2.1.0
with:
directory: ${{ matrix.directory }}
- name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }}
# Run only validate pre-commit check on min version supported
if: ${{ matrix.directory != '.' }}
uses: clowdhaus/terraform-composite-actions/pre-commit@v1.14.0
with:
terraform-version: ${{ steps.minMax.outputs.minVersion }}
tflint-version: ${{ env.TFLINT_VERSION }}
args: 'terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*'
- name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }}
# Run only validate pre-commit check on min version supported
if: ${{ matrix.directory == '.' }}
uses: clowdhaus/terraform-composite-actions/pre-commit@v1.14.0
with:
terraform-version: ${{ steps.minMax.outputs.minVersion }}
tflint-version: ${{ env.TFLINT_VERSION }}
args: 'terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)'
preCommitMaxVersion:
name: Max TF pre-commit
runs-on: ubuntu-latest
needs: collectInputs
steps:
- name: Install rmz
uses: jaxxstorm/action-install-gh-release@v2.1.0
with:
repo: SUPERCILEX/fuc
asset-name: x86_64-unknown-linux-gnu-rmz
rename-to: rmz
chmod: 0755
extension-matching: disable
# https://github.com/orgs/community/discussions/25678#discussioncomment-5242449
- name: Delete unnecessary files
run: |
formatByteCount() { echo $(numfmt --to=iec-i --suffix=B --padding=7 $1'000'); }
getAvailableSpace() { echo $(df -a $1 | awk 'NR > 1 {avail+=$4} END {print avail}'); }
BEFORE=$(getAvailableSpace)
ln -s /opt/hostedtoolcache/SUPERCILEX/x86_64-unknown-linux-gnu-rmz/latest/linux-x64/rmz /usr/local/bin/rmz
rmz -f /opt/hostedtoolcache/CodeQL &
rmz -f /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk &
rmz -f /opt/hostedtoolcache/PyPy &
rmz -f /opt/hostedtoolcache/Ruby &
rmz -f /opt/hostedtoolcache/go &
sudo rmz -f /usr/local/lib/android &
if [[ ${{ github.repository }} == terraform-aws-modules/terraform-aws-security-group ]]; then
sudo rmz -f /usr/share/dotnet &
sudo rmz -f /usr/local/.ghcup &
sudo apt-get -qq remove -y 'azure-.*'
sudo apt-get -qq remove -y 'cpp-.*'
sudo apt-get -qq remove -y 'dotnet-runtime-.*'
sudo apt-get -qq remove -y 'google-.*'
sudo apt-get -qq remove -y 'libclang-.*'
sudo apt-get -qq remove -y 'libllvm.*'
sudo apt-get -qq remove -y 'llvm-.*'
sudo apt-get -qq remove -y 'mysql-.*'
sudo apt-get -qq remove -y 'postgresql-.*'
sudo apt-get -qq remove -y 'php.*'
sudo apt-get -qq remove -y 'temurin-.*'
sudo apt-get -qq remove -y kubectl firefox mono-devel
sudo apt-get -qq autoremove -y
sudo apt-get -qq clean
fi
wait
AFTER=$(getAvailableSpace)
SAVED=$((AFTER-BEFORE))
echo "=> Saved $(formatByteCount $SAVED)"
- name: Checkout
uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Terraform min/max versions
id: minMax
uses: clowdhaus/terraform-min-max@v2.1.0
- name: Hide template dir
# Special to this repo, we don't want to check this dir
if: ${{ github.repository == 'terraform-aws-modules/terraform-aws-security-group' }}
run: rm -rf modules/_templates
- name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }}
uses: clowdhaus/terraform-composite-actions/pre-commit@v1.14.0
with:
terraform-version: ${{ steps.minMax.outputs.maxVersion }}
tflint-version: ${{ env.TFLINT_VERSION }}
terraform-docs-version: ${{ env.TERRAFORM_DOCS_VERSION }}
install-hcledit: true

45
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,45 @@
name: Release
on:
workflow_dispatch:
push:
branches:
- main
- master
paths:
- '**/*.tpl'
- '**/*.py'
- '**/*.tf'
- '.github/workflows/release.yml'
jobs:
release:
name: Release
runs-on: ubuntu-latest
# Skip running release workflow on forks
if: github.repository_owner == 'terraform-aws-modules'
steps:
- name: Checkout
uses: actions/checkout@v5
with:
persist-credentials: false
fetch-depth: 0
- name: Set correct Node.js version
uses: actions/setup-node@v6
with:
node-version: 24
- name: Install dependencies
run: |
npm install \
@semantic-release/changelog@6.0.3 \
@semantic-release/git@10.0.1 \
conventional-changelog-conventionalcommits@9.1.0
- name: Release
uses: cycjimmy/semantic-release-action@v5
with:
semantic_version: 25.0.0
env:
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}

View file

@ -1,30 +0,0 @@
name: Release
on:
push:
branches:
- main
paths:
- '**.tf'
- '!examples/**.tf'
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 14
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
run: npx semantic-release

32
.github/workflows/stale-actions.yaml vendored Normal file
View file

@ -0,0 +1,32 @@
name: 'Mark or close stale issues and PRs'
on:
schedule:
- cron: '0 0 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# Staling issues and PR's
days-before-stale: 30
stale-issue-label: stale
stale-pr-label: stale
stale-issue-message: |
This issue has been automatically marked as stale because it has been open 30 days
with no activity. Remove stale label or comment or this issue will be closed in 10 days
stale-pr-message: |
This PR has been automatically marked as stale because it has been open 30 days
with no activity. Remove stale label or comment or this PR will be closed in 10 days
# Not stale if have this labels or part of milestone
exempt-issue-labels: bug,wip,on-hold
exempt-pr-labels: bug,wip,on-hold
exempt-all-milestones: true
# Close issue operations
# Label will be automatically removed if the issues are no longer closed nor locked.
days-before-close: 10
delete-branch: true
close-issue-message: This issue was automatically closed because of stale in 10 days
close-pr-message: This PR was automatically closed because of stale in 10 days

View file

@ -1,77 +0,0 @@
name: static-checks
on:
pull_request:
jobs:
versionExtract:
name: Get min/max versions
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Terraform min/max versions
id: minMax
uses: clowdhaus/terraform-min-max@main
outputs:
minVersion: ${{ steps.minMax.outputs.minVersion }}
maxVersion: ${{ steps.minMax.outputs.maxVersion }}
versionEvaluate:
name: Evaluate Terraform versions
runs-on: ubuntu-latest
needs: versionExtract
strategy:
fail-fast: false
matrix:
version:
- ${{ needs.versionExtract.outputs.minVersion }}
- ${{ needs.versionExtract.outputs.maxVersion }}
directory:
- examples/mysql_iam_cluster
- examples/mysql_iam_instance
- examples/postgresql_iam_cluster
- examples/postgresql_iam_instance
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Terraform v${{ matrix.version }}
uses: hashicorp/setup-terraform@v1
with:
terraform_version: ${{ matrix.version }}
- name: Init & validate v${{ matrix.version }}
run: |
cd ${{ matrix.directory }}
terraform init
terraform validate
- name: tflint
uses: reviewdog/action-tflint@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
working_directory: ${{ matrix.directory }}
fail_on_error: 'true'
filter_mode: 'nofilter'
flags: '--module'
format:
name: Check code format
runs-on: ubuntu-latest
needs: versionExtract
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Terraform v${{ needs.versionExtract.outputs.maxVersion }}
uses: hashicorp/setup-terraform@v1
with:
terraform_version: ${{ needs.versionExtract.outputs.maxVersion }}
- name: Check Terraform format changes
run: terraform fmt --recursive -check=true

24
.gitignore vendored
View file

@ -1,13 +1,13 @@
# Local .terraform directories # Local .terraform directories
**/.terraform/* **/.terraform/*
# Terraform lockfile
.terraform.lock.hcl
# .tfstate files # .tfstate files
*.tfstate *.tfstate
*.tfstate.* *.tfstate.*
# terraform lockfile
.terraform.lock.hcl
# Crash log files # Crash log files
crash.log crash.log
@ -15,7 +15,6 @@ crash.log
# password, private keys, and other secrets. These should not be part of version # password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject # control as they are data points which are potentially sensitive and subject
# to change depending on the environment. # to change depending on the environment.
#
*.tfvars *.tfvars
# Ignore override files as they are usually used to override resources locally and so # Ignore override files as they are usually used to override resources locally and so
@ -25,13 +24,16 @@ override.tf.json
*_override.tf *_override.tf
*_override.tf.json *_override.tf.json
# Include override files you do wish to add to version control using negated pattern
#
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*
# Ignore CLI configuration files # Ignore CLI configuration files
.terraformrc .terraformrc
terraform.rc terraform.rc
# Lambda build artifacts
builds/
__pycache__/
*.zip
.tox
# Local editors/macos files
.DS_Store
.idea

View file

@ -1,10 +1,31 @@
repos: repos:
- repo: git://github.com/antonbabenko/pre-commit-terraform - repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.45.0 rev: v1.103.0
hooks: hooks:
- id: terraform_fmt - id: terraform_fmt
- id: terraform_wrapper_module_for_each
- id: terraform_docs - id: terraform_docs
- repo: git://github.com/pre-commit/pre-commit-hooks args:
rev: v3.4.0 - '--args=--lockfile=false'
- id: terraform_tflint
args:
- '--args=--only=terraform_deprecated_interpolation'
- '--args=--only=terraform_deprecated_index'
- '--args=--only=terraform_unused_declarations'
- '--args=--only=terraform_comment_syntax'
- '--args=--only=terraform_documented_outputs'
- '--args=--only=terraform_documented_variables'
- '--args=--only=terraform_typed_variables'
- '--args=--only=terraform_module_pinned_source'
- '--args=--only=terraform_naming_convention'
- '--args=--only=terraform_required_version'
- '--args=--only=terraform_required_providers'
- '--args=--only=terraform_standard_module_structure'
- '--args=--only=terraform_workspace_remote'
- id: terraform_validate
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks: hooks:
- id: check-merge-conflict - id: check-merge-conflict
- id: end-of-file-fixer
- id: trailing-whitespace

View file

@ -1,10 +1,45 @@
{ {
"branches": [ "branches": [
"main" "main",
"master"
], ],
"ci": false,
"plugins": [ "plugins": [
[
"@semantic-release/commit-analyzer", "@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits"
}
],
[
"@semantic-release/release-notes-generator", "@semantic-release/release-notes-generator",
"@semantic-release/github" {
"preset": "conventionalcommits"
}
],
[
"@semantic-release/github",
{
"successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:",
"labels": false,
"releasedLabels": false
}
],
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md",
"changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file."
}
],
[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md"
],
"message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
]
] ]
} }

100
CHANGELOG.md Normal file
View file

@ -0,0 +1,100 @@
# Changelog
All notable changes to this project will be documented in this file.
## [4.2.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v4.2.0...v4.2.1) (2025-10-21)
### Bug Fixes
* Update CI workflow versions to latest ([#40](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/40)) ([5deff22](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/5deff22cf4c471ce824c016687c3b933cd8b783c))
## [4.2.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v4.1.0...v4.2.0) (2025-10-14)
### Features
* Support `default_auth_scheme` ([#39](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/39)) ([c2073a0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/c2073a031c947270dac3f17c7f76e2996cd1b5b1))
## [4.1.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v4.0.0...v4.1.0) (2025-10-01)
### Features
* Add Terragrunt wrappers ([#38](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/38)) ([33b43c7](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/33b43c72abdad0b01655238d844e56dabca5e6d4))
## [4.0.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.2.1...v4.0.0) (2025-09-16)
### ⚠ BREAKING CHANGES
* Upgrade AWS provider and min required Terraform version to `6.0` and `1.5.7` respectively (#34)
### Features
* Upgrade AWS provider and min required Terraform version to `6.0` and `1.5.7` respectively ([#34](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/34)) ([47c0fca](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/47c0fcad4b3e40ef112544028dba1a4c10ee50dc))
## [3.2.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.2.0...v3.2.1) (2025-05-22)
### Bug Fixes
* Correct service principal to rds.amazonaws.com (incl China) ([#32](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/32)) ([bbbf50c](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/bbbf50ce8734f05d4ac69fa41c23c88094b82356))
## [3.2.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.1.1...v3.2.0) (2024-11-19)
### Features
* Add CloudWatch log group name to outputs ([#28](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/28)) ([0fc0e19](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/0fc0e19e642a2fdcd8f546bf219f78b5db252c65))
### Bug Fixes
* Update CI workflow versions to latest ([#27](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/27)) ([b6f22be](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/b6f22becf63614f365e72a81151c1955ab0d4df3))
## [3.1.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.1.0...v3.1.1) (2024-03-06)
### Bug Fixes
* Update CI workflow versions to remove deprecated runtime warnings ([#26](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/26)) ([a31a810](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/a31a81097b9828776e91864973783d0e9530e12d))
## [3.1.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v3.0.0...v3.1.0) (2023-08-30)
### Features
* Add IAM role output ([#22](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/22)) ([d18ae45](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/d18ae45d9ebf8253f7144e6bdc6ef39af9a4863f))
## [3.0.0](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v2.1.2...v3.0.0) (2023-06-09)
### ⚠ BREAKING CHANGES
* Increase Terraform and AWS provider minimum supported versions; update `auth` configuration schema (#17)
### Features
* Increase Terraform and AWS provider minimum supported versions; update `auth` configuration schema ([#17](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/17)) ([cc39e9d](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/cc39e9d0295495574c406acfed9e288fb6d5df3c))
### [2.1.2](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v2.1.1...v2.1.2) (2022-10-27)
### Bug Fixes
* Update CI configuration files to use latest version ([#13](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/13)) ([2e11175](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/2e111751a3b6d6a28ac3c7bf8924ac5dcf07e10e))
### [2.1.1](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/compare/v2.1.0...v2.1.1) (2022-08-10)
### Bug Fixes
* Disable endpoint creation when setting `create_proxy = false` ([#12](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/12)) ([26724ab](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/26724abef985c1669d223ff4e12e43cfd35c529a))
* Update documentation to remove prior notice and deprecated workflow ([#9](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/issues/9)) ([8c1720c](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/commit/8c1720cee3a1402a2114c46990061672befcd6b9))
## [2.1.0](https://github.com/clowdhaus/terraform-aws-rds-proxy/compare/v2.0.1...v2.1.0) (2022-04-20)
### Features
* Repo has moved to [terraform-aws-modules](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy) organization ([ec9c760](https://github.com/clowdhaus/terraform-aws-rds-proxy/commit/ec9c76000eb6a2df12759fbfdd1a44c0207cd6b4))

25
LICENSE
View file

@ -174,28 +174,3 @@
of your accepting any such warranty or additional liability. of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2021 Clowd Haus, LLC.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

199
README.md
View file

@ -2,40 +2,44 @@
Terraform module which creates an AWS RDS Proxy and its supporting resources. Terraform module which creates an AWS RDS Proxy and its supporting resources.
The following resources are supported:
- [AWS RDS Proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy)
- [AWS RDS Proxy Default Target Group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_default_target_group)
- [AWS RDS Proxy Target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target)
## Usage ## Usage
See [`examples`](./examples) directory for working examples to reference: See [`examples`](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/tree/master/examples) directory for working examples to reference:
```hcl ```hcl
module "rds_proxy" { module "rds_proxy" {
source = "clowdhaus/rds-proxy/aws" source = "terraform-aws-modules/rds-proxy/aws"
name = "rds-proxy" name = "rds-proxy"
iam_role_name = "rds-proxy-role" iam_role_name = "rds-proxy-role"
vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"] vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"]
vpc_security_group_ids = ["sg-f1d03a88"] vpc_security_group_ids = ["sg-f1d03a88"]
secrets = { endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"]
vpc_security_group_ids = ["sg-f1d03a88"]
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"]
vpc_security_group_ids = ["sg-f1d03a88"]
target_role = "READ_ONLY"
}
}
auth = {
"superuser" = { "superuser" = {
description = "Aurora PostgreSQL superuser password" description = "Aurora PostgreSQL superuser password"
arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:superuser-6gsjLD" secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:superuser-6gsjLD"
kms_key_id = "6ca29066-552a-46c5-a7d7-7bf9a15fc255"
} }
} }
engine_family = "POSTGRESQL"
db_host = "myendpoint.cluster-custom-123456789012.us-east-1.rds.amazonaws.com"
db_name = "example"
# Target Aurora cluster # Target Aurora cluster
engine_family = "POSTGRESQL"
target_db_cluster = true target_db_cluster = true
db_cluster_identifier = "myendpoint" db_cluster_identifier = "my-endpoint"
tags = { tags = {
Terraform = "true" Terraform = "true"
@ -46,96 +50,121 @@ module "rds_proxy" {
## Examples ## Examples
Examples codified under the [`examples`](./examples) are intended to give users references for how to use the module(s) as well as testing/validating changes to the source code of the module(s). If contributing to the project, please be sure to make any appropriate updates to the relevant examples to allow maintainers to test your changes and to keep the examples up to date for users. Thank you! Examples codified under the [`examples`](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/tree/master/examples) are intended to give users references for how to use the module(s) as well as testing/validating changes to the source code of the module(s). If contributing to the project, please be sure to make any appropriate updates to the relevant examples to allow maintainers to test your changes and to keep the examples up to date for users. Thank you!
- [IAM auth. w/ MySQL Aurora cluster](./examples/mysql_iam_cluster) - [IAM auth. w/ MySQL Aurora cluster](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/tree/master/examples/mysql-iam-cluster)
- [IAM auth. w/ MySQL RDS instance](./examples/mysql_iam_instance) - [IAM auth. w/ MySQL RDS instance](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/tree/master/examples/mysql-iam-instance)
- [IAM auth. w/ PostgreSQL Aurora cluster](./examples/postgresql_iam_cluster) - [IAM auth. w/ PostgreSQL Aurora cluster](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/tree/master/examples/postgresql-iam-cluster)
- [IAM auth. w/ PostgreSQL RDS instance](./examples/postgresql_iam_instance) - [IAM auth. w/ PostgreSQL RDS instance](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/tree/master/examples/postgresql-iam-instance)
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> <!-- BEGIN_TF_DOCS -->
## Requirements ## Requirements
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| terraform | >= 0.12.26 | | <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| aws | >= 3.9 | | <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.15 |
## Providers ## Providers
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| aws | >= 3.9 | | <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.15 |
## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
| [aws_db_proxy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy) | resource |
| [aws_db_proxy_default_target_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_default_target_group) | resource |
| [aws_db_proxy_endpoint.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_endpoint) | resource |
| [aws_db_proxy_target.db_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target) | resource |
| [aws_db_proxy_target.db_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target) | resource |
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
| [aws_service_principal.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/service_principal) | data source |
## Inputs ## Inputs
| Name | Description | Type | Default | Required | | Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:| |------|-------------|------|---------|:--------:|
| auth | Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters | `map(string)` | `{}` | no | | <a name="input_auth"></a> [auth](#input\_auth) | Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters | <pre>map(object({<br/> auth_scheme = optional(string)<br/> client_password_auth_type = optional(string)<br/> description = optional(string)<br/> iam_auth = optional(string)<br/> secret_arn = optional(string)<br/> username = optional(string)<br/> }))</pre> | <pre>{<br/> "default": {<br/> "auth_scheme": "SECRETS"<br/> }<br/>}</pre> | no |
| auth\_scheme | The type of authentication that the proxy uses for connections from the proxy to the underlying database. One of `SECRETS` | `string` | `"SECRETS"` | no | | <a name="input_connection_borrow_timeout"></a> [connection\_borrow\_timeout](#input\_connection\_borrow\_timeout) | The number of seconds for a proxy to wait for a connection to become available in the connection pool | `number` | `null` | no |
| connection\_borrow\_timeout | The number of seconds for a proxy to wait for a connection to become available in the connection pool | `number` | `null` | no | | <a name="input_create"></a> [create](#input\_create) | Whether cluster should be created (affects nearly all resources) | `bool` | `true` | no |
| create\_iam\_policy | Determines whether an IAM policy is created | `bool` | `true` | no | | <a name="input_create_iam_policy"></a> [create\_iam\_policy](#input\_create\_iam\_policy) | Determines whether an IAM policy is created | `bool` | `true` | no |
| create\_iam\_role | Determines whether an IAM role is created | `bool` | `true` | no | | <a name="input_create_iam_role"></a> [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created | `bool` | `true` | no |
| create\_proxy | Determines whether a proxy and its resources will be created | `bool` | `true` | no | | <a name="input_db_cluster_identifier"></a> [db\_cluster\_identifier](#input\_db\_cluster\_identifier) | DB cluster identifier | `string` | `""` | no |
| db\_cluster\_identifier | DB cluster identifier | `string` | `""` | no | | <a name="input_db_instance_identifier"></a> [db\_instance\_identifier](#input\_db\_instance\_identifier) | DB instance identifier | `string` | `""` | no |
| db\_host | The identifier to use for the database endpoint | `string` | `""` | no | | <a name="input_debug_logging"></a> [debug\_logging](#input\_debug\_logging) | Whether the proxy includes detailed information about SQL statements in its logs | `bool` | `false` | no |
| db\_instance\_identifier | DB instance identifier | `string` | `""` | no | | <a name="input_default_auth_scheme"></a> [default\_auth\_scheme](#input\_default\_auth\_scheme) | Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. Valid values are NONE and IAM\_AUTH. Defaults to NONE | `string` | `null` | no |
| db\_name | The name of the database | `string` | `""` | no | | <a name="input_endpoints"></a> [endpoints](#input\_endpoints) | Map of DB proxy endpoints to create and their attributes | <pre>map(object({<br/> name = optional(string)<br/> vpc_subnet_ids = list(string)<br/> vpc_security_group_ids = optional(list(string))<br/> target_role = optional(string)<br/> tags = optional(map(string), {})<br/> }))</pre> | `{}` | no |
| debug\_logging | Whether the proxy includes detailed information about SQL statements in its logs | `bool` | `false` | no | | <a name="input_engine_family"></a> [engine\_family](#input\_engine\_family) | The kind of database engine that the proxy will connect to. Valid values are `MYSQL` or `POSTGRESQL` | `string` | `""` | no |
| engine\_family | The kind of database engine that the proxy will connect to. Valid values are `MYSQL` or `POSTGRESQL` | `string` | `""` | no | | <a name="input_iam_policy_name"></a> [iam\_policy\_name](#input\_iam\_policy\_name) | The name of the role policy. If omitted, Terraform will assign a random, unique name | `string` | `""` | no |
| iam\_auth | Whether to require or disallow AWS Identity and Access Management (IAM) authentication for connections to the proxy. One of `DISABLED`, `REQUIRED` | `string` | `"REQUIRED"` | no | | <a name="input_iam_role_description"></a> [iam\_role\_description](#input\_iam\_role\_description) | The description of the role | `string` | `""` | no |
| iam\_creation\_wait\_duration | Time duration delay to wait for IAM resource creation/propagation. For example, 30s for 30 seconds or 5m for 5 minutes. Updating this value by itself will not trigger a delay. | `string` | `"30s"` | no | | <a name="input_iam_role_force_detach_policies"></a> [iam\_role\_force\_detach\_policies](#input\_iam\_role\_force\_detach\_policies) | Specifies to force detaching any policies the role has before destroying it | `bool` | `true` | no |
| iam\_policy\_name | The name of the role policy. If omitted, Terraform will assign a random, unique name | `string` | `""` | no | | <a name="input_iam_role_max_session_duration"></a> [iam\_role\_max\_session\_duration](#input\_iam\_role\_max\_session\_duration) | The maximum session duration (in seconds) that you want to set for the specified role | `number` | `43200` | no |
| iam\_role\_description | The description of the role | `string` | `""` | no | | <a name="input_iam_role_name"></a> [iam\_role\_name](#input\_iam\_role\_name) | The name of the role. If omitted, Terraform will assign a random, unique name | `string` | `""` | no |
| iam\_role\_force\_detach\_policies | Specifies to force detaching any policies the role has before destroying it | `bool` | `true` | no | | <a name="input_iam_role_path"></a> [iam\_role\_path](#input\_iam\_role\_path) | The path to the role | `string` | `null` | no |
| iam\_role\_max\_session\_duration | The maximum session duration (in seconds) that you want to set for the specified role | `number` | `43200` | no | | <a name="input_iam_role_permissions_boundary"></a> [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | The ARN of the policy that is used to set the permissions boundary for the role | `string` | `null` | no |
| iam\_role\_name | The name of the role. If omitted, Terraform will assign a random, unique name | `string` | `""` | no | | <a name="input_iam_role_tags"></a> [iam\_role\_tags](#input\_iam\_role\_tags) | A map of tags to apply to the IAM role | `map(string)` | `{}` | no |
| iam\_role\_path | The path to the role | `string` | `null` | no | | <a name="input_idle_client_timeout"></a> [idle\_client\_timeout](#input\_idle\_client\_timeout) | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no |
| iam\_role\_permissions\_boundary | The ARN of the policy that is used to set the permissions boundary for the role | `string` | `null` | no | | <a name="input_init_query"></a> [init\_query](#input\_init\_query) | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `""` | no |
| iam\_role\_tags | A map of tags to apply to the IAM role | `map(string)` | `{}` | no | | <a name="input_kms_key_arns"></a> [kms\_key\_arns](#input\_kms\_key\_arns) | List of KMS Key ARNs to allow access to decrypt SecretsManager secrets | `list(string)` | `[]` | no |
| idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | | <a name="input_log_group_class"></a> [log\_group\_class](#input\_log\_group\_class) | Specified the log class of the log group. Possible values are: `STANDARD` or `INFREQUENT_ACCESS` | `string` | `null` | no |
| init\_query | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `""` | no | | <a name="input_log_group_kms_key_id"></a> [log\_group\_kms\_key\_id](#input\_log\_group\_kms\_key\_id) | The ARN of the KMS Key to use when encrypting log data | `string` | `null` | no |
| log\_group\_kms\_key\_id | The ARN of the KMS Key to use when encrypting log data | `string` | `null` | no | | <a name="input_log_group_retention_in_days"></a> [log\_group\_retention\_in\_days](#input\_log\_group\_retention\_in\_days) | Specifies the number of days you want to retain log events in the log group | `number` | `30` | no |
| log\_group\_retention\_in\_days | Specifies the number of days you want to retain log events in the log group | `number` | `30` | no | | <a name="input_log_group_tags"></a> [log\_group\_tags](#input\_log\_group\_tags) | A map of tags to apply to the CloudWatch log group | `map(string)` | `{}` | no |
| log\_group\_tags | A map of tags to apply to the CloudWatch log group | `map(string)` | `{}` | no | | <a name="input_manage_log_group"></a> [manage\_log\_group](#input\_manage\_log\_group) | Determines whether Terraform will create/manage the CloudWatch log group or not. Note - this will fail if set to true after the log group has been created as the resource will already exist | `bool` | `true` | no |
| manage\_log\_group | Determines whether Terraform will create/manage the CloudWatch log group or not. Note - this will fail if set to true after the log group has been created as the resource will already exist | `bool` | `true` | no | | <a name="input_max_connections_percent"></a> [max\_connections\_percent](#input\_max\_connections\_percent) | The maximum size of the connection pool for each target in a target group | `number` | `90` | no |
| max\_connections\_percent | The maximum size of the connection pool for each target in a target group | `number` | `90` | no | | <a name="input_max_idle_connections_percent"></a> [max\_idle\_connections\_percent](#input\_max\_idle\_connections\_percent) | Controls how actively the proxy closes idle database connections in the connection pool | `number` | `50` | no |
| max\_idle\_connections\_percent | Controls how actively the proxy closes idle database connections in the connection pool | `number` | `50` | no | | <a name="input_name"></a> [name](#input\_name) | The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens | `string` | `""` | no |
| name | The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens | `string` | `""` | no | | <a name="input_proxy_tags"></a> [proxy\_tags](#input\_proxy\_tags) | A map of tags to apply to the RDS Proxy | `map(string)` | `{}` | no |
| proxy\_tags | A map of tags to apply to the RDS Proxy | `map(string)` | `{}` | no | | <a name="input_region"></a> [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no |
| require\_tls | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy | `bool` | `true` | no | | <a name="input_require_tls"></a> [require\_tls](#input\_require\_tls) | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy | `bool` | `true` | no |
| role\_arn | The Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | `""` | no | | <a name="input_role_arn"></a> [role\_arn](#input\_role\_arn) | The Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | `""` | no |
| secrets | Map of secerets to be used by RDS Proxy for authentication to the database | `map(object({ arn = string, description = string, kms_key_id = string }))` | `{}` | no | | <a name="input_session_pinning_filters"></a> [session\_pinning\_filters](#input\_session\_pinning\_filters) | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `[]` | no |
| session\_pinning\_filters | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `[]` | no | | <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
| tags | A map of tags to use on all resources | `map(string)` | `{}` | no | | <a name="input_target_db_cluster"></a> [target\_db\_cluster](#input\_target\_db\_cluster) | Determines whether DB cluster is targeted by proxy | `bool` | `false` | no |
| target\_db\_cluster | Determines whether DB cluster is targetted by proxy | `bool` | `false` | no | | <a name="input_target_db_instance"></a> [target\_db\_instance](#input\_target\_db\_instance) | Determines whether DB instance is targeted by proxy | `bool` | `false` | no |
| target\_db\_instance | Determines whether DB instance is targetted by proxy | `bool` | `false` | no | | <a name="input_use_policy_name_prefix"></a> [use\_policy\_name\_prefix](#input\_use\_policy\_name\_prefix) | Whether to use unique name beginning with the specified `iam_policy_name` | `bool` | `false` | no |
| use\_policy\_name\_prefix | Whether to use unique name beginning with the specified `iam_policy_name` | `bool` | `false` | no | | <a name="input_use_role_name_prefix"></a> [use\_role\_name\_prefix](#input\_use\_role\_name\_prefix) | Whether to use unique name beginning with the specified `iam_role_name` | `bool` | `false` | no |
| use\_role\_name\_prefix | Whether to use unique name beginning with the specified `iam_role_name` | `bool` | `false` | no | | <a name="input_vpc_security_group_ids"></a> [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | One or more VPC security group IDs to associate with the new proxy | `list(string)` | `[]` | no |
| vpc\_security\_group\_ids | One or more VPC security group IDs to associate with the new proxy | `list(string)` | `[]` | no | | <a name="input_vpc_subnet_ids"></a> [vpc\_subnet\_ids](#input\_vpc\_subnet\_ids) | One or more VPC subnet IDs to associate with the new proxy | `list(string)` | `[]` | no |
| vpc\_subnet\_ids | One or more VPC subnet IDs to associate with the new proxy | `list(string)` | `[]` | no |
## Outputs ## Outputs
| Name | Description | | Name | Description |
|------|-------------| |------|-------------|
| log\_group\_arn | The Amazon Resource Name (ARN) of the CloudWatch log group | | <a name="output_db_proxy_endpoints"></a> [db\_proxy\_endpoints](#output\_db\_proxy\_endpoints) | Array containing the full resource object and attributes for all DB proxy endpoints created |
| proxy\_arn | The Amazon Resource Name (ARN) for the proxy | | <a name="output_iam_role_arn"></a> [iam\_role\_arn](#output\_iam\_role\_arn) | The Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager. |
| proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) for the default target group | | <a name="output_iam_role_name"></a> [iam\_role\_name](#output\_iam\_role\_name) | IAM role name |
| proxy\_default\_target\_group\_id | The ID for the default target group | | <a name="output_iam_role_unique_id"></a> [iam\_role\_unique\_id](#output\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| proxy\_default\_target\_group\_name | The name of the default target group | | <a name="output_log_group_arn"></a> [log\_group\_arn](#output\_log\_group\_arn) | The Amazon Resource Name (ARN) of the CloudWatch log group |
| proxy\_endpoint | The endpoint that you can use to connect to the proxy | | <a name="output_log_group_name"></a> [log\_group\_name](#output\_log\_group\_name) | The name of the CloudWatch log group |
| proxy\_id | The ID for the proxy | | <a name="output_proxy_arn"></a> [proxy\_arn](#output\_proxy\_arn) | The Amazon Resource Name (ARN) for the proxy |
| proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type | | <a name="output_proxy_default_target_group_arn"></a> [proxy\_default\_target\_group\_arn](#output\_proxy\_default\_target\_group\_arn) | The Amazon Resource Name (ARN) for the default target group |
| proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) | | <a name="output_proxy_default_target_group_id"></a> [proxy\_default\_target\_group\_id](#output\_proxy\_default\_target\_group\_id) | The ID for the default target group |
| proxy\_target\_port | Port for the target RDS DB Instance or Aurora DB Cluster | | <a name="output_proxy_default_target_group_name"></a> [proxy\_default\_target\_group\_name](#output\_proxy\_default\_target\_group\_name) | The name of the default target group |
| proxy\_target\_rds\_resource\_id | Identifier representing the DB Instance or DB Cluster target | | <a name="output_proxy_endpoint"></a> [proxy\_endpoint](#output\_proxy\_endpoint) | The endpoint that you can use to connect to the proxy |
| proxy\_target\_target\_arn | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API | | <a name="output_proxy_id"></a> [proxy\_id](#output\_proxy\_id) | The ID for the proxy |
| proxy\_target\_tracked\_cluster\_id | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster | | <a name="output_proxy_target_endpoint"></a> [proxy\_target\_endpoint](#output\_proxy\_target\_endpoint) | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| proxy\_target\_type | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` | | <a name="output_proxy_target_id"></a> [proxy\_target\_id](#output\_proxy\_target\_id) | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| <a name="output_proxy_target_port"></a> [proxy\_target\_port](#output\_proxy\_target\_port) | Port for the target RDS DB Instance or Aurora DB Cluster |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> | <a name="output_proxy_target_rds_resource_id"></a> [proxy\_target\_rds\_resource\_id](#output\_proxy\_target\_rds\_resource\_id) | Identifier representing the DB Instance or DB Cluster target |
| <a name="output_proxy_target_target_arn"></a> [proxy\_target\_target\_arn](#output\_proxy\_target\_target\_arn) | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| <a name="output_proxy_target_tracked_cluster_id"></a> [proxy\_target\_tracked\_cluster\_id](#output\_proxy\_target\_tracked\_cluster\_id) | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| <a name="output_proxy_target_type"></a> [proxy\_target\_type](#output\_proxy\_target\_type) | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
<!-- END_TF_DOCS -->
## License ## License
Apache-2.0 Licensed. See [LICENSE](LICENSE). Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/blob/master/LICENSE).

79
docs/UPGRADE-3.0.md Normal file
View file

@ -0,0 +1,79 @@
# Upgrade from v2.x to v3.x
If you have any questions regarding this upgrade process, please consult the `examples` directory.
If you find a bug, please open an issue with supporting configuration to reproduce.
## List of backwards incompatible changes
- Minimum supported Terraform version is now 1.0
- Minimum supported AWS provider version is now 5.0
- The manner in which authentication is configured has changed - previously auth settings were provided under `secrets` in conjunction with `auth_scheme` and `iam_auth` variables. Now, auth settings are provided under the `auth` variable for multiple auth entries.
### Variable and output changes
1. Removed variables:
- `auth_scheme` is now set under the `auth` variable for a given auth entry
- `iam_auth` is now set under the `auth` variable for a given auth entry
2. Renamed variables:
- `create_proxy` -> `create`
- `secrets` -> `auth`
- `db_proxy_endpoints` -> `endpoints`
3. Added variables:
- `kms_key_arns` - list of KMS key ARNs to use allowing permission to decrypt SecretsManager secrets
4. Removed outputs:
- None
5. Renamed outputs:
- None
6. Added outputs:
- None
## Diff of Before (v2.x) vs After (v3.x)
```diff
module "rds_proxy" {
source = "terraform-aws-modules/rds-proxy/aws"
- version = "~> 2.0"
+ version = "~> 3.0"
# Only the affected attributes are shown
- create_proxy = true
+ create = true
- db_proxy_endpoints = {
- ...
- }
+ endpoints = {
+ ...
+ }
- secrets = {
- "superuser" = {
- description = "Aurora PostgreSQL superuser password"
- arn = "arn:aws:secretsmanager:eu-west-1:123456789012:secret:superuser-6gsjLD"
- kms_key_id = "6ca29066-552a-46c5-a7d7-7bf9a15fc255"
- }
- }
+ auth = {
+ "superuser" = {
+ description = "Aurora PostgreSQL superuser password"
+ secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:superuser-6gsjLD"
+ }
+ }
+ kms_key_arns = ["arn:aws:kms:eu-west-1:123456789012:key/6ca29066-552a-46c5-a7d7-7bf9a15fc255"]
}
```
### State Changes
- None

8
examples/README.md Normal file
View file

@ -0,0 +1,8 @@
# Examples
Please note - the examples provided serve two primary means:
1. Show users working examples of the various ways in which the module can be configured and features supported
2. A means of testing/validating module changes
Please do not mistake the examples provided as "best practices". It is up to users to consult the AWS service documentation for best practices, usage recommendations, etc.

View file

@ -0,0 +1,83 @@
# RDS Proxy - IAM Authentication & MySQL Cluster
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS Aurora MySQL cluster
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window
4. You should now be connected to the `example` database in the RDS instance via the AWS Proxy using IAM authentication
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.15 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.15 |
## Modules
| Name | Source | Version |
|------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds-aurora/aws | ~> 9.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 |
## Resources
| Name | Type |
|------|------|
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
## Inputs
No inputs.
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_db_proxy_endpoints"></a> [db\_proxy\_endpoints](#output\_db\_proxy\_endpoints) | Array containing the full resource object and attributes for all DB proxy endpoints created |
| <a name="output_log_group_arn"></a> [log\_group\_arn](#output\_log\_group\_arn) | The Amazon Resource Name (ARN) of the CloudWatch log group |
| <a name="output_log_group_name"></a> [log\_group\_name](#output\_log\_group\_name) | The name of the CloudWatch log group |
| <a name="output_proxy_arn"></a> [proxy\_arn](#output\_proxy\_arn) | The Amazon Resource Name (ARN) for the proxy |
| <a name="output_proxy_default_target_group_arn"></a> [proxy\_default\_target\_group\_arn](#output\_proxy\_default\_target\_group\_arn) | The Amazon Resource Name (ARN) for the default target group |
| <a name="output_proxy_default_target_group_id"></a> [proxy\_default\_target\_group\_id](#output\_proxy\_default\_target\_group\_id) | The ID for the default target group |
| <a name="output_proxy_default_target_group_name"></a> [proxy\_default\_target\_group\_name](#output\_proxy\_default\_target\_group\_name) | The name of the default target group |
| <a name="output_proxy_endpoint"></a> [proxy\_endpoint](#output\_proxy\_endpoint) | The endpoint that you can use to connect to the proxy |
| <a name="output_proxy_id"></a> [proxy\_id](#output\_proxy\_id) | The ID for the proxy |
| <a name="output_proxy_target_endpoint"></a> [proxy\_target\_endpoint](#output\_proxy\_target\_endpoint) | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| <a name="output_proxy_target_id"></a> [proxy\_target\_id](#output\_proxy\_target\_id) | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| <a name="output_proxy_target_port"></a> [proxy\_target\_port](#output\_proxy\_target\_port) | Port for the target RDS DB Instance or Aurora DB Cluster |
| <a name="output_proxy_target_rds_resource_id"></a> [proxy\_target\_rds\_resource\_id](#output\_proxy\_target\_rds\_resource\_id) | Identifier representing the DB Instance or DB Cluster target |
| <a name="output_proxy_target_target_arn"></a> [proxy\_target\_target\_arn](#output\_proxy\_target\_target\_arn) | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| <a name="output_proxy_target_tracked_cluster_id"></a> [proxy\_target\_tracked\_cluster\_id](#output\_proxy\_target\_tracked\_cluster\_id) | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| <a name="output_proxy_target_type"></a> [proxy\_target\_type](#output\_proxy\_target\_type) | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
<!-- END_TF_DOCS -->
Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/blob/master/LICENSE).

View file

@ -0,0 +1,144 @@
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
locals {
name = "ex-${basename(path.cwd)}"
region = "eu-west-1"
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Example = local.name
GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
auth = {
"root" = {
description = "Cluster generated master user password"
secret_arn = module.rds.cluster_master_user_secret[0].secret_arn
}
}
engine_family = "MYSQL"
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.cluster_id
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 6.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "~> 9.0"
name = local.name
engine = "aurora-mysql"
engine_version = "8.0"
master_username = "root"
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
instance_class = "db.r6g.large"
instances = {
1 = {}
2 = {}
}
vpc_id = module.vpc.vpc_id
db_subnet_group_name = module.vpc.database_subnet_group_name
security_group_rules = {
vpc_ingress = {
cidr_blocks = module.vpc.private_subnets_cidr_blocks
}
}
apply_immediately = true
skip_final_snapshot = true
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "${local.name}-proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}

View file

@ -66,24 +66,19 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endpoints
output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints
}
# CloudWatch logs # CloudWatch logs
output "log_group_arn" { output "log_group_arn" {
description = "The Amazon Resource Name (ARN) of the CloudWatch log group" description = "The Amazon Resource Name (ARN) of the CloudWatch log group"
value = module.rds_proxy.log_group_arn value = module.rds_proxy.log_group_arn
} }
# For aiding in testing & verification output "log_group_name" {
output "superuser_db_password_connect" { description = "The name of the CloudWatch log group"
description = "Connect to database using superuser with username/password directly to database" value = module.rds_proxy.log_group_name
value = "mysql --host=${module.rds.this_rds_cluster_endpoint} --user=${local.db_username} --password=${local.db_password} ${module.rds.this_rds_cluster_database_name}"
}
output "superuser_proxy_iam_token" {
description = "Gerate connection token for connecting to RDS Proxy with IAM auth"
value = "TOKEN=$(aws rds generate-db-auth-token --hostname ${module.rds_proxy.proxy_endpoint} --port 3306 --region ${local.region} --username ${local.db_username})"
}
output "superuser_proxy_iam_connect" {
description = "Connect to RDS Proxy using IAM auth via token generated"
value = "mysql --host=${module.rds_proxy.proxy_endpoint} --user=${local.db_username} --password=$TOKEN ${module.rds.this_rds_cluster_database_name} --ssl-ca=/home/ssm-user/AmazonRootCA1.pem --enable-cleartext-plugin"
} }

View file

View file

@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.5.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.15"
}
}
}

View file

@ -0,0 +1,91 @@
# RDS Proxy - IAM Authentication & MySQL Instance
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS MySQL instance
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window
4. You should now be connected to the `example` database in the Aurora cluster via the AWS Proxy using IAM authentication
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.15 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.15 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |
## Modules
| Name | Source | Version |
|------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds/aws | ~> 6.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_rds_sg"></a> [rds\_sg](#module\_rds\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 |
## Resources
| Name | Type |
|------|------|
| [aws_secretsmanager_secret.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource |
| [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source |
## Inputs
No inputs.
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_db_proxy_endpoints"></a> [db\_proxy\_endpoints](#output\_db\_proxy\_endpoints) | Array containing the full resource object and attributes for all DB proxy endpoints created |
| <a name="output_log_group_arn"></a> [log\_group\_arn](#output\_log\_group\_arn) | The Amazon Resource Name (ARN) of the CloudWatch log group |
| <a name="output_log_group_name"></a> [log\_group\_name](#output\_log\_group\_name) | The name of the CloudWatch log group |
| <a name="output_proxy_arn"></a> [proxy\_arn](#output\_proxy\_arn) | The Amazon Resource Name (ARN) for the proxy |
| <a name="output_proxy_default_target_group_arn"></a> [proxy\_default\_target\_group\_arn](#output\_proxy\_default\_target\_group\_arn) | The Amazon Resource Name (ARN) for the default target group |
| <a name="output_proxy_default_target_group_id"></a> [proxy\_default\_target\_group\_id](#output\_proxy\_default\_target\_group\_id) | The ID for the default target group |
| <a name="output_proxy_default_target_group_name"></a> [proxy\_default\_target\_group\_name](#output\_proxy\_default\_target\_group\_name) | The name of the default target group |
| <a name="output_proxy_endpoint"></a> [proxy\_endpoint](#output\_proxy\_endpoint) | The endpoint that you can use to connect to the proxy |
| <a name="output_proxy_id"></a> [proxy\_id](#output\_proxy\_id) | The ID for the proxy |
| <a name="output_proxy_target_endpoint"></a> [proxy\_target\_endpoint](#output\_proxy\_target\_endpoint) | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| <a name="output_proxy_target_id"></a> [proxy\_target\_id](#output\_proxy\_target\_id) | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| <a name="output_proxy_target_port"></a> [proxy\_target\_port](#output\_proxy\_target\_port) | Port for the target RDS DB Instance or Aurora DB Cluster |
| <a name="output_proxy_target_rds_resource_id"></a> [proxy\_target\_rds\_resource\_id](#output\_proxy\_target\_rds\_resource\_id) | Identifier representing the DB Instance or DB Cluster target |
| <a name="output_proxy_target_target_arn"></a> [proxy\_target\_target\_arn](#output\_proxy\_target\_target\_arn) | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| <a name="output_proxy_target_tracked_cluster_id"></a> [proxy\_target\_tracked\_cluster\_id](#output\_proxy\_target\_tracked\_cluster\_id) | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| <a name="output_proxy_target_type"></a> [proxy\_target\_type](#output\_proxy\_target\_type) | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
<!-- END_TF_DOCS -->
Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/blob/master/LICENSE).

View file

@ -0,0 +1,200 @@
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
locals {
name = "ex-${basename(path.cwd)}"
region = "eu-west-1"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Example = local.name
GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
auth = {
(local.db_username) = {
description = aws_secretsmanager_secret.superuser.description
secret_arn = aws_secretsmanager_secret.superuser.arn
}
}
engine_family = "MYSQL"
debug_logging = true
# Target RDS instance
target_db_instance = true
db_instance_identifier = module.rds.db_instance_identifier
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 6.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "~> 6.0"
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
identifier = local.name
engine = "mysql"
engine_version = "8.0"
family = "mysql8.0" # DB parameter group
major_engine_version = "8.0" # DB option group
instance_class = "db.t4g.large"
allocated_storage = 20
port = 3306
apply_immediately = true
db_subnet_group_name = module.vpc.database_subnet_group
vpc_security_group_ids = [module.rds_sg.security_group_id]
multi_az = true
backup_retention_period = 0
deletion_protection = false
tags = local.tags
}
module "rds_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "rds"
description = "MySQL RDS example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "${local.name}-proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, database connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}

View file

@ -66,24 +66,19 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endpoints
output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints
}
# CloudWatch logs # CloudWatch logs
output "log_group_arn" { output "log_group_arn" {
description = "The Amazon Resource Name (ARN) of the CloudWatch log group" description = "The Amazon Resource Name (ARN) of the CloudWatch log group"
value = module.rds_proxy.log_group_arn value = module.rds_proxy.log_group_arn
} }
# For aiding in testing & verification output "log_group_name" {
output "superuser_db_password_connect" { description = "The name of the CloudWatch log group"
description = "Connect to database using superuser with username/password directly to database" value = module.rds_proxy.log_group_name
value = "PGPASSWORD=${local.db_password} psql -h ${module.rds.this_db_instance_address} -p 5432 -d ${module.rds.this_db_instance_name} -U ${local.db_username} --set=sslmode=require"
}
output "superuser_proxy_iam_token" {
description = "Gerate connection token for connecting to RDS Proxy with IAM auth"
value = "TOKEN=$(aws rds generate-db-auth-token --hostname ${module.rds_proxy.proxy_endpoint} --port 5432 --region ${local.region} --username ${local.db_username})"
}
output "superuser_proxy_iam_connect" {
description = "Connect to RDS Proxy using IAM auth via token generated"
value = "psql \"host=${module.rds_proxy.proxy_endpoint} port=5432 sslmode=verify-full sslrootcert=/home/ssm-user/AmazonRootCA1.pem dbname=${module.rds.this_db_instance_name} user=${local.db_username} password=$TOKEN\""
} }

View file

View file

@ -0,0 +1,14 @@
terraform {
required_version = ">= 1.5.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.15"
}
random = {
source = "hashicorp/random"
version = ">= 2.0"
}
}
}

View file

@ -1,71 +0,0 @@
# RDS Proxy - IAM Authentication & MySQL Cluster
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS Aurora MySQL cluster
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window
4. You should now be connected to the `example` database in the RDS instance via the AWS Proxy using IAM authentication
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 0.12.26 |
| aws | >= 3.9 |
## Providers
| Name | Version |
|------|---------|
| aws | >= 3.9 |
| random | n/a |
## Inputs
No input.
## Outputs
| Name | Description |
|------|-------------|
| log\_group\_arn | The Amazon Resource Name (ARN) of the CloudWatch log group |
| proxy\_arn | The Amazon Resource Name (ARN) for the proxy |
| proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) for the default target group |
| proxy\_default\_target\_group\_id | The ID for the default target group |
| proxy\_default\_target\_group\_name | The name of the default target group |
| proxy\_endpoint | The endpoint that you can use to connect to the proxy |
| proxy\_id | The ID for the proxy |
| proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| proxy\_target\_port | Port for the target RDS DB Instance or Aurora DB Cluster |
| proxy\_target\_rds\_resource\_id | Identifier representing the DB Instance or DB Cluster target |
| proxy\_target\_target\_arn | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| proxy\_target\_tracked\_cluster\_id | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| proxy\_target\_type | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
| superuser\_db\_password\_connect | Connect to database using superuser with username/password directly to database |
| superuser\_proxy\_iam\_connect | Connect to RDS Proxy using IAM auth via token generated |
| superuser\_proxy\_iam\_token | Gerate connection token for connecting to RDS Proxy with IAM auth |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Apache-2.0 Licensed. See [LICENSE](../../LICENSE).

View file

@ -1,284 +0,0 @@
provider "aws" {
region = local.region
}
locals {
region = "us-east-1"
name = "example-${replace(basename(path.cwd), "_", "-")}"
db_name = "example"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
db_proxy_resource_id = element(split(":", module.rds_proxy.proxy_arn), 6)
db_iam_connect_prefix = "arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${local.db_proxy_resource_id}"
tags = {
Example = local.name
Environment = "dev"
}
}
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.64.0"
name = local.name
cidr = "10.0.0.0/18"
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"]
create_database_subnet_group = true
enable_nat_gateway = true
single_nat_gateway = true
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "3.0.0"
name = local.name
database_name = local.db_name
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
engine = "aurora-mysql"
engine_version = "5.7"
replica_count = 1
instance_type = "db.t3.medium"
storage_encrypted = false
apply_immediately = true
skip_final_snapshot = true
vpc_id = module.vpc.vpc_id
subnets = module.vpc.database_subnets
allowed_security_groups = [module.rds_proxy_sg.this_security_group_id]
db_subnet_group_name = local.name # Created by VPC module
db_parameter_group_name = aws_db_parameter_group.aurora_db_mysql57_parameter_group.id
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_mysql57_parameter_group.id
tags = local.tags
}
resource "aws_db_parameter_group" "aurora_db_mysql57_parameter_group" {
name = "example-aurora-db-57-parameter-group"
family = "aurora-mysql5.7"
description = "example-aurora-db-57-parameter-group"
}
resource "aws_rds_cluster_parameter_group" "aurora_cluster_mysql57_parameter_group" {
name = "example-aurora-57-cluster-parameter-group"
family = "aurora-mysql5.7"
description = "example-aurora-57-cluster-parameter-group"
}
################################################################################
# Test Resources
################################################################################
resource "aws_iam_instance_profile" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.name
}
data "aws_iam_policy_document" "ec2_test_assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "ec2_test" {
name_prefix = local.name
force_detach_policies = true
assume_role_policy = data.aws_iam_policy_document.ec2_test_assume.json
}
data "aws_iam_policy_document" "ec2_test" {
statement {
actions = ["rds-db:connect"]
resources = ["${local.db_iam_connect_prefix}/${local.db_username}"]
}
}
resource "aws_iam_role_policy" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.id
policy = data.aws_iam_policy_document.ec2_test.json
}
resource "aws_iam_role_policy_attachment" "ec2_ssm" {
role = aws_iam_role.ec2_test.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["679593333241"]
filter {
name = "name"
values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
module "ec2_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "ec2"
description = "EC2 RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
egress_rules = ["all-all"]
tags = local.tags
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "2.16.0"
name = local.name
instance_count = 1
associate_public_ip_address = true
iam_instance_profile = aws_iam_instance_profile.ec2_test.name
user_data = <<-EOT
#!/usr/bin/env bash
mkdir -p /home/ssm-user/ && wget -O /home/ssm-user/AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
apt update
apt install awscli mysql-server -y
EOT
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
vpc_security_group_ids = [module.ec2_sg.this_security_group_id]
subnet_ids = module.vpc.private_subnets
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "rds_proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
module "rds_proxy" {
source = "../../"
create_proxy = true
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.this_security_group_id]
secrets = {
"${local.db_username}" = {
description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
}
}
engine_family = "MYSQL"
db_host = module.rds.this_rds_cluster_endpoint
db_name = module.rds.this_rds_cluster_database_name
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.this_rds_cluster_id
tags = local.tags
}

View file

@ -1,7 +0,0 @@
terraform {
required_version = ">= 0.12.26"
required_providers {
aws = ">= 3.9"
}
}

View file

@ -1,71 +0,0 @@
# RDS Proxy - IAM Authentication & MySQL Instance
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS MySQL instance
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window
4. You should now be connected to the `example` database in the Aurora cluster via the AWS Proxy using IAM authentication
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 0.12.26 |
| aws | >= 3.9 |
## Providers
| Name | Version |
|------|---------|
| aws | >= 3.9 |
| random | n/a |
## Inputs
No input.
## Outputs
| Name | Description |
|------|-------------|
| log\_group\_arn | The Amazon Resource Name (ARN) of the CloudWatch log group |
| proxy\_arn | The Amazon Resource Name (ARN) for the proxy |
| proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) for the default target group |
| proxy\_default\_target\_group\_id | The ID for the default target group |
| proxy\_default\_target\_group\_name | The name of the default target group |
| proxy\_endpoint | The endpoint that you can use to connect to the proxy |
| proxy\_id | The ID for the proxy |
| proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| proxy\_target\_port | Port for the target RDS DB Instance or Aurora DB Cluster |
| proxy\_target\_rds\_resource\_id | Identifier representing the DB Instance or DB Cluster target |
| proxy\_target\_target\_arn | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| proxy\_target\_tracked\_cluster\_id | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| proxy\_target\_type | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
| superuser\_db\_password\_connect | Connect to database using superuser with username/password directly to database |
| superuser\_proxy\_iam\_connect | Connect to RDS Proxy using IAM auth via token generated |
| superuser\_proxy\_iam\_token | Gerate connection token for connecting to RDS Proxy with IAM auth |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Apache-2.0 Licensed. See [LICENSE](../../LICENSE).

View file

@ -1,294 +0,0 @@
provider "aws" {
region = local.region
}
locals {
region = "us-east-1"
name = "example-${replace(basename(path.cwd), "_", "-")}"
db_name = "example"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
db_proxy_resource_id = element(split(":", module.rds_proxy.proxy_arn), 6)
db_iam_connect_prefix = "arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${local.db_proxy_resource_id}"
tags = {
Example = local.name
Environment = "dev"
}
}
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.64.0"
name = local.name
cidr = "10.0.0.0/18"
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
tags = local.tags
}
module "rds_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "rds"
description = "MySQL RDS example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "2.20.0"
name = local.db_name
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
identifier = local.name
engine = "mysql"
engine_version = "5.7.31"
family = "mysql5.7"
major_engine_version = "5.7"
port = 3306
instance_class = "db.t3.micro"
allocated_storage = 5
storage_encrypted = false
apply_immediately = true
vpc_security_group_ids = [module.rds_sg.this_security_group_id]
subnet_ids = module.vpc.database_subnets
maintenance_window = "Mon:00:00-Mon:03:00"
backup_window = "03:00-06:00"
backup_retention_period = 0
deletion_protection = false
tags = local.tags
}
################################################################################
# Test Resources
################################################################################
resource "aws_iam_instance_profile" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.name
}
data "aws_iam_policy_document" "ec2_test_assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "ec2_test" {
name_prefix = local.name
force_detach_policies = true
assume_role_policy = data.aws_iam_policy_document.ec2_test_assume.json
}
data "aws_iam_policy_document" "ec2_test" {
statement {
actions = ["rds-db:connect"]
resources = ["${local.db_iam_connect_prefix}/${local.db_username}"]
}
}
resource "aws_iam_role_policy" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.id
policy = data.aws_iam_policy_document.ec2_test.json
}
resource "aws_iam_role_policy_attachment" "ec2_ssm" {
role = aws_iam_role.ec2_test.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["679593333241"]
filter {
name = "name"
values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
module "ec2_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "ec2"
description = "EC2 RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
egress_rules = ["all-all"]
tags = local.tags
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "2.16.0"
name = local.name
instance_count = 1
associate_public_ip_address = true
iam_instance_profile = aws_iam_instance_profile.ec2_test.name
user_data = <<-EOT
#!/usr/bin/env bash
mkdir -p /home/ssm-user/ && wget -O /home/ssm-user/AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
apt update
apt install awscli mysql-server -y
EOT
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
vpc_security_group_ids = [module.ec2_sg.this_security_group_id]
subnet_ids = module.vpc.private_subnets
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "rds_proxy"
description = "MySQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
module "rds_proxy" {
source = "../../"
create_proxy = true
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.this_security_group_id]
secrets = {
"${local.db_username}" = {
description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
}
}
engine_family = "MYSQL"
db_host = module.rds.this_db_instance_address
db_name = module.rds.this_db_instance_name
debug_logging = true
# Target RDS instance
target_db_instance = true
db_instance_identifier = module.rds.this_db_instance_id
tags = local.tags
}

View file

@ -1,7 +0,0 @@
terraform {
required_version = ">= 0.12.26"
required_providers {
aws = ">= 3.9"
}
}

View file

@ -0,0 +1,86 @@
# RDS Proxy - IAM Authentication & PostgreSQL Cluster
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS Aurora PostgreSQL cluster
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window - NOTE: remove the string escape slashes `psql \"host...` -> `psql "host...`
4. You should now be connected to the `example` database in the RDS instance via the AWS Proxy using IAM authentication
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.15 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.15 |
## Modules
| Name | Source | Version |
|------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds-aurora/aws | ~> 9.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 |
## Resources
| Name | Type |
|------|------|
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
## Inputs
No inputs.
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_db_proxy_endpoints"></a> [db\_proxy\_endpoints](#output\_db\_proxy\_endpoints) | Array containing the full resource object and attributes for all DB proxy endpoints created |
| <a name="output_iam_role_arn"></a> [iam\_role\_arn](#output\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the role proxy uses to access secrets |
| <a name="output_iam_role_name"></a> [iam\_role\_name](#output\_iam\_role\_name) | The name of the role proxy uses to access secrets |
| <a name="output_iam_role_unique_id"></a> [iam\_role\_unique\_id](#output\_iam\_role\_unique\_id) | Stable and unique string identifying the role proxy uses to access secrets |
| <a name="output_log_group_arn"></a> [log\_group\_arn](#output\_log\_group\_arn) | The Amazon Resource Name (ARN) of the CloudWatch log group |
| <a name="output_log_group_name"></a> [log\_group\_name](#output\_log\_group\_name) | The name of the CloudWatch log group |
| <a name="output_proxy_arn"></a> [proxy\_arn](#output\_proxy\_arn) | The Amazon Resource Name (ARN) for the proxy |
| <a name="output_proxy_default_target_group_arn"></a> [proxy\_default\_target\_group\_arn](#output\_proxy\_default\_target\_group\_arn) | The Amazon Resource Name (ARN) for the default target group |
| <a name="output_proxy_default_target_group_id"></a> [proxy\_default\_target\_group\_id](#output\_proxy\_default\_target\_group\_id) | The ID for the default target group |
| <a name="output_proxy_default_target_group_name"></a> [proxy\_default\_target\_group\_name](#output\_proxy\_default\_target\_group\_name) | The name of the default target group |
| <a name="output_proxy_endpoint"></a> [proxy\_endpoint](#output\_proxy\_endpoint) | The endpoint that you can use to connect to the proxy |
| <a name="output_proxy_id"></a> [proxy\_id](#output\_proxy\_id) | The ID for the proxy |
| <a name="output_proxy_target_endpoint"></a> [proxy\_target\_endpoint](#output\_proxy\_target\_endpoint) | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| <a name="output_proxy_target_id"></a> [proxy\_target\_id](#output\_proxy\_target\_id) | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| <a name="output_proxy_target_port"></a> [proxy\_target\_port](#output\_proxy\_target\_port) | Port for the target RDS DB Instance or Aurora DB Cluster |
| <a name="output_proxy_target_rds_resource_id"></a> [proxy\_target\_rds\_resource\_id](#output\_proxy\_target\_rds\_resource\_id) | Identifier representing the DB Instance or DB Cluster target |
| <a name="output_proxy_target_target_arn"></a> [proxy\_target\_target\_arn](#output\_proxy\_target\_target\_arn) | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| <a name="output_proxy_target_tracked_cluster_id"></a> [proxy\_target\_tracked\_cluster\_id](#output\_proxy\_target\_tracked\_cluster\_id) | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| <a name="output_proxy_target_type"></a> [proxy\_target\_type](#output\_proxy\_target\_type) | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
<!-- END_TF_DOCS -->
Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/blob/master/LICENSE).

View file

@ -0,0 +1,144 @@
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
locals {
name = "ex-${basename(path.cwd)}"
region = "eu-west-1"
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Example = local.name
GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
auth = {
"root" = {
description = "Cluster generated master user password"
secret_arn = module.rds.cluster_master_user_secret[0].secret_arn
}
}
engine_family = "POSTGRESQL"
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.cluster_id
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 6.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "~> 9.0"
name = local.name
engine = "aurora-postgresql"
engine_version = "17.5"
master_username = "root"
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
instance_class = "db.r6g.large"
instances = {
1 = {}
2 = {}
}
vpc_id = module.vpc.vpc_id
db_subnet_group_name = module.vpc.database_subnet_group_name
security_group_rules = {
vpc_ingress = {
cidr_blocks = module.vpc.private_subnets_cidr_blocks
}
}
apply_immediately = true
skip_final_snapshot = true
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "${local.name}-proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}

View file

@ -66,24 +66,35 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endpoints
output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints
}
# CloudWatch logs # CloudWatch logs
output "log_group_arn" { output "log_group_arn" {
description = "The Amazon Resource Name (ARN) of the CloudWatch log group" description = "The Amazon Resource Name (ARN) of the CloudWatch log group"
value = module.rds_proxy.log_group_arn value = module.rds_proxy.log_group_arn
} }
# For aiding in testing & verification output "log_group_name" {
output "superuser_db_password_connect" { description = "The name of the CloudWatch log group"
description = "Connect to database using superuser with username/password directly to database" value = module.rds_proxy.log_group_name
value = "mysql --host=${module.rds.this_db_instance_address} --user=${local.db_username} --password=${local.db_password} ${module.rds.this_db_instance_name}"
} }
output "superuser_proxy_iam_token" { # IAM role
description = "Gerate connection token for connecting to RDS Proxy with IAM auth" output "iam_role_arn" {
value = "TOKEN=$(aws rds generate-db-auth-token --hostname ${module.rds_proxy.proxy_endpoint} --port 3306 --region ${local.region} --username ${local.db_username})" description = "The Amazon Resource Name (ARN) specifying the role proxy uses to access secrets"
value = module.rds_proxy.iam_role_arn
} }
output "superuser_proxy_iam_connect" { output "iam_role_name" {
description = "Connect to RDS Proxy using IAM auth via token generated" description = "The name of the role proxy uses to access secrets"
value = "mysql --host=${module.rds_proxy.proxy_endpoint} --user=${local.db_username} --password=$TOKEN ${module.rds.this_db_instance_name} --ssl-ca=/home/ssm-user/AmazonRootCA1.pem --enable-cleartext-plugin" value = module.rds_proxy.iam_role_name
}
output "iam_role_unique_id" {
description = "Stable and unique string identifying the role proxy uses to access secrets"
value = module.rds_proxy.iam_role_unique_id
} }

View file

@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.5.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.15"
}
}
}

View file

@ -0,0 +1,91 @@
# RDS Proxy - IAM Authentication & PostgreSQL Instance
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS PostgreSQL instance
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window - NOTE: remove the string escape slashes `psql \"host...` -> `psql "host...`
4. You should now be connected to the `example` database in the Aurora cluster via the AWS Proxy using IAM authentication
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.15 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.15 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |
## Modules
| Name | Source | Version |
|------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds/aws | ~> 6.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_rds_sg"></a> [rds\_sg](#module\_rds\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 |
## Resources
| Name | Type |
|------|------|
| [aws_secretsmanager_secret.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource |
| [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source |
## Inputs
No inputs.
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_db_proxy_endpoints"></a> [db\_proxy\_endpoints](#output\_db\_proxy\_endpoints) | Array containing the full resource object and attributes for all DB proxy endpoints created |
| <a name="output_log_group_arn"></a> [log\_group\_arn](#output\_log\_group\_arn) | The Amazon Resource Name (ARN) of the CloudWatch log group |
| <a name="output_log_group_name"></a> [log\_group\_name](#output\_log\_group\_name) | The name of the CloudWatch log group |
| <a name="output_proxy_arn"></a> [proxy\_arn](#output\_proxy\_arn) | The Amazon Resource Name (ARN) for the proxy |
| <a name="output_proxy_default_target_group_arn"></a> [proxy\_default\_target\_group\_arn](#output\_proxy\_default\_target\_group\_arn) | The Amazon Resource Name (ARN) for the default target group |
| <a name="output_proxy_default_target_group_id"></a> [proxy\_default\_target\_group\_id](#output\_proxy\_default\_target\_group\_id) | The ID for the default target group |
| <a name="output_proxy_default_target_group_name"></a> [proxy\_default\_target\_group\_name](#output\_proxy\_default\_target\_group\_name) | The name of the default target group |
| <a name="output_proxy_endpoint"></a> [proxy\_endpoint](#output\_proxy\_endpoint) | The endpoint that you can use to connect to the proxy |
| <a name="output_proxy_id"></a> [proxy\_id](#output\_proxy\_id) | The ID for the proxy |
| <a name="output_proxy_target_endpoint"></a> [proxy\_target\_endpoint](#output\_proxy\_target\_endpoint) | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| <a name="output_proxy_target_id"></a> [proxy\_target\_id](#output\_proxy\_target\_id) | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| <a name="output_proxy_target_port"></a> [proxy\_target\_port](#output\_proxy\_target\_port) | Port for the target RDS DB Instance or Aurora DB Cluster |
| <a name="output_proxy_target_rds_resource_id"></a> [proxy\_target\_rds\_resource\_id](#output\_proxy\_target\_rds\_resource\_id) | Identifier representing the DB Instance or DB Cluster target |
| <a name="output_proxy_target_target_arn"></a> [proxy\_target\_target\_arn](#output\_proxy\_target\_target\_arn) | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| <a name="output_proxy_target_tracked_cluster_id"></a> [proxy\_target\_tracked\_cluster\_id](#output\_proxy\_target\_tracked\_cluster\_id) | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| <a name="output_proxy_target_type"></a> [proxy\_target\_type](#output\_proxy\_target\_type) | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
<!-- END_TF_DOCS -->
Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-rds-proxy/blob/master/LICENSE).

View file

@ -0,0 +1,200 @@
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
locals {
name = "ex-${basename(path.cwd)}"
region = "eu-west-1"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Example = local.name
GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
auth = {
(local.db_username) = {
description = aws_secretsmanager_secret.superuser.description
secret_arn = aws_secretsmanager_secret.superuser.arn
}
}
engine_family = "POSTGRESQL"
debug_logging = true
# Target RDS instance
target_db_instance = true
db_instance_identifier = module.rds.db_instance_identifier
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 6.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "~> 6.0"
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
identifier = local.name
engine = "postgres"
engine_version = "14"
family = "postgres14" # DB parameter group
major_engine_version = "14" # DB option group
instance_class = "db.t4g.large"
allocated_storage = 20
port = 5432
apply_immediately = true
db_subnet_group_name = module.vpc.database_subnet_group
vpc_security_group_ids = [module.rds_sg.security_group_id]
multi_az = true
backup_retention_period = 0
deletion_protection = false
tags = local.tags
}
module "rds_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "rds"
description = "PostgreSQL RDS example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "rds_proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, database connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}

View file

@ -66,24 +66,19 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endpoints
output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints
}
# CloudWatch logs # CloudWatch logs
output "log_group_arn" { output "log_group_arn" {
description = "The Amazon Resource Name (ARN) of the CloudWatch log group" description = "The Amazon Resource Name (ARN) of the CloudWatch log group"
value = module.rds_proxy.log_group_arn value = module.rds_proxy.log_group_arn
} }
# For aiding in testing & verification output "log_group_name" {
output "superuser_db_password_connect" { description = "The name of the CloudWatch log group"
description = "Connect to database using superuser with username/password directly to database" value = module.rds_proxy.log_group_name
value = "PGPASSWORD=${local.db_password} psql -h ${module.rds.this_rds_cluster_endpoint} -p 5432 -d ${module.rds.this_rds_cluster_database_name} -U ${local.db_username} --set=sslmode=require"
}
output "superuser_proxy_iam_token" {
description = "Gerate connection token for connecting to RDS Proxy with IAM auth"
value = "TOKEN=$(aws rds generate-db-auth-token --hostname ${module.rds_proxy.proxy_endpoint} --port 5432 --region ${local.region} --username ${local.db_username})"
}
output "superuser_proxy_iam_connect" {
description = "Connect to RDS Proxy using IAM auth via token generated"
value = "psql \"host=${module.rds_proxy.proxy_endpoint} port=5432 sslmode=verify-full sslrootcert=/home/ssm-user/AmazonRootCA1.pem dbname=${module.rds.this_rds_cluster_database_name} user=${local.db_username} password=$TOKEN\""
} }

View file

@ -0,0 +1,14 @@
terraform {
required_version = ">= 1.5.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.15"
}
random = {
source = "hashicorp/random"
version = ">= 2.0"
}
}
}

View file

@ -1,71 +0,0 @@
# RDS Proxy - IAM Authentication & PostgreSQL Cluster
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS Aurora PostgreSQL cluster
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window - NOTE: remove the string escape slashes `psql \"host...` -> `psql "host...`
4. You should now be connected to the `example` database in the RDS instance via the AWS Proxy using IAM authentication
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 0.12.26 |
| aws | >= 3.9 |
## Providers
| Name | Version |
|------|---------|
| aws | >= 3.9 |
| random | n/a |
## Inputs
No input.
## Outputs
| Name | Description |
|------|-------------|
| log\_group\_arn | The Amazon Resource Name (ARN) of the CloudWatch log group |
| proxy\_arn | The Amazon Resource Name (ARN) for the proxy |
| proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) for the default target group |
| proxy\_default\_target\_group\_id | The ID for the default target group |
| proxy\_default\_target\_group\_name | The name of the default target group |
| proxy\_endpoint | The endpoint that you can use to connect to the proxy |
| proxy\_id | The ID for the proxy |
| proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| proxy\_target\_port | Port for the target RDS DB Instance or Aurora DB Cluster |
| proxy\_target\_rds\_resource\_id | Identifier representing the DB Instance or DB Cluster target |
| proxy\_target\_target\_arn | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| proxy\_target\_tracked\_cluster\_id | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| proxy\_target\_type | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
| superuser\_db\_password\_connect | Connect to database using superuser with username/password directly to database |
| superuser\_proxy\_iam\_connect | Connect to RDS Proxy using IAM auth via token generated |
| superuser\_proxy\_iam\_token | Gerate connection token for connecting to RDS Proxy with IAM auth |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Apache-2.0 Licensed. See [LICENSE](../../LICENSE).

View file

@ -1,284 +0,0 @@
provider "aws" {
region = local.region
}
locals {
region = "us-east-1"
name = "example-${replace(basename(path.cwd), "_", "-")}"
db_name = "example"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
db_proxy_resource_id = element(split(":", module.rds_proxy.proxy_arn), 6)
db_iam_connect_prefix = "arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${local.db_proxy_resource_id}"
tags = {
Example = local.name
Environment = "dev"
}
}
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.64.0"
name = local.name
cidr = "10.0.0.0/18"
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"]
create_database_subnet_group = true
enable_nat_gateway = true
single_nat_gateway = true
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "3.0.0"
name = local.name
database_name = local.db_name
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
engine = "aurora-postgresql"
engine_version = "11.9"
replica_count = 1
instance_type = "db.t3.medium"
storage_encrypted = false
apply_immediately = true
skip_final_snapshot = true
vpc_id = module.vpc.vpc_id
subnets = module.vpc.database_subnets
allowed_security_groups = [module.rds_proxy_sg.this_security_group_id]
db_subnet_group_name = local.name # Created by VPC module
db_parameter_group_name = aws_db_parameter_group.aurora_db_postgres11_parameter_group.id
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_postgres11_parameter_group.id
tags = local.tags
}
resource "aws_db_parameter_group" "aurora_db_postgres11_parameter_group" {
name = "example-aurora-db-postgres11-parameter-group"
family = "aurora-postgresql11"
description = "test-aurora-db-postgres11-parameter-group"
}
resource "aws_rds_cluster_parameter_group" "aurora_cluster_postgres11_parameter_group" {
name = "example-aurora-postgres11-cluster-parameter-group"
family = "aurora-postgresql11"
description = "example-aurora-postgres11-cluster-parameter-group"
}
################################################################################
# Test Resources
################################################################################
resource "aws_iam_instance_profile" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.name
}
data "aws_iam_policy_document" "ec2_test_assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "ec2_test" {
name_prefix = local.name
force_detach_policies = true
assume_role_policy = data.aws_iam_policy_document.ec2_test_assume.json
}
data "aws_iam_policy_document" "ec2_test" {
statement {
actions = ["rds-db:connect"]
resources = ["${local.db_iam_connect_prefix}/${local.db_username}"]
}
}
resource "aws_iam_role_policy" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.id
policy = data.aws_iam_policy_document.ec2_test.json
}
resource "aws_iam_role_policy_attachment" "ec2_ssm" {
role = aws_iam_role.ec2_test.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["679593333241"]
filter {
name = "name"
values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
module "ec2_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "ec2"
description = "EC2 RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
egress_rules = ["all-all"]
tags = local.tags
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "2.16.0"
name = local.name
instance_count = 1
associate_public_ip_address = true
iam_instance_profile = aws_iam_instance_profile.ec2_test.name
user_data = <<-EOT
#!/usr/bin/env bash
mkdir -p /home/ssm-user/ && wget -O /home/ssm-user/AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
apt update
apt install awscli postgresql-client -y
EOT
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
vpc_security_group_ids = [module.ec2_sg.this_security_group_id]
subnet_ids = module.vpc.private_subnets
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "rds_proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
module "rds_proxy" {
source = "../../"
create_proxy = true
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.this_security_group_id]
secrets = {
"${local.db_username}" = {
description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
}
}
engine_family = "POSTGRESQL"
db_host = module.rds.this_rds_cluster_endpoint
db_name = module.rds.this_rds_cluster_database_name
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.this_rds_cluster_id
tags = local.tags
}

View file

@ -1,7 +0,0 @@
terraform {
required_version = ">= 0.12.26"
required_providers {
aws = ">= 3.9"
}
}

View file

@ -1,71 +0,0 @@
# RDS Proxy - IAM Authentication & PostgreSQL Instance
Configuration in this directory creates:
- AWS RDS Proxy w/ IAM authentication enabled for an RDS PostgreSQL instance
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources.
## Validation
An EC2 instance configuration has been provided for use in validating the example configuration. After provisioning the configuration, there are some outputs that have been provided to aid in validating changes. To perform validation, after the EC2 instance finishes provisioning:
1. Connect to the EC2 instance using Session Manager
2. Copy the output from `superuser_proxy_iam_token` and paste it into the Session Manager window - this generates the token for connecting to the proxy with IAM auth.
3. Copy the output from `superuser_proxy_iam_connect` and paste it into the window - NOTE: remove the string escape slashes `psql \"host...` -> `psql "host...`
4. You should now be connected to the `example` database in the Aurora cluster via the AWS Proxy using IAM authentication
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 0.12.26 |
| aws | >= 3.9 |
## Providers
| Name | Version |
|------|---------|
| aws | >= 3.9 |
| random | n/a |
## Inputs
No input.
## Outputs
| Name | Description |
|------|-------------|
| log\_group\_arn | The Amazon Resource Name (ARN) of the CloudWatch log group |
| proxy\_arn | The Amazon Resource Name (ARN) for the proxy |
| proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) for the default target group |
| proxy\_default\_target\_group\_id | The ID for the default target group |
| proxy\_default\_target\_group\_name | The name of the default target group |
| proxy\_endpoint | The endpoint that you can use to connect to the proxy |
| proxy\_id | The ID for the proxy |
| proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type |
| proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/) |
| proxy\_target\_port | Port for the target RDS DB Instance or Aurora DB Cluster |
| proxy\_target\_rds\_resource\_id | Identifier representing the DB Instance or DB Cluster target |
| proxy\_target\_target\_arn | Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API |
| proxy\_target\_tracked\_cluster\_id | DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS\_INSTANCE target that is part of a DB Cluster |
| proxy\_target\_type | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` |
| superuser\_db\_password\_connect | Connect to database using superuser with username/password directly to database |
| superuser\_proxy\_iam\_connect | Connect to RDS Proxy using IAM auth via token generated |
| superuser\_proxy\_iam\_token | Gerate connection token for connecting to RDS Proxy with IAM auth |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Apache-2.0 Licensed. See [LICENSE](../../LICENSE).

View file

@ -1,294 +0,0 @@
provider "aws" {
region = local.region
}
locals {
region = "us-east-1"
name = "example-${replace(basename(path.cwd), "_", "-")}"
db_name = "example"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
db_proxy_resource_id = element(split(":", module.rds_proxy.proxy_arn), 6)
db_iam_connect_prefix = "arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${local.db_proxy_resource_id}"
tags = {
Example = local.name
Environment = "dev"
}
}
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.64.0"
name = local.name
cidr = "10.0.0.0/18"
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
tags = local.tags
}
module "rds_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "rds"
description = "PostgreSQL RDS example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "2.20.0"
name = local.db_name
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
identifier = local.name
engine = "postgres"
engine_version = "11.9"
family = "postgres11"
major_engine_version = "11"
port = 5432
instance_class = "db.t3.micro"
allocated_storage = 5
storage_encrypted = false
apply_immediately = true
vpc_security_group_ids = [module.rds_sg.this_security_group_id]
subnet_ids = module.vpc.database_subnets
maintenance_window = "Mon:00:00-Mon:03:00"
backup_window = "03:00-06:00"
backup_retention_period = 0
deletion_protection = false
tags = local.tags
}
################################################################################
# Test Resources
################################################################################
resource "aws_iam_instance_profile" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.name
}
data "aws_iam_policy_document" "ec2_test_assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "ec2_test" {
name_prefix = local.name
force_detach_policies = true
assume_role_policy = data.aws_iam_policy_document.ec2_test_assume.json
}
data "aws_iam_policy_document" "ec2_test" {
statement {
actions = ["rds-db:connect"]
resources = ["${local.db_iam_connect_prefix}/${local.db_username}"]
}
}
resource "aws_iam_role_policy" "ec2_test" {
name_prefix = local.name
role = aws_iam_role.ec2_test.id
policy = data.aws_iam_policy_document.ec2_test.json
}
resource "aws_iam_role_policy_attachment" "ec2_ssm" {
role = aws_iam_role.ec2_test.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["679593333241"]
filter {
name = "name"
values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
module "ec2_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "ec2"
description = "EC2 RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
egress_rules = ["all-all"]
tags = local.tags
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "2.16.0"
name = local.name
instance_count = 1
associate_public_ip_address = true
iam_instance_profile = aws_iam_instance_profile.ec2_test.name
user_data = <<-EOT
#!/usr/bin/env bash
mkdir -p /home/ssm-user/ && wget -O /home/ssm-user/AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
apt update
apt install awscli postgresql -y
EOT
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
vpc_security_group_ids = [module.ec2_sg.this_security_group_id]
subnet_ids = module.vpc.private_subnets
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "3.17.0"
name = "rds_proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
module "rds_proxy" {
source = "../../"
create_proxy = true
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.this_security_group_id]
secrets = {
"${local.db_username}" = {
description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
}
}
engine_family = "POSTGRESQL"
db_host = module.rds.this_db_instance_address
db_name = module.rds.this_db_instance_name
debug_logging = true
# Target RDS instance
target_db_instance = true
db_instance_identifier = module.rds.this_db_instance_id
tags = local.tags
}

View file

@ -1,7 +0,0 @@
terraform {
required_version = ">= 0.12.26"
required_providers {
aws = ">= 3.9"
}
}

142
main.tf
View file

@ -1,47 +1,48 @@
locals {
db_identifier_key = var.db_instance_identifier != "" ? "dbInstanceIdentifier" : "dbClusterIdentifier"
db_identifier_value = var.db_instance_identifier != "" ? var.db_instance_identifier : var.db_cluster_identifier
role_arn = var.create_proxy && var.create_iam_role ? aws_iam_role.this[0].arn : var.role_arn
role_name = coalesce(var.iam_role_name, var.name)
policy_name = coalesce(var.iam_policy_name, var.name)
}
data "aws_region" "current" {}
################################################################################ ################################################################################
# RDS Proxy # RDS Proxy
################################################################################ ################################################################################
resource "aws_db_proxy" "this" { resource "aws_db_proxy" "this" {
count = var.create_proxy ? 1 : 0 count = var.create ? 1 : 0
name = var.name region = var.region
debug_logging = var.debug_logging
engine_family = var.engine_family
idle_client_timeout = var.idle_client_timeout
require_tls = var.require_tls
role_arn = local.role_arn
vpc_security_group_ids = var.vpc_security_group_ids
vpc_subnet_ids = var.vpc_subnet_ids
dynamic "auth" { dynamic "auth" {
for_each = var.secrets for_each = var.auth
content { content {
auth_scheme = var.auth_scheme auth_scheme = auth.value.auth_scheme
client_password_auth_type = auth.value.client_password_auth_type
description = auth.value.description description = auth.value.description
iam_auth = var.iam_auth iam_auth = auth.value.iam_auth
secret_arn = auth.value.arn secret_arn = auth.value.secret_arn
username = auth.value.username
} }
} }
debug_logging = var.debug_logging
default_auth_scheme = var.default_auth_scheme
engine_family = var.engine_family
idle_client_timeout = var.idle_client_timeout
name = var.name
require_tls = var.require_tls
role_arn = try(aws_iam_role.this[0].arn, var.role_arn)
vpc_security_group_ids = var.vpc_security_group_ids
vpc_subnet_ids = var.vpc_subnet_ids
tags = merge(var.tags, var.proxy_tags) tags = merge(var.tags, var.proxy_tags)
depends_on = [aws_cloudwatch_log_group.this] depends_on = [aws_cloudwatch_log_group.this]
} }
################################################################################
# Default Target Group
################################################################################
resource "aws_db_proxy_default_target_group" "this" { resource "aws_db_proxy_default_target_group" "this" {
count = var.create_proxy ? 1 : 0 count = var.create ? 1 : 0
region = var.region
db_proxy_name = aws_db_proxy.this[0].name db_proxy_name = aws_db_proxy.this[0].name
@ -54,8 +55,14 @@ resource "aws_db_proxy_default_target_group" "this" {
} }
} }
################################################################################
# Target(s)
################################################################################
resource "aws_db_proxy_target" "db_instance" { resource "aws_db_proxy_target" "db_instance" {
count = var.create_proxy && var.target_db_instance ? 1 : 0 count = var.create && var.target_db_instance ? 1 : 0
region = var.region
db_proxy_name = aws_db_proxy.this[0].name db_proxy_name = aws_db_proxy.this[0].name
target_group_name = aws_db_proxy_default_target_group.this[0].name target_group_name = aws_db_proxy_default_target_group.this[0].name
@ -63,7 +70,9 @@ resource "aws_db_proxy_target" "db_instance" {
} }
resource "aws_db_proxy_target" "db_cluster" { resource "aws_db_proxy_target" "db_cluster" {
count = var.create_proxy && var.target_db_cluster ? 1 : 0 count = var.create && var.target_db_cluster ? 1 : 0
region = var.region
db_proxy_name = aws_db_proxy.this[0].name db_proxy_name = aws_db_proxy.this[0].name
target_group_name = aws_db_proxy_default_target_group.this[0].name target_group_name = aws_db_proxy_default_target_group.this[0].name
@ -71,15 +80,36 @@ resource "aws_db_proxy_target" "db_cluster" {
} }
################################################################################ ################################################################################
# CloudWatch Logs # Endpoint(s)
################################################################################
resource "aws_db_proxy_endpoint" "this" {
for_each = { for k, v in var.endpoints : k => v if var.create }
region = var.region
db_proxy_name = aws_db_proxy.this[0].name
db_proxy_endpoint_name = coalesce(each.value.name, each.key)
vpc_subnet_ids = each.value.vpc_subnet_ids
vpc_security_group_ids = each.value.vpc_security_group_ids
target_role = each.value.target_role
tags = merge(var.tags, each.value.tags)
}
################################################################################
# CloudWatch Log Group
################################################################################ ################################################################################
resource "aws_cloudwatch_log_group" "this" { resource "aws_cloudwatch_log_group" "this" {
count = var.create_proxy && var.manage_log_group ? 1 : 0 count = var.create && var.manage_log_group ? 1 : 0
region = var.region
name = "/aws/rds/proxy/${var.name}" name = "/aws/rds/proxy/${var.name}"
retention_in_days = var.log_group_retention_in_days retention_in_days = var.log_group_retention_in_days
kms_key_id = var.log_group_kms_key_id kms_key_id = var.log_group_kms_key_id
log_group_class = var.log_group_class
tags = merge(var.tags, var.log_group_tags) tags = merge(var.tags, var.log_group_tags)
} }
@ -88,8 +118,37 @@ resource "aws_cloudwatch_log_group" "this" {
# IAM Role # IAM Role
################################################################################ ################################################################################
locals {
create_iam_role = var.create && var.create_iam_role
role_name = coalesce(var.iam_role_name, var.name)
policy_name = coalesce(var.iam_policy_name, var.name)
partition = try(data.aws_partition.current[0].partition, "aws")
dns_suffix = try(data.aws_partition.current[0].dns_suffix, "amazonaws.com")
region = try(data.aws_region.current[0].region, var.region)
}
data "aws_region" "current" {
count = local.create_iam_role ? 1 : 0
region = var.region
}
data "aws_partition" "current" {
count = local.create_iam_role ? 1 : 0
}
data "aws_service_principal" "rds" {
count = local.create_iam_role ? 1 : 0
service_name = "rds"
region = data.aws_region.current[0].region
}
data "aws_iam_policy_document" "assume_role" { data "aws_iam_policy_document" "assume_role" {
count = var.create_proxy && var.create_iam_role ? 1 : 0 count = local.create_iam_role ? 1 : 0
statement { statement {
sid = "RDSAssume" sid = "RDSAssume"
@ -98,13 +157,13 @@ data "aws_iam_policy_document" "assume_role" {
principals { principals {
type = "Service" type = "Service"
identifiers = ["rds.amazonaws.com"] identifiers = [data.aws_service_principal.rds[0].name]
} }
} }
} }
resource "aws_iam_role" "this" { resource "aws_iam_role" "this" {
count = var.create_proxy && var.create_iam_role ? 1 : 0 count = local.create_iam_role ? 1 : 0
name = var.use_role_name_prefix ? null : local.role_name name = var.use_role_name_prefix ? null : local.role_name
name_prefix = var.use_role_name_prefix ? "${local.role_name}-" : null name_prefix = var.use_role_name_prefix ? "${local.role_name}-" : null
@ -119,20 +178,27 @@ resource "aws_iam_role" "this" {
tags = merge(var.tags, var.iam_role_tags) tags = merge(var.tags, var.iam_role_tags)
} }
################################################################################
# IAM Role Policy
################################################################################
data "aws_iam_policy_document" "this" { data "aws_iam_policy_document" "this" {
count = var.create_proxy && var.create_iam_role ? 1 : 0 count = local.create_iam_role && var.create_iam_policy ? 1 : 0
statement { statement {
sid = "DecryptSecrets" sid = "DecryptSecrets"
effect = "Allow" effect = "Allow"
actions = ["kms:Decrypt"] actions = ["kms:Decrypt"]
resources = distinct([for secret in var.secrets : secret.kms_key_id]) resources = coalescelist(
var.kms_key_arns,
["arn:${local.partition}:kms:*:*:key/*"]
)
condition { condition {
test = "StringEquals" test = "StringEquals"
variable = "kms:ViaService" variable = "kms:ViaService"
values = [ values = [
"secretsmanager.${data.aws_region.current.name}.amazonaws.com" "secretsmanager.${local.region}.${local.dns_suffix}"
] ]
} }
} }
@ -157,12 +223,12 @@ data "aws_iam_policy_document" "this" {
"secretsmanager:ListSecretVersionIds", "secretsmanager:ListSecretVersionIds",
] ]
resources = distinct([for secret in var.secrets : secret.arn]) resources = distinct([for auth in var.auth : auth.secret_arn])
} }
} }
resource "aws_iam_role_policy" "this" { resource "aws_iam_role_policy" "this" {
count = var.create_proxy && var.create_iam_role && var.create_iam_policy ? 1 : 0 count = local.create_iam_role && var.create_iam_policy ? 1 : 0
name = var.use_policy_name_prefix ? null : local.policy_name name = var.use_policy_name_prefix ? null : local.policy_name
name_prefix = var.use_policy_name_prefix ? "${local.policy_name}-" : null name_prefix = var.use_policy_name_prefix ? "${local.policy_name}-" : null

View file

@ -1,73 +1,118 @@
################################################################################
# RDS Proxy # RDS Proxy
################################################################################
output "proxy_id" { output "proxy_id" {
description = "The ID for the proxy" description = "The ID for the proxy"
value = element(concat(aws_db_proxy.this.*.id, [""]), 0) value = try(aws_db_proxy.this[0].id, null)
} }
output "proxy_arn" { output "proxy_arn" {
description = "The Amazon Resource Name (ARN) for the proxy" description = "The Amazon Resource Name (ARN) for the proxy"
value = element(concat(aws_db_proxy.this.*.arn, [""]), 0) value = try(aws_db_proxy.this[0].arn, null)
} }
output "proxy_endpoint" { output "proxy_endpoint" {
description = "The endpoint that you can use to connect to the proxy" description = "The endpoint that you can use to connect to the proxy"
value = element(concat(aws_db_proxy.this.*.endpoint, [""]), 0) value = try(aws_db_proxy.this[0].endpoint, null)
} }
# Proxy Default Target Group ################################################################################
# Default Target Group
################################################################################
output "proxy_default_target_group_id" { output "proxy_default_target_group_id" {
description = "The ID for the default target group" description = "The ID for the default target group"
value = element(concat(aws_db_proxy_default_target_group.this.*.id, [""]), 0) value = try(aws_db_proxy_default_target_group.this[0].id, null)
} }
output "proxy_default_target_group_arn" { output "proxy_default_target_group_arn" {
description = "The Amazon Resource Name (ARN) for the default target group" description = "The Amazon Resource Name (ARN) for the default target group"
value = element(concat(aws_db_proxy_default_target_group.this.*.arn, [""]), 0) value = try(aws_db_proxy_default_target_group.this[0].arn, null)
} }
output "proxy_default_target_group_name" { output "proxy_default_target_group_name" {
description = "The name of the default target group" description = "The name of the default target group"
value = element(concat(aws_db_proxy_default_target_group.this.*.name, [""]), 0) value = try(aws_db_proxy_default_target_group.this[0].name, null)
} }
# Proxy Target ################################################################################
# Target(s)
################################################################################
output "proxy_target_endpoint" { output "proxy_target_endpoint" {
description = "Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type" description = "Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type"
value = element(concat(aws_db_proxy_target.db_instance.*.endpoint, aws_db_proxy_target.db_cluster.*.endpoint, [""]), 0) value = try(aws_db_proxy_target.db_instance[0].endpoint, aws_db_proxy_target.db_cluster[0].endpoint, null)
} }
output "proxy_target_id" { output "proxy_target_id" {
description = "Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/)" description = "Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/)"
value = element(concat(aws_db_proxy_target.db_instance.*.id, aws_db_proxy_target.db_cluster.*.id, [""]), 0) value = try(aws_db_proxy_target.db_instance[0].id, aws_db_proxy_target.db_cluster[0].id, null)
} }
output "proxy_target_port" { output "proxy_target_port" {
description = "Port for the target RDS DB Instance or Aurora DB Cluster" description = "Port for the target RDS DB Instance or Aurora DB Cluster"
value = element(concat(aws_db_proxy_target.db_instance.*.port, aws_db_proxy_target.db_cluster.*.port, [""]), 0) value = try(aws_db_proxy_target.db_instance[0].port, aws_db_proxy_target.db_cluster[0].port, null)
} }
output "proxy_target_rds_resource_id" { output "proxy_target_rds_resource_id" {
description = "Identifier representing the DB Instance or DB Cluster target" description = "Identifier representing the DB Instance or DB Cluster target"
value = element(concat(aws_db_proxy_target.db_instance.*.rds_resource_id, aws_db_proxy_target.db_cluster.*.rds_resource_id, [""]), 0) value = try(aws_db_proxy_target.db_instance[0].rds_resource_id, aws_db_proxy_target.db_cluster[0].rds_resource_id, null)
} }
output "proxy_target_target_arn" { output "proxy_target_target_arn" {
description = "Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API" description = "Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API"
value = element(concat(aws_db_proxy_target.db_instance.*.target_arn, aws_db_proxy_target.db_cluster.*.target_arn, [""]), 0) value = try(aws_db_proxy_target.db_instance[0].target_arn, aws_db_proxy_target.db_cluster[0].target_arn, null)
} }
output "proxy_target_tracked_cluster_id" { output "proxy_target_tracked_cluster_id" {
description = "DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS_INSTANCE target that is part of a DB Cluster" description = "DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS_INSTANCE target that is part of a DB Cluster"
value = element(concat(aws_db_proxy_target.db_cluster.*.tracked_cluster_id, [""]), 0) value = try(aws_db_proxy_target.db_cluster[0].tracked_cluster_id, null)
} }
output "proxy_target_type" { output "proxy_target_type" {
description = "Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`" description = "Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`"
value = element(concat(aws_db_proxy_target.db_instance.*.type, aws_db_proxy_target.db_cluster.*.type, [""]), 0) value = try(aws_db_proxy_target.db_instance[0].type, aws_db_proxy_target.db_cluster[0].type, null)
} }
# CloudWatch logs ################################################################################
# Endpoint(s)
################################################################################
output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = aws_db_proxy_endpoint.this
}
################################################################################
# CloudWatch Log Group
################################################################################
output "log_group_arn" { output "log_group_arn" {
description = "The Amazon Resource Name (ARN) of the CloudWatch log group" description = "The Amazon Resource Name (ARN) of the CloudWatch log group"
value = element(concat(aws_cloudwatch_log_group.this.*.arn, [""]), 0) value = try(aws_cloudwatch_log_group.this[0].arn, null)
}
output "log_group_name" {
description = "The name of the CloudWatch log group"
value = try(aws_cloudwatch_log_group.this[0].name, null)
}
################################################################################
# IAM Role
################################################################################
output "iam_role_arn" {
description = "The Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager."
value = try(aws_iam_role.this[0].arn, null)
}
output "iam_role_name" {
description = "IAM role name"
value = try(aws_iam_role.this[0].name, null)
}
output "iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = try(aws_iam_role.this[0].unique_id, null)
} }

View file

@ -1,15 +1,24 @@
variable "create" {
description = "Whether cluster should be created (affects nearly all resources)"
type = bool
default = true
}
variable "region" {
description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration"
type = string
default = null
}
variable "tags" { variable "tags" {
description = "A map of tags to use on all resources" description = "A map of tags to add to all resources"
type = map(string) type = map(string)
default = {} default = {}
} }
################################################################################
# RDS Proxy # RDS Proxy
variable "create_proxy" { ################################################################################
description = "Determines whether a proxy and its resources will be created"
type = bool
default = true
}
variable "name" { variable "name" {
description = "The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens" description = "The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens"
@ -19,8 +28,19 @@ variable "name" {
variable "auth" { variable "auth" {
description = "Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters" description = "Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters"
type = map(string) type = map(object({
default = {} auth_scheme = optional(string)
client_password_auth_type = optional(string)
description = optional(string)
iam_auth = optional(string)
secret_arn = optional(string)
username = optional(string)
}))
default = {
default = {
auth_scheme = "SECRETS"
}
}
} }
variable "debug_logging" { variable "debug_logging" {
@ -29,6 +49,12 @@ variable "debug_logging" {
default = false default = false
} }
variable "default_auth_scheme" {
description = "Default authentication scheme that the proxy uses for client connections to the proxy and connections from the proxy to the underlying database. Valid values are NONE and IAM_AUTH. Defaults to NONE"
type = string
default = null
}
variable "engine_family" { variable "engine_family" {
description = "The kind of database engine that the proxy will connect to. Valid values are `MYSQL` or `POSTGRESQL`" description = "The kind of database engine that the proxy will connect to. Valid values are `MYSQL` or `POSTGRESQL`"
type = string type = string
@ -65,43 +91,16 @@ variable "vpc_subnet_ids" {
default = [] default = []
} }
variable "auth_scheme" {
description = "The type of authentication that the proxy uses for connections from the proxy to the underlying database. One of `SECRETS`"
type = string
default = "SECRETS"
}
variable "iam_auth" {
description = "Whether to require or disallow AWS Identity and Access Management (IAM) authentication for connections to the proxy. One of `DISABLED`, `REQUIRED`"
type = string
default = "REQUIRED"
}
variable "proxy_tags" { variable "proxy_tags" {
description = "A map of tags to apply to the RDS Proxy" description = "A map of tags to apply to the RDS Proxy"
type = map(string) type = map(string)
default = {} default = {}
} }
variable "secrets" { ################################################################################
description = "Map of secerets to be used by RDS Proxy for authentication to the database" # Default Target Group
type = map(object({ arn = string, description = string, kms_key_id = string })) ################################################################################
default = {}
}
variable "db_host" {
description = "The identifier to use for the database endpoint"
type = string
default = ""
}
variable "db_name" {
description = "The name of the database"
type = string
default = ""
}
# Proxy Default Target Group
variable "connection_borrow_timeout" { variable "connection_borrow_timeout" {
description = "The number of seconds for a proxy to wait for a connection to become available in the connection pool" description = "The number of seconds for a proxy to wait for a connection to become available in the connection pool"
type = number type = number
@ -132,9 +131,12 @@ variable "session_pinning_filters" {
default = [] default = []
} }
# Proxy Target ################################################################################
# Target(s)
################################################################################
variable "target_db_instance" { variable "target_db_instance" {
description = "Determines whether DB instance is targetted by proxy" description = "Determines whether DB instance is targeted by proxy"
type = bool type = bool
default = false default = false
} }
@ -146,7 +148,7 @@ variable "db_instance_identifier" {
} }
variable "target_db_cluster" { variable "target_db_cluster" {
description = "Determines whether DB cluster is targetted by proxy" description = "Determines whether DB cluster is targeted by proxy"
type = bool type = bool
default = false default = false
} }
@ -157,7 +159,26 @@ variable "db_cluster_identifier" {
default = "" default = ""
} }
################################################################################
# Endpoint(s)
################################################################################
variable "endpoints" {
description = "Map of DB proxy endpoints to create and their attributes"
type = map(object({
name = optional(string)
vpc_subnet_ids = list(string)
vpc_security_group_ids = optional(list(string))
target_role = optional(string)
tags = optional(map(string), {})
}))
default = {}
}
################################################################################
# CloudWatch Logs # CloudWatch Logs
################################################################################
variable "manage_log_group" { variable "manage_log_group" {
description = "Determines whether Terraform will create/manage the CloudWatch log group or not. Note - this will fail if set to true after the log group has been created as the resource will already exist" description = "Determines whether Terraform will create/manage the CloudWatch log group or not. Note - this will fail if set to true after the log group has been created as the resource will already exist"
type = bool type = bool
@ -176,13 +197,22 @@ variable "log_group_kms_key_id" {
default = null default = null
} }
variable "log_group_class" {
description = "Specified the log class of the log group. Possible values are: `STANDARD` or `INFREQUENT_ACCESS`"
type = string
default = null
}
variable "log_group_tags" { variable "log_group_tags" {
description = "A map of tags to apply to the CloudWatch log group" description = "A map of tags to apply to the CloudWatch log group"
type = map(string) type = map(string)
default = {} default = {}
} }
################################################################################
# IAM Role # IAM Role
################################################################################
variable "create_iam_role" { variable "create_iam_role" {
description = "Determines whether an IAM role is created" description = "Determines whether an IAM role is created"
type = bool type = bool
@ -237,7 +267,10 @@ variable "iam_role_tags" {
default = {} default = {}
} }
# IAM Policy ################################################################################
# IAM Role Policy
################################################################################
variable "create_iam_policy" { variable "create_iam_policy" {
description = "Determines whether an IAM policy is created" description = "Determines whether an IAM policy is created"
type = bool type = bool
@ -256,8 +289,8 @@ variable "use_policy_name_prefix" {
default = false default = false
} }
variable "iam_creation_wait_duration" { variable "kms_key_arns" {
description = "Time duration delay to wait for IAM resource creation/propagation. For example, 30s for 30 seconds or 5m for 5 minutes. Updating this value by itself will not trigger a delay." description = "List of KMS Key ARNs to allow access to decrypt SecretsManager secrets"
type = string type = list(string)
default = "30s" default = []
} }

View file

@ -1,7 +1,10 @@
terraform { terraform {
required_version = ">= 0.12.26" required_version = ">= 1.5.7"
required_providers { required_providers {
aws = ">= 3.9" aws = {
source = "hashicorp/aws"
version = ">= 6.15"
}
} }
} }

100
wrappers/README.md Normal file
View file

@ -0,0 +1,100 @@
# Wrapper for the root module
The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
This wrapper does not implement any extra functionality.
## Usage with Terragrunt
`terragrunt.hcl`:
```hcl
terraform {
source = "tfr:///terraform-aws-modules/rds-proxy/aws//wrappers"
# Alternative source:
# source = "git::git@github.com:terraform-aws-modules/terraform-aws-rds-proxy.git//wrappers?ref=master"
}
inputs = {
defaults = { # Default values
create = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
items = {
my-item = {
# omitted... can be any argument supported by the module
}
my-second-item = {
# omitted... can be any argument supported by the module
}
# omitted...
}
}
```
## Usage with Terraform
```hcl
module "wrapper" {
source = "terraform-aws-modules/rds-proxy/aws//wrappers"
defaults = { # Default values
create = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
items = {
my-item = {
# omitted... can be any argument supported by the module
}
my-second-item = {
# omitted... can be any argument supported by the module
}
# omitted...
}
}
```
## Example: Manage multiple S3 buckets in one Terragrunt layer
`eu-west-1/s3-buckets/terragrunt.hcl`:
```hcl
terraform {
source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
# Alternative source:
# source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
}
inputs = {
defaults = {
force_destroy = true
attach_elb_log_delivery_policy = true
attach_lb_log_delivery_policy = true
attach_deny_insecure_transport_policy = true
attach_require_latest_tls_policy = true
}
items = {
bucket1 = {
bucket = "my-random-bucket-1"
}
bucket2 = {
bucket = "my-random-bucket-2"
tags = {
Secure = "probably"
}
}
}
}
```

52
wrappers/main.tf Normal file
View file

@ -0,0 +1,52 @@
module "wrapper" {
source = "../"
for_each = var.items
auth = try(each.value.auth, var.defaults.auth, {
default = {
auth_scheme = "SECRETS"
}
})
connection_borrow_timeout = try(each.value.connection_borrow_timeout, var.defaults.connection_borrow_timeout, null)
create = try(each.value.create, var.defaults.create, true)
create_iam_policy = try(each.value.create_iam_policy, var.defaults.create_iam_policy, true)
create_iam_role = try(each.value.create_iam_role, var.defaults.create_iam_role, true)
db_cluster_identifier = try(each.value.db_cluster_identifier, var.defaults.db_cluster_identifier, "")
db_instance_identifier = try(each.value.db_instance_identifier, var.defaults.db_instance_identifier, "")
debug_logging = try(each.value.debug_logging, var.defaults.debug_logging, false)
default_auth_scheme = try(each.value.default_auth_scheme, var.defaults.default_auth_scheme, null)
endpoints = try(each.value.endpoints, var.defaults.endpoints, {})
engine_family = try(each.value.engine_family, var.defaults.engine_family, "")
iam_policy_name = try(each.value.iam_policy_name, var.defaults.iam_policy_name, "")
iam_role_description = try(each.value.iam_role_description, var.defaults.iam_role_description, "")
iam_role_force_detach_policies = try(each.value.iam_role_force_detach_policies, var.defaults.iam_role_force_detach_policies, true)
iam_role_max_session_duration = try(each.value.iam_role_max_session_duration, var.defaults.iam_role_max_session_duration, 43200)
iam_role_name = try(each.value.iam_role_name, var.defaults.iam_role_name, "")
iam_role_path = try(each.value.iam_role_path, var.defaults.iam_role_path, null)
iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.defaults.iam_role_permissions_boundary, null)
iam_role_tags = try(each.value.iam_role_tags, var.defaults.iam_role_tags, {})
idle_client_timeout = try(each.value.idle_client_timeout, var.defaults.idle_client_timeout, 1800)
init_query = try(each.value.init_query, var.defaults.init_query, "")
kms_key_arns = try(each.value.kms_key_arns, var.defaults.kms_key_arns, [])
log_group_class = try(each.value.log_group_class, var.defaults.log_group_class, null)
log_group_kms_key_id = try(each.value.log_group_kms_key_id, var.defaults.log_group_kms_key_id, null)
log_group_retention_in_days = try(each.value.log_group_retention_in_days, var.defaults.log_group_retention_in_days, 30)
log_group_tags = try(each.value.log_group_tags, var.defaults.log_group_tags, {})
manage_log_group = try(each.value.manage_log_group, var.defaults.manage_log_group, true)
max_connections_percent = try(each.value.max_connections_percent, var.defaults.max_connections_percent, 90)
max_idle_connections_percent = try(each.value.max_idle_connections_percent, var.defaults.max_idle_connections_percent, 50)
name = try(each.value.name, var.defaults.name, "")
proxy_tags = try(each.value.proxy_tags, var.defaults.proxy_tags, {})
region = try(each.value.region, var.defaults.region, null)
require_tls = try(each.value.require_tls, var.defaults.require_tls, true)
role_arn = try(each.value.role_arn, var.defaults.role_arn, "")
session_pinning_filters = try(each.value.session_pinning_filters, var.defaults.session_pinning_filters, [])
tags = try(each.value.tags, var.defaults.tags, {})
target_db_cluster = try(each.value.target_db_cluster, var.defaults.target_db_cluster, false)
target_db_instance = try(each.value.target_db_instance, var.defaults.target_db_instance, false)
use_policy_name_prefix = try(each.value.use_policy_name_prefix, var.defaults.use_policy_name_prefix, false)
use_role_name_prefix = try(each.value.use_role_name_prefix, var.defaults.use_role_name_prefix, false)
vpc_security_group_ids = try(each.value.vpc_security_group_ids, var.defaults.vpc_security_group_ids, [])
vpc_subnet_ids = try(each.value.vpc_subnet_ids, var.defaults.vpc_subnet_ids, [])
}

5
wrappers/outputs.tf Normal file
View file

@ -0,0 +1,5 @@
output "wrapper" {
description = "Map of outputs of a wrapper."
value = module.wrapper
# sensitive = false # No sensitive module output found
}

11
wrappers/variables.tf Normal file
View file

@ -0,0 +1,11 @@
variable "defaults" {
description = "Map of default values which will be used for each item."
type = any
default = {}
}
variable "items" {
description = "Maps of items to create a wrapper from. Values are passed through to the module."
type = any
default = {}
}

10
wrappers/versions.tf Normal file
View file

@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.5.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.15"
}
}
}