From 59a9e88c0edd08be6ef77e1492c3c212d322c975 Mon Sep 17 00:00:00 2001 From: Cris Daniluk Date: Sat, 2 Mar 2024 19:41:45 -0500 Subject: [PATCH 1/5] initial commit --- .github/CODEOWNERS | 1 + .github/workflows/misspell.yaml | 23 ++++ .github/workflows/pre-commit.yaml | 30 +++++ .github/workflows/pullRequest.yaml | 81 +++++++++++ .github/workflows/tflint.yaml | 27 ++++ .github/workflows/tfsec.yaml | 26 ++++ .github/workflows/yamllint.yaml | 22 +++ .gitignore | 17 +++ .pre-commit-config.yaml | 50 +++++++ .terraform-version | 1 + .tflint.hcl | 44 ++++++ .yamllint.yml | 2 + README.md | 91 +++++++++++++ bin/install-macos.sh | 17 +++ bin/install-ubuntu.sh | 32 +++++ examples/basic/README.md | 58 ++++++++ examples/basic/main.tf | 10 ++ main.tf | 66 +++++++++ outputs.tf | 0 variables.tf | 209 +++++++++++++++++++++++++++++ versions.tf | 10 ++ 21 files changed, 817 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/misspell.yaml create mode 100644 .github/workflows/pre-commit.yaml create mode 100644 .github/workflows/pullRequest.yaml create mode 100644 .github/workflows/tflint.yaml create mode 100644 .github/workflows/tfsec.yaml create mode 100644 .github/workflows/yamllint.yaml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .terraform-version create mode 100644 .tflint.hcl create mode 100644 .yamllint.yml create mode 100644 README.md create mode 100755 bin/install-macos.sh create mode 100755 bin/install-ubuntu.sh create mode 100644 examples/basic/README.md create mode 100644 examples/basic/main.tf create mode 100644 main.tf create mode 100644 outputs.tf create mode 100644 variables.tf create mode 100644 versions.tf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..f67eda9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @rhythmictech/engineering diff --git a/.github/workflows/misspell.yaml b/.github/workflows/misspell.yaml new file mode 100644 index 0000000..6574e3d --- /dev/null +++ b/.github/workflows/misspell.yaml @@ -0,0 +1,23 @@ +--- +name: misspell +on: + push: + branches: + - main + - master + - prod + - develop + +jobs: + misspell: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: misspell + uses: reviewdog/action-misspell@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + locale: "US" + reporter: github-check + filter_mode: nofilter + level: error diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000..398767c --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,30 @@ +--- +name: pre-commit-check +on: + push: + branches: + - master + - prod + - develop + +jobs: + pre-commit-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh + - name: initialize Terraform + run: terraform init --backend=false + - name: pre-commit + uses: pre-commit/action@v2.0.3 + env: + AWS_DEFAULT_REGION: us-east-1 + # many of these are covered by better reviewdog linters below + SKIP: >- + terraform_tflint_deep, + no-commit-to-branch, + terraform_tflint_nocreds, + terraform_tfsec diff --git a/.github/workflows/pullRequest.yaml b/.github/workflows/pullRequest.yaml new file mode 100644 index 0000000..8f1eba5 --- /dev/null +++ b/.github/workflows/pullRequest.yaml @@ -0,0 +1,81 @@ +--- +name: pull request +on: + pull_request: + +jobs: + # TODO: #22 add job using https://github.com/reviewdog/action-alex + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh + - name: initialize Terraform + run: terraform init --backend=false + - name: pre-commit + uses: pre-commit/action@v2.0.3 + env: + AWS_DEFAULT_REGION: us-east-1 + # many of these are covered by better reviewdog linters below + SKIP: >- + terraform_tflint_deep, + no-commit-to-branch, + terraform_tflint_nocreds, + terraform_tfsec + tflint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh + - name: Terraform init + run: terraform init --backend=false + - name: tflint + uses: reviewdog/action-tflint@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-pr-check + filter_mode: added + flags: --module + level: error + tfsec: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh + - name: Terraform init + run: terraform init --backend=false + - name: tfsec + uses: reviewdog/action-tfsec@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-pr-check + filter_mode: added + level: warning + misspell: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: misspell + uses: reviewdog/action-misspell@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + locale: "US" + reporter: github-pr-check + filter_mode: added + level: error + yamllint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: yamllint + uses: reviewdog/action-yamllint@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-pr-check + filter_mode: added + level: error diff --git a/.github/workflows/tflint.yaml b/.github/workflows/tflint.yaml new file mode 100644 index 0000000..10457b5 --- /dev/null +++ b/.github/workflows/tflint.yaml @@ -0,0 +1,27 @@ +--- +name: tflint +on: + push: + branches: + - main + - master + - prod + - develop + +jobs: + tflint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh + - name: Terraform init + run: terraform init --backend=false + - name: tflint + uses: reviewdog/action-tflint@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-check + filter_mode: nofilter + flags: --module + level: error diff --git a/.github/workflows/tfsec.yaml b/.github/workflows/tfsec.yaml new file mode 100644 index 0000000..2f75a3e --- /dev/null +++ b/.github/workflows/tfsec.yaml @@ -0,0 +1,26 @@ +--- +name: tfsec +on: + push: + branches: + - main + - master + - prod + - develop + +jobs: + tfsec: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh + - name: Terraform init + run: terraform init --backend=false + - name: tfsec + uses: reviewdog/action-tfsec@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-check + filter_mode: nofilter + level: error diff --git a/.github/workflows/yamllint.yaml b/.github/workflows/yamllint.yaml new file mode 100644 index 0000000..0b6f93a --- /dev/null +++ b/.github/workflows/yamllint.yaml @@ -0,0 +1,22 @@ +--- +name: yamllint +on: + push: + branches: + - main + - master + - prod + - develop + +jobs: + yamllint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: yamllint + uses: reviewdog/action-yamllint@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-check + filter_mode: nofilter + level: error diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74c83e8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# .tfvars files +*.tfvars + +# macs +.DS_Store + +# temp folders +tmp + +.terraform.lock.hcl diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b18d80c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,50 @@ +exclude: ".terraform" +repos: + - repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.86.0 + hooks: + - id: terraform_docs + always_run: true + - id: terraform_fmt + - id: terraform_validate + args: + - --hook-config=--retry-once-with-cleanup=true + - id: terraform_tflint + alias: terraform_tflint_nocreds + name: terraform_tflint_nocreds + - id: terraform_trivy + - id: terraform_providers_lock + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-json + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + args: + - --unsafe + - id: detect-private-key + - id: end-of-file-fixer + - id: mixed-line-ending + args: + - --fix=lf + - id: no-commit-to-branch + args: + - --branch + - main + - --branch + - master + - --branch + - prod + - id: pretty-format-json + args: + - --autofix + - --top-keys=name,Name + - id: trailing-whitespace + args: + - --markdown-linebreak-ext=md + exclude: README.md +ci: + skip: [terraform_docs, terraform_fmt, terraform_tflint, terraform_tfsec, tflock] diff --git a/.terraform-version b/.terraform-version new file mode 100644 index 0000000..f1ce147 --- /dev/null +++ b/.terraform-version @@ -0,0 +1 @@ +latest:^1.5 diff --git a/.tflint.hcl b/.tflint.hcl new file mode 100644 index 0000000..854fb92 --- /dev/null +++ b/.tflint.hcl @@ -0,0 +1,44 @@ +config { + module = true +} + +rule "terraform_deprecated_interpolation" { + enabled = true +} + +rule "terraform_unused_declarations" { + enabled = true +} + +rule "terraform_comment_syntax" { + enabled = true +} + +rule "terraform_documented_outputs" { + enabled = true +} + +rule "terraform_documented_variables" { + enabled = true +} + +rule "terraform_typed_variables" { + enabled = true +} + +rule "terraform_module_pinned_source" { + enabled = true +} + +rule "terraform_naming_convention" { + enabled = true + format = "snake_case" +} + +rule "terraform_required_version" { + enabled = false +} + +rule "terraform_required_providers" { + enabled = true +} diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 0000000..e1a518a --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,2 @@ +truthy: + check-keys: false diff --git a/README.md b/README.md new file mode 100644 index 0000000..f35c82d --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +# terraform-aws-rhythmic-account-monitor +Configures AWS health and account related notifications + +[![tflint](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/tflint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Atflint+event%3Apush+branch%3Amaster) +[![tfsec](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/tfsec/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Atfsec+event%3Apush+branch%3Amaster) +[![yamllint](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/yamllint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Ayamllint+event%3Apush+branch%3Amaster) +[![misspell](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/misspell/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Amisspell+event%3Apush+branch%3Amaster) +[![pre-commit-check](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/pre-commit-check/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Apre-commit-check+event%3Apush+branch%3Amaster) +follow on Twitter + +## Example +Here's what using the module will look like +```hcl +module "example" { + source = "rhythmictech/terraform-aws-rhythmic-cost-monitor + datadog_api_key_secret_arn = "" +} +``` + +## About +A bit about this module + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.5 | +| [aws](#requirement\_aws) | >= 4.62 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.36.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [tags](#module\_tags) | rhythmictech/tags/terraform | ~> 1.1.1 | + +## Resources + +| Name | Type | +|------|------| +| [aws_sns_topic.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | +| [aws_sns_topic_policy.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource | +| [aws_sns_topic_subscription.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [aws_secretsmanager_secret.datadog_api_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/secretsmanager_secret) | data source | +| [aws_secretsmanager_secret_version.datadog_api_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/secretsmanager_secret_version) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [anomaly\_total\_impact\_absolute\_threshold](#input\_anomaly\_total\_impact\_absolute\_threshold) | Minimum dollar threshold | `number` | `100` | no | +| [anomaly\_total\_impact\_percentage\_threshold](#input\_anomaly\_total\_impact\_percentage\_threshold) | Percentage threshold | `number` | `10` | no | +| [aws\_service\_shorthand\_map](#input\_aws\_service\_shorthand\_map) | Map of shorthand notation for AWS services to their long form AWS services in cost and usage reporting, sorted alphabetically with lowercase keys | `map(string)` |
{
"apiGateway": "Amazon API Gateway",
"appFlow": "Amazon AppFlow",
"appRunner": "AWS App Runner",
"appSync": "AWS AppSync",
"athena": "Amazon Athena",
"backup": "AWS Backup",
"braket": "Amazon Braket",
"chime": "Amazon Chime",
"cloudFront": "Amazon CloudFront",
"cloudWatch": "Amazon CloudWatch",
"codeArtifact": "AWS CodeArtifact",
"codeBuild": "AWS CodeBuild",
"codeCommit": "AWS CodeCommit",
"codeDeploy": "AWS CodeDeploy",
"codePipeline": "AWS CodePipeline",
"codeStar": "AWS CodeStar",
"comprehend": "Amazon Comprehend",
"connect": "Amazon Connect",
"dataPipeline": "AWS Data Pipeline",
"datadog": "Datadog",
"deepComposer": "AWS DeepComposer",
"deepLens": "AWS DeepLens",
"deepRacer": "AWS DeepRacer",
"detective": "Amazon Detective",
"directConnect": "AWS Direct Connect",
"dms": "AWS Database Migration Service",
"documentDB": "Amazon DocumentDB",
"dynamodb": "Amazon DynamoDB",
"ec2": "Amazon Elastic Compute Cloud - Compute",
"ecs": "Amazon Elastic Container Service",
"efs": "Amazon Elastic File System",
"eks": "Amazon Elastic Kubernetes Service",
"elasticache": "Amazon ElastiCache",
"emr": "Amazon Elastic MapReduce",
"es": "Amazon Elasticsearch Service",
"fargate": "AWS Fargate",
"forecast": "Amazon Forecast",
"fsx": "Amazon FSx",
"gameLift": "Amazon GameLift",
"glue": "AWS Glue",
"greengrass": "AWS Greengrass",
"guardDuty": "Amazon GuardDuty",
"healthLake": "Amazon HealthLake",
"honeycode": "Amazon Honeycode",
"iam": "AWS Identity and Access Management",
"inspector": "Amazon Inspector",
"iot1Click": "AWS IoT 1-Click",
"iotAnalytics": "AWS IoT Analytics",
"iotButton": "AWS IoT Button",
"iotCore": "AWS IoT Core",
"iotDeviceManagement": "AWS IoT Device Management",
"iotEvents": "AWS IoT Events",
"iotSiteWise": "AWS IoT SiteWise",
"iotThingsGraph": "AWS IoT Things Graph",
"ivs": "Amazon Interactive Video Service",
"kendra": "Amazon Kendra",
"kinesis": "Amazon Kinesis",
"kms": "AWS Key Management Service",
"lambda": "AWS Lambda",
"lex": "Amazon Lex",
"lightsail": "Amazon Lightsail",
"lookoutForVision": "Amazon Lookout for Vision",
"lumberyard": "Amazon Lumberyard",
"macie": "Amazon Macie",
"managedBlockchain": "Amazon Managed Blockchain",
"mq": "Amazon MQ",
"msk": "Amazon Managed Streaming for Apache Kafka",
"neptune": "Amazon Neptune",
"opensearch": "Amazon OpenSearch Service",
"outposts": "AWS Outposts",
"pinpoint": "Amazon Pinpoint",
"polly": "Amazon Polly",
"qldb": "Amazon Quantum Ledger Database",
"qls": "AWS Quantum Ledger Service",
"quicksight": "Amazon QuickSight",
"rds": "Amazon Relational Database Service",
"redshift": "Amazon Redshift",
"rekognition": "Amazon Rekognition",
"robomaker": "AWS RoboMaker",
"route53": "Amazon Route 53",
"s3": "Amazon Simple Storage Service",
"s3Outposts": "Amazon S3 on Outposts",
"sagemaker": "Amazon SageMaker",
"ses": "Amazon Simple Email Service",
"sesv2": "Amazon Simple Email Service v2",
"shield": "AWS Shield",
"snowball": "AWS Snowball",
"sns": "Amazon Simple Notification Service",
"sqs": "Amazon Simple Queue Service",
"stepFunctions": "AWS Step Functions",
"storageGateway": "AWS Storage Gateway",
"sumerian": "Amazon Sumerian",
"swf": "Amazon Simple Workflow Service",
"textract": "Amazon Textract",
"timestream": "Amazon Timestream",
"transcribe": "Amazon Transcribe",
"transcribeMedical": "Amazon Transcribe Medical",
"transfer": "AWS Transfer for SFTP",
"translate": "Amazon Translate",
"vpn": "AWS VPN",
"waf": "AWS WAF",
"wellArchitectedTool": "AWS Well-Architected Tool",
"workDocs": "Amazon WorkDocs",
"workLink": "Amazon WorkLink",
"workMail": "Amazon WorkMail",
"workSpaces": "Amazon WorkSpaces",
"xRay": "AWS X-Ray",
"zocalo": "Amazon Zocalo"
}
| no | +| [cur\_forwarding\_bucket\_arn](#input\_cur\_forwarding\_bucket\_arn) | S3 bucket ARN where CUR data will be forwarded | `string` | `null` | no | +| [datadog\_api\_key\_secret\_arn](#input\_datadog\_api\_key\_secret\_arn) | ARN of the AWS Secret containing the Datadog API key | `string` | n/a | yes | +| [enable\_cur\_collection](#input\_enable\_cur\_collection) | Enable Cost and Usage Report collection. Be mindful of existing CUR collection processes before enabling. | `bool` | `false` | no | +| [enable\_cur\_forwarding](#input\_enable\_cur\_forwarding) | Enable Cost and Usage Report forwarding. Do not enable unless `enable_cur_collection` is also enabled. | `bool` | `false` | no | +| [enable\_datadog\_cost\_management](#input\_enable\_datadog\_cost\_management) | Enable Datadog cost management | `bool` | `false` | no | +| [monitor\_ri\_utilization](#input\_monitor\_ri\_utilization) | Enable monitoring of Reserverd Instances Utilization | `bool` | `false` | no | +| [monitor\_sp\_utilization](#input\_monitor\_sp\_utilization) | Enable monitoring of Savings Plan Utilization | `bool` | `false` | no | +| [ri\_utilization\_services](#input\_ri\_utilization\_services) | List of services for Reserved Instance utilization monitoring | `list(string)` |
[
"ec2",
"elasticache",
"es",
"opensearch",
"rds",
"redshift"
]
| no | +| [service\_budgets](#input\_service\_budgets) | Map of service budgets |
map(object({
time_unit : string
limit_amount : string
limit_unit : string
threshold : number
threshold_type : string
notification_type : string
}))
|
{
"ec2": {
"limit_amount": "5",
"limit_unit": "USD",
"notification_type": "ACTUAL",
"threshold": 90,
"threshold_type": "PERCENTAGE",
"time_unit": "MONTHLY"
}
}
| no | +| [tags](#input\_tags) | User-Defined tags | `map(string)` | `{}` | no | + +## Outputs + +No outputs. + + +## Getting Started +This workflow has a few prerequisites which are installed through the `./bin/install-x.sh` scripts and are linked below. The install script will also work on your local machine. + +- [pre-commit](https://pre-commit.com) +- [terraform](https://terraform.io) +- [tfenv](https://github.com/tfutils/tfenv) +- [terraform-docs](https://github.com/segmentio/terraform-docs) +- [tfsec](https://github.com/tfsec/tfsec) +- [tflint](https://github.com/terraform-linters/tflint) + +We use `tfenv` to manage `terraform` versions, so the version is defined in the `versions.tf` and `tfenv` installs the latest compliant version. +`pre-commit` is like a package manager for scripts that integrate with git hooks. We use them to run the rest of the tools before apply. +`terraform-docs` creates the beautiful docs (above), `tfsec` scans for security no-nos, `tflint` scans for best practices. diff --git a/bin/install-macos.sh b/bin/install-macos.sh new file mode 100755 index 0000000..3800165 --- /dev/null +++ b/bin/install-macos.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo 'installing brew packages' +brew update +brew tap liamg/tfsec +brew install tfenv tflint terraform-docs pre-commit liamg/tfsec/tfsec coreutils +brew upgrade tfenv tflint terraform-docs pre-commit liamg/tfsec/tfsec coreutils + +echo 'installing pre-commit hooks' +pre-commit install + +echo 'setting pre-commit hooks to auto-install on clone in the future' +git config --global init.templateDir ~/.git-template +pre-commit init-templatedir ~/.git-template + +echo 'installing terraform with tfenv' +tfenv install diff --git a/bin/install-ubuntu.sh b/bin/install-ubuntu.sh new file mode 100755 index 0000000..670d0b9 --- /dev/null +++ b/bin/install-ubuntu.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +echo 'installing dependencies' +sudo apt install python3-pip gawk &&\ +pip3 install pre-commit + +# terraform docs +mkdir tmp +cd tmp +curl -Lo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-$(uname)-amd64.tar.gz +tar -xzf terraform-docs.tar.gz +chmod +x terraform-docs +sudo mv terraform-docs /usr/bin/ +cd .. +rm -rf tmp + +curl -L "$(curl -sL https://api.github.com/repos/terraform-linters/tflint/releases/latest | grep -o -E "https://.+?_linux_amd64.zip")" > tflint.zip && unzip tflint.zip && rm tflint.zip && sudo mv tflint /usr/bin/ +go install github.com/aquasecurity/tfsec/cmd/tfsec@latest +git clone https://github.com/tfutils/tfenv.git ~/.tfenv || true +mkdir -p ~/.local/bin/ +. ~/.profile +ln -s ~/.tfenv/bin/* ~/.local/bin + +echo 'installing pre-commit hooks' +pre-commit install + +echo 'setting pre-commit hooks to auto-install on clone in the future' +git config --global init.templateDir ~/.git-template +pre-commit init-templatedir ~/.git-template + +echo 'installing terraform with tfenv' +tfenv install diff --git a/examples/basic/README.md b/examples/basic/README.md new file mode 100644 index 0000000..fc4ffc2 --- /dev/null +++ b/examples/basic/README.md @@ -0,0 +1,58 @@ +# basic example +A basic example for this repository + +## Code +Look to [main.tf](./main.tf), or be helpful and copy/paste that code here. + +## Applying +``` +> terraform apply + +Apply complete! Resources: 0 added, 0 changed, 0 destroyed. + +Outputs: + +example = { + "tags_module" = { + "name" = "TEST" + "name32" = "TEST" + "name6" = "TEST" + "namenosymbols" = "TEST" + "tags" = { + "Name" = "TEST" + "terraform_managed" = true + "terraform_module" = "terraform-terraform-tags-1.0.0" + "terraform_root_module" = "." + "terraform_workspace" = "default" + } + "tags_as_list_of_maps" = [ + { + "key" = "Name" + "value" = "TEST" + }, + { + "key" = "terraform_managed" + "value" = true + }, + { + "key" = "terraform_module" + "value" = "terraform-terraform-tags-1.0.0" + }, + { + "key" = "terraform_root_module" + "value" = "." + }, + { + "key" = "terraform_workspace" + "value" = "default" + }, + ] + "tags_no_name" = { + "terraform_managed" = true + "terraform_module" = "terraform-terraform-tags-1.0.0" + "terraform_root_module" = "." + "terraform_workspace" = "default" + } + } +} +``` diff --git a/examples/basic/main.tf b/examples/basic/main.tf new file mode 100644 index 0000000..13ef2c1 --- /dev/null +++ b/examples/basic/main.tf @@ -0,0 +1,10 @@ + +module "example" { + source = "../.." + + name = "test" +} + +output "example" { + value = module.example +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..f9a5a67 --- /dev/null +++ b/main.tf @@ -0,0 +1,66 @@ +data "aws_caller_identity" "current" { +} + +data "aws_region" "current" { +} + + +module "tags" { + source = "rhythmictech/tags/terraform" + version = "~> 1.1.1" + + enforce_case = "UPPER" + names = ["Rhythmic-AccountMonitoring"] + tags = merge(var.tags, { + "team" = "Rhythmic" + "service" = "aws_managed_services" + }) +} + +locals { + account_id = data.aws_caller_identity.current.account_id + region = data.aws_region.current.name + tags = module.tags.tags_no_name +} + +resource "aws_sns_topic" "account_alerts" { + name = "Rhythmic-AccountAlerts" + kms_master_key_id = "alias/rhythmic-notifications" + tags = local.tags +} + +data "aws_iam_policy_document" "account_alerts" { + statement { + actions = [ + "sns:Publish" + ] + + principals { + type = "Service" + identifiers = ["events.amazonaws.com"] + } + + resources = [ + aws_sns_topic.account_alerts.arn + ] + } +} + +resource "aws_sns_topic_policy" "account_alerts" { + arn = aws_sns_topic.account_alerts.arn + policy = data.aws_iam_policy_document.account_alerts.json +} + +data "aws_secretsmanager_secret" "datadog_api_key" { + name = var.datadog_api_key_secret_arn +} + +data "aws_secretsmanager_secret_version" "datadog_api_key" { + secret_id = data.aws_secretsmanager_secret.datadog_api_key.id +} + +resource "aws_sns_topic_subscription" "account_alerts" { + topic_arn = aws_sns_topic.account_alerts.arn + protocol = "https" + endpoint = "https://app.datadoghq.com/intake/webhook/sns?api_key=${data.aws_secretsmanager_secret_version.datadog_api_key.secret_string}" +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..a0fe626 --- /dev/null +++ b/variables.tf @@ -0,0 +1,209 @@ +variable "tags" { + default = {} + description = "User-Defined tags" + type = map(string) +} + +variable "datadog_api_key_secret_arn" { + description = "ARN of the AWS Secret containing the Datadog API key" + type = string +} + +######################################## +# Anomaly Detection Vars +######################################## +variable "anomaly_total_impact_absolute_threshold" { + description = "Minimum dollar threshold" + type = number + default = 100 +} + +variable "anomaly_total_impact_percentage_threshold" { + description = "Percentage threshold" + type = number + default = 10 +} + +######################################## +# Budget Vars +######################################## +variable "monitor_ri_utilization" { + description = "Enable monitoring of Reserverd Instances Utilization" + type = bool + default = false +} + +variable "monitor_sp_utilization" { + description = "Enable monitoring of Savings Plan Utilization" + type = bool + default = false +} + +variable "ri_utilization_services" { + default = ["ec2", "elasticache", "es", "opensearch", "rds", "redshift"] + description = "List of services for Reserved Instance utilization monitoring" + type = list(string) +} + +variable "service_budgets" { + default = { + "ec2" = { + time_unit = "MONTHLY" + limit_amount = "5" # Adjust this value based on your budget + limit_unit = "USD" + threshold = 90 # Notify when spending exceeds 90% of the budget + threshold_type = "PERCENTAGE" + notification_type = "ACTUAL" + } + } + description = "Map of service budgets" + type = map(object({ + time_unit : string + limit_amount : string + limit_unit : string + threshold : number + threshold_type : string + notification_type : string + })) + +} + +variable "aws_service_shorthand_map" { + description = "Map of shorthand notation for AWS services to their long form AWS services in cost and usage reporting, sorted alphabetically with lowercase keys" + type = map(string) + default = { + "apiGateway" = "Amazon API Gateway", + "appFlow" = "Amazon AppFlow", + "appRunner" = "AWS App Runner", + "appSync" = "AWS AppSync", + "athena" = "Amazon Athena", + "backup" = "AWS Backup", + "braket" = "Amazon Braket", + "chime" = "Amazon Chime", + "cloudFront" = "Amazon CloudFront", + "cloudWatch" = "Amazon CloudWatch", + "codeArtifact" = "AWS CodeArtifact", + "codeBuild" = "AWS CodeBuild", + "codeCommit" = "AWS CodeCommit", + "codeDeploy" = "AWS CodeDeploy", + "codePipeline" = "AWS CodePipeline", + "codeStar" = "AWS CodeStar", + "comprehend" = "Amazon Comprehend", + "connect" = "Amazon Connect", + "dataPipeline" = "AWS Data Pipeline", + "datadog" = "Datadog", + "deepComposer" = "AWS DeepComposer", + "deepLens" = "AWS DeepLens", + "deepRacer" = "AWS DeepRacer", + "detective" = "Amazon Detective", + "directConnect" = "AWS Direct Connect", + "documentDB" = "Amazon DocumentDB", + "dms" = "AWS Database Migration Service", + "dynamodb" = "Amazon DynamoDB", + "ec2" = "Amazon Elastic Compute Cloud - Compute", + "ecs" = "Amazon Elastic Container Service", + "efs" = "Amazon Elastic File System", + "eks" = "Amazon Elastic Kubernetes Service", + "elasticache" = "Amazon ElastiCache", + "emr" = "Amazon Elastic MapReduce", + "es" = "Amazon Elasticsearch Service", + "fargate" = "AWS Fargate", + "forecast" = "Amazon Forecast", + "fsx" = "Amazon FSx", + "gameLift" = "Amazon GameLift", + "glue" = "AWS Glue", + "greengrass" = "AWS Greengrass", + "guardDuty" = "Amazon GuardDuty", + "healthLake" = "Amazon HealthLake", + "honeycode" = "Amazon Honeycode", + "iam" = "AWS Identity and Access Management", + "inspector" = "Amazon Inspector", + "iot1Click" = "AWS IoT 1-Click", + "iotAnalytics" = "AWS IoT Analytics", + "iotButton" = "AWS IoT Button", + "iotCore" = "AWS IoT Core", + "iotDeviceManagement" = "AWS IoT Device Management", + "iotEvents" = "AWS IoT Events", + "iotSiteWise" = "AWS IoT SiteWise", + "iotThingsGraph" = "AWS IoT Things Graph", + "ivs" = "Amazon Interactive Video Service", + "kendra" = "Amazon Kendra", + "kinesis" = "Amazon Kinesis", + "kms" = "AWS Key Management Service", + "lambda" = "AWS Lambda", + "lex" = "Amazon Lex", + "lightsail" = "Amazon Lightsail", + "lookoutForVision" = "Amazon Lookout for Vision", + "lumberyard" = "Amazon Lumberyard", + "macie" = "Amazon Macie", + "managedBlockchain" = "Amazon Managed Blockchain", + "mq" = "Amazon MQ", + "msk" = "Amazon Managed Streaming for Apache Kafka", + "neptune" = "Amazon Neptune", + "opensearch" = "Amazon OpenSearch Service", + "outposts" = "AWS Outposts", + "pinpoint" = "Amazon Pinpoint", + "polly" = "Amazon Polly", + "qldb" = "Amazon Quantum Ledger Database", + "qls" = "AWS Quantum Ledger Service", + "quicksight" = "Amazon QuickSight", + "rds" = "Amazon Relational Database Service", + "redshift" = "Amazon Redshift", + "rekognition" = "Amazon Rekognition", + "robomaker" = "AWS RoboMaker", + "route53" = "Amazon Route 53", + "s3" = "Amazon Simple Storage Service", + "s3Outposts" = "Amazon S3 on Outposts", + "sagemaker" = "Amazon SageMaker", + "ses" = "Amazon Simple Email Service", + "sesv2" = "Amazon Simple Email Service v2", + "shield" = "AWS Shield", + "sns" = "Amazon Simple Notification Service", + "snowball" = "AWS Snowball", + "sqs" = "Amazon Simple Queue Service", + "stepFunctions" = "AWS Step Functions", + "storageGateway" = "AWS Storage Gateway", + "sumerian" = "Amazon Sumerian", + "swf" = "Amazon Simple Workflow Service", + "textract" = "Amazon Textract", + "timestream" = "Amazon Timestream", + "transcribe" = "Amazon Transcribe", + "transcribeMedical" = "Amazon Transcribe Medical", + "translate" = "Amazon Translate", + "transfer" = "AWS Transfer for SFTP", + "vpn" = "AWS VPN", + "waf" = "AWS WAF", + "wellArchitectedTool" = "AWS Well-Architected Tool", + "workDocs" = "Amazon WorkDocs", + "workLink" = "Amazon WorkLink", + "workMail" = "Amazon WorkMail", + "workSpaces" = "Amazon WorkSpaces", + "xRay" = "AWS X-Ray", + "zocalo" = "Amazon Zocalo" + } +} + +# Cost and Usage aggregation vars +variable "enable_cur_forwarding" { + description = "Enable Cost and Usage Report forwarding. Do not enable unless `enable_cur_collection` is also enabled." + type = bool + default = false +} + +variable "enable_cur_collection" { + description = "Enable Cost and Usage Report collection. Be mindful of existing CUR collection processes before enabling." + type = bool + default = false +} + +variable "enable_datadog_cost_management" { + default = false + description = "Enable Datadog cost management" + type = bool +} + +variable "cur_forwarding_bucket_arn" { + default = null + description = "S3 bucket ARN where CUR data will be forwarded" + type = string +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..6647f80 --- /dev/null +++ b/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.62" + } + } +} From 9db3f975119f78774c7ca5e46e7d15198155494c Mon Sep 17 00:00:00 2001 From: Cris Daniluk Date: Sat, 2 Mar 2024 19:42:05 -0500 Subject: [PATCH 2/5] initial commit --- variables.tf | 198 --------------------------------------------------- 1 file changed, 198 deletions(-) diff --git a/variables.tf b/variables.tf index a0fe626..5aab86b 100644 --- a/variables.tf +++ b/variables.tf @@ -9,201 +9,3 @@ variable "datadog_api_key_secret_arn" { type = string } -######################################## -# Anomaly Detection Vars -######################################## -variable "anomaly_total_impact_absolute_threshold" { - description = "Minimum dollar threshold" - type = number - default = 100 -} - -variable "anomaly_total_impact_percentage_threshold" { - description = "Percentage threshold" - type = number - default = 10 -} - -######################################## -# Budget Vars -######################################## -variable "monitor_ri_utilization" { - description = "Enable monitoring of Reserverd Instances Utilization" - type = bool - default = false -} - -variable "monitor_sp_utilization" { - description = "Enable monitoring of Savings Plan Utilization" - type = bool - default = false -} - -variable "ri_utilization_services" { - default = ["ec2", "elasticache", "es", "opensearch", "rds", "redshift"] - description = "List of services for Reserved Instance utilization monitoring" - type = list(string) -} - -variable "service_budgets" { - default = { - "ec2" = { - time_unit = "MONTHLY" - limit_amount = "5" # Adjust this value based on your budget - limit_unit = "USD" - threshold = 90 # Notify when spending exceeds 90% of the budget - threshold_type = "PERCENTAGE" - notification_type = "ACTUAL" - } - } - description = "Map of service budgets" - type = map(object({ - time_unit : string - limit_amount : string - limit_unit : string - threshold : number - threshold_type : string - notification_type : string - })) - -} - -variable "aws_service_shorthand_map" { - description = "Map of shorthand notation for AWS services to their long form AWS services in cost and usage reporting, sorted alphabetically with lowercase keys" - type = map(string) - default = { - "apiGateway" = "Amazon API Gateway", - "appFlow" = "Amazon AppFlow", - "appRunner" = "AWS App Runner", - "appSync" = "AWS AppSync", - "athena" = "Amazon Athena", - "backup" = "AWS Backup", - "braket" = "Amazon Braket", - "chime" = "Amazon Chime", - "cloudFront" = "Amazon CloudFront", - "cloudWatch" = "Amazon CloudWatch", - "codeArtifact" = "AWS CodeArtifact", - "codeBuild" = "AWS CodeBuild", - "codeCommit" = "AWS CodeCommit", - "codeDeploy" = "AWS CodeDeploy", - "codePipeline" = "AWS CodePipeline", - "codeStar" = "AWS CodeStar", - "comprehend" = "Amazon Comprehend", - "connect" = "Amazon Connect", - "dataPipeline" = "AWS Data Pipeline", - "datadog" = "Datadog", - "deepComposer" = "AWS DeepComposer", - "deepLens" = "AWS DeepLens", - "deepRacer" = "AWS DeepRacer", - "detective" = "Amazon Detective", - "directConnect" = "AWS Direct Connect", - "documentDB" = "Amazon DocumentDB", - "dms" = "AWS Database Migration Service", - "dynamodb" = "Amazon DynamoDB", - "ec2" = "Amazon Elastic Compute Cloud - Compute", - "ecs" = "Amazon Elastic Container Service", - "efs" = "Amazon Elastic File System", - "eks" = "Amazon Elastic Kubernetes Service", - "elasticache" = "Amazon ElastiCache", - "emr" = "Amazon Elastic MapReduce", - "es" = "Amazon Elasticsearch Service", - "fargate" = "AWS Fargate", - "forecast" = "Amazon Forecast", - "fsx" = "Amazon FSx", - "gameLift" = "Amazon GameLift", - "glue" = "AWS Glue", - "greengrass" = "AWS Greengrass", - "guardDuty" = "Amazon GuardDuty", - "healthLake" = "Amazon HealthLake", - "honeycode" = "Amazon Honeycode", - "iam" = "AWS Identity and Access Management", - "inspector" = "Amazon Inspector", - "iot1Click" = "AWS IoT 1-Click", - "iotAnalytics" = "AWS IoT Analytics", - "iotButton" = "AWS IoT Button", - "iotCore" = "AWS IoT Core", - "iotDeviceManagement" = "AWS IoT Device Management", - "iotEvents" = "AWS IoT Events", - "iotSiteWise" = "AWS IoT SiteWise", - "iotThingsGraph" = "AWS IoT Things Graph", - "ivs" = "Amazon Interactive Video Service", - "kendra" = "Amazon Kendra", - "kinesis" = "Amazon Kinesis", - "kms" = "AWS Key Management Service", - "lambda" = "AWS Lambda", - "lex" = "Amazon Lex", - "lightsail" = "Amazon Lightsail", - "lookoutForVision" = "Amazon Lookout for Vision", - "lumberyard" = "Amazon Lumberyard", - "macie" = "Amazon Macie", - "managedBlockchain" = "Amazon Managed Blockchain", - "mq" = "Amazon MQ", - "msk" = "Amazon Managed Streaming for Apache Kafka", - "neptune" = "Amazon Neptune", - "opensearch" = "Amazon OpenSearch Service", - "outposts" = "AWS Outposts", - "pinpoint" = "Amazon Pinpoint", - "polly" = "Amazon Polly", - "qldb" = "Amazon Quantum Ledger Database", - "qls" = "AWS Quantum Ledger Service", - "quicksight" = "Amazon QuickSight", - "rds" = "Amazon Relational Database Service", - "redshift" = "Amazon Redshift", - "rekognition" = "Amazon Rekognition", - "robomaker" = "AWS RoboMaker", - "route53" = "Amazon Route 53", - "s3" = "Amazon Simple Storage Service", - "s3Outposts" = "Amazon S3 on Outposts", - "sagemaker" = "Amazon SageMaker", - "ses" = "Amazon Simple Email Service", - "sesv2" = "Amazon Simple Email Service v2", - "shield" = "AWS Shield", - "sns" = "Amazon Simple Notification Service", - "snowball" = "AWS Snowball", - "sqs" = "Amazon Simple Queue Service", - "stepFunctions" = "AWS Step Functions", - "storageGateway" = "AWS Storage Gateway", - "sumerian" = "Amazon Sumerian", - "swf" = "Amazon Simple Workflow Service", - "textract" = "Amazon Textract", - "timestream" = "Amazon Timestream", - "transcribe" = "Amazon Transcribe", - "transcribeMedical" = "Amazon Transcribe Medical", - "translate" = "Amazon Translate", - "transfer" = "AWS Transfer for SFTP", - "vpn" = "AWS VPN", - "waf" = "AWS WAF", - "wellArchitectedTool" = "AWS Well-Architected Tool", - "workDocs" = "Amazon WorkDocs", - "workLink" = "Amazon WorkLink", - "workMail" = "Amazon WorkMail", - "workSpaces" = "Amazon WorkSpaces", - "xRay" = "AWS X-Ray", - "zocalo" = "Amazon Zocalo" - } -} - -# Cost and Usage aggregation vars -variable "enable_cur_forwarding" { - description = "Enable Cost and Usage Report forwarding. Do not enable unless `enable_cur_collection` is also enabled." - type = bool - default = false -} - -variable "enable_cur_collection" { - description = "Enable Cost and Usage Report collection. Be mindful of existing CUR collection processes before enabling." - type = bool - default = false -} - -variable "enable_datadog_cost_management" { - default = false - description = "Enable Datadog cost management" - type = bool -} - -variable "cur_forwarding_bucket_arn" { - default = null - description = "S3 bucket ARN where CUR data will be forwarded" - type = string -} From bf099c614bafb1021a6ca50a833f488d4b7c6af1 Mon Sep 17 00:00:00 2001 From: Cris Daniluk Date: Sat, 9 Mar 2024 12:12:00 -0500 Subject: [PATCH 3/5] update checks and linting --- .pre-commit-config.yaml | 6 +++++- .tflint.hcl | 6 ++++++ README.md | 43 ++++++++++++++++++++++------------------- main.tf | 11 +---------- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b18d80c..898f6eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,8 @@ +# excluding a few checks because it isn't coping well with the hacky way we do the rds monitoring lambda exclude: ".terraform" repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.86.0 + rev: v1.88.0 hooks: - id: terraform_docs always_run: true @@ -9,10 +10,13 @@ repos: - id: terraform_validate args: - --hook-config=--retry-once-with-cleanup=true + exclude: examples\/ - id: terraform_tflint alias: terraform_tflint_nocreds name: terraform_tflint_nocreds - id: terraform_trivy + args: + - --args=--skip-dirs="**/.terraform,examples/*" - id: terraform_providers_lock - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 diff --git a/.tflint.hcl b/.tflint.hcl index 854fb92..5379e3b 100644 --- a/.tflint.hcl +++ b/.tflint.hcl @@ -2,6 +2,12 @@ config { module = true } +plugin "aws" { + enabled = true + version = "0.12.0" + source = "github.com/terraform-linters/tflint-ruleset-aws" +} + rule "terraform_deprecated_interpolation" { enabled = true } diff --git a/README.md b/README.md index f35c82d..4af743a 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,26 @@ # terraform-aws-rhythmic-account-monitor Configures AWS health and account related notifications -[![tflint](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/tflint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Atflint+event%3Apush+branch%3Amaster) -[![tfsec](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/tfsec/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Atfsec+event%3Apush+branch%3Amaster) -[![yamllint](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/yamllint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Ayamllint+event%3Apush+branch%3Amaster) -[![misspell](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/misspell/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Amisspell+event%3Apush+branch%3Amaster) -[![pre-commit-check](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/workflows/pre-commit-check/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-cost-monitor/actions?query=workflow%3Apre-commit-check+event%3Apush+branch%3Amaster) +[![tflint](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/workflows/tflint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/actions?query=workflow%3Atflint+event%3Apush+branch%3Amaster) +[![tfsec](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/workflows/tfsec/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/actions?query=workflow%3Atfsec+event%3Apush+branch%3Amaster) +[![yamllint](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/workflows/yamllint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/actions?query=workflow%3Ayamllint+event%3Apush+branch%3Amaster) +[![misspell](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/workflows/misspell/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/actions?query=workflow%3Amisspell+event%3Apush+branch%3Amaster) +[![pre-commit-check](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/workflows/pre-commit-check/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-rhythmic-account-monitor/actions?query=workflow%3Apre-commit-check+event%3Apush+branch%3Amaster) follow on Twitter ## Example Here's what using the module will look like ```hcl module "example" { - source = "rhythmictech/terraform-aws-rhythmic-cost-monitor + source = "rhythmictech/rhythmic-account-monitor/aws" datadog_api_key_secret_arn = "" } ``` ## About -A bit about this module +Rhythmic is an AWS Managed Services Provider. We rely heavily on automation to deliver our services, ingesting configuration, event and state information from AWS via listeners (e.g., EventBridge and SNS), services (e.g., Anomaly Detection), and APIs via custom scripts (e.g., Trusted Advisor). + +We open source the vast majority of the resources we use to deliver our managed services because transparency is one of our principles. ## Requirements @@ -44,12 +46,22 @@ A bit about this module | Name | Type | |------|------| +| [aws_accessanalyzer_analyzer.analyzer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/accessanalyzer_analyzer) | resource | +| [aws_accessanalyzer_analyzer.analyzer_unused](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/accessanalyzer_analyzer) | resource | +| [aws_cloudwatch_event_rule.analyzer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_rule.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_rule.backup_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_rule.backup_vaultlock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_rule.glacier_vaultlock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_target.analyzer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_event_target.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_event_target.backup_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_event_target.backup_vaultlock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_event_target.glacier_vaultlock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_sns_topic.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | | [aws_sns_topic_policy.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource | | [aws_sns_topic_subscription.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | -| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.account_alerts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | | [aws_secretsmanager_secret.datadog_api_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/secretsmanager_secret) | data source | | [aws_secretsmanager_secret_version.datadog_api_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/secretsmanager_secret_version) | data source | @@ -57,18 +69,9 @@ A bit about this module | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [anomaly\_total\_impact\_absolute\_threshold](#input\_anomaly\_total\_impact\_absolute\_threshold) | Minimum dollar threshold | `number` | `100` | no | -| [anomaly\_total\_impact\_percentage\_threshold](#input\_anomaly\_total\_impact\_percentage\_threshold) | Percentage threshold | `number` | `10` | no | -| [aws\_service\_shorthand\_map](#input\_aws\_service\_shorthand\_map) | Map of shorthand notation for AWS services to their long form AWS services in cost and usage reporting, sorted alphabetically with lowercase keys | `map(string)` |
{
"apiGateway": "Amazon API Gateway",
"appFlow": "Amazon AppFlow",
"appRunner": "AWS App Runner",
"appSync": "AWS AppSync",
"athena": "Amazon Athena",
"backup": "AWS Backup",
"braket": "Amazon Braket",
"chime": "Amazon Chime",
"cloudFront": "Amazon CloudFront",
"cloudWatch": "Amazon CloudWatch",
"codeArtifact": "AWS CodeArtifact",
"codeBuild": "AWS CodeBuild",
"codeCommit": "AWS CodeCommit",
"codeDeploy": "AWS CodeDeploy",
"codePipeline": "AWS CodePipeline",
"codeStar": "AWS CodeStar",
"comprehend": "Amazon Comprehend",
"connect": "Amazon Connect",
"dataPipeline": "AWS Data Pipeline",
"datadog": "Datadog",
"deepComposer": "AWS DeepComposer",
"deepLens": "AWS DeepLens",
"deepRacer": "AWS DeepRacer",
"detective": "Amazon Detective",
"directConnect": "AWS Direct Connect",
"dms": "AWS Database Migration Service",
"documentDB": "Amazon DocumentDB",
"dynamodb": "Amazon DynamoDB",
"ec2": "Amazon Elastic Compute Cloud - Compute",
"ecs": "Amazon Elastic Container Service",
"efs": "Amazon Elastic File System",
"eks": "Amazon Elastic Kubernetes Service",
"elasticache": "Amazon ElastiCache",
"emr": "Amazon Elastic MapReduce",
"es": "Amazon Elasticsearch Service",
"fargate": "AWS Fargate",
"forecast": "Amazon Forecast",
"fsx": "Amazon FSx",
"gameLift": "Amazon GameLift",
"glue": "AWS Glue",
"greengrass": "AWS Greengrass",
"guardDuty": "Amazon GuardDuty",
"healthLake": "Amazon HealthLake",
"honeycode": "Amazon Honeycode",
"iam": "AWS Identity and Access Management",
"inspector": "Amazon Inspector",
"iot1Click": "AWS IoT 1-Click",
"iotAnalytics": "AWS IoT Analytics",
"iotButton": "AWS IoT Button",
"iotCore": "AWS IoT Core",
"iotDeviceManagement": "AWS IoT Device Management",
"iotEvents": "AWS IoT Events",
"iotSiteWise": "AWS IoT SiteWise",
"iotThingsGraph": "AWS IoT Things Graph",
"ivs": "Amazon Interactive Video Service",
"kendra": "Amazon Kendra",
"kinesis": "Amazon Kinesis",
"kms": "AWS Key Management Service",
"lambda": "AWS Lambda",
"lex": "Amazon Lex",
"lightsail": "Amazon Lightsail",
"lookoutForVision": "Amazon Lookout for Vision",
"lumberyard": "Amazon Lumberyard",
"macie": "Amazon Macie",
"managedBlockchain": "Amazon Managed Blockchain",
"mq": "Amazon MQ",
"msk": "Amazon Managed Streaming for Apache Kafka",
"neptune": "Amazon Neptune",
"opensearch": "Amazon OpenSearch Service",
"outposts": "AWS Outposts",
"pinpoint": "Amazon Pinpoint",
"polly": "Amazon Polly",
"qldb": "Amazon Quantum Ledger Database",
"qls": "AWS Quantum Ledger Service",
"quicksight": "Amazon QuickSight",
"rds": "Amazon Relational Database Service",
"redshift": "Amazon Redshift",
"rekognition": "Amazon Rekognition",
"robomaker": "AWS RoboMaker",
"route53": "Amazon Route 53",
"s3": "Amazon Simple Storage Service",
"s3Outposts": "Amazon S3 on Outposts",
"sagemaker": "Amazon SageMaker",
"ses": "Amazon Simple Email Service",
"sesv2": "Amazon Simple Email Service v2",
"shield": "AWS Shield",
"snowball": "AWS Snowball",
"sns": "Amazon Simple Notification Service",
"sqs": "Amazon Simple Queue Service",
"stepFunctions": "AWS Step Functions",
"storageGateway": "AWS Storage Gateway",
"sumerian": "Amazon Sumerian",
"swf": "Amazon Simple Workflow Service",
"textract": "Amazon Textract",
"timestream": "Amazon Timestream",
"transcribe": "Amazon Transcribe",
"transcribeMedical": "Amazon Transcribe Medical",
"transfer": "AWS Transfer for SFTP",
"translate": "Amazon Translate",
"vpn": "AWS VPN",
"waf": "AWS WAF",
"wellArchitectedTool": "AWS Well-Architected Tool",
"workDocs": "Amazon WorkDocs",
"workLink": "Amazon WorkLink",
"workMail": "Amazon WorkMail",
"workSpaces": "Amazon WorkSpaces",
"xRay": "AWS X-Ray",
"zocalo": "Amazon Zocalo"
}
| no | -| [cur\_forwarding\_bucket\_arn](#input\_cur\_forwarding\_bucket\_arn) | S3 bucket ARN where CUR data will be forwarded | `string` | `null` | no | | [datadog\_api\_key\_secret\_arn](#input\_datadog\_api\_key\_secret\_arn) | ARN of the AWS Secret containing the Datadog API key | `string` | n/a | yes | -| [enable\_cur\_collection](#input\_enable\_cur\_collection) | Enable Cost and Usage Report collection. Be mindful of existing CUR collection processes before enabling. | `bool` | `false` | no | -| [enable\_cur\_forwarding](#input\_enable\_cur\_forwarding) | Enable Cost and Usage Report forwarding. Do not enable unless `enable_cur_collection` is also enabled. | `bool` | `false` | no | -| [enable\_datadog\_cost\_management](#input\_enable\_datadog\_cost\_management) | Enable Datadog cost management | `bool` | `false` | no | -| [monitor\_ri\_utilization](#input\_monitor\_ri\_utilization) | Enable monitoring of Reserverd Instances Utilization | `bool` | `false` | no | -| [monitor\_sp\_utilization](#input\_monitor\_sp\_utilization) | Enable monitoring of Savings Plan Utilization | `bool` | `false` | no | -| [ri\_utilization\_services](#input\_ri\_utilization\_services) | List of services for Reserved Instance utilization monitoring | `list(string)` |
[
"ec2",
"elasticache",
"es",
"opensearch",
"rds",
"redshift"
]
| no | -| [service\_budgets](#input\_service\_budgets) | Map of service budgets |
map(object({
time_unit : string
limit_amount : string
limit_unit : string
threshold : number
threshold_type : string
notification_type : string
}))
|
{
"ec2": {
"limit_amount": "5",
"limit_unit": "USD",
"notification_type": "ACTUAL",
"threshold": 90,
"threshold_type": "PERCENTAGE",
"time_unit": "MONTHLY"
}
}
| no | +| [enable\_iam\_access\_analyzer](#input\_enable\_iam\_access\_analyzer) | A boolean flag to enable/disable IAM Access Analyzer | `bool` | `false` | no | +| [iam\_analyzer\_unused\_access\_age](#input\_iam\_analyzer\_unused\_access\_age) | The age in days after which IAM access is considered unused. | `number` | `90` | no | | [tags](#input\_tags) | User-Defined tags | `map(string)` | `{}` | no | ## Outputs diff --git a/main.tf b/main.tf index f9a5a67..bce705b 100644 --- a/main.tf +++ b/main.tf @@ -1,10 +1,3 @@ -data "aws_caller_identity" "current" { -} - -data "aws_region" "current" { -} - - module "tags" { source = "rhythmictech/tags/terraform" version = "~> 1.1.1" @@ -18,9 +11,7 @@ module "tags" { } locals { - account_id = data.aws_caller_identity.current.account_id - region = data.aws_region.current.name - tags = module.tags.tags_no_name + tags = module.tags.tags_no_name } resource "aws_sns_topic" "account_alerts" { From 771b989dba8668bf3936131756c31ceb441a6733 Mon Sep 17 00:00:00 2001 From: Cris Daniluk Date: Sat, 9 Mar 2024 12:12:44 -0500 Subject: [PATCH 4/5] add cloudtrail event monitors for backups and added access analyzer --- backup.tf | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ iam.tf | 47 +++++++++++++++++++++++++++++++++++++++++++++++ variables.tf | 11 +++++++++++ vaultlock.tf | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 backup.tf create mode 100644 iam.tf create mode 100644 vaultlock.tf diff --git a/backup.tf b/backup.tf new file mode 100644 index 0000000..d3c8dcb --- /dev/null +++ b/backup.tf @@ -0,0 +1,49 @@ +resource "aws_cloudwatch_event_rule" "backup" { + + name = "backup-events-monitor" + description = "Capture AWS Backup events" + + event_pattern = jsonencode({ + source = ["aws.backup"] + detail-type = ["AWS API Call via CloudTrail"] + detail = { + eventSource = ["backup.amazonaws.com"] + eventName = [ + "DeleteBackupPlan", + "DeleteBackupSelection", + "DeleteBackupVault", + "DeleteRecoveryPoint", + "PutBackupVaultAccessPolicy", + "UpdateRecoveryPointLifecycle" + ] + } + }) +} + +resource "aws_cloudwatch_event_target" "backup" { + arn = aws_sns_topic.account_alerts.arn + rule = aws_cloudwatch_event_rule.backup.name + target_id = "SendToSNS" +} + +resource "aws_cloudwatch_event_rule" "backup_event" { + + name_prefix = "backup-events-monitor" + description = "AWS Backup failures" + + event_pattern = < Date: Sat, 9 Mar 2024 12:20:34 -0500 Subject: [PATCH 5/5] update ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 74c83e8..4a36b56 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ # temp folders tmp +# modules should not submit lock files .terraform.lock.hcl