/terraform-aws-rdsinit

Monitors RDS DB creation events and then populates the database according to custom script

Primary LanguageHCLApache License 2.0Apache-2.0

terraform-aws-rdsinit

Build Status Latest Release GitHub tag (latest SemVer) Terraform Version Infrastructure Tests pre-commit checkov Infrastructure Tests

After https://gist.github.com/pat/7b61376981b40cfdbb1166734b8d184f

Automatic RDS initiator

This Terraform configuration allows running of a set of SQL commands on a new AWS RDS database instance that's operating within an AWS VPC.

The commands are executed via AWS Lambda functions - the first (rds_creation) operates outside the VPC and connects to the AWS API to determine credential information for the new database (endpoint, port, username, database). It then sends these details via SNS to another function operating within the VPC (rds_setup), which connects to the Postgres database and executes the SQL commands.

The initial notification comes via SNS from the RDS events (and there is the configuration within the Terraform file here to set up that subscription).

Please note:

  • There are variables with defaults defined - everything else should be pretty self-contained.automatic (though you should definitely read through all of the code to ensure you understand it before using it).
  • The internal Lambda function is expecting a Postgres database. This will need changing if you're going to use MySQL/Aurora/etc.
  • The internal Lambda function connects via SSL, and so requires a local copy of the AWS SSL Certificate file (which I have saved as rds-cert.pem within the rds_setup directory).
curl https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem -o ./rds_setup/rds-cert.pem
  • Build the lambdas

Each lambda function is stored within their respective folders (rds_creation, rds_setup), with their package.json for NPM to build.

Building:

npm install

These folders are automatically archived/zipped by Terraform.

This template uses:

  • Cloudwatch
  • S3
  • Lambda
  • SNS
  • IAM
  • aws-sdk
  • SPS
  • node

Usage

Set tags to allow tf to find VPC, Subnets and Security groups. Expects a Subnet called RDS to exist.

Requirements

Name Version
terraform >= 0.13
archive 2.0.0
aws 3.24.1
template 2.2.0

Providers

Name Version
archive 2.0.0
aws 3.24.1

Modules

No modules.

Resources

Name Type
aws_db_event_subscription.creation resource
aws_iam_role.rds_external_lambda resource
aws_iam_role.rds_internal_lambda resource
aws_iam_role_policy.rds_dump resource
aws_iam_role_policy.rds_external resource
aws_iam_role_policy.rds_internal resource
aws_iam_role_policy.rds_sps resource
aws_iam_role_policy_attachment.rds_lambda_vpc resource
aws_lambda_function.rds_creation resource
aws_lambda_function.rds_setup resource
aws_lambda_permission.rds_creation resource
aws_lambda_permission.rds_setup resource
aws_s3_bucket.postgres resource
aws_s3_bucket_object.stuff resource
aws_s3_bucket_public_access_block.access resource
aws_sns_topic.internal resource
aws_sns_topic.rds resource
aws_sns_topic_subscription.rds resource
aws_sns_topic_subscription.rds_internal resource
archive_file.rds_creation_zip data source
archive_file.rds_setup_zip data source
aws_caller_identity.current data source
aws_region.current data source
aws_security_group.rds data source
aws_subnet_ids.core data source
aws_vpcs.rds data source

Inputs

Name Description Type Default Required
common_tags To implement the common tags scheme map(any) {} no
db_password_path The path in the parameter store where your encrypted db password can be retrieved string "/rds/postgres/database/password" no
region AWS region string n/a yes
runtime n/a string "nodejs12.x" no
sg_tag The tag to find your security group for your RDS access, you will most likely need to change/supply this value set(string)
[
"RDS"
]
no
sse_algorithm (optional) describe your variable string "aws:kms" no
subnet_tag A Name tag to find your private subnets, you will most likely need to change/supply this value string "*private*" no
table_name The name of the database to create all objects in, probably want to/change supply this string "data" no
vpc_tag A Name tag to find your VPC, you will need to supply this value string "*Default*" no

Outputs

No outputs.

Policy

This is the policy required to build this project:

The Terraform resource required is:

resource "aws_iam_policy" "terraform_pike" {
  name_prefix = "terraform_pike"
  path        = "/"
  description = "Pike Autogenerated policy from IAC"

  policy = jsonencode({
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "SNS:CreateTopic",
                "SNS:DeleteTopic",
                "SNS:GetTopicAttributes",
                "SNS:ListTagsForResource",
                "SNS:SetTopicAttributes",
                "SNS:TagResource",
                "SNS:UnTagResource"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeAccountAttributes",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeVpcs"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "iam:AttachRolePolicy",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:DeleteRolePolicy",
                "iam:DetachRolePolicy",
                "iam:GetRole",
                "iam:GetRolePolicy",
                "iam:ListAttachedRolePolicies",
                "iam:ListInstanceProfilesForRole",
                "iam:ListRolePolicies",
                "iam:PassRole",
                "iam:PutRolePolicy",
                "iam:TagRole"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor3",
            "Effect": "Allow",
            "Action": [
                "lambda:AddPermission",
                "lambda:CreateFunction",
                "lambda:DeleteFunction",
                "lambda:GetFunction",
                "lambda:GetFunctionCodeSigningConfig",
                "lambda:GetPolicy",
                "lambda:ListVersionsByFunction",
                "lambda:RemovePermission",
                "lambda:TagResource",
                "lambda:UntagResource"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor4",
            "Effect": "Allow",
            "Action": [
                "s3:CreateBucket",
                "s3:DeleteBucket",
                "s3:DeleteObject",
                "s3:GetAccelerateConfiguration",
                "s3:GetBucketAcl",
                "s3:GetBucketCORS",
                "s3:GetBucketLogging",
                "s3:GetBucketObjectLockConfiguration",
                "s3:GetBucketPolicy",
                "s3:GetBucketPublicAccessBlock",
                "s3:GetBucketRequestPayment",
                "s3:GetBucketTagging",
                "s3:GetBucketVersioning",
                "s3:GetBucketWebsite",
                "s3:GetEncryptionConfiguration",
                "s3:GetLifecycleConfiguration",
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:GetObjectTagging",
                "s3:GetReplicationConfiguration",
                "s3:ListBucket",
                "s3:PutBucketPublicAccessBlock",
                "s3:PutObject"
            ],
            "Resource": "*"
        }
    ]
})
}

Replace invoke.sql with your own database script.

Help

Got a question?

File a GitHub issue.

Contributing

Bug Reports & Feature Requests

Please use the issue tracker to report any bugs or file feature requests.

Copyrights

Copyright 2021-2022 James Woolfenden

License

License

See LICENSE for full details.

Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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

https://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.

Contributors

James Woolfenden
pat
michele

James Woolfenden
Pat Allen
michele