├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .terraform-version
├── .terraform.lock.hcl
├── .tflint.hcl
├── CHANGELOG.md
├── README.md
├── main.tf
├── outputs.tf
├── scripts
├── aws_cli_runner.sh
├── terraform-module-support.sh
└── tflint-support.sh
├── tests
├── Require reworking
│ ├── script_removes_all_files
│ │ ├── expected_plan_errors.json
│ │ ├── expected_variables.json
│ │ ├── terraform.tfvars
│ │ └── test.sh
│ ├── script_retains_all_files
│ │ ├── expected_plan_errors.json
│ │ ├── expected_variables.json
│ │ ├── terraform.tfvars
│ │ └── test.sh
│ └── test_data_retrieval_with_empty_result
│ │ ├── expected_variables.json
│ │ ├── terraform.tfvars
│ │ └── test.sh
├── aws_error_profile_does_not_exist
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── common.sh
├── terraform_validation_error_external_id_invalid_characters
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_external_id_too_long
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_external_id_too_long_and_invalid_characters
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_external_id_too_short
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_invalid_role_arn
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_profile_does_not_match_regex
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_profile_does_not_start_with_a_letter
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_region_does_not_match_regex
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_role_session_name_invalid_characters
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_role_session_name_too_long
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_role_session_name_too_long_and_invalid_characters
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── terraform_validation_error_role_session_name_too_short
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── test_data_retrieval_with_no_role_arn_and_error
│ ├── expected_plan_errors.json
│ ├── expected_variables.json
│ ├── terraform.tfvars
│ └── test.sh
├── test_empty_command
│ ├── expected_plan_errors.json
│ ├── terraform.tfvars
│ └── test.sh
├── test_version_retrieval_will_error
│ ├── expected_apply_outputs.json
│ ├── terraform.tfvars
│ └── test.sh
└── tests.sh
├── variables.tf
└── versions.tf
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | strategy:
11 | matrix:
12 | terraform_version:
13 | - 1.12.1
14 | - 1.11.3
15 | - 1.10.5
16 | - 1.9.8
17 | - 1.8.5
18 | - 1.7.5
19 | - 1.6.6
20 |
21 | steps:
22 | - name: Checkout code
23 | uses: actions/checkout@v4
24 |
25 | - name: Install tfenv
26 | run: |
27 | git clone https://github.com/tfutils/tfenv.git $HOME/.tfenv
28 | echo "$HOME/.tfenv/bin" >> $GITHUB_PATH
29 |
30 | - name: Install Terraform v${{ matrix.terraform_version }}
31 | run: |
32 | echo ${{ matrix.terraform_version }} > .terraform-version
33 | tfenv install ${{ matrix.terraform_version }}
34 | tfenv use ${{ matrix.terraform_version }}
35 |
36 | - name: Update the test result for 1 file
37 | run: |
38 | AWS_CLI_VERSION=$(aws --version) envsubst '\$AWS_CLI_VERSION' < tests/test_version_retrieval_will_error/expected_apply_outputs.json > temp.json
39 | mv -f temp.json tests/test_version_retrieval_will_error/expected_apply_outputs.json
40 |
41 | - name: Run tests
42 | run: |
43 | tests/tests.sh
44 |
45 | - name: Capture logs
46 | uses: actions/upload-artifact@v4
47 | if: always()
48 | with:
49 | name: logs-${{ matrix.terraform_version }}
50 | path: test-reports/**/*
51 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /test-reports/
2 | .idea/
3 | /PersonalSettingsMakefile
4 | /.env
5 | vendor/
6 |
7 | .terraform/
8 | /temp/
9 | aliased-providers.tf.json
10 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 |
3 | - repo: local
4 | hooks:
5 | - id: tflint-setup
6 | always_run: true
7 | args:
8 | - setup
9 | entry: ./scripts/tflint-support.sh
10 | language: system
11 | name: Setup before TFLint
12 | pass_filenames: false
13 | stages: [pre-commit]
14 |
15 | - repo: https://github.com/antonbabenko/pre-commit-terraform
16 | rev: v1.98.0
17 | hooks:
18 | - id: terraform_tflint
19 | stages: [pre-commit]
20 | - id: terraform_fmt
21 | stages: [pre-commit]
22 | - id: terraform_validate
23 | exclude: |
24 | (?x)(
25 | ^.terraform/|
26 | ^modules/|
27 | ^validate/
28 | )
29 | stages: [pre-commit]
30 | - id: terraform_docs
31 | args:
32 | - --hook-config=--path-to-file=README.md
33 | - --hook-config=--add-to-existing-file=true
34 | - --hook-config=--create-file-if-not-exist=true
35 | stages: [pre-commit]
36 |
37 | - repo: local
38 | hooks:
39 | - id: tflint-teardown
40 | always_run: true
41 | args:
42 | - teardown
43 | entry: ./scripts/tflint-support.sh
44 | name: Teardown after TFLint
45 | language: system
46 | pass_filenames: false
47 | stages: [pre-commit]
48 |
49 | - repo: local
50 | hooks:
51 | - id: check-changelog-updated
52 | always_run: true
53 | entry: ./scripts/terraform-module-support.sh
54 | files: CHANGELOG.md
55 | language: system
56 | name: Check if CHANGELOG.md is updated before push
57 | stages: [pre-push]
58 |
59 | - repo: https://github.com/pre-commit/pre-commit-hooks
60 | rev: v5.0.0
61 | hooks:
62 | - id: check-added-large-files
63 | stages: [pre-commit]
64 | - id: check-executables-have-shebangs
65 | stages: [pre-commit]
66 | - id: check-json
67 | stages: [pre-commit]
68 | - id: check-merge-conflict
69 | stages: [pre-commit]
70 | - id: check-symlinks
71 | stages: [pre-commit]
72 | - id: check-yaml
73 | stages: [pre-commit]
74 | - id: detect-aws-credentials
75 | args:
76 | - --allow-missing-credentials
77 | stages: [pre-commit]
78 | - id: detect-private-key
79 | stages: [pre-commit]
80 | - id: end-of-file-fixer
81 | stages: [pre-commit]
82 | - id: fix-byte-order-marker
83 | stages: [pre-commit]
84 | - id: pretty-format-json
85 | args:
86 | - --autofix
87 | - --indent=2
88 | - --no-sort-keys
89 | files: .*\.json$
90 | stages: [pre-commit]
91 | - id: trailing-whitespace
92 | args:
93 | - --markdown-linebreak-ext=md
94 | stages: [pre-commit]
95 |
96 | - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt
97 | rev: 0.2.3
98 | hooks:
99 | - id: yamlfmt
100 | args:
101 | - --implicit_start
102 | - --preserve-quotes
103 | - --mapping=2
104 | - --offset=2
105 | - --sequence=4
106 | - --width=300
107 | stages: [pre-commit]
108 |
109 | - repo: https://github.com/gitleaks/gitleaks
110 | rev: v8.24.2
111 | hooks:
112 | - id: gitleaks
113 | stages: [pre-commit]
114 |
--------------------------------------------------------------------------------
/.terraform-version:
--------------------------------------------------------------------------------
1 | 1.12.1
2 |
--------------------------------------------------------------------------------
/.terraform.lock.hcl:
--------------------------------------------------------------------------------
1 | # This file is maintained automatically by "terraform init".
2 | # Manual edits may be lost in future updates.
3 |
4 | provider "registry.terraform.io/hashicorp/external" {
5 | version = "2.3.4"
6 | constraints = "~> 2.0"
7 | hashes = [
8 | "h1:U6W8rgrdmR2pZ2cicFoGOSQ4GXuIf/4EK7s0vTJN7is=",
9 | "h1:XWkRZOLKMjci9/JAtE8X8fWOt7A4u+9mgXSUjc4Wuyo=",
10 | "h1:cCabxnWQ5fX1lS7ZqgUzsvWmKZw9FA7NRxAZ94vcTcc=",
11 | "zh:037fd82cd86227359bc010672cd174235e2d337601d4686f526d0f53c87447cb",
12 | "zh:0ea1db63d6173d01f2fa8eb8989f0809a55135a0d8d424b08ba5dabad73095fa",
13 | "zh:17a4d0a306566f2e45778fbac48744b6fd9c958aaa359e79f144c6358cb93af0",
14 | "zh:298e5408ab17fd2e90d2cd6d406c6d02344fe610de5b7dae943a58b958e76691",
15 | "zh:38ecfd29ee0785fd93164812dcbe0664ebbe5417473f3b2658087ca5a0286ecb",
16 | "zh:59f6a6f31acf66f4ea3667a555a70eba5d406c6e6d93c2c641b81d63261eeace",
17 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
18 | "zh:ad0279dfd09d713db0c18469f585e58d04748ca72d9ada83883492e0dd13bd58",
19 | "zh:c69f66fd21f5e2c8ecf7ca68d9091c40f19ad913aef21e3ce23836e91b8cbb5f",
20 | "zh:d4a56f8c48aa86fc8e0c233d56850f5783f322d6336f3bf1916e293246b6b5d4",
21 | "zh:f2b394ebd4af33f343835517e80fc876f79361f4688220833bc3c77655dd2202",
22 | "zh:f31982f29f12834e5d21e010856eddd19d59cd8f449adf470655bfd19354377e",
23 | ]
24 | }
25 |
26 | provider "registry.terraform.io/hashicorp/local" {
27 | version = "2.5.2"
28 | constraints = "~> 2.0"
29 | hashes = [
30 | "h1:IyFbOIO6mhikFNL/2h1iZJ6kyN3U00jgkpCLUCThAfE=",
31 | "h1:JlMZD6nYqJ8sSrFfEAH0Vk/SL8WLZRmFaMUF9PJK5wM=",
32 | "h1:p99F1AoV9z51aJ4EdItxz/vLwWIyhx/0Iw7L7sWSH1o=",
33 | "zh:136299545178ce281c56f36965bf91c35407c11897f7082b3b983d86cb79b511",
34 | "zh:3b4486858aa9cb8163378722b642c57c529b6c64bfbfc9461d940a84cd66ebea",
35 | "zh:4855ee628ead847741aa4f4fc9bed50cfdbf197f2912775dd9fe7bc43fa077c0",
36 | "zh:4b8cd2583d1edcac4011caafe8afb7a95e8110a607a1d5fb87d921178074a69b",
37 | "zh:52084ddaff8c8cd3f9e7bcb7ce4dc1eab00602912c96da43c29b4762dc376038",
38 | "zh:71562d330d3f92d79b2952ffdda0dad167e952e46200c767dd30c6af8d7c0ed3",
39 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
40 | "zh:805f81ade06ff68fa8b908d31892eaed5c180ae031c77ad35f82cb7a74b97cf4",
41 | "zh:8b6b3ebeaaa8e38dd04e56996abe80db9be6f4c1df75ac3cccc77642899bd464",
42 | "zh:ad07750576b99248037b897de71113cc19b1a8d0bc235eb99173cc83d0de3b1b",
43 | "zh:b9f1c3bfadb74068f5c205292badb0661e17ac05eb23bfe8bd809691e4583d0e",
44 | "zh:cc4cbcd67414fefb111c1bf7ab0bc4beb8c0b553d01719ad17de9a047adff4d1",
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/.tflint.hcl:
--------------------------------------------------------------------------------
1 | config {
2 | call_module_type = "all"
3 | force = false
4 | format = "compact"
5 | ignore_module = {
6 | "Invicton-Labs/deepmerge/null" = true
7 | }
8 | }
9 |
10 | tflint {
11 | required_version = ">= 0.56.0"
12 | }
13 |
14 | # Only the AWS plugin is enabled. The Google and Azure plugins are not enabled as we have no current use for them.
15 | plugin "aws" {
16 | enabled = true
17 | source = "github.com/terraform-linters/tflint-ruleset-aws"
18 | version = "0.38.0"
19 | deep_check = true
20 | }
21 |
22 | #
23 | # Please check https://github.com/terraform-linters/tflint-ruleset-terraform/tree/v0.5.0/docs/rules for new rules
24 | # (adjust the version accordingly)
25 | #
26 |
27 | # Use '#' for comments rather than '//'.
28 | rule "terraform_comment_syntax" {
29 | enabled = true
30 | }
31 |
32 | # List items should be accessed using square brackets
33 | rule "terraform_deprecated_index" {
34 | enabled = true
35 | }
36 |
37 | # Interpolation-only expressions are deprecated in Terraform v0.12.14
38 | rule "terraform_deprecated_interpolation" {
39 | enabled = true
40 | }
41 |
42 | # Lookup with 2 arguments is deprecated
43 | rule "terraform_deprecated_lookup" {
44 | enabled = true
45 | }
46 |
47 | # Outputs require a description
48 | rule "terraform_documented_outputs" {
49 | enabled = true
50 | }
51 |
52 | # Variables require a description
53 | rule "terraform_documented_variables" {
54 | enabled = true
55 | }
56 |
57 | # Comparing a collection with an empty list is invalid. To detect an empty collection, check its length
58 | rule "terraform_empty_list_equality" {
59 | enabled = true
60 | }
61 |
62 | # Disallow specifying a git or mercurial repository as a module source without pinning to a version
63 | rule terraform_module_pinned_source {
64 | enabled = true
65 | }
66 |
67 | # Ensure that all modules sourced from a Terraform Registry specify a version
68 | rule "terraform_module_version" {
69 | enabled = true
70 | exact = false # default
71 | }
72 |
73 | # Enforces naming conventions
74 | rule "terraform_naming_convention" {
75 | enabled = true
76 | format = "snake_case"
77 | }
78 |
79 | # Require that all providers specify a source and version constraint through required_providers
80 | rule "terraform_required_providers" {
81 | enabled = true
82 |
83 | # defaults
84 | source = true
85 | version = true
86 | }
87 |
88 | # Disallow terraform declarations without required_version
89 | rule "terraform_required_version" {
90 | enabled = true
91 | }
92 |
93 | # Ensure that a module complies with the Terraform Standard Module Structure / https://www.terraform.io/docs/modules/index.html#standard-module-structure
94 | rule "terraform_standard_module_structure" {
95 | enabled = true
96 | }
97 |
98 | # Disallow variable declarations without type
99 | rule "terraform_typed_variables" {
100 | enabled = true
101 | }
102 |
103 | # Disallow variables, data sources, and locals that are declared but never used
104 | rule terraform_unused_declarations {
105 | enabled = true
106 | }
107 |
108 | # Check that all required_providers are used in the module
109 | rule terraform_unused_required_providers {
110 | enabled = true
111 | }
112 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | # V7.0.1 - 2025/04/28
4 | - Add v1.11.3, and reduced the number of builds to just the latest in the minor versions of Terraform from 1.6.0 onwards.
5 | - Minor reorganization to match [Terraform Standard Module Structure](https://www.terraform.io/docs/modules/index.html#standard-module-structure).
6 | - Small enhancement for TFLint when aliased providers are used.
7 | - Added warning to README.md regarding destructive use. Thank you, [Yves Vogl](https://github.com/digitickets/terraform-aws-cli/issues/25).
8 |
9 | # v7.0.0 - 2024/08/06
10 | - Fix a typo in the description for the `var.external_id`.
11 | - Fix handling of invalid JSON returned from the AWS CLI. Thank you, [홍수민 and horststumpf](https://github.com/digitickets/terraform-aws-cli/pull/19).
12 | - Introduced 2 new outputs:
13 | - `output.result_raw = string` - This will contain the raw output from the AWS CLI call.
14 | - `output.result_was_decoded = bool` - This will indicate if the output from the AWS CLI call was successfully JSON decoded.
15 |
16 | These were introduced as some of the results from the AWS CLI are not JSON decodable. For example `aws ec2 create-tags` returns nothing.
17 |
18 | # v6.1.0 - 2024/01/31
19 | - Added testing for Terraform 1.7+
20 | - FIX : If `var.profile` and `var.assume_role_arn` are used, then continuing to use `var.profile` invalidates the
21 | assumed role. The `aws_cli_runner.sh` now no longer uses `var.profile` when a role has been successfully assumed.
22 | Thank you, [Garrett Blinkhorn](https://github.com/digitickets/terraform-aws-cli/issues/11).
23 |
24 | # v6.0.2 - 2024/01/31
25 | - FIX : Typo in `aws_cli_runner.sh` when running assuming a role. Thank you, [Garrett Blinkhorn](https://github.com/digitickets/terraform-aws-cli/issues/11).
26 |
27 | # v6.0.1 - 2023/12/22
28 | - Set the minimum version of Terraform to v1.6.0 as that is the lowest version to support `data.lifecycle` block.
29 |
30 | # v6.0.0 - 2023/12/15
31 | - Added error handling for errors generated by the AWS CLI to stop the Terraform Plan. The error is also present in the
32 | `terraform show` output in the `checks[*].instances[*].problems` node (See the
33 | [expected plan errors](tests/aws_error_profile_does_not_exist/expected_plan_errors.json) when an AWS error is
34 | triggered).
35 | - Added a lot of Terraform variable validation to ensure the supplied parameters match the limits imposed by AWS (the
36 | minimum/maximum length, allowable characters, rules on first characters, etc.)
37 | - Rewritten the [AWS CLI Runner script](./scripts/aws_cli_runner.sh) to not need to deal with wrapping parameters in
38 | quotes.
39 | - Rewritten tests, mainly to reduce the amount of effort to configure them in the future.
40 |
41 | ## BACKWARDS INCOMPATIBILITY
42 |
43 | - The `debug_log_filename` variable has been removed. As the new code will generate more files to assist in any
44 | debugging if it becomes necessary, a new variable `alternative_path` has been added. If set, this path will contain
45 | the following files:
46 |
47 | 1. `jq_data.json` - The data managed by `jq` to get the Terraform variables accessible to AWS CLI.
48 | 2. `jq_error.log` - Any errors generated by `jq` whilst attempting to parse the supplied JSON.
49 | 3. `aws_sts.json` - The data returned by AWS when assuming a role.
50 | 4. `aws_sts_error.log` - The full debug and any errors when assuming a role.
51 | 5. `aws_call.json` - The data returned by AWS when running AWS CLI for the required call.
52 | 6. `aws_call_error.log` - The full debug and any errors when running AWS CLI for the required call.
53 | 7. `results.json` - The results of the AWS CLI call that are fed back to Terraform.
54 |
55 | But to reduce the amount of files left behind, as standard, all files except `results.json` are deleted before
56 | Terraform is given the `results.json` file to process.
57 |
58 | If you need to have access to the other files, then setting the environment variable
59 | `MODULE_TERRAFORM_AWS_CLI_RETAIN_LOGS` to `true` will retain all the logs shown above.
60 |
61 | If the `alternative_path` variable is not set, then a default path will be used based upon `./temp/[hash]`. The hash
62 | is the md5 of all the values of the variables supplied to the module.
63 |
64 | # v5.2.0 - 2023/07/20
65 |
66 | - Fixed issue introduce in v5.1.0 regarding the use of `var.external_id`.
67 | - Introduces support for `var.profile` to allow you to supply your own AWS profile. Thank you, [coopengo-glecomte](https://github.com/digitickets/terraform-aws-cli/issues/8).
68 | - Introduces support for `var.region` to allow you to supply your own AWS region.
69 | - Refactored tests due to changes within Terraform.
70 |
71 | # v5.1.0 - 2023/07/20
72 |
73 | - Introduce support for `var.external_id`. Thank you, [Joshua Rosen](https://github.com/digitickets/terraform-aws-cli/pull/6).
74 |
75 | # v5.0.4 - 2022/11/28
76 |
77 | - Allow `var.role_session_name` to be optional. Thank you, [Byron Kim](https://github.com/digitickets/terraform-aws-cli/issues/4).
78 |
79 | # v5.0.3 - 2022/05/31
80 |
81 | - Fix for when the AWS call being made has no output (which is invalid JSON). Thank you, [Yaron Yarimi and Pavel Kargin](https://github.com/digitickets/terraform-aws-cli/issues/3).
82 |
83 | # v5.0.2 - 2022/05/26
84 |
85 | - Fix for when this module is used in an iteration.
86 |
87 | # v5.0.1 - 2022/05/24
88 |
89 | - Explicitly specify output type as json for assume role call. Thank you, [Niranjan Rajendran](https://github.com/digitickets/terraform-aws-cli/pull/2).
90 |
91 | # v5.0.0 - 2022/01/27
92 |
93 | - Fixed incompatibilities with Terraform 1.1.0.
94 |
95 | # v4.1.0 - 2021/10/05
96 |
97 | - Validate role_session_name so that the maximum length is 64 characters and that it must match a specific regex.
98 |
99 | # v4.0.0 - 2021/05/18
100 |
101 | - Set minimum terraform version to 0.15.0.
102 |
103 | # No release required - 2021/03/30
104 |
105 | - Updated tests to use an AWS request that does not require credentials, allowing the full terraform plan and apply
106 | process to be run and tested with the module.
107 |
108 | # v3.1.1 - 2021/03/25
109 |
110 | - Re-releasing as accidentally released v3.0.0 as v3.1.0.
111 |
112 | # v3.1.0 - 2021/03/25
113 |
114 | - Add an optional `debug_log_filename` variable. If supplied, a log file will be produced in the supplied location. This
115 | option enables the `--debug` option of the AWS CLI. Use this in safe environments as potentially sensitive content may
116 | be logged.
117 | - Added [adaptive retry mode](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-retries.html#cli-usage-retries-modes-adaptive)
118 | to help alleviate throttling issues.
119 |
120 | # v3.0.0 - 2020/12/03
121 |
122 | - Set minimum terraform version to 0.14.0.
123 | - Introduced `.terraform.lock.hcl` for versioning of dependencies.
124 |
125 | # v2.0.1 - 2020/09/17
126 |
127 | - Add `depends_on` to enforce the order in which the resources get instantiated / evaluated.
128 |
129 | # v2.0.0 - 2020/09/17
130 |
131 | - Set minimum terraform version to 0.13.0
132 | - Added variable validation to optional `assume_role_arn` to match syntax described in
133 | [IAM Identifiers](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html).
134 |
135 | # v1.3.0 - 2020/08/03
136 |
137 | - Set minimum version of random provider to 2.3.0
138 |
139 | # v1.2.2 - 2020/05/11
140 |
141 | - Updated examples in [README.md](README.md).
142 |
143 | # v1.2.1 - 2020/05/11
144 |
145 | - Updated [README.md](README.md) to reflect `digiticketsgroup/terraforming` image that includes all the required
146 | resources for using this module.
147 |
148 | # v1.2.0 - 2020/05/11
149 |
150 | - Drop down to using `sh` rather than `bash` so this module can operate with Hashicorp Terraform Docker image.
151 |
152 | # v1.1.0 - 2020/05/07
153 |
154 | - Updated examples in README.md with registry path as displayed by registry.
155 | - Updated `assume_role_arn` to reflect that it is optional.
156 |
157 | # v1.0.0 - 2020/05/07
158 | Initial release
159 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/digitickets/terraform-aws-cli/actions/workflows/build.yml)
2 | [](https://github.com/digitickets/terraform-aws-cli/issues)
3 |
4 | # terraform-aws-cli
5 |
6 | Run the AWS CLI, with the ability to run under an assumed role, to access resources and properties missing from the
7 | Terraform AWS Provider.
8 |
9 | # Additional requirements
10 |
11 | This module requires a couple of additional tools to operate successfully.
12 |
13 | 1. Amazon Web Service Command Line Interface (`aws`)
14 | : This is available in several forms [here](https://aws.amazon.com/cli/).
15 | As the awscli tool gets updated regularly, any version 2 should be usable, but please try to keep as uptodate as the
16 | functionality included in later versions may be what you need when using this module. If you are not getting the
17 | functionality you require, please read the
18 | [AWS CLI V2 Changelog](https://raw.githubusercontent.com/aws/aws-cli/v2/CHANGELOG.rst) to see if you are just needing
19 | to upgrade.
20 |
21 | 2. JSON processor (`jq`)
22 | : This is available [here](https://stedolan.github.io/jq/).
23 | At least version `jq-1.5` is required but has been tested and actively used with `jq-1.6`.
24 |
25 | # Examples
26 |
27 | ## 1. Get the desired capacity of an autoscaling group.
28 |
29 | If you are using a blue/green style deployment, you would want to create the same number of EC2 instances as you are
30 | replacing.
31 |
32 | ```hcl-terraform
33 | module "current_desired_capacity" {
34 | source = "digitickets/cli/aws"
35 | role_session_name = "GettingDesiredCapacityFor${var.environment}"
36 | aws_cli_commands = ["autoscaling", "describe-auto-scaling-groups"]
37 | aws_cli_query = "AutoScalingGroups[?Tags[?Key==`Name`]|[?Value==`digitickets-${var.environment}-asg-app`]]|[0].DesiredCapacity"
38 | }
39 | ```
40 |
41 | You can now set the desired capacity of an aws_autoscaling_group:
42 |
43 | ```hcl-terraform
44 | desired_capacity = module.current_desired_capacity.result
45 | ```
46 |
47 | ## 2. Assuming a role.
48 |
49 | Extending the first example above, assuming a role is as simple as adding an `assume_role_arn` to the module:
50 |
51 | ```hcl-terraform
52 | module "current_desired_capacity" {
53 | source = "digitickets/cli/aws"
54 | assume_role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/OrganizationAccountAccessRole"
55 | role_session_name = "GettingDesiredCapacityFor${var.environment}"
56 | aws_cli_commands = ["autoscaling", "describe-auto-scaling-groups"]
57 | aws_cli_query = "AutoScalingGroups[?Tags[?Key==`Name`]|[?Value==`digitickets-${var.environment}-asg-app`]]|[0].DesiredCapacity"
58 | }
59 | ```
60 |
61 | ## 3. Adding your own profile.
62 |
63 | Extending the example above, you can supply your own profile by adding a `profile` to the module:
64 |
65 | ```hcl-terraform
66 | module "current_desired_capacity" {
67 | source = "digitickets/cli/aws"
68 | assume_role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/OrganizationAccountAccessRole"
69 | role_session_name = "GettingDesiredCapacityFor${var.environment}"
70 | aws_cli_commands = ["autoscaling", "describe-auto-scaling-groups"]
71 | aws_cli_query = "AutoScalingGroups[?Tags[?Key==`Name`]|[?Value==`digitickets-${var.environment}-asg-app`]]|[0].DesiredCapacity"
72 | profile = "your-own-profile"
73 | }
74 | ```
75 |
76 | ## 4. Adding your external ID.
77 |
78 | Extending the example above, you can supply your own external ID by adding an `external_id` to the module:
79 |
80 | ```hcl-terraform
81 | module "current_desired_capacity" {
82 | source = "digitickets/cli/aws"
83 | assume_role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/OrganizationAccountAccessRole"
84 | role_session_name = "GettingDesiredCapacityFor${var.environment}"
85 | aws_cli_commands = ["autoscaling", "describe-auto-scaling-groups"]
86 | aws_cli_query = "AutoScalingGroups[?Tags[?Key==`Name`]|[?Value==`digitickets-${var.environment}-asg-app`]]|[0].DesiredCapacity"
87 | profile = "your-own-profile"
88 | external_id = "your-external-id"
89 | }
90 | ```
91 |
92 | Further information regarding the use of external IDs can be found [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html).
93 |
94 | # Warning
95 |
96 | This module uses Terraform's `external` provider to allow an `external` data source to be used to call the AWS CLI tool,
97 | and retrieve information not yet available via the AWS Terraform Provider.
98 |
99 | As per the warnings [here](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external),
100 | the `external` data source, and as a consequence, this module, it is expected that this module is used with caution.
101 |
102 | This module is _NOT_ a replacement for the AWS Terraform Provider.
103 |
104 | As per the last paragraph of the warnings from the official documentation regarding the `external` data source...
105 |
106 | "Terraform expects a data source to have _no observable side-effects_,
107 | and will re-run the program each time the state is refreshed."
108 |
109 | If you use this module to perform destructive changes to your AWS environment, then they will be triggered each time a
110 | Terraform plan and apply are run.
111 |
112 | # Terraform requirements, providers, resources, etc.
113 |
114 |
115 | ## Requirements
116 |
117 | | Name | Version |
118 | |------|---------|
119 | | [terraform](#requirement\_terraform) | >= 1.6.0 |
120 | | [external](#requirement\_external) | ~> 2.0 |
121 | | [local](#requirement\_local) | ~> 2.0 |
122 |
123 | ## Providers
124 |
125 | | Name | Version |
126 | |------|---------|
127 | | [external](#provider\_external) | 2.3.4 |
128 | | [local](#provider\_local) | 2.5.2 |
129 |
130 | ## Modules
131 |
132 | No modules.
133 |
134 | ## Resources
135 |
136 | | Name | Type |
137 | |------|------|
138 | | [external_external.awscli_program](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) | data source |
139 | | [local_file.awscli_results_file](https://registry.terraform.io/providers/hashicorp/local/latest/docs/data-sources/file) | data source |
140 |
141 | ## Inputs
142 |
143 | | Name | Description | Type | Default | Required | Validation |
144 | |------|-------------|------|---------|:--------:|------------|
145 | | [alternative\_path](#input\_alternative\_path) | Use an alternative path for all files produced internally | `string` | `""` | no | None |
146 | | [assume\_role\_arn](#input\_assume\_role\_arn) | The ARN of the role being assumed (optional).
The optional ARN must match the format documented in https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html. | `string` | `""` | no | The optional ARN must match the format documented in https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html. |
147 | | [aws\_cli\_commands](#input\_aws\_cli\_commands) | The AWS CLI command, subcommands, and options.
For options that can accept a value, then the following examples are both fine to use:
1. `"--option", "value"`
2. `"--option=value"`
In the event that the value contains a space, it must be wrapped with quotes.
1. `"--option", "'value with a space wrapped in single quotes'"`
2. `"--option='value with a space wrapped in single quotes'"` | `list(string)` | n/a | yes | None |
148 | | [aws\_cli\_query](#input\_aws\_cli\_query) | The `--query` value for the AWS CLI call.
The value for `var.aws_cli_query` is based upon JMESPath, and you can get good information from https://jmespath.org.
If not supplied, then the entire results from the AWS CLI call will be returned. | `string` | `""` | no | None |
149 | | [external\_id](#input\_external\_id) | External id for assuming the role (optional).
The length of optional external\_id, when supplied, must be between 2 and 1224 characters.
The optional external\_id can only contain upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: `=,.@-`.
The optional external\_id match the regular expression `^[\w=,.@-]*$`. | `string` | `""` | no | The length of optional external\_id, when supplied, must be between 2 and 1224 characters.
The optional external\_id must match the regular expression '^[\w=,.@-]*$'. |
150 | | [profile](#input\_profile) | The specific AWS profile to use (must be configured appropriately and is optional).
The optional profile must start with a letter and can only contain letters, numbers, hyphens, and underscores. | `string` | `""` | no | The optional profile must start with a letter and can only contain letters, numbers, hyphens, and underscores. |
151 | | [region](#input\_region) | The specific AWS region to use.
The region must start with two letters representing the geographical area, followed by one or more letters or digits representing the specific region within that area. | `string` | `""` | no | The optional region must start with two letters representing the geographical area, followed by one or more letters or digits representing the specific region within that area. |
152 | | [role\_session\_name](#input\_role\_session\_name) | The role session name that will be used when assuming a role (optional)
The length of the optional role session name, when supplied, must be between 2 and 64 characters.
The optional role session name can only contain upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: `=,.@-`.
The optional role session name match the regular expression `^[\w=,.@-]*$`.
If the assume\_role\_arn is supplied, but the role\_session\_name is left empty, an internal default of "AssumingRole" will be used. | `string` | `""` | no | The length of the optional role session name, when supplied, must be between 2 and 64 characters.
The role session name match the regular expression '^[\w=,.@-]*$'. |
153 |
154 | ## Outputs
155 |
156 | | Name | Description |
157 | |------|-------------|
158 | | [result](#output\_result) | The output of the AWS CLI command, if it can be JSON decoded |
159 | | [result\_raw](#output\_result\_raw) | The raw, non JSON decoded output of the AWS CLI command |
160 | | [result\_was\_decoded](#output\_result\_was\_decoded) | Can the output from the AWS CLI command can be JSON decoded |
161 |
162 |
163 | # Docker
164 |
165 | To help with getting this running in a pipeline that uses Docker, the image [digiticketsgroup/terraforming](https://hub.docker.com/repository/docker/digiticketsgroup/terraforming) has Terraform, AWSCLI, and jq all ready to go.
166 |
167 | If you want to build or adapt your own image, then the Dockerfile below is how that image has been built.
168 |
169 | ```Dockerfile
170 | # Based upon https://github.com/aws/aws-cli/blob/2.0.10/docker/Dockerfile
171 | FROM amazonlinux:2 as installer
172 | ARG TERRAFORM_VERSION
173 | RUN yum update -y \
174 | && yum install -y unzip \
175 | && curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscli-exe-linux-x86_64.zip \
176 | && unzip awscli-exe-linux-x86_64.zip \
177 | # The --bin-dir is specified so that we can copy the
178 | # entire bin directory from the installer stage into
179 | # into /usr/local/bin of the final stage without
180 | # accidentally copying over any other executables that
181 | # may be present in /usr/local/bin of the installer stage.
182 | && ./aws/install --bin-dir /aws-cli-bin/ \
183 | && curl "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" -o terraform.zip \
184 | && unzip terraform.zip
185 |
186 | FROM amazonlinux:2
187 | COPY --from=installer /usr/local/aws-cli/ /usr/local/aws-cli/
188 | COPY --from=installer /aws-cli-bin/ /usr/local/bin/
189 | COPY --from=installer terraform /usr/bin/
190 | RUN yum update -y \
191 | && yum install -y less groff jq \
192 | && yum clean all
193 |
194 | ENTRYPOINT ["/bin/sh"]
195 | ```
196 |
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | joined_aws_cli_command = join(" ", var.aws_cli_commands)
3 | external_program_query = {
4 | assume_role_arn = var.assume_role_arn
5 | role_session_name = length(var.assume_role_arn) > 0 ? var.role_session_name : ""
6 | aws_cli_commands = local.joined_aws_cli_command
7 | aws_cli_query = var.aws_cli_query
8 | external_id = var.external_id
9 | profile = var.profile
10 | region = var.region
11 | }
12 | standard_results_file = format("%s/temp/%s/results.json", path.module, md5(join("-", values(local.external_program_query))))
13 | alternative_results_file = format("%s/results.json", var.alternative_path)
14 | results_file = length(var.alternative_path) == 0 ? local.standard_results_file : local.alternative_results_file
15 | }
16 |
17 | data "external" "awscli_program" {
18 | program = [
19 | format("%s/scripts/aws_cli_runner.sh", path.module),
20 | local.results_file
21 | ]
22 | query = local.external_program_query
23 | }
24 |
25 | # Due to the way the Terraform External Provider has various limitations on processing the output of an external
26 | # program, the script that is called creates a separate file and is then referenced via a local_file data block.
27 | # Amongst the chief benefits is that all the data types returned from AWS are not converted to strings for Terraform to
28 | # access.
29 | data "local_file" "awscli_results_file" {
30 | depends_on = [data.external.awscli_program]
31 | filename = local.results_file
32 |
33 | lifecycle {
34 | postcondition {
35 | condition = try(jsondecode(self.content).error, false) == false
36 | error_message = try(jsondecode(self.content).error, "Unknown error")
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/outputs.tf:
--------------------------------------------------------------------------------
1 | output "result" {
2 | depends_on = [data.local_file.awscli_results_file]
3 | description = "The output of the AWS CLI command, if it can be JSON decoded"
4 | value = try(jsondecode(data.local_file.awscli_results_file.content), "")
5 | }
6 |
7 | output "result_raw" {
8 | depends_on = [data.local_file.awscli_results_file]
9 | description = "The raw, non JSON decoded output of the AWS CLI command"
10 | value = data.local_file.awscli_results_file.content
11 | }
12 |
13 | output "result_was_decoded" {
14 | depends_on = [data.local_file.awscli_results_file]
15 | description = "Can the output from the AWS CLI command can be JSON decoded"
16 | value = can(jsondecode(data.local_file.awscli_results_file.content))
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/aws_cli_runner.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # Validate required commands
4 | if [ ! -x "$(command -v aws)" ]; then
5 | echo '{"error":"aws cli is not installed"}'
6 | exit 1
7 | fi
8 | if [ ! -x "$(command -v jq)" ]; then
9 | echo '{"error":"jq is not installed"}'
10 | exit 2
11 | fi
12 |
13 | # Validate required results file as the first argument
14 | if [ -z "${1}" ]; then
15 | echo '{"error":"No results filename supplied"}'
16 | exit 3
17 | fi
18 |
19 | # Extract directory from results file name for all logs.
20 | RESULTS_FILE="${1}"
21 | ROOT_DIRECTORY=$(dirname "${RESULTS_FILE}")
22 |
23 | # Build all the paths for all the files.
24 | ## JQ json and error log
25 | JQ_JSON="${ROOT_DIRECTORY}/jq_data.json"
26 | JQ_ERROR_LOG="${ROOT_DIRECTORY}/jq_error.log"
27 |
28 | ## AWS STS json and error log
29 | AWS_STS_JSON="${ROOT_DIRECTORY}/aws_sts.json"
30 | AWS_STS_ERROR_LOG="${ROOT_DIRECTORY}/aws_sts_error.log"
31 |
32 | ## The actual AWS call json and error log
33 | AWS_CALL_JSON="${ROOT_DIRECTORY}/aws_call.json"
34 | AWS_CALL_ERROR_LOG="${ROOT_DIRECTORY}/aws_call_error.log"
35 |
36 | # Remove any files that would match the above list
37 | mkdir -p "${ROOT_DIRECTORY}"
38 | rm -rf \
39 | "${JQ_JSON}" \
40 | "${JQ_ERROR_LOG}" \
41 | "${AWS_STS_JSON}" \
42 | "${AWS_STS_ERROR_LOG}" \
43 | "${AWS_CALL_JSON}" \
44 | "${AWS_CALL_ERROR_LOG}" \
45 | "${RESULTS_FILE}" \
46 |
47 | # Get the query and store it
48 | jq -Mcr . >"${JQ_JSON}" 2>"${JQ_ERROR_LOG}"
49 |
50 | # Extract the query attributes
51 | AWS_CLI_COMMANDS=$( jq -r '.aws_cli_commands' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
52 | AWS_CLI_QUERY=$( jq -r '.aws_cli_query' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
53 | ASSUME_ROLE_ARN=$( jq -r '.assume_role_arn' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
54 | ROLE_SESSION_NAME=$(jq -r '.role_session_name' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
55 | EXTERNAL_ID=$( jq -r '.external_id' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
56 | PROFILE_NAME=$( jq -r '.profile' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
57 | REGION_NAME=$( jq -r '.region' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
58 | KEEP_LOGS=$( jq -r '.keep_logs' "${JQ_JSON}" 2>>"${JQ_ERROR_LOG}")
59 |
60 | # Build the required parameters for the AWS calls.
61 |
62 | ## Do we have a profile?
63 | if [ -n "${PROFILE_NAME}" ]; then
64 | AWS_CLI_PROFILE_PARAM="--profile=${PROFILE_NAME}"
65 | fi
66 |
67 | ## Do we have a region?
68 | if [ -n "${REGION_NAME}" ]; then
69 | AWS_CLI_REGION_PARAM="--region=${REGION_NAME}"
70 | fi
71 |
72 | ## Do we need to assume a role?
73 | if [ -n "${ASSUME_ROLE_ARN}" ]; then
74 |
75 | ### Do we have an external ID?
76 | if [ -n "${EXTERNAL_ID}" ]; then
77 | AWS_CLI_EXTERNAL_ID_PARAM="--external-id=${EXTERNAL_ID}"
78 | fi
79 |
80 | ### Get temporary credentials from AWS STS
81 | if ! eval "aws sts assume-role \
82 | --role-arn ${ASSUME_ROLE_ARN} \
83 | ${AWS_CLI_EXTERNAL_ID_PARAM:-} \
84 | --role-session-name ${ROLE_SESSION_NAME:-AssumingRole} \
85 | --output json \
86 | --debug \
87 | ${AWS_CLI_PROFILE_PARAM:-} \
88 | ${AWS_CLI_REGION_PARAM:-} \
89 | " \
90 | >"${AWS_STS_JSON}" \
91 | 2>"${AWS_STS_ERROR_LOG}"; then
92 | echo '{"error":"The call to AWS to get temporary credentials failed"}' >&2
93 | exit 4
94 | fi
95 | export AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' "$AWS_STS_JSON")
96 | export AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretAccessKey' "$AWS_STS_JSON")
97 | export AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' "$AWS_STS_JSON")
98 |
99 | ### Having assumed a role, drop the profile as that will override any credentials retrieved by the assumed role when
100 | ### reused as part of the AWS CLI call.
101 | ### References :
102 | ### 1. https://github.com/digitickets/terraform-aws-cli/issues/11 - Thank you Garrett Blinkhorn.
103 | ### 2. https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html#using-temp-creds-sdk-cli
104 | unset AWS_CLI_PROFILE_PARAM
105 | fi
106 |
107 | # Do we have a query?
108 | if [ -n "${AWS_CLI_QUERY}" ]; then
109 | AWS_CLI_QUERY_PARAM="--query='${AWS_CLI_QUERY}'"
110 | fi
111 |
112 | # Disable any assigned pager
113 | export AWS_PAGER=""
114 |
115 | # Configure adaptive retry mode
116 | export AWS_RETRY_MODE=adaptive
117 |
118 | # Run the AWS_CLI command
119 | AWS_COMMAND_LINE=""
120 | if ! eval "aws \
121 | ${AWS_CLI_COMMANDS} \
122 | ${AWS_CLI_PROFILE_PARAM:-} \
123 | ${AWS_CLI_REGION_PARAM:-} \
124 | ${AWS_CLI_QUERY_PARAM:-} \
125 | --output json \
126 | " \
127 | >"${AWS_CALL_JSON}" \
128 | 2> "${AWS_CALL_ERROR_LOG}"; then
129 | # Convert the error into a JSON string and exit
130 | jq -MRcs '{"error":gsub("^\n+|\n+$"; "")}' "${AWS_CALL_ERROR_LOG}" > "${RESULTS_FILE}"
131 | cat "${RESULTS_FILE}"
132 | exit 0
133 | fi
134 |
135 | # All is good.
136 | cp "${AWS_CALL_JSON}" "${RESULTS_FILE}"
137 | echo '{"result":"'"${RESULTS_FILE}"'"}'
138 |
139 | # Clean up, but allow a test mode to retain all files except the result
140 | if [ "${MODULE_TERRAFORM_AWS_CLI_RETAIN_LOGS}" != "true" ]; then
141 | rm -rf \
142 | "${JQ_JSON}" \
143 | "${JQ_ERROR_LOG}" \
144 | "${AWS_STS_JSON}" \
145 | "${AWS_STS_ERROR_LOG}" \
146 | "${AWS_CALL_JSON}" \
147 | "${AWS_CALL_ERROR_LOG}"
148 | fi
149 |
--------------------------------------------------------------------------------
/scripts/terraform-module-support.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o pipefail
4 |
5 | # Get the branch being pushed
6 | current_branch=$(git rev-parse --abbrev-ref HEAD)
7 |
8 | # Exit early if the current branch is master
9 | if [ "$current_branch" = "master" ]; then
10 | exit 0
11 | fi
12 |
13 | # Check if CHANGELOG.md is in the list of files supplied by the pre-commit application.
14 | if ! echo "$@" | grep -q "CHANGELOG.md"; then
15 | echo "Warning: You are pushing to '$current_branch' without modifying CHANGELOG.md."
16 | echo "Consider updating the CHANGELOG.md before pushing."
17 | echo ""
18 | echo "You can use the --no-verify option to ignore this restriction."
19 | exit 1 # Fails the push
20 | fi
21 |
22 | exit 0
23 |
--------------------------------------------------------------------------------
/scripts/tflint-support.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o pipefail
4 |
5 | validate_credentials() {
6 | if [[ "$AWS_SESSION_TOKEN" == "" ]]; then
7 | echo 'Missing or expired AWS credentials.' >&2
8 | echo 'This may cause TFLint to fail.' >&2
9 | exit 1
10 | fi
11 | }
12 |
13 | setup_tflint() {
14 | terraform-config-inspect --json . |
15 | jq -r '
16 | [.required_providers[].aliases]
17 | | flatten
18 | | del(.[] | select(. == null))
19 | | reduce .[] as $entry (
20 | {};
21 | .provider[$entry.name] //= []
22 | | .provider[$entry.name] += [{"alias": $entry.alias}]
23 | )' > aliased-providers.tf.json || true
24 | }
25 |
26 | teardown_tflint() {
27 | rm -f aliased-providers.tf.json
28 | }
29 |
30 | # Check if a function name was provided
31 | if [[ $# -eq 0 ]]; then
32 | echo "Usage: $0 {setup|teardown}"
33 | exit 1
34 | fi
35 |
36 | # Call the function based on the first argument
37 | case "$1" in
38 | setup)
39 | setup_tflint
40 | validate_credentials
41 | ;;
42 | teardown)
43 | teardown_tflint
44 | ;;
45 | *)
46 | echo "Invalid argument: $1"
47 | echo "Usage: $0 {setup|teardown}"
48 | exit 1
49 | ;;
50 | esac
51 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_removes_all_files/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "data.local_file.awscli_results_file",
4 | "problems": [
5 | "An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied"
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_removes_all_files/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/script_removes_all_files/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "s3api",
6 | "list-objects",
7 | "--bucket=ryft-public-sample-data",
8 | "--no-sign-request"
9 | ],
10 | "aws_cli_query": "max_by(Contents, &Size)",
11 | "external_id": "",
12 | "profile": "",
13 | "region": "eu-west-1",
14 | "role_session_name": ""
15 | }
16 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_removes_all_files/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["s3api", "list-objects", "--bucket=ryft-public-sample-data", "--no-sign-request"]
2 | aws_cli_query = "max_by(Contents, &Size)"
3 | region = "eu-west-1"
4 |
5 | alternative_path = "test-reports/script_removes_all_files/aws"
6 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_removes_all_files/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=true
4 |
5 | function test_setup() {
6 | export MODULE_TERRAFORM_AWS_CLI_RETAIN_LOGS=false
7 | }
8 |
9 | function test_teardown() {
10 | echo "MODULE_TERRAFORM_AWS_CLI_RETAIN_LOGS = ${MODULE_TERRAFORM_AWS_CLI_RETAIN_LOGS}"
11 | ROOT_DIRECTORY="test-reports/${TEST_NAME}/aws"
12 |
13 | # Build all the paths for all the files.
14 |
15 | ## Results file
16 | RESULTS_FILE="${ROOT_DIRECTORY}/results.json"
17 |
18 | ## JQ json and error log
19 | JQ_JSON="${ROOT_DIRECTORY}/jq_data.json"
20 | JQ_ERROR_LOG="${ROOT_DIRECTORY}/jq_error.log"
21 |
22 | ## AWS STS json and error log
23 | AWS_STS_JSON="${ROOT_DIRECTORY}/aws_sts.json"
24 | AWS_STS_ERROR_LOG="${ROOT_DIRECTORY}/aws_sts_error.log"
25 |
26 | ## The actual AWS call json and error log
27 | AWS_CALL_JSON="${ROOT_DIRECTORY}/aws_call.json"
28 | AWS_CALL_ERROR_LOG="${ROOT_DIRECTORY}/aws_call_error.log"
29 |
30 | AWS_SCRIPT_FILENAMES=(
31 | "${JQ_JSON}" "${JQ_ERROR_LOG}"
32 | "${AWS_STS_JSON}" "${AWS_STS_ERROR_LOG}"
33 | "${AWS_CALL_JSON}" "${AWS_CALL_ERROR_LOG}"
34 | )
35 |
36 | TEST_PASSED=true
37 | for AWS_SCRIPT_FILENAME in "${AWS_SCRIPT_FILENAMES[@]}"; do
38 | if [ -f "${AWS_SCRIPT_FILENAME}" ]; then
39 | echo "Failed to remove '${AWS_SCRIPT_FILENAME}'" | indent
40 | TEST_PASSED=false
41 | fi
42 | done
43 |
44 | if [ ! -f "${RESULTS_FILE}" ]; then
45 | echo "Failed to retain '${RESULTS_FILE}'" | indent
46 | TEST_PASSED=false
47 | fi
48 |
49 | if [ "${TEST_PASSED}" != "true" ]; then
50 | echo "Failed : $TEST_PATH"
51 | exit 1;
52 | fi
53 | }
54 |
55 | . tests/common.sh $0
56 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_retains_all_files/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "data.local_file.awscli_results_file",
4 | "problems": [
5 | "An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied"
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_retains_all_files/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/script_retains_all_files/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "s3api",
6 | "list-objects",
7 | "--bucket=ryft-public-sample-data",
8 | "--no-sign-request"
9 | ],
10 | "aws_cli_query": "max_by(Contents, &Size)",
11 | "external_id": "",
12 | "profile": "",
13 | "region": "eu-west-1",
14 | "role_session_name": ""
15 | }
16 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_retains_all_files/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["s3api", "list-objects", "--bucket=ryft-public-sample-data", "--no-sign-request"]
2 | aws_cli_query = "max_by(Contents, &Size)"
3 | region = "eu-west-1"
4 |
5 | alternative_path = "test-reports/script_retains_all_files/aws"
6 |
--------------------------------------------------------------------------------
/tests/Require reworking/script_retains_all_files/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=true
4 |
5 | function test_teardown() {
6 | ROOT_DIRECTORY="test-reports/${TEST_NAME}/aws"
7 |
8 | # Build all the paths for all the files.
9 |
10 | ## Results file
11 | RESULTS_FILE="${ROOT_DIRECTORY}/results.json"
12 |
13 | ## JQ json and error log
14 | JQ_JSON="${ROOT_DIRECTORY}/jq_data.json"
15 | JQ_ERROR_LOG="${ROOT_DIRECTORY}/jq_error.log"
16 |
17 | ## AWS STS json and error log
18 | AWS_STS_JSON="${ROOT_DIRECTORY}/aws_sts.json"
19 | AWS_STS_ERROR_LOG="${ROOT_DIRECTORY}/aws_sts_error.log"
20 |
21 | ## The actual AWS call json and error log
22 | AWS_CALL_JSON="${ROOT_DIRECTORY}/aws_call.json"
23 | AWS_CALL_ERROR_LOG="${ROOT_DIRECTORY}/aws_call_error.log"
24 |
25 | # Not all the files are created as the test does not generate these errors
26 | AWS_SCRIPT_FILENAMES=(
27 | "${JQ_JSON}" "${JQ_ERROR_LOG}"
28 | "${AWS_STS_JSON}" "${AWS_STS_ERROR_LOG}"
29 | "${AWS_CALL_JSON}" "${AWS_CALL_ERROR_LOG}"
30 | )
31 |
32 | TEST_PASSED=true
33 | for AWS_SCRIPT_FILENAME in "${AWS_SCRIPT_FILENAMES[@]}"; do
34 | if [[ ! -f "${AWS_SCRIPT_FILENAME}" ]]; then
35 | echo "Failed to retain '${AWS_SCRIPT_FILENAME}'" | indent
36 | TEST_PASSED=false
37 | fi
38 | done
39 |
40 | if [ ! -f "${RESULTS_FILE}" ]; then
41 | echo "Failed to retain '${RESULTS_FILE}'" | indent
42 | TEST_PASSED=false
43 | fi
44 |
45 | if [ "${TEST_PASSED}" != "true" ]; then
46 | exit 1;
47 | fi
48 | }
49 |
50 | . tests/common.sh $0
51 |
--------------------------------------------------------------------------------
/tests/Require reworking/test_data_retrieval_with_empty_result/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/test_data_retrieval_with_empty_result/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "guardduty",
6 | "update-detector",
7 | "--finding-publishing-frequency",
8 | "ONE_HOUR",
9 | "--detector-id="
10 | ],
11 | "aws_cli_query": "",
12 | "external_id": "",
13 | "profile": "",
14 | "region": "",
15 | "role_session_name": "empty_result"
16 | }
17 |
--------------------------------------------------------------------------------
/tests/Require reworking/test_data_retrieval_with_empty_result/terraform.tfvars:
--------------------------------------------------------------------------------
1 | // An empty result from AWS
2 | aws_cli_commands = [
3 | "guardduty",
4 | "update-detector",
5 | "--finding-publishing-frequency",
6 | "ONE_HOUR",
7 | "--detector-id="
8 | ]
9 | role_session_name = "empty_result"
10 |
11 | alternative_path = "test-reports/test_data_retrieval_with_empty_result/aws"
12 |
--------------------------------------------------------------------------------
/tests/Require reworking/test_data_retrieval_with_empty_result/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | function test_setup() {
4 | if [ -f .env ]; then
5 | . .env
6 | export ALLOW_APPLY=true
7 |
8 | EXISTING_DETECTOR_ID=$(aws guardduty list-detectors --query='DetectorIds[0]' | jq -cr .)
9 |
10 | if [ "${EXISTING_DETECTOR_ID}" == "null" ]; then
11 | DETECTOR_ID=$(aws guardduty create-detector --enable --output json | jq -r '.DetectorId')
12 | echo "Created detector : ${DETECTOR_ID}" | indent
13 | else
14 | DETECTOR_ID=${EXISTING_DETECTOR_ID}
15 | echo "Reusing detector : ${DETECTOR_ID}" | indent
16 | fi
17 |
18 | sed -i.bak 's/"--detector-id=.*"/"--detector-id='${DETECTOR_ID}'"/' $(dirname $0)/terraform.tfvars
19 | sed -i.bak 's/"--detector-id=.*"/"--detector-id='${DETECTOR_ID}'"/' $(dirname $0)/expected_variables.json
20 | rm -rf $(dirname $0)/terraform.tfvars.bak
21 | rm -rf $(dirname $0)/expected_variables.json.bak
22 |
23 | else
24 | export ALLOW_PLAN=false
25 | export ALLOW_APPLY=false
26 | echo 'Test skipped as AWS credentials are required in the .env file.' | indent
27 | fi
28 | }
29 |
30 | function test_teardown() {
31 | if [ -f .env ]; then
32 | aws guardduty delete-detector --detector-id $DETECTOR_ID
33 | echo "Deleted detector : ${DETECTOR_ID}" | indent
34 |
35 | DETECTOR_ID=01234567890123456789012345678901
36 | sed -i.bak 's/"--detector-id=.*"/"--detector-id='${DETECTOR_ID}'"/' $(dirname $0)/terraform.tfvars
37 | sed -i.bak 's/"--detector-id=.*"/"--detector-id='${DETECTOR_ID}'"/' $(dirname $0)/expected_variables.json
38 | rm -rf $(dirname $0)/terraform.tfvars.bak
39 | rm -rf $(dirname $0)/expected_variables.json.bak
40 | fi
41 | }
42 |
43 | . tests/common.sh $0
44 |
--------------------------------------------------------------------------------
/tests/aws_error_profile_does_not_exist/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "data.local_file.awscli_results_file",
4 | "problems": [
5 | "The config profile (non-existent-profile) could not be found"
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/aws_error_profile_does_not_exist/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/aws_error_profile_does_not_exist/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "s3api",
6 | "list-objects",
7 | "--bucket=ryft-public-sample-data",
8 | "--no-sign-request"
9 | ],
10 | "aws_cli_query": "max_by(Contents, &Size)",
11 | "external_id": "",
12 | "profile": "non-existent-profile",
13 | "region": "",
14 | "role_session_name": ""
15 | }
16 |
--------------------------------------------------------------------------------
/tests/aws_error_profile_does_not_exist/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["s3api", "list-objects", "--bucket=ryft-public-sample-data", "--no-sign-request"]
2 | aws_cli_query = "max_by(Contents, &Size)"
3 | profile = "non-existent-profile"
4 |
5 | alternative_path = "test-reports/aws_error_profile_does_not_exist/aws"
6 |
--------------------------------------------------------------------------------
/tests/aws_error_profile_does_not_exist/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/common.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | function underline() {
4 | U="${1//?/${2:--}}"
5 | echo -e "\n$1\n${U:0:${#1}}\n"
6 | }
7 |
8 | function indent() {
9 | if [ ! -z "$1" ]; then
10 | echo "$1" | sed 's/^/ /'
11 | else
12 | cat - | sed 's/^/ /'
13 | fi
14 | }
15 |
16 | function validate_init() {
17 | if [ ! -f "${TERRAFORM_INIT_LOG}" ]; then
18 | echo "FAILED : ${TERRAFORM_INIT_LOG} failed to be created"
19 | echo ''
20 | exit 11;
21 | fi
22 |
23 | if [ -s "${TERRAFORM_INIT_ERROR_LOG}" ]; then
24 | echo "FAILED : ${TERRAFORM_INIT_ERROR_LOG} is not empty"
25 | echo ""
26 | cat ${TERRAFORM_INIT_ERROR_LOG} | indent
27 | echo ''
28 | exit 12;
29 | fi
30 | }
31 |
32 | function validate_plan() {
33 | jq -r '
34 | .variables |
35 | walk(
36 | if type == "object" and has("value") then
37 | .value
38 | else
39 | .
40 | end
41 | )
42 | ' "${TERRAFORM_PLAN_SHOW_JSON}" > "${TERRAFORM_PLAN_SHOW_EXTRACTED_VARIABLES_JSON}"
43 |
44 | if [ -f "${EXPECTED_VARIABLES}" ]; then
45 | DIFFERENCE_IN_EXPECTED_VARIABLES=$(diff -U 3 -W 120 --suppress-common-lines "${EXPECTED_VARIABLES}" "${TERRAFORM_PLAN_SHOW_EXTRACTED_VARIABLES_JSON}")
46 | if [ ! -z "${DIFFERENCE_IN_EXPECTED_VARIABLES}" ]; then
47 | echo 'FAILED : Difference in expected variables'
48 | echo "${DIFFERENCE_IN_EXPECTED_VARIABLES}" | indent
49 | echo ''
50 | exit 21
51 | else
52 | echo 'Variables processed successfully' | indent
53 | fi
54 | fi
55 |
56 | jq -r '
57 | [
58 | .checks[] |
59 | select(.status == "fail") |
60 | {
61 | variable: .address.to_display,
62 | problems: .instances[].problems[].message
63 | }
64 | ] |
65 | group_by(.variable) |
66 | map(
67 | {
68 | variable: .[0].variable,
69 | problems: map(.problems)
70 | }
71 | ) |
72 | select(length > 0)
73 | ' "${TERRAFORM_PLAN_SHOW_JSON}" > "${TERRAFORM_PLAN_SHOW_EXTRACTED_ERRORS_JSON}"
74 |
75 | if [ -f "${EXPECTED_ERRORS}" ]; then
76 | DIFFERENCE_IN_EXPECTED_ERRORS=$(diff -U 3 -W 120 --suppress-common-lines "${EXPECTED_ERRORS}" "${TERRAFORM_PLAN_SHOW_EXTRACTED_ERRORS_JSON}")
77 | if [ ! -z "${DIFFERENCE_IN_EXPECTED_ERRORS}" ]; then
78 | echo 'FAILED : Difference in expected errors'
79 | echo "${DIFFERENCE_IN_EXPECTED_ERRORS}" | indent
80 | echo ''
81 | exit 22
82 | else
83 | echo 'Expected errors generated successfully' | indent
84 | fi
85 | else
86 | if [ -s "${TERRAFORM_PLAN_SHOW_EXTRACTED_ERRORS_JSON}" ]; then
87 | echo 'FAILED : Generated unexpected errors'
88 | cat "${TERRAFORM_PLAN_SHOW_EXTRACTED_ERRORS_JSON}" | indent
89 | echo ''
90 | exit 23
91 | else
92 | echo 'No unexpected errors generated' | indent
93 | fi
94 | fi
95 | }
96 |
97 | function validate_apply() {
98 | jq -r '
99 | .values.outputs |
100 | walk(
101 | if type == "object" and has("value") then
102 | .value
103 | else
104 | .
105 | end
106 | )
107 | ' "${TERRAFORM_APPLY_SHOW_JSON}" > "${TERRAFORM_APPLY_SHOW_EXTRACTED_OUTPUTS_JSON}"
108 |
109 | if [ -f "${EXPECTED_OUTPUTS}" ]; then
110 | DIFFERENCE_IN_EXPECTED_OUTPUTS=$(diff -U 3 -W 120 --suppress-common-lines "${EXPECTED_OUTPUTS}" "${TERRAFORM_APPLY_SHOW_EXTRACTED_OUTPUTS_JSON}")
111 | if [ ! -z "${DIFFERENCE_IN_EXPECTED_OUTPUTS}" ]; then
112 | echo 'FAILED : Difference in expected outputs'
113 | echo "${DIFFERENCE_IN_EXPECTED_OUTPUTS}" | indent
114 | echo ''
115 | exit 31
116 | else
117 | echo 'Expected outputs generated successfully' | indent
118 | fi
119 | else
120 | if [ -s "${TERRAFORM_APPLY_SHOW_EXTRACTED_OUTPUTS_JSON}" ]; then
121 | echo 'FAILED : Generated unexpected outputs'
122 | cat "${TERRAFORM_APPLY_SHOW_EXTRACTED_OUTPUTS_JSON}" | indent
123 | echo ''
124 | exit 32
125 | else
126 | echo 'No unexpected outputs generated' | indent
127 | fi
128 | fi
129 | }
130 |
131 | function run_function() {
132 | function_name="${1:-true}"
133 |
134 | if type -t "$function_name" > /dev/null; then
135 | echo "Running : $function_name" | indent
136 | "$function_name"
137 | fi
138 | }
139 |
140 | function common_setup() {
141 | TEST_PATH=$(dirname "${1}")
142 | TEST_NAME=$(basename "${TEST_PATH}")
143 |
144 | echo "Start : ${TEST_PATH}"
145 |
146 | TERRAFORM_TFVARS="${TEST_PATH}/terraform.tfvars"
147 | EXPECTED_VARIABLES="${TEST_PATH}/expected_variables.json"
148 | EXPECTED_ERRORS="${TEST_PATH}/expected_plan_errors.json"
149 | EXPECTED_OUTPUTS="${TEST_PATH}/expected_apply_outputs.json"
150 |
151 | ROOT_DIRECTORY="test-reports/${TEST_NAME}/terraform"
152 | mkdir -p "${ROOT_DIRECTORY}"
153 |
154 | ## Terraform init output, errors, and trace
155 | TERRAFORM_INIT_LOG="${ROOT_DIRECTORY}/init.log"
156 | TERRAFORM_INIT_ERROR_LOG="${ROOT_DIRECTORY}/init_error.log"
157 | TERRAFORM_INIT_TRACE_LOG="${ROOT_DIRECTORY}/init_trace.log"
158 |
159 | ## Terraform plan output, errors, and trace
160 | TERRAFORM_PLAN="${ROOT_DIRECTORY}/terraform.plan"
161 | TERRAFORM_PLAN_LOG="${ROOT_DIRECTORY}/plan.log"
162 | TERRAFORM_PLAN_ERROR_LOG="${ROOT_DIRECTORY}/plan_error.log"
163 | TERRAFORM_PLAN_TRACE_LOG="${ROOT_DIRECTORY}/plan_trace.log"
164 |
165 | ## Terraform show json, errors, and trace from plan
166 | TERRAFORM_PLAN_SHOW_JSON="${ROOT_DIRECTORY}/plan_show.json"
167 | TERRAFORM_PLAN_SHOW_ERROR_LOG="${ROOT_DIRECTORY}/plan_show_error.log"
168 | TERRAFORM_PLAN_SHOW_TRACE_LOG="${ROOT_DIRECTORY}/plan_show_trace.log"
169 |
170 | ## Extracted data
171 | TERRAFORM_PLAN_SHOW_EXTRACTED_VARIABLES_JSON="${ROOT_DIRECTORY}/plan_show_extracted_variables.json"
172 | TERRAFORM_PLAN_SHOW_EXTRACTED_ERRORS_JSON="${ROOT_DIRECTORY}/plan_show_extracted_errors.json"
173 | TERRAFORM_APPLY_SHOW_EXTRACTED_OUTPUTS_JSON="${ROOT_DIRECTORY}/apply_show_extracted_outputs.json"
174 |
175 | ## Terraform apply output, errors, and trace
176 | TERRAFORM_APPLY_STATE_FILE="${ROOT_DIRECTORY}/terraform.state"
177 | TERRAFORM_APPLY_LOG="${ROOT_DIRECTORY}/apply.log"
178 | TERRAFORM_APPLY_ERROR_LOG="${ROOT_DIRECTORY}/apply_error.log"
179 | TERRAFORM_APPLY_TRACE_LOG="${ROOT_DIRECTORY}/apply_trace.log"
180 |
181 | ## Terraform show json, errors, and trace from apply
182 | TERRAFORM_APPLY_SHOW_JSON="${ROOT_DIRECTORY}/apply_show.json"
183 | TERRAFORM_APPLY_SHOW_ERROR_LOG="${ROOT_DIRECTORY}/apply_show_error.log"
184 | TERRAFORM_APPLY_SHOW_TRACE_LOG="${ROOT_DIRECTORY}/apply_show_trace.log"
185 |
186 | # Some tests may not be able to be run
187 | export ALLOW_PLAN=true
188 |
189 | # Tell the AWS Script to hold onto all the log files
190 | export MODULE_TERRAFORM_AWS_CLI_RETAIN_LOGS=true
191 | }
192 |
193 | function run_test() {
194 | if [ "${ALLOW_PLAN}" == "true" ]; then
195 | # Turn off coloured Terraform output (makes logs a little easier to read in an IDE)
196 | export TF_CLI_ARGS="-no-color"
197 |
198 | # Enable full trace mode when running Terraform
199 | export TF_LOG=TRACE
200 |
201 | # Initialise Terraform.
202 | TF_LOG_PATH="${TERRAFORM_INIT_TRACE_LOG}" \
203 | terraform init \
204 | >"${TERRAFORM_INIT_LOG}" \
205 | 2> "${TERRAFORM_INIT_ERROR_LOG}"
206 | validate_init
207 |
208 | TF_LOG_PATH="${TERRAFORM_PLAN_TRACE_LOG}" \
209 | terraform plan \
210 | -var-file=${TERRAFORM_TFVARS} \
211 | -out=${TERRAFORM_PLAN} \
212 | >"${TERRAFORM_PLAN_LOG}" \
213 | 2> "${TERRAFORM_PLAN_ERROR_LOG}"
214 |
215 | TF_LOG_PATH="${TERRAFORM_PLAN_SHOW_TRACE_LOG}" \
216 | terraform show \
217 | -json \
218 | "${TERRAFORM_PLAN}" \
219 | >"${TERRAFORM_PLAN_SHOW_JSON}"
220 | validate_plan
221 |
222 | if [ "${ALLOW_APPLY}" == "true" ]; then
223 | TF_LOG_PATH="${TERRAFORM_APPLY_TRACE_LOG}" \
224 | terraform apply \
225 | -auto-approve \
226 | -backup=- \
227 | -state-out "${TERRAFORM_APPLY_STATE_FILE}" \
228 | "${TERRAFORM_PLAN}" \
229 | > "${TERRAFORM_APPLY_LOG}" \
230 | 2> "${TERRAFORM_APPLY_ERROR_LOG}"
231 |
232 | TF_LOG_PATH="${TERRAFORM_APPLY_SHOW_TRACE_LOG}" \
233 | terraform show \
234 | -json \
235 | "${TERRAFORM_APPLY_STATE_FILE}" \
236 | >"${TERRAFORM_APPLY_SHOW_JSON}" \
237 | 2>"${TERRAFORM_APPLY_SHOW_ERROR_LOG}"
238 |
239 | validate_apply
240 | fi
241 |
242 | run_function test_teardown
243 |
244 | echo "Passed : $TEST_PATH"
245 | else
246 | echo "Skipped : $TEST_PATH"
247 | fi
248 |
249 | echo ''
250 | }
251 |
252 | # Prepare everything for running the test that is common to all tests
253 | common_setup "${1}"
254 |
255 | # Prepare anything specific to the actual test (optional function in the tests test.sh script)
256 | run_function test_setup
257 |
258 | # Run the test! This will also, if required, run the optional test_teardown function if that exists.
259 | run_test
260 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_invalid_characters/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.external_id",
4 | "problems": [
5 | "The optional external_id must match the regular expression '^[\\w=,.@-]*$'."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_invalid_characters/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_external_id_invalid_characters/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "1 space 2",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_invalid_characters/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | external_id = "1 space 2"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_external_id_invalid_characters/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_invalid_characters/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.external_id",
4 | "problems": [
5 | "The length of optional external_id, when supplied, must be between 2 and 1224 characters."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_external_id_too_long/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "a1,b2.c3@d4-e5,f6.g7@h8-i9,j10.k11@l12-m13,n14.o15@p16-q17,r18.s19@t20-u21,v22.w23@x24-y25,z26.A27@B28-C29,D30.E31@F32-G33,H34.I35@J36-K37,L38.M39@N40-O41,P42.Q43@R44-S45,T46.U47@V48-W49,X50.Y51@Z52-a53,b54.c55@d56-e57,f58.g59@h60-i61,j62.k63@l64-m65,n66.o67@p68-q69,r70.s71@t72-u73,v74.w75@x76-y77,z78.A79@B80-C81,D82.E83@F84-G85,H86.I87@J88-K89,L90.M91@N92-O93,P94.Q95@R96-S97,T98.U99@V100-W101,X102.Y103@Z104-a105,b106.c107@d108-e109,f110.g111@h112-i113,j114.k115@l116-m117,n118.o119@p120-q121,r122.s123@t124-u125,v126.w127@x128-y129,z130.A131@B132-C133,D134.E135@F136-G137,H138.I139@J140-K141,L142.M143@N144-O145,P146.Q147@R148-S149,T150.U151@V152-W153,X154.Y155@Z156-a157,b158.c159@d160-e161,f162.g163@h164-i165,j166.k167@l168-m169,n170.o171@p172-q173,r174.s175@t176-u177,v178.w179@x180-y181,z182.A183@B184-C185,D186.E187@F188-G189,H190.I191@J192-K193,L194.M195@N196-O197,P198.Q199@R200-S201,T202.U203@V204-W205,X206.Y207@Z208-a209,b210.c211@d212-e213,f214.g215@h216-i217,j218.k219@l220-m221,n222.o223@p224-q225,r226.s227@t228-u229,v230.w231@x232-y233,z234.A235@B236-C237,D238.E239@F240-G241,H242.I243@J244-K245,L246.M247@N248-O249,P250.Q251@R252-S253,T254.U255@V256-W257,X258.Y259@Z260-a261,b262.c263@d264-e265,f266.g26",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | external_id = "a1,b2.c3@d4-e5,f6.g7@h8-i9,j10.k11@l12-m13,n14.o15@p16-q17,r18.s19@t20-u21,v22.w23@x24-y25,z26.A27@B28-C29,D30.E31@F32-G33,H34.I35@J36-K37,L38.M39@N40-O41,P42.Q43@R44-S45,T46.U47@V48-W49,X50.Y51@Z52-a53,b54.c55@d56-e57,f58.g59@h60-i61,j62.k63@l64-m65,n66.o67@p68-q69,r70.s71@t72-u73,v74.w75@x76-y77,z78.A79@B80-C81,D82.E83@F84-G85,H86.I87@J88-K89,L90.M91@N92-O93,P94.Q95@R96-S97,T98.U99@V100-W101,X102.Y103@Z104-a105,b106.c107@d108-e109,f110.g111@h112-i113,j114.k115@l116-m117,n118.o119@p120-q121,r122.s123@t124-u125,v126.w127@x128-y129,z130.A131@B132-C133,D134.E135@F136-G137,H138.I139@J140-K141,L142.M143@N144-O145,P146.Q147@R148-S149,T150.U151@V152-W153,X154.Y155@Z156-a157,b158.c159@d160-e161,f162.g163@h164-i165,j166.k167@l168-m169,n170.o171@p172-q173,r174.s175@t176-u177,v178.w179@x180-y181,z182.A183@B184-C185,D186.E187@F188-G189,H190.I191@J192-K193,L194.M195@N196-O197,P198.Q199@R200-S201,T202.U203@V204-W205,X206.Y207@Z208-a209,b210.c211@d212-e213,f214.g215@h216-i217,j218.k219@l220-m221,n222.o223@p224-q225,r226.s227@t228-u229,v230.w231@x232-y233,z234.A235@B236-C237,D238.E239@F240-G241,H242.I243@J244-K245,L246.M247@N248-O249,P250.Q251@R252-S253,T254.U255@V256-W257,X258.Y259@Z260-a261,b262.c263@d264-e265,f266.g26"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_external_id_too_long/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long_and_invalid_characters/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.external_id",
4 | "problems": [
5 | "The length of optional external_id, when supplied, must be between 2 and 1224 characters.",
6 | "The optional external_id must match the regular expression '^[\\w=,.@-]*$'."
7 | ]
8 | }
9 | ]
10 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long_and_invalid_characters/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_external_id_too_long_and_invalid_characters/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "a1,b2.c3 d4-e5,f6.g7 h8-i9,j10.k11 l12-m13,n14.o15 p16-q17,r18.s19 t20-u21,v22.w23 x24-y25,z26.A27 B28-C29,D30.E31 F32-G33,H34.I35 J36-K37,L38.M39 N40-O41,P42.Q43 R44-S45,T46.U47 V48-W49,X50.Y51 Z52-a53,b54.c55 d56-e57,f58.g59 h60-i61,j62.k63 l64-m65,n66.o67 p68-q69,r70.s71 t72-u73,v74.w75 x76-y77,z78.A79 B80-C81,D82.E83 F84-G85,H86.I87 J88-K89,L90.M91 N92-O93,P94.Q95 R96-S97,T98.U99 V100-W101,X102.Y103 Z104-a105,b106.c107 d108-e109,f110.g111 h112-i113,j114.k115 l116-m117,n118.o119 p120-q121,r122.s123 t124-u125,v126.w127 x128-y129,z130.A131 B132-C133,D134.E135 F136-G137,H138.I139 J140-K141,L142.M143 N144-O145,P146.Q147 R148-S149,T150.U151 V152-W153,X154.Y155 Z156-a157,b158.c159 d160-e161,f162.g163 h164-i165,j166.k167 l168-m169,n170.o171 p172-q173,r174.s175 t176-u177,v178.w179 x180-y181,z182.A183 B184-C185,D186.E187 F188-G189,H190.I191 J192-K193,L194.M195 N196-O197,P198.Q199 R200-S201,T202.U203 V204-W205,X206.Y207 Z208-a209,b210.c211 d212-e213,f214.g215 h216-i217,j218.k219 l220-m221,n222.o223 p224-q225,r226.s227 t228-u229,v230.w231 x232-y233,z234.A235 B236-C237,D238.E239 F240-G241,H242.I243 J244-K245,L246.M247 N248-O249,P250.Q251 R252-S253,T254.U255 V256-W257,X258.Y259 Z260-a261,b262.c263 d264-e265,f266.g26",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long_and_invalid_characters/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | external_id = "a1,b2.c3 d4-e5,f6.g7 h8-i9,j10.k11 l12-m13,n14.o15 p16-q17,r18.s19 t20-u21,v22.w23 x24-y25,z26.A27 B28-C29,D30.E31 F32-G33,H34.I35 J36-K37,L38.M39 N40-O41,P42.Q43 R44-S45,T46.U47 V48-W49,X50.Y51 Z52-a53,b54.c55 d56-e57,f58.g59 h60-i61,j62.k63 l64-m65,n66.o67 p68-q69,r70.s71 t72-u73,v74.w75 x76-y77,z78.A79 B80-C81,D82.E83 F84-G85,H86.I87 J88-K89,L90.M91 N92-O93,P94.Q95 R96-S97,T98.U99 V100-W101,X102.Y103 Z104-a105,b106.c107 d108-e109,f110.g111 h112-i113,j114.k115 l116-m117,n118.o119 p120-q121,r122.s123 t124-u125,v126.w127 x128-y129,z130.A131 B132-C133,D134.E135 F136-G137,H138.I139 J140-K141,L142.M143 N144-O145,P146.Q147 R148-S149,T150.U151 V152-W153,X154.Y155 Z156-a157,b158.c159 d160-e161,f162.g163 h164-i165,j166.k167 l168-m169,n170.o171 p172-q173,r174.s175 t176-u177,v178.w179 x180-y181,z182.A183 B184-C185,D186.E187 F188-G189,H190.I191 J192-K193,L194.M195 N196-O197,P198.Q199 R200-S201,T202.U203 V204-W205,X206.Y207 Z208-a209,b210.c211 d212-e213,f214.g215 h216-i217,j218.k219 l220-m221,n222.o223 p224-q225,r226.s227 t228-u229,v230.w231 x232-y233,z234.A235 B236-C237,D238.E239 F240-G241,H242.I243 J244-K245,L246.M247 N248-O249,P250.Q251 R252-S253,T254.U255 V256-W257,X258.Y259 Z260-a261,b262.c263 d264-e265,f266.g26"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_external_id_too_long_and_invalid_characters/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_long_and_invalid_characters/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_short/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.external_id",
4 | "problems": [
5 | "The length of optional external_id, when supplied, must be between 2 and 1224 characters."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_short/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_external_id_too_short/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "1",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_short/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | external_id = "1"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_external_id_too_short/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_external_id_too_short/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_invalid_role_arn/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.assume_role_arn",
4 | "problems": [
5 | "The optional ARN must match the format documented in https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_invalid_role_arn/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_invalid_role_arn/aws",
3 | "assume_role_arn": "bad_arn",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_invalid_role_arn/terraform.tfvars:
--------------------------------------------------------------------------------
1 | assume_role_arn = "bad_arn"
2 | aws_cli_commands = ["version"]
3 |
4 | alternative_path = "test-reports/terraform_validation_error_invalid_role_arn/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_invalid_role_arn/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_match_regex/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.profile",
4 | "problems": [
5 | "The optional profile must start with a letter and can only contain letters, numbers, hyphens, and underscores."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_match_regex/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_profile_does_not_match_regex/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "Spaces are not allowed",
10 | "region": "",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_match_regex/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | profile = "Spaces are not allowed"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_profile_does_not_match_regex/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_match_regex/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_start_with_a_letter/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.profile",
4 | "problems": [
5 | "The optional profile must start with a letter and can only contain letters, numbers, hyphens, and underscores."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_start_with_a_letter/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_profile_does_not_start_with_a_letter/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "1digit2many",
10 | "region": "",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_start_with_a_letter/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | profile = "1digit2many"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_profile_does_not_start_with_a_letter/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_profile_does_not_start_with_a_letter/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_region_does_not_match_regex/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.region",
4 | "problems": [
5 | "The optional region must start with two letters representing the geographical area, followed by one or more letters or digits representing the specific region within that area."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_region_does_not_match_regex/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_region_does_not_match_regex/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "",
10 | "region": "US East (Ohio) us-east-2",
11 | "role_session_name": ""
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_region_does_not_match_regex/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | region = "US East (Ohio) us-east-2"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_region_does_not_match_regex/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_region_does_not_match_regex/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_invalid_characters/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.role_session_name",
4 | "problems": [
5 | "The role session name match the regular expression '^[\\w=,.@-]*$'."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_invalid_characters/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_role_session_name_invalid_characters/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": "1 space 2"
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_invalid_characters/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | role_session_name = "1 space 2"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_role_session_name_invalid_characters/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_invalid_characters/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.role_session_name",
4 | "problems": [
5 | "The length of the optional role session name, when supplied, must be between 2 and 64 characters."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_role_session_name_too_long/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": "a1,b2.c3@d4-e5,f6.g7@h8-i9,j10.k11@l12-m13,n14.o15@p16-q17,r18.s1"
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | role_session_name = "a1,b2.c3@d4-e5,f6.g7@h8-i9,j10.k11@l12-m13,n14.o15@p16-q17,r18.s1"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_role_session_name_too_long/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long_and_invalid_characters/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.role_session_name",
4 | "problems": [
5 | "The length of the optional role session name, when supplied, must be between 2 and 64 characters.",
6 | "The role session name match the regular expression '^[\\w=,.@-]*$'."
7 | ]
8 | }
9 | ]
10 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long_and_invalid_characters/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_role_session_name_too_long_and_invalid_characters/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": "a1,b2.c3 d4-e5,f6.g7 h8-i9,j10.k11 l12-m13,n14.o15 p16-q17,r18.s1"
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long_and_invalid_characters/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | role_session_name = "a1,b2.c3 d4-e5,f6.g7 h8-i9,j10.k11 l12-m13,n14.o15 p16-q17,r18.s1"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_role_session_name_too_long_and_invalid_characters/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_long_and_invalid_characters/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_short/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "var.role_session_name",
4 | "problems": [
5 | "The length of the optional role session name, when supplied, must be between 2 and 64 characters."
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_short/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/terraform_validation_error_role_session_name_too_short/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "version"
6 | ],
7 | "aws_cli_query": "",
8 | "external_id": "",
9 | "profile": "",
10 | "region": "",
11 | "role_session_name": "1"
12 | }
13 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_short/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["version"]
2 | role_session_name = "1"
3 |
4 | alternative_path = "test-reports/terraform_validation_error_role_session_name_too_short/aws"
5 |
--------------------------------------------------------------------------------
/tests/terraform_validation_error_role_session_name_too_short/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=false
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/test_data_retrieval_with_no_role_arn_and_error/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "data.local_file.awscli_results_file",
4 | "problems": [
5 | "An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied"
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/test_data_retrieval_with_no_role_arn_and_error/expected_variables.json:
--------------------------------------------------------------------------------
1 | {
2 | "alternative_path": "test-reports/test_data_retrieval_with_no_role_arn_and_error/aws",
3 | "assume_role_arn": "",
4 | "aws_cli_commands": [
5 | "s3api",
6 | "list-objects",
7 | "--bucket=ryft-public-sample-data",
8 | "--no-sign-request"
9 | ],
10 | "aws_cli_query": "max_by(Contents, &Size)",
11 | "external_id": "",
12 | "profile": "",
13 | "region": "eu-west-1",
14 | "role_session_name": ""
15 | }
16 |
--------------------------------------------------------------------------------
/tests/test_data_retrieval_with_no_role_arn_and_error/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = ["s3api", "list-objects", "--bucket=ryft-public-sample-data", "--no-sign-request"]
2 | aws_cli_query = "max_by(Contents, &Size)"
3 | region = "eu-west-1"
4 |
5 | alternative_path = "test-reports/test_data_retrieval_with_no_role_arn_and_error/aws"
6 |
--------------------------------------------------------------------------------
/tests/test_data_retrieval_with_no_role_arn_and_error/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=true
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/test_empty_command/expected_plan_errors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "variable": "data.local_file.awscli_results_file",
4 | "problems": [
5 | "usage: aws [options] [ ...] [parameters]\nTo see help text, you can run:\n\n aws help\n aws help\n aws help\n\naws: error: the following arguments are required: command"
6 | ]
7 | }
8 | ]
9 |
--------------------------------------------------------------------------------
/tests/test_empty_command/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = []
2 | region = "eu-west-1"
3 |
4 | alternative_path = "test-reports/test_empty_command/aws"
5 |
--------------------------------------------------------------------------------
/tests/test_empty_command/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=true
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/test_version_retrieval_will_error/expected_apply_outputs.json:
--------------------------------------------------------------------------------
1 | {
2 | "result": "",
3 | "result_raw": "$AWS_CLI_VERSION\n",
4 | "result_was_decoded": false
5 | }
6 |
--------------------------------------------------------------------------------
/tests/test_version_retrieval_will_error/terraform.tfvars:
--------------------------------------------------------------------------------
1 | aws_cli_commands = [
2 | "--version",
3 | ]
4 | region = "eu-west-1"
5 |
6 | alternative_path = "test-reports/test_version_retrieval_will_error/aws"
7 |
--------------------------------------------------------------------------------
/tests/test_version_retrieval_will_error/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | export ALLOW_APPLY=true
4 |
5 | . tests/common.sh $0
6 |
--------------------------------------------------------------------------------
/tests/tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | function underline() {
4 | U="${1//?/${2:--}}"
5 | echo -e "\n$1\n${U:0:${#1}}\n"
6 | }
7 |
8 | set -e
9 | rm -rf temp
10 | rm -rf test-reports
11 |
12 | underline 'Running tests' =
13 |
14 | find ./tests -type f -name test.sh -maxdepth 2 | sort | xargs -L 1 bash
15 |
--------------------------------------------------------------------------------
/variables.tf:
--------------------------------------------------------------------------------
1 | # Variables related to calling AWS CLI
2 | variable "aws_cli_commands" {
3 | description = <= 2 && length(var.external_id) <= 1224)
56 | error_message = "The length of optional external_id, when supplied, must be between 2 and 1224 characters."
57 | }
58 |
59 | validation {
60 | condition = can(regex("^[\\w=,.@-]*$", var.external_id))
61 | error_message = "The optional external_id must match the regular expression '^[\\w=,.@-]*$'."
62 | }
63 | }
64 |
65 | variable "profile" {
66 | description = <= 2 && length(var.role_session_name) <= 64)
110 | error_message = "The length of the optional role session name, when supplied, must be between 2 and 64 characters."
111 | }
112 |
113 | validation {
114 | condition = can(regex("^[\\w=,.@-]*$", var.role_session_name))
115 | error_message = "The role session name match the regular expression '^[\\w=,.@-]*$'."
116 | }
117 | }
118 |
119 | # Variable for debugging
120 | variable "alternative_path" {
121 | description = "Use an alternative path for all files produced internally"
122 | type = string
123 | default = ""
124 | }
125 |
--------------------------------------------------------------------------------
/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.6.0"
3 | required_providers {
4 | external = {
5 | source = "hashicorp/external"
6 | version = "~> 2.0"
7 | }
8 | local = {
9 | source = "hashicorp/local"
10 | version = "~> 2.0"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------