├── .circleci ├── config.yml └── gpg.private.enc ├── .envrc ├── .git-crypt ├── .gitattributes └── keys │ └── default │ └── 0 │ ├── 41D2606F66C3FF28874362B61A16916844CE9D82.gpg │ ├── 933E3994686DC15C99D1369844037399AEDB1D8D.gpg │ ├── C0C40EAB26F642004F894370379FF7A159431A89.gpg │ └── D164A61C69E23C0F74475FBE5FFE76AD095FCA07.gpg ├── .gitattributes ├── .github └── dependabot.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .ruby-version ├── .tool-versions ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Rakefile ├── accounts.tf ├── config ├── defaults.yaml ├── gpg │ ├── jonas.gpg.public │ ├── liam.gpg.public │ └── toby.gpg.public ├── hiera.yaml ├── roles │ ├── basic.yaml │ ├── prerequisites.yaml │ └── root.yaml └── secrets │ ├── .unlocked │ ├── ci │ ├── aws-credentials.sh │ ├── encryption.passphrase │ ├── gpg.private │ ├── gpg.public │ ├── ssh.private │ └── ssh.public │ ├── circle_ci │ └── config.yaml │ └── github │ └── config.yaml ├── examples └── basic │ ├── .terraform.lock.hcl │ ├── organization.tf │ ├── outputs.tf │ ├── prerequisites.tf │ ├── provider.tf │ ├── terraform.tf │ └── variables.tf ├── go ├── lib ├── paths.rb └── version.rb ├── main.tf ├── organization.tf ├── organizational_units.tf ├── outputs.tf ├── scripts └── ci │ ├── common │ ├── configure-git.sh │ ├── install-git-crypt.sh │ ├── install-gpg-key.sh │ └── install-orb-deps.sh │ └── steps │ ├── build.sh │ ├── merge-pull-request.sh │ ├── prerelease.sh │ ├── release.sh │ └── test.sh ├── spec └── unit │ ├── accounts_spec.rb │ ├── infra │ ├── prerequisites │ │ ├── .terraform.lock.hcl │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── provider.tf │ │ ├── terraform.tf │ │ └── variables.tf │ └── root │ │ ├── .terraform.lock.hcl │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── provider.tf │ │ ├── terraform.tf │ │ └── variables.tf │ ├── organization_spec.rb │ ├── organizational_units_spec.rb │ └── spec_helper.rb ├── terraform.tf └── variables.tf /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | queue: eddiewebb/queue@1.6.4 5 | slack: circleci/slack@4.8.3 6 | 7 | defaults: &defaults 8 | docker: 9 | - image: ruby:3.1.1 10 | 11 | slack_context: &slack_context 12 | context: 13 | - slack 14 | 15 | only_main: &only_main 16 | filters: 17 | branches: 18 | only: 19 | - main 20 | 21 | only_dependabot: &only_dependabot 22 | filters: 23 | branches: 24 | only: 25 | - /^dependabot.*/ 26 | 27 | only_main_and_dependabot: &only_main_and_dependabot 28 | filters: 29 | branches: 30 | only: 31 | - main 32 | - /^dependabot.*/ 33 | 34 | commands: 35 | notify: 36 | steps: 37 | - when: 38 | condition: 39 | matches: 40 | pattern: "^dependabot.*" 41 | value: << pipeline.git.branch >> 42 | steps: 43 | - slack/notify: 44 | event: fail 45 | channel: builds-dependabot 46 | template: SLACK_FAILURE_NOTIFICATION 47 | - slack/notify: 48 | event: pass 49 | channel: builds-dependabot 50 | template: SLACK_SUCCESS_NOTIFICATION 51 | - when: 52 | condition: 53 | matches: 54 | pattern: "^(?!dependabot).*" 55 | value: << pipeline.git.branch >> 56 | steps: 57 | - slack/notify: 58 | event: fail 59 | channel: dev 60 | template: SLACK_FAILURE_NOTIFICATION 61 | - slack/notify: 62 | event: pass 63 | channel: builds 64 | template: SLACK_SUCCESS_NOTIFICATION 65 | configure_tools: 66 | steps: 67 | - run: ./scripts/ci/common/install-git-crypt.sh 68 | - run: ./scripts/ci/common/install-gpg-key.sh 69 | - run: ./scripts/ci/common/install-orb-deps.sh 70 | - run: ./scripts/ci/common/configure-git.sh 71 | 72 | jobs: 73 | build: 74 | <<: *defaults 75 | steps: 76 | - checkout 77 | - configure_tools 78 | - queue/until_front_of_line: 79 | consider-branch: false 80 | - run: ./scripts/ci/steps/build.sh 81 | - notify 82 | 83 | test: 84 | <<: *defaults 85 | steps: 86 | - checkout 87 | - configure_tools 88 | - run: ./scripts/ci/steps/test.sh 89 | - store_artifacts: 90 | path: build/logs 91 | - store_artifacts: 92 | path: state 93 | - notify 94 | 95 | prerelease: 96 | <<: *defaults 97 | steps: 98 | - checkout 99 | - configure_tools 100 | - run: ./scripts/ci/steps/prerelease.sh 101 | - notify 102 | 103 | release: 104 | <<: *defaults 105 | steps: 106 | - checkout 107 | - configure_tools 108 | - run: ./scripts/ci/steps/release.sh 109 | - notify 110 | 111 | merge_pull_request: 112 | <<: *defaults 113 | steps: 114 | - checkout 115 | - configure_tools 116 | - run: ./scripts/ci/steps/merge-pull-request.sh 117 | - notify 118 | 119 | workflows: 120 | version: 2 121 | pipeline: 122 | jobs: 123 | - build: 124 | <<: *only_main_and_dependabot 125 | <<: *slack_context 126 | - test: 127 | <<: *only_main_and_dependabot 128 | <<: *slack_context 129 | requires: 130 | - build 131 | - merge_pull_request: 132 | <<: *only_dependabot 133 | <<: *slack_context 134 | requires: 135 | - test 136 | - prerelease: 137 | <<: *only_main 138 | <<: *slack_context 139 | requires: 140 | - test 141 | - slack/on-hold: 142 | <<: *only_main 143 | <<: *slack_context 144 | requires: 145 | - prerelease 146 | channel: release 147 | template: SLACK_ON_HOLD_NOTIFICATION 148 | - hold: 149 | <<: *only_main 150 | type: approval 151 | requires: 152 | - prerelease 153 | - slack/on-hold 154 | - release: 155 | <<: *only_main 156 | <<: *slack_context 157 | requires: 158 | - hold 159 | -------------------------------------------------------------------------------- /.circleci/gpg.private.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/.circleci/gpg.private.enc -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROJECT_DIR="$(pwd)" 4 | 5 | PATH_add "${PROJECT_DIR}" 6 | PATH_add "${PROJECT_DIR}"/vendor/**/bin 7 | 8 | if has asdf; then 9 | asdf install 10 | fi 11 | 12 | layout ruby 13 | layout node 14 | -------------------------------------------------------------------------------- /.git-crypt/.gitattributes: -------------------------------------------------------------------------------- 1 | # Do not edit this file. To specify the files to encrypt, create your own 2 | # .gitattributes file in the directory where your files are. 3 | * !filter !diff 4 | *.gpg binary 5 | -------------------------------------------------------------------------------- /.git-crypt/keys/default/0/41D2606F66C3FF28874362B61A16916844CE9D82.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/.git-crypt/keys/default/0/41D2606F66C3FF28874362B61A16916844CE9D82.gpg -------------------------------------------------------------------------------- /.git-crypt/keys/default/0/933E3994686DC15C99D1369844037399AEDB1D8D.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/.git-crypt/keys/default/0/933E3994686DC15C99D1369844037399AEDB1D8D.gpg -------------------------------------------------------------------------------- /.git-crypt/keys/default/0/C0C40EAB26F642004F894370379FF7A159431A89.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/.git-crypt/keys/default/0/C0C40EAB26F642004F894370379FF7A159431A89.gpg -------------------------------------------------------------------------------- /.git-crypt/keys/default/0/D164A61C69E23C0F74475FBE5FFE76AD095FCA07.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/.git-crypt/keys/default/0/D164A61C69E23C0F74475FBE5FFE76AD095FCA07.gpg -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | config/secrets/** filter=git-crypt diff=git-crypt 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "terraform" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | 9 | - package-ecosystem: "bundler" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # vim 2 | *.swp 3 | *.swo 4 | 5 | # IntelliJ 6 | .idea/ 7 | *.ipr 8 | *.iml 9 | *.iws 10 | 11 | # Build 12 | vendor/ 13 | build/ 14 | dist/ 15 | .bundle 16 | .rakeTasks 17 | .direnv 18 | 19 | # OS 20 | .DS_Store 21 | 22 | # Temporary 23 | run/pids/ 24 | run/logs/ 25 | *.log 26 | .tmp 27 | 28 | # RSpec 29 | .rspec_status 30 | 31 | # Terraform 32 | state/ 33 | .terraform 34 | *.tfplan 35 | *.tfstate 36 | *.tfstate.backup 37 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-rake 3 | - rubocop-rspec 4 | 5 | AllCops: 6 | NewCops: enable 7 | 8 | Layout/LineLength: 9 | Max: 80 10 | 11 | Metrics/BlockLength: 12 | AllowedMethods: 13 | - describe 14 | - context 15 | - shared_examples 16 | - it 17 | Exclude: 18 | - Rakefile 19 | 20 | Style/Documentation: 21 | Enabled: false 22 | 23 | RSpec/ExampleLength: 24 | Max: 40 25 | 26 | RSpec/DescribeClass: 27 | Enabled: false 28 | 29 | RSpec/InstanceVariable: 30 | Enabled: false 31 | 32 | RSpec/BeforeAfterAll: 33 | Enabled: false 34 | 35 | RSpec/MultipleMemoizedHelpers: 36 | Max: 10 37 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.1.1 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | ruby 3.1.1 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Unreleased 2 | 3 | IMPROVEMENTS: 4 | 5 | * Added an `enabled_policy_types` variable to allow passing through enabled 6 | policy types to the created organization. 7 | * Made `allow_iam_users_access_to_billing` on account definitions optional, 8 | defaulting to `true` as is the case when not provided to the AWS API. 9 | 10 | ## 2.0.0 (March 10th, 2023) 11 | 12 | BACKWARDS INCOMPATIBILITIES / NOTES: 13 | 14 | * This module is now compatible with Terraform 1.3 and higher. 15 | * The variables `organizational_units` and `accounts` have been replaced by a 16 | generic `organization` variable which describes the account hierarchy and the 17 | generated organizational units and accounts are inferred from this variable. 18 | See the `examples` directory for a basic example. 19 | * This module now uses organizational unit and account indexing by name rather 20 | than array index. This means that if you try to upgrade from 1.x.x the module 21 | will suggest that it needs to destroy all existing resources and create new 22 | ones. To overcome this you will need to manually update your Terraform state 23 | file. 24 | * This module now uses organizational unit and account output indexing by key 25 | rather than array index. This means that if you're leveraging the outputs in 26 | other modules you'll need to update the usage. 27 | 28 | ## 1.1.0 (October 12th, 2022) 29 | 30 | IMPROVEMENTS: 31 | 32 | * Any AWS provider with version greater than or equal to 3.29 can now be used 33 | with this module. 34 | * A new variable, `aws_service_access_principals`, can now be provided to 35 | configure the AWS service access principals for which integration is enabled 36 | in the organization. 37 | 38 | BACKWARDS INCOMPATIBILITIES / NOTES: 39 | 40 | * This module is now compatible with Terraform 1.0 and higher. 41 | 42 | ## 1.0.0 (May 28th, 2021) 43 | 44 | BACKWARDS INCOMPATIBILITIES / NOTES: 45 | 46 | * This module is now compatible with Terraform 0.14 and higher. 47 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of 9 | experience, nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or reject 41 | comments, commits, code, wiki edits, issues, and other contributions that are 42 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 43 | contributor for other behaviors that they deem inappropriate, threatening, 44 | offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at maintainers@infrablocks.io. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an 62 | incident. Further details of specific enforcement policies may be posted 63 | separately. 64 | 65 | Project maintainers who do not follow or enforce the Code of Conduct in good 66 | faith may face temporary or permanent repercussions as determined by other 67 | members of the project's leadership. 68 | 69 | ## Attribution 70 | 71 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 72 | version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 73 | 74 | [homepage]: http://contributor-covenant.org 75 | 76 | [version]: http://contributor-covenant.org/version/1/4/ 77 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | gem 'awspec' 6 | gem 'confidante' 7 | gem 'git' 8 | gem 'nokogiri' 9 | gem 'rake' 10 | gem 'rake_circle_ci' 11 | gem 'rake_git' 12 | gem 'rake_git_crypt' 13 | gem 'rake_github' 14 | gem 'rake_gpg' 15 | gem 'rake_ssh' 16 | gem 'rake_terraform' 17 | gem 'rspec' 18 | gem 'rspec-terraform' 19 | gem 'rubocop' 20 | gem 'rubocop-rake' 21 | gem 'rubocop-rspec' 22 | gem 'rubyzip' 23 | gem 'semantic' 24 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (7.1.3.4) 5 | base64 6 | bigdecimal 7 | concurrent-ruby (~> 1.0, >= 1.0.2) 8 | connection_pool (>= 2.2.5) 9 | drb 10 | i18n (>= 1.6, < 2) 11 | minitest (>= 5.1) 12 | mutex_m 13 | tzinfo (~> 2.0) 14 | addressable (2.8.7) 15 | public_suffix (>= 2.0.2, < 7.0) 16 | ast (2.4.3) 17 | aws-eventstream (1.3.0) 18 | aws-partitions (1.1043.0) 19 | aws-sdk (3.2.0) 20 | aws-sdk-resources (~> 3) 21 | aws-sdk-accessanalyzer (1.65.0) 22 | aws-sdk-core (~> 3, >= 3.216.0) 23 | aws-sigv4 (~> 1.5) 24 | aws-sdk-account (1.37.0) 25 | aws-sdk-core (~> 3, >= 3.216.0) 26 | aws-sigv4 (~> 1.5) 27 | aws-sdk-acm (1.82.0) 28 | aws-sdk-core (~> 3, >= 3.216.0) 29 | aws-sigv4 (~> 1.5) 30 | aws-sdk-acmpca (1.86.0) 31 | aws-sdk-core (~> 3, >= 3.216.0) 32 | aws-sigv4 (~> 1.5) 33 | aws-sdk-amplify (1.77.0) 34 | aws-sdk-core (~> 3, >= 3.216.0) 35 | aws-sigv4 (~> 1.5) 36 | aws-sdk-amplifybackend (1.44.0) 37 | aws-sdk-core (~> 3, >= 3.216.0) 38 | aws-sigv4 (~> 1.1) 39 | aws-sdk-amplifyuibuilder (1.38.0) 40 | aws-sdk-core (~> 3, >= 3.216.0) 41 | aws-sigv4 (~> 1.1) 42 | aws-sdk-apigateway (1.111.0) 43 | aws-sdk-core (~> 3, >= 3.216.0) 44 | aws-sigv4 (~> 1.5) 45 | aws-sdk-apigatewaymanagementapi (1.56.0) 46 | aws-sdk-core (~> 3, >= 3.216.0) 47 | aws-sigv4 (~> 1.1) 48 | aws-sdk-apigatewayv2 (1.69.0) 49 | aws-sdk-core (~> 3, >= 3.216.0) 50 | aws-sigv4 (~> 1.1) 51 | aws-sdk-appconfig (1.62.0) 52 | aws-sdk-core (~> 3, >= 3.216.0) 53 | aws-sigv4 (~> 1.5) 54 | aws-sdk-appconfigdata (1.33.0) 55 | aws-sdk-core (~> 3, >= 3.216.0) 56 | aws-sigv4 (~> 1.1) 57 | aws-sdk-appfabric (1.22.0) 58 | aws-sdk-core (~> 3, >= 3.216.0) 59 | aws-sigv4 (~> 1.1) 60 | aws-sdk-appflow (1.71.0) 61 | aws-sdk-core (~> 3, >= 3.216.0) 62 | aws-sigv4 (~> 1.5) 63 | aws-sdk-appintegrationsservice (1.46.0) 64 | aws-sdk-core (~> 3, >= 3.216.0) 65 | aws-sigv4 (~> 1.5) 66 | aws-sdk-applicationautoscaling (1.100.0) 67 | aws-sdk-core (~> 3, >= 3.216.0) 68 | aws-sigv4 (~> 1.5) 69 | aws-sdk-applicationcostprofiler (1.36.0) 70 | aws-sdk-core (~> 3, >= 3.216.0) 71 | aws-sigv4 (~> 1.5) 72 | aws-sdk-applicationdiscoveryservice (1.82.0) 73 | aws-sdk-core (~> 3, >= 3.216.0) 74 | aws-sigv4 (~> 1.5) 75 | aws-sdk-applicationinsights (1.60.0) 76 | aws-sdk-core (~> 3, >= 3.216.0) 77 | aws-sigv4 (~> 1.5) 78 | aws-sdk-applicationsignals (1.14.0) 79 | aws-sdk-core (~> 3, >= 3.216.0) 80 | aws-sigv4 (~> 1.5) 81 | aws-sdk-appmesh (1.74.0) 82 | aws-sdk-core (~> 3, >= 3.216.0) 83 | aws-sigv4 (~> 1.1) 84 | aws-sdk-appregistry (1.47.0) 85 | aws-sdk-core (~> 3, >= 3.216.0) 86 | aws-sigv4 (~> 1.5) 87 | aws-sdk-apprunner (1.52.0) 88 | aws-sdk-core (~> 3, >= 3.216.0) 89 | aws-sigv4 (~> 1.5) 90 | aws-sdk-appstream (1.104.0) 91 | aws-sdk-core (~> 3, >= 3.216.0) 92 | aws-sigv4 (~> 1.5) 93 | aws-sdk-appsync (1.98.0) 94 | aws-sdk-core (~> 3, >= 3.216.0) 95 | aws-sigv4 (~> 1.5) 96 | aws-sdk-apptest (1.11.0) 97 | aws-sdk-core (~> 3, >= 3.216.0) 98 | aws-sigv4 (~> 1.5) 99 | aws-sdk-arczonalshift (1.27.0) 100 | aws-sdk-core (~> 3, >= 3.216.0) 101 | aws-sigv4 (~> 1.5) 102 | aws-sdk-artifact (1.17.0) 103 | aws-sdk-core (~> 3, >= 3.216.0) 104 | aws-sigv4 (~> 1.5) 105 | aws-sdk-athena (1.99.0) 106 | aws-sdk-core (~> 3, >= 3.216.0) 107 | aws-sigv4 (~> 1.5) 108 | aws-sdk-auditmanager (1.60.0) 109 | aws-sdk-core (~> 3, >= 3.216.0) 110 | aws-sigv4 (~> 1.5) 111 | aws-sdk-augmentedairuntime (1.50.0) 112 | aws-sdk-core (~> 3, >= 3.216.0) 113 | aws-sigv4 (~> 1.5) 114 | aws-sdk-autoscaling (1.129.0) 115 | aws-sdk-core (~> 3, >= 3.216.0) 116 | aws-sigv4 (~> 1.5) 117 | aws-sdk-autoscalingplans (1.67.0) 118 | aws-sdk-core (~> 3, >= 3.216.0) 119 | aws-sigv4 (~> 1.5) 120 | aws-sdk-b2bi (1.25.0) 121 | aws-sdk-core (~> 3, >= 3.216.0) 122 | aws-sigv4 (~> 1.5) 123 | aws-sdk-backup (1.84.0) 124 | aws-sdk-core (~> 3, >= 3.216.0) 125 | aws-sigv4 (~> 1.5) 126 | aws-sdk-backupgateway (1.32.0) 127 | aws-sdk-core (~> 3, >= 3.216.0) 128 | aws-sigv4 (~> 1.1) 129 | aws-sdk-backupsearch (1.1.0) 130 | aws-sdk-core (~> 3, >= 3.216.0) 131 | aws-sigv4 (~> 1.5) 132 | aws-sdk-batch (1.108.0) 133 | aws-sdk-core (~> 3, >= 3.216.0) 134 | aws-sigv4 (~> 1.5) 135 | aws-sdk-bcmdataexports (1.16.0) 136 | aws-sdk-core (~> 3, >= 3.216.0) 137 | aws-sigv4 (~> 1.1) 138 | aws-sdk-bcmpricingcalculator (1.3.0) 139 | aws-sdk-core (~> 3, >= 3.216.0) 140 | aws-sigv4 (~> 1.5) 141 | aws-sdk-bedrock (1.34.0) 142 | aws-sdk-core (~> 3, >= 3.216.0) 143 | aws-sigv4 (~> 1.5) 144 | aws-sdk-bedrockagent (1.43.0) 145 | aws-sdk-core (~> 3, >= 3.216.0) 146 | aws-sigv4 (~> 1.5) 147 | aws-sdk-bedrockagentruntime (1.40.0) 148 | aws-sdk-core (~> 3, >= 3.216.0) 149 | aws-sigv4 (~> 1.5) 150 | aws-sdk-bedrockdataautomation (1.2.0) 151 | aws-sdk-core (~> 3, >= 3.216.0) 152 | aws-sigv4 (~> 1.5) 153 | aws-sdk-bedrockdataautomationruntime (1.2.0) 154 | aws-sdk-core (~> 3, >= 3.216.0) 155 | aws-sigv4 (~> 1.5) 156 | aws-sdk-bedrockruntime (1.36.0) 157 | aws-sdk-core (~> 3, >= 3.216.0) 158 | aws-sigv4 (~> 1.5) 159 | aws-sdk-billing (1.2.0) 160 | aws-sdk-core (~> 3, >= 3.216.0) 161 | aws-sigv4 (~> 1.5) 162 | aws-sdk-billingconductor (1.35.0) 163 | aws-sdk-core (~> 3, >= 3.216.0) 164 | aws-sigv4 (~> 1.1) 165 | aws-sdk-braket (1.48.0) 166 | aws-sdk-core (~> 3, >= 3.216.0) 167 | aws-sigv4 (~> 1.1) 168 | aws-sdk-budgets (1.80.0) 169 | aws-sdk-core (~> 3, >= 3.216.0) 170 | aws-sigv4 (~> 1.5) 171 | aws-sdk-chatbot (1.20.0) 172 | aws-sdk-core (~> 3, >= 3.216.0) 173 | aws-sigv4 (~> 1.5) 174 | aws-sdk-chime (1.97.0) 175 | aws-sdk-core (~> 3, >= 3.216.0) 176 | aws-sigv4 (~> 1.5) 177 | aws-sdk-chimesdkidentity (1.38.0) 178 | aws-sdk-core (~> 3, >= 3.216.0) 179 | aws-sigv4 (~> 1.5) 180 | aws-sdk-chimesdkmediapipelines (1.35.0) 181 | aws-sdk-core (~> 3, >= 3.216.0) 182 | aws-sigv4 (~> 1.5) 183 | aws-sdk-chimesdkmeetings (1.45.0) 184 | aws-sdk-core (~> 3, >= 3.216.0) 185 | aws-sigv4 (~> 1.5) 186 | aws-sdk-chimesdkmessaging (1.44.0) 187 | aws-sdk-core (~> 3, >= 3.216.0) 188 | aws-sigv4 (~> 1.5) 189 | aws-sdk-chimesdkvoice (1.35.0) 190 | aws-sdk-core (~> 3, >= 3.216.0) 191 | aws-sigv4 (~> 1.5) 192 | aws-sdk-cleanrooms (1.38.0) 193 | aws-sdk-core (~> 3, >= 3.216.0) 194 | aws-sigv4 (~> 1.5) 195 | aws-sdk-cleanroomsml (1.21.0) 196 | aws-sdk-core (~> 3, >= 3.216.0) 197 | aws-sigv4 (~> 1.5) 198 | aws-sdk-cloud9 (1.83.0) 199 | aws-sdk-core (~> 3, >= 3.216.0) 200 | aws-sigv4 (~> 1.5) 201 | aws-sdk-cloudcontrolapi (1.35.0) 202 | aws-sdk-core (~> 3, >= 3.216.0) 203 | aws-sigv4 (~> 1.5) 204 | aws-sdk-clouddirectory (1.70.0) 205 | aws-sdk-core (~> 3, >= 3.216.0) 206 | aws-sigv4 (~> 1.5) 207 | aws-sdk-cloudformation (1.125.0) 208 | aws-sdk-core (~> 3, >= 3.216.0) 209 | aws-sigv4 (~> 1.5) 210 | aws-sdk-cloudfront (1.109.0) 211 | aws-sdk-core (~> 3, >= 3.216.0) 212 | aws-sigv4 (~> 1.5) 213 | aws-sdk-cloudfrontkeyvaluestore (1.18.0) 214 | aws-sdk-core (~> 3, >= 3.216.0) 215 | aws-sigv4 (~> 1.1) 216 | aws-sdk-cloudhsm (1.66.0) 217 | aws-sdk-core (~> 3, >= 3.216.0) 218 | aws-sigv4 (~> 1.5) 219 | aws-sdk-cloudhsmv2 (1.72.0) 220 | aws-sdk-core (~> 3, >= 3.216.0) 221 | aws-sigv4 (~> 1.5) 222 | aws-sdk-cloudsearch (1.69.0) 223 | aws-sdk-core (~> 3, >= 3.216.0) 224 | aws-sigv4 (~> 1.5) 225 | aws-sdk-cloudsearchdomain (1.56.0) 226 | aws-sdk-core (~> 3, >= 3.216.0) 227 | aws-sigv4 (~> 1.5) 228 | aws-sdk-cloudtrail (1.99.0) 229 | aws-sdk-core (~> 3, >= 3.216.0) 230 | aws-sigv4 (~> 1.5) 231 | aws-sdk-cloudtraildata (1.24.0) 232 | aws-sdk-core (~> 3, >= 3.216.0) 233 | aws-sigv4 (~> 1.1) 234 | aws-sdk-cloudwatch (1.109.0) 235 | aws-sdk-core (~> 3, >= 3.216.0) 236 | aws-sigv4 (~> 1.5) 237 | aws-sdk-cloudwatchevents (1.86.0) 238 | aws-sdk-core (~> 3, >= 3.216.0) 239 | aws-sigv4 (~> 1.5) 240 | aws-sdk-cloudwatchevidently (1.36.0) 241 | aws-sdk-core (~> 3, >= 3.216.0) 242 | aws-sigv4 (~> 1.1) 243 | aws-sdk-cloudwatchlogs (1.107.0) 244 | aws-sdk-core (~> 3, >= 3.216.0) 245 | aws-sigv4 (~> 1.5) 246 | aws-sdk-cloudwatchrum (1.35.0) 247 | aws-sdk-core (~> 3, >= 3.216.0) 248 | aws-sigv4 (~> 1.1) 249 | aws-sdk-codeartifact (1.57.0) 250 | aws-sdk-core (~> 3, >= 3.216.0) 251 | aws-sigv4 (~> 1.5) 252 | aws-sdk-codebuild (1.140.0) 253 | aws-sdk-core (~> 3, >= 3.216.0) 254 | aws-sigv4 (~> 1.5) 255 | aws-sdk-codecatalyst (1.31.0) 256 | aws-sdk-core (~> 3, >= 3.216.0) 257 | aws-sdk-codecommit (1.81.0) 258 | aws-sdk-core (~> 3, >= 3.216.0) 259 | aws-sigv4 (~> 1.5) 260 | aws-sdk-codeconnections (1.16.0) 261 | aws-sdk-core (~> 3, >= 3.216.0) 262 | aws-sigv4 (~> 1.5) 263 | aws-sdk-codedeploy (1.80.0) 264 | aws-sdk-core (~> 3, >= 3.216.0) 265 | aws-sigv4 (~> 1.5) 266 | aws-sdk-codeguruprofiler (1.50.0) 267 | aws-sdk-core (~> 3, >= 3.216.0) 268 | aws-sigv4 (~> 1.1) 269 | aws-sdk-codegurureviewer (1.61.0) 270 | aws-sdk-core (~> 3, >= 3.216.0) 271 | aws-sigv4 (~> 1.5) 272 | aws-sdk-codegurusecurity (1.25.0) 273 | aws-sdk-core (~> 3, >= 3.216.0) 274 | aws-sigv4 (~> 1.1) 275 | aws-sdk-codepipeline (1.93.0) 276 | aws-sdk-core (~> 3, >= 3.216.0) 277 | aws-sigv4 (~> 1.5) 278 | aws-sdk-codestarconnections (1.56.0) 279 | aws-sdk-core (~> 3, >= 3.216.0) 280 | aws-sigv4 (~> 1.5) 281 | aws-sdk-codestarnotifications (1.47.0) 282 | aws-sdk-core (~> 3, >= 3.216.0) 283 | aws-sigv4 (~> 1.5) 284 | aws-sdk-cognitoidentity (1.68.0) 285 | aws-sdk-core (~> 3, >= 3.216.0) 286 | aws-sigv4 (~> 1.5) 287 | aws-sdk-cognitoidentityprovider (1.114.0) 288 | aws-sdk-core (~> 3, >= 3.216.0) 289 | aws-sigv4 (~> 1.5) 290 | aws-sdk-cognitosync (1.63.0) 291 | aws-sdk-core (~> 3, >= 3.216.0) 292 | aws-sigv4 (~> 1.5) 293 | aws-sdk-comprehend (1.96.0) 294 | aws-sdk-core (~> 3, >= 3.216.0) 295 | aws-sigv4 (~> 1.5) 296 | aws-sdk-comprehendmedical (1.65.0) 297 | aws-sdk-core (~> 3, >= 3.216.0) 298 | aws-sigv4 (~> 1.5) 299 | aws-sdk-computeoptimizer (1.73.0) 300 | aws-sdk-core (~> 3, >= 3.216.0) 301 | aws-sigv4 (~> 1.5) 302 | aws-sdk-configservice (1.124.0) 303 | aws-sdk-core (~> 3, >= 3.216.0) 304 | aws-sigv4 (~> 1.5) 305 | aws-sdk-connect (1.194.0) 306 | aws-sdk-core (~> 3, >= 3.216.0) 307 | aws-sigv4 (~> 1.5) 308 | aws-sdk-connectcampaignservice (1.29.0) 309 | aws-sdk-core (~> 3, >= 3.216.0) 310 | aws-sigv4 (~> 1.1) 311 | aws-sdk-connectcampaignsv2 (1.2.0) 312 | aws-sdk-core (~> 3, >= 3.216.0) 313 | aws-sigv4 (~> 1.5) 314 | aws-sdk-connectcases (1.37.0) 315 | aws-sdk-core (~> 3, >= 3.216.0) 316 | aws-sigv4 (~> 1.1) 317 | aws-sdk-connectcontactlens (1.39.0) 318 | aws-sdk-core (~> 3, >= 3.216.0) 319 | aws-sigv4 (~> 1.5) 320 | aws-sdk-connectparticipant (1.59.0) 321 | aws-sdk-core (~> 3, >= 3.216.0) 322 | aws-sigv4 (~> 1.5) 323 | aws-sdk-connectwisdomservice (1.43.0) 324 | aws-sdk-core (~> 3, >= 3.216.0) 325 | aws-sigv4 (~> 1.1) 326 | aws-sdk-controlcatalog (1.18.0) 327 | aws-sdk-core (~> 3, >= 3.216.0) 328 | aws-sigv4 (~> 1.5) 329 | aws-sdk-controltower (1.37.0) 330 | aws-sdk-core (~> 3, >= 3.216.0) 331 | aws-sigv4 (~> 1.5) 332 | aws-sdk-core (3.217.0) 333 | aws-eventstream (~> 1, >= 1.3.0) 334 | aws-partitions (~> 1, >= 1.992.0) 335 | aws-sigv4 (~> 1.9) 336 | jmespath (~> 1, >= 1.6.1) 337 | aws-sdk-costandusagereportservice (1.69.0) 338 | aws-sdk-core (~> 3, >= 3.216.0) 339 | aws-sigv4 (~> 1.5) 340 | aws-sdk-costexplorer (1.119.0) 341 | aws-sdk-core (~> 3, >= 3.216.0) 342 | aws-sigv4 (~> 1.5) 343 | aws-sdk-costoptimizationhub (1.20.0) 344 | aws-sdk-core (~> 3, >= 3.216.0) 345 | aws-sigv4 (~> 1.5) 346 | aws-sdk-customerprofiles (1.59.0) 347 | aws-sdk-core (~> 3, >= 3.216.0) 348 | aws-sigv4 (~> 1.5) 349 | aws-sdk-databasemigrationservice (1.112.0) 350 | aws-sdk-core (~> 3, >= 3.216.0) 351 | aws-sigv4 (~> 1.5) 352 | aws-sdk-dataexchange (1.62.0) 353 | aws-sdk-core (~> 3, >= 3.216.0) 354 | aws-sigv4 (~> 1.5) 355 | aws-sdk-datapipeline (1.63.0) 356 | aws-sdk-core (~> 3, >= 3.216.0) 357 | aws-sigv4 (~> 1.5) 358 | aws-sdk-datasync (1.96.0) 359 | aws-sdk-core (~> 3, >= 3.216.0) 360 | aws-sigv4 (~> 1.5) 361 | aws-sdk-datazone (1.30.0) 362 | aws-sdk-core (~> 3, >= 3.216.0) 363 | aws-sigv4 (~> 1.1) 364 | aws-sdk-dax (1.66.0) 365 | aws-sdk-core (~> 3, >= 3.216.0) 366 | aws-sigv4 (~> 1.5) 367 | aws-sdk-deadline (1.19.0) 368 | aws-sdk-core (~> 3, >= 3.216.0) 369 | aws-sigv4 (~> 1.5) 370 | aws-sdk-detective (1.62.0) 371 | aws-sdk-core (~> 3, >= 3.216.0) 372 | aws-sigv4 (~> 1.5) 373 | aws-sdk-devicefarm (1.82.0) 374 | aws-sdk-core (~> 3, >= 3.216.0) 375 | aws-sigv4 (~> 1.5) 376 | aws-sdk-devopsguru (1.55.0) 377 | aws-sdk-core (~> 3, >= 3.216.0) 378 | aws-sigv4 (~> 1.5) 379 | aws-sdk-directconnect (1.86.0) 380 | aws-sdk-core (~> 3, >= 3.216.0) 381 | aws-sigv4 (~> 1.5) 382 | aws-sdk-directoryservice (1.80.0) 383 | aws-sdk-core (~> 3, >= 3.216.0) 384 | aws-sigv4 (~> 1.5) 385 | aws-sdk-directoryservicedata (1.5.0) 386 | aws-sdk-core (~> 3, >= 3.216.0) 387 | aws-sigv4 (~> 1.1) 388 | aws-sdk-dlm (1.84.0) 389 | aws-sdk-core (~> 3, >= 3.216.0) 390 | aws-sigv4 (~> 1.5) 391 | aws-sdk-docdb (1.81.0) 392 | aws-sdk-core (~> 3, >= 3.216.0) 393 | aws-sigv4 (~> 1.5) 394 | aws-sdk-docdbelastic (1.27.0) 395 | aws-sdk-core (~> 3, >= 3.216.0) 396 | aws-sigv4 (~> 1.5) 397 | aws-sdk-drs (1.44.0) 398 | aws-sdk-core (~> 3, >= 3.216.0) 399 | aws-sigv4 (~> 1.1) 400 | aws-sdk-dsql (1.2.0) 401 | aws-sdk-core (~> 3, >= 3.216.0) 402 | aws-sigv4 (~> 1.5) 403 | aws-sdk-dynamodb (1.134.0) 404 | aws-sdk-core (~> 3, >= 3.216.0) 405 | aws-sigv4 (~> 1.5) 406 | aws-sdk-dynamodbstreams (1.71.0) 407 | aws-sdk-core (~> 3, >= 3.216.0) 408 | aws-sigv4 (~> 1.5) 409 | aws-sdk-ebs (1.54.0) 410 | aws-sdk-core (~> 3, >= 3.216.0) 411 | aws-sigv4 (~> 1.5) 412 | aws-sdk-ec2 (1.503.0) 413 | aws-sdk-core (~> 3, >= 3.216.0) 414 | aws-sigv4 (~> 1.5) 415 | aws-sdk-ec2instanceconnect (1.53.0) 416 | aws-sdk-core (~> 3, >= 3.216.0) 417 | aws-sigv4 (~> 1.5) 418 | aws-sdk-ecr (1.92.0) 419 | aws-sdk-core (~> 3, >= 3.216.0) 420 | aws-sigv4 (~> 1.5) 421 | aws-sdk-ecrpublic (1.43.0) 422 | aws-sdk-core (~> 3, >= 3.216.0) 423 | aws-sigv4 (~> 1.5) 424 | aws-sdk-ecs (1.176.0) 425 | aws-sdk-core (~> 3, >= 3.216.0) 426 | aws-sigv4 (~> 1.5) 427 | aws-sdk-efs (1.90.0) 428 | aws-sdk-core (~> 3, >= 3.216.0) 429 | aws-sigv4 (~> 1.5) 430 | aws-sdk-eks (1.127.0) 431 | aws-sdk-core (~> 3, >= 3.216.0) 432 | aws-sigv4 (~> 1.5) 433 | aws-sdk-eksauth (1.16.0) 434 | aws-sdk-core (~> 3, >= 3.216.0) 435 | aws-sigv4 (~> 1.1) 436 | aws-sdk-elasticache (1.120.0) 437 | aws-sdk-core (~> 3, >= 3.216.0) 438 | aws-sigv4 (~> 1.5) 439 | aws-sdk-elasticbeanstalk (1.82.0) 440 | aws-sdk-core (~> 3, >= 3.216.0) 441 | aws-sigv4 (~> 1.5) 442 | aws-sdk-elasticinference (1.50.0) 443 | aws-sdk-core (~> 3, >= 3.216.0) 444 | aws-sigv4 (~> 1.5) 445 | aws-sdk-elasticloadbalancing (1.69.0) 446 | aws-sdk-core (~> 3, >= 3.216.0) 447 | aws-sigv4 (~> 1.5) 448 | aws-sdk-elasticloadbalancingv2 (1.126.0) 449 | aws-sdk-core (~> 3, >= 3.216.0) 450 | aws-sigv4 (~> 1.5) 451 | aws-sdk-elasticsearchservice (1.98.0) 452 | aws-sdk-core (~> 3, >= 3.216.0) 453 | aws-sigv4 (~> 1.5) 454 | aws-sdk-elastictranscoder (1.67.0) 455 | aws-sdk-core (~> 3, >= 3.216.0) 456 | aws-sigv4 (~> 1.5) 457 | aws-sdk-emr (1.104.0) 458 | aws-sdk-core (~> 3, >= 3.216.0) 459 | aws-sigv4 (~> 1.5) 460 | aws-sdk-emrcontainers (1.50.0) 461 | aws-sdk-core (~> 3, >= 3.216.0) 462 | aws-sigv4 (~> 1.5) 463 | aws-sdk-emrserverless (1.40.0) 464 | aws-sdk-core (~> 3, >= 3.216.0) 465 | aws-sigv4 (~> 1.5) 466 | aws-sdk-entityresolution (1.24.0) 467 | aws-sdk-core (~> 3, >= 3.216.0) 468 | aws-sigv4 (~> 1.5) 469 | aws-sdk-eventbridge (1.75.0) 470 | aws-sdk-core (~> 3, >= 3.216.0) 471 | aws-sigv4 (~> 1.5) 472 | aws-sdk-finspace (1.49.0) 473 | aws-sdk-core (~> 3, >= 3.216.0) 474 | aws-sigv4 (~> 1.5) 475 | aws-sdk-finspacedata (1.47.0) 476 | aws-sdk-core (~> 3, >= 3.216.0) 477 | aws-sigv4 (~> 1.5) 478 | aws-sdk-firehose (1.87.0) 479 | aws-sdk-core (~> 3, >= 3.216.0) 480 | aws-sigv4 (~> 1.5) 481 | aws-sdk-fis (1.45.0) 482 | aws-sdk-core (~> 3, >= 3.216.0) 483 | aws-sigv4 (~> 1.5) 484 | aws-sdk-fms (1.88.0) 485 | aws-sdk-core (~> 3, >= 3.216.0) 486 | aws-sigv4 (~> 1.5) 487 | aws-sdk-forecastqueryservice (1.50.0) 488 | aws-sdk-core (~> 3, >= 3.216.0) 489 | aws-sigv4 (~> 1.5) 490 | aws-sdk-forecastservice (1.67.0) 491 | aws-sdk-core (~> 3, >= 3.216.0) 492 | aws-sigv4 (~> 1.5) 493 | aws-sdk-frauddetector (1.66.0) 494 | aws-sdk-core (~> 3, >= 3.216.0) 495 | aws-sigv4 (~> 1.5) 496 | aws-sdk-freetier (1.17.0) 497 | aws-sdk-core (~> 3, >= 3.216.0) 498 | aws-sigv4 (~> 1.1) 499 | aws-sdk-fsx (1.107.0) 500 | aws-sdk-core (~> 3, >= 3.216.0) 501 | aws-sigv4 (~> 1.5) 502 | aws-sdk-gamelift (1.99.0) 503 | aws-sdk-core (~> 3, >= 3.216.0) 504 | aws-sigv4 (~> 1.5) 505 | aws-sdk-geomaps (1.2.0) 506 | aws-sdk-core (~> 3, >= 3.216.0) 507 | aws-sigv4 (~> 1.5) 508 | aws-sdk-geoplaces (1.2.0) 509 | aws-sdk-core (~> 3, >= 3.216.0) 510 | aws-sigv4 (~> 1.5) 511 | aws-sdk-georoutes (1.2.0) 512 | aws-sdk-core (~> 3, >= 3.216.0) 513 | aws-sigv4 (~> 1.5) 514 | aws-sdk-glacier (1.74.0) 515 | aws-sdk-core (~> 3, >= 3.216.0) 516 | aws-sigv4 (~> 1.5) 517 | aws-sdk-globalaccelerator (1.74.0) 518 | aws-sdk-core (~> 3, >= 3.216.0) 519 | aws-sigv4 (~> 1.5) 520 | aws-sdk-glue (1.208.0) 521 | aws-sdk-core (~> 3, >= 3.216.0) 522 | aws-sigv4 (~> 1.5) 523 | aws-sdk-gluedatabrew (1.50.0) 524 | aws-sdk-core (~> 3, >= 3.216.0) 525 | aws-sigv4 (~> 1.5) 526 | aws-sdk-greengrass (1.77.0) 527 | aws-sdk-core (~> 3, >= 3.216.0) 528 | aws-sigv4 (~> 1.1) 529 | aws-sdk-greengrassv2 (1.52.0) 530 | aws-sdk-core (~> 3, >= 3.216.0) 531 | aws-sigv4 (~> 1.5) 532 | aws-sdk-groundstation (1.61.0) 533 | aws-sdk-core (~> 3, >= 3.216.0) 534 | aws-sigv4 (~> 1.5) 535 | aws-sdk-guardduty (1.110.0) 536 | aws-sdk-core (~> 3, >= 3.216.0) 537 | aws-sigv4 (~> 1.5) 538 | aws-sdk-health (1.76.0) 539 | aws-sdk-core (~> 3, >= 3.216.0) 540 | aws-sigv4 (~> 1.5) 541 | aws-sdk-healthlake (1.43.0) 542 | aws-sdk-core (~> 3, >= 3.216.0) 543 | aws-sigv4 (~> 1.5) 544 | aws-sdk-iam (1.115.0) 545 | aws-sdk-core (~> 3, >= 3.216.0) 546 | aws-sigv4 (~> 1.5) 547 | aws-sdk-identitystore (1.48.0) 548 | aws-sdk-core (~> 3, >= 3.216.0) 549 | aws-sigv4 (~> 1.1) 550 | aws-sdk-imagebuilder (1.76.0) 551 | aws-sdk-core (~> 3, >= 3.216.0) 552 | aws-sigv4 (~> 1.5) 553 | aws-sdk-importexport (1.57.0) 554 | aws-sdk-core (~> 3, >= 3.216.0) 555 | aws-sigv2 (~> 1.0) 556 | aws-sdk-inspector (1.71.0) 557 | aws-sdk-core (~> 3, >= 3.216.0) 558 | aws-sigv4 (~> 1.5) 559 | aws-sdk-inspector2 (1.46.0) 560 | aws-sdk-core (~> 3, >= 3.216.0) 561 | aws-sigv4 (~> 1.5) 562 | aws-sdk-inspectorscan (1.17.0) 563 | aws-sdk-core (~> 3, >= 3.216.0) 564 | aws-sigv4 (~> 1.1) 565 | aws-sdk-internetmonitor (1.33.0) 566 | aws-sdk-core (~> 3, >= 3.216.0) 567 | aws-sigv4 (~> 1.5) 568 | aws-sdk-invoicing (1.1.0) 569 | aws-sdk-core (~> 3, >= 3.216.0) 570 | aws-sigv4 (~> 1.5) 571 | aws-sdk-iot (1.143.0) 572 | aws-sdk-core (~> 3, >= 3.216.0) 573 | aws-sigv4 (~> 1.5) 574 | aws-sdk-iotanalytics (1.77.0) 575 | aws-sdk-core (~> 3, >= 3.216.0) 576 | aws-sigv4 (~> 1.5) 577 | aws-sdk-iotdataplane (1.71.0) 578 | aws-sdk-core (~> 3, >= 3.216.0) 579 | aws-sigv4 (~> 1.5) 580 | aws-sdk-iotdeviceadvisor (1.45.0) 581 | aws-sdk-core (~> 3, >= 3.216.0) 582 | aws-sigv4 (~> 1.5) 583 | aws-sdk-iotevents (1.62.0) 584 | aws-sdk-core (~> 3, >= 3.216.0) 585 | aws-sigv4 (~> 1.5) 586 | aws-sdk-ioteventsdata (1.55.0) 587 | aws-sdk-core (~> 3, >= 3.216.0) 588 | aws-sigv4 (~> 1.5) 589 | aws-sdk-iotfleethub (1.39.0) 590 | aws-sdk-core (~> 3, >= 3.216.0) 591 | aws-sigv4 (~> 1.5) 592 | aws-sdk-iotfleetwise (1.39.0) 593 | aws-sdk-core (~> 3, >= 3.216.0) 594 | aws-sigv4 (~> 1.5) 595 | aws-sdk-iotjobsdataplane (1.64.0) 596 | aws-sdk-core (~> 3, >= 3.216.0) 597 | aws-sigv4 (~> 1.5) 598 | aws-sdk-iotsecuretunneling (1.49.0) 599 | aws-sdk-core (~> 3, >= 3.216.0) 600 | aws-sigv4 (~> 1.5) 601 | aws-sdk-iotsitewise (1.80.0) 602 | aws-sdk-core (~> 3, >= 3.216.0) 603 | aws-sigv4 (~> 1.5) 604 | aws-sdk-iotthingsgraph (1.51.0) 605 | aws-sdk-core (~> 3, >= 3.216.0) 606 | aws-sigv4 (~> 1.5) 607 | aws-sdk-iottwinmaker (1.37.0) 608 | aws-sdk-core (~> 3, >= 3.216.0) 609 | aws-sigv4 (~> 1.1) 610 | aws-sdk-iotwireless (1.62.0) 611 | aws-sdk-core (~> 3, >= 3.216.0) 612 | aws-sigv4 (~> 1.5) 613 | aws-sdk-ivs (1.65.0) 614 | aws-sdk-core (~> 3, >= 3.216.0) 615 | aws-sigv4 (~> 1.5) 616 | aws-sdk-ivschat (1.38.0) 617 | aws-sdk-core (~> 3, >= 3.216.0) 618 | aws-sigv4 (~> 1.5) 619 | aws-sdk-ivsrealtime (1.36.0) 620 | aws-sdk-core (~> 3, >= 3.216.0) 621 | aws-sigv4 (~> 1.5) 622 | aws-sdk-kafka (1.87.0) 623 | aws-sdk-core (~> 3, >= 3.216.0) 624 | aws-sigv4 (~> 1.5) 625 | aws-sdk-kafkaconnect (1.35.0) 626 | aws-sdk-core (~> 3, >= 3.216.0) 627 | aws-sigv4 (~> 1.5) 628 | aws-sdk-kendra (1.95.0) 629 | aws-sdk-core (~> 3, >= 3.216.0) 630 | aws-sigv4 (~> 1.5) 631 | aws-sdk-kendraranking (1.26.0) 632 | aws-sdk-core (~> 3, >= 3.216.0) 633 | aws-sigv4 (~> 1.5) 634 | aws-sdk-keyspaces (1.35.0) 635 | aws-sdk-core (~> 3, >= 3.216.0) 636 | aws-sigv4 (~> 1.5) 637 | aws-sdk-kinesis (1.72.0) 638 | aws-sdk-core (~> 3, >= 3.216.0) 639 | aws-sigv4 (~> 1.5) 640 | aws-sdk-kinesisanalytics (1.67.0) 641 | aws-sdk-core (~> 3, >= 3.216.0) 642 | aws-sigv4 (~> 1.5) 643 | aws-sdk-kinesisanalyticsv2 (1.71.0) 644 | aws-sdk-core (~> 3, >= 3.216.0) 645 | aws-sigv4 (~> 1.5) 646 | aws-sdk-kinesisvideo (1.75.0) 647 | aws-sdk-core (~> 3, >= 3.216.0) 648 | aws-sigv4 (~> 1.5) 649 | aws-sdk-kinesisvideoarchivedmedia (1.72.0) 650 | aws-sdk-core (~> 3, >= 3.216.0) 651 | aws-sigv4 (~> 1.5) 652 | aws-sdk-kinesisvideomedia (1.64.0) 653 | aws-sdk-core (~> 3, >= 3.216.0) 654 | aws-sigv4 (~> 1.5) 655 | aws-sdk-kinesisvideosignalingchannels (1.46.0) 656 | aws-sdk-core (~> 3, >= 3.216.0) 657 | aws-sigv4 (~> 1.5) 658 | aws-sdk-kinesisvideowebrtcstorage (1.27.0) 659 | aws-sdk-core (~> 3, >= 3.216.0) 660 | aws-sigv4 (~> 1.1) 661 | aws-sdk-kms (1.97.0) 662 | aws-sdk-core (~> 3, >= 3.216.0) 663 | aws-sigv4 (~> 1.5) 664 | aws-sdk-lakeformation (1.66.0) 665 | aws-sdk-core (~> 3, >= 3.216.0) 666 | aws-sigv4 (~> 1.5) 667 | aws-sdk-lambda (1.145.0) 668 | aws-sdk-core (~> 3, >= 3.216.0) 669 | aws-sigv4 (~> 1.5) 670 | aws-sdk-launchwizard (1.18.0) 671 | aws-sdk-core (~> 3, >= 3.216.0) 672 | aws-sigv4 (~> 1.1) 673 | aws-sdk-lex (1.74.0) 674 | aws-sdk-core (~> 3, >= 3.216.0) 675 | aws-sigv4 (~> 1.5) 676 | aws-sdk-lexmodelbuildingservice (1.85.0) 677 | aws-sdk-core (~> 3, >= 3.216.0) 678 | aws-sigv4 (~> 1.5) 679 | aws-sdk-lexmodelsv2 (1.67.0) 680 | aws-sdk-core (~> 3, >= 3.216.0) 681 | aws-sigv4 (~> 1.5) 682 | aws-sdk-lexruntimev2 (1.47.0) 683 | aws-sdk-core (~> 3, >= 3.216.0) 684 | aws-sigv4 (~> 1.5) 685 | aws-sdk-licensemanager (1.68.0) 686 | aws-sdk-core (~> 3, >= 3.216.0) 687 | aws-sigv4 (~> 1.1) 688 | aws-sdk-licensemanagerlinuxsubscriptions (1.26.0) 689 | aws-sdk-core (~> 3, >= 3.216.0) 690 | aws-sigv4 (~> 1.5) 691 | aws-sdk-licensemanagerusersubscriptions (1.28.0) 692 | aws-sdk-core (~> 3, >= 3.216.0) 693 | aws-sigv4 (~> 1.5) 694 | aws-sdk-lightsail (1.105.0) 695 | aws-sdk-core (~> 3, >= 3.216.0) 696 | aws-sigv4 (~> 1.5) 697 | aws-sdk-locationservice (1.65.0) 698 | aws-sdk-core (~> 3, >= 3.216.0) 699 | aws-sigv4 (~> 1.1) 700 | aws-sdk-lookoutequipment (1.45.0) 701 | aws-sdk-core (~> 3, >= 3.216.0) 702 | aws-sigv4 (~> 1.5) 703 | aws-sdk-lookoutforvision (1.45.0) 704 | aws-sdk-core (~> 3, >= 3.216.0) 705 | aws-sigv4 (~> 1.5) 706 | aws-sdk-lookoutmetrics (1.49.0) 707 | aws-sdk-core (~> 3, >= 3.216.0) 708 | aws-sigv4 (~> 1.5) 709 | aws-sdk-machinelearning (1.67.0) 710 | aws-sdk-core (~> 3, >= 3.216.0) 711 | aws-sigv4 (~> 1.5) 712 | aws-sdk-macie2 (1.82.0) 713 | aws-sdk-core (~> 3, >= 3.216.0) 714 | aws-sigv4 (~> 1.5) 715 | aws-sdk-mailmanager (1.17.0) 716 | aws-sdk-core (~> 3, >= 3.216.0) 717 | aws-sigv4 (~> 1.5) 718 | aws-sdk-mainframemodernization (1.32.0) 719 | aws-sdk-core (~> 3, >= 3.216.0) 720 | aws-sigv4 (~> 1.5) 721 | aws-sdk-managedblockchain (1.66.0) 722 | aws-sdk-core (~> 3, >= 3.216.0) 723 | aws-sigv4 (~> 1.5) 724 | aws-sdk-managedblockchainquery (1.24.0) 725 | aws-sdk-core (~> 3, >= 3.216.0) 726 | aws-sigv4 (~> 1.1) 727 | aws-sdk-managedgrafana (1.42.0) 728 | aws-sdk-core (~> 3, >= 3.216.0) 729 | aws-sigv4 (~> 1.1) 730 | aws-sdk-marketplaceagreement (1.15.0) 731 | aws-sdk-core (~> 3, >= 3.216.0) 732 | aws-sigv4 (~> 1.1) 733 | aws-sdk-marketplacecatalog (1.55.0) 734 | aws-sdk-core (~> 3, >= 3.216.0) 735 | aws-sigv4 (~> 1.5) 736 | aws-sdk-marketplacecommerceanalytics (1.70.0) 737 | aws-sdk-core (~> 3, >= 3.216.0) 738 | aws-sigv4 (~> 1.5) 739 | aws-sdk-marketplacedeployment (1.15.0) 740 | aws-sdk-core (~> 3, >= 3.216.0) 741 | aws-sigv4 (~> 1.1) 742 | aws-sdk-marketplaceentitlementservice (1.64.0) 743 | aws-sdk-core (~> 3, >= 3.216.0) 744 | aws-sigv4 (~> 1.5) 745 | aws-sdk-marketplacemetering (1.73.0) 746 | aws-sdk-core (~> 3, >= 3.216.0) 747 | aws-sigv4 (~> 1.5) 748 | aws-sdk-marketplacereporting (1.3.0) 749 | aws-sdk-core (~> 3, >= 3.216.0) 750 | aws-sigv4 (~> 1.5) 751 | aws-sdk-mediaconnect (1.75.0) 752 | aws-sdk-core (~> 3, >= 3.216.0) 753 | aws-sigv4 (~> 1.5) 754 | aws-sdk-mediaconvert (1.149.0) 755 | aws-sdk-core (~> 3, >= 3.216.0) 756 | aws-sigv4 (~> 1.5) 757 | aws-sdk-medialive (1.143.0) 758 | aws-sdk-core (~> 3, >= 3.216.0) 759 | aws-sigv4 (~> 1.5) 760 | aws-sdk-mediapackage (1.84.0) 761 | aws-sdk-core (~> 3, >= 3.216.0) 762 | aws-sigv4 (~> 1.1) 763 | aws-sdk-mediapackagev2 (1.34.0) 764 | aws-sdk-core (~> 3, >= 3.216.0) 765 | aws-sigv4 (~> 1.5) 766 | aws-sdk-mediapackagevod (1.66.0) 767 | aws-sdk-core (~> 3, >= 3.216.0) 768 | aws-sigv4 (~> 1.1) 769 | aws-sdk-mediastore (1.68.0) 770 | aws-sdk-core (~> 3, >= 3.216.0) 771 | aws-sigv4 (~> 1.5) 772 | aws-sdk-mediastoredata (1.65.0) 773 | aws-sdk-core (~> 3, >= 3.216.0) 774 | aws-sigv4 (~> 1.5) 775 | aws-sdk-mediatailor (1.92.0) 776 | aws-sdk-core (~> 3, >= 3.216.0) 777 | aws-sigv4 (~> 1.1) 778 | aws-sdk-medicalimaging (1.23.0) 779 | aws-sdk-core (~> 3, >= 3.216.0) 780 | aws-sigv4 (~> 1.5) 781 | aws-sdk-memorydb (1.41.0) 782 | aws-sdk-core (~> 3, >= 3.216.0) 783 | aws-sigv4 (~> 1.5) 784 | aws-sdk-mgn (1.44.0) 785 | aws-sdk-core (~> 3, >= 3.216.0) 786 | aws-sigv4 (~> 1.1) 787 | aws-sdk-migrationhub (1.69.0) 788 | aws-sdk-core (~> 3, >= 3.216.0) 789 | aws-sigv4 (~> 1.5) 790 | aws-sdk-migrationhubconfig (1.48.0) 791 | aws-sdk-core (~> 3, >= 3.216.0) 792 | aws-sigv4 (~> 1.5) 793 | aws-sdk-migrationhuborchestrator (1.27.0) 794 | aws-sdk-core (~> 3, >= 3.216.0) 795 | aws-sigv4 (~> 1.1) 796 | aws-sdk-migrationhubrefactorspaces (1.37.0) 797 | aws-sdk-core (~> 3, >= 3.216.0) 798 | aws-sigv4 (~> 1.1) 799 | aws-sdk-migrationhubstrategyrecommendations (1.34.0) 800 | aws-sdk-core (~> 3, >= 3.216.0) 801 | aws-sigv4 (~> 1.1) 802 | aws-sdk-mq (1.75.0) 803 | aws-sdk-core (~> 3, >= 3.216.0) 804 | aws-sigv4 (~> 1.5) 805 | aws-sdk-mturk (1.67.0) 806 | aws-sdk-core (~> 3, >= 3.216.0) 807 | aws-sigv4 (~> 1.5) 808 | aws-sdk-mwaa (1.53.0) 809 | aws-sdk-core (~> 3, >= 3.216.0) 810 | aws-sigv4 (~> 1.5) 811 | aws-sdk-neptune (1.79.0) 812 | aws-sdk-core (~> 3, >= 3.216.0) 813 | aws-sigv4 (~> 1.5) 814 | aws-sdk-neptunedata (1.22.0) 815 | aws-sdk-core (~> 3, >= 3.216.0) 816 | aws-sigv4 (~> 1.1) 817 | aws-sdk-neptunegraph (1.26.0) 818 | aws-sdk-core (~> 3, >= 3.216.0) 819 | aws-sigv4 (~> 1.5) 820 | aws-sdk-networkfirewall (1.59.0) 821 | aws-sdk-core (~> 3, >= 3.216.0) 822 | aws-sigv4 (~> 1.5) 823 | aws-sdk-networkflowmonitor (1.1.0) 824 | aws-sdk-core (~> 3, >= 3.216.0) 825 | aws-sigv4 (~> 1.5) 826 | aws-sdk-networkmanager (1.58.0) 827 | aws-sdk-core (~> 3, >= 3.216.0) 828 | aws-sigv4 (~> 1.5) 829 | aws-sdk-networkmonitor (1.16.0) 830 | aws-sdk-core (~> 3, >= 3.216.0) 831 | aws-sigv4 (~> 1.1) 832 | aws-sdk-notifications (1.2.0) 833 | aws-sdk-core (~> 3, >= 3.216.0) 834 | aws-sigv4 (~> 1.5) 835 | aws-sdk-notificationscontacts (1.1.0) 836 | aws-sdk-core (~> 3, >= 3.216.0) 837 | aws-sigv4 (~> 1.5) 838 | aws-sdk-oam (1.28.0) 839 | aws-sdk-core (~> 3, >= 3.216.0) 840 | aws-sigv4 (~> 1.1) 841 | aws-sdk-observabilityadmin (1.1.0) 842 | aws-sdk-core (~> 3, >= 3.216.0) 843 | aws-sigv4 (~> 1.5) 844 | aws-sdk-omics (1.42.0) 845 | aws-sdk-core (~> 3, >= 3.216.0) 846 | aws-sigv4 (~> 1.5) 847 | aws-sdk-opensearchserverless (1.32.0) 848 | aws-sdk-core (~> 3, >= 3.216.0) 849 | aws-sigv4 (~> 1.5) 850 | aws-sdk-opensearchservice (1.63.0) 851 | aws-sdk-core (~> 3, >= 3.216.0) 852 | aws-sigv4 (~> 1.5) 853 | aws-sdk-opsworks (1.70.0) 854 | aws-sdk-core (~> 3, >= 3.216.0) 855 | aws-sigv4 (~> 1.5) 856 | aws-sdk-opsworkscm (1.79.0) 857 | aws-sdk-core (~> 3, >= 3.216.0) 858 | aws-sigv4 (~> 1.5) 859 | aws-sdk-organizations (1.111.0) 860 | aws-sdk-core (~> 3, >= 3.216.0) 861 | aws-sigv4 (~> 1.5) 862 | aws-sdk-osis (1.28.0) 863 | aws-sdk-core (~> 3, >= 3.216.0) 864 | aws-sigv4 (~> 1.5) 865 | aws-sdk-outposts (1.76.0) 866 | aws-sdk-core (~> 3, >= 3.216.0) 867 | aws-sigv4 (~> 1.5) 868 | aws-sdk-panorama (1.37.0) 869 | aws-sdk-core (~> 3, >= 3.216.0) 870 | aws-sigv4 (~> 1.1) 871 | aws-sdk-partnercentralselling (1.4.0) 872 | aws-sdk-core (~> 3, >= 3.216.0) 873 | aws-sigv4 (~> 1.5) 874 | aws-sdk-paymentcryptography (1.29.0) 875 | aws-sdk-core (~> 3, >= 3.216.0) 876 | aws-sigv4 (~> 1.5) 877 | aws-sdk-paymentcryptographydata (1.28.0) 878 | aws-sdk-core (~> 3, >= 3.216.0) 879 | aws-sigv4 (~> 1.5) 880 | aws-sdk-pcaconnectorad (1.18.0) 881 | aws-sdk-core (~> 3, >= 3.216.0) 882 | aws-sigv4 (~> 1.1) 883 | aws-sdk-pcaconnectorscep (1.12.0) 884 | aws-sdk-core (~> 3, >= 3.216.0) 885 | aws-sigv4 (~> 1.5) 886 | aws-sdk-pcs (1.11.0) 887 | aws-sdk-core (~> 3, >= 3.216.0) 888 | aws-sigv4 (~> 1.5) 889 | aws-sdk-personalize (1.77.0) 890 | aws-sdk-core (~> 3, >= 3.216.0) 891 | aws-sigv4 (~> 1.5) 892 | aws-sdk-personalizeevents (1.58.0) 893 | aws-sdk-core (~> 3, >= 3.216.0) 894 | aws-sigv4 (~> 1.5) 895 | aws-sdk-personalizeruntime (1.64.0) 896 | aws-sdk-core (~> 3, >= 3.216.0) 897 | aws-sigv4 (~> 1.5) 898 | aws-sdk-pi (1.73.0) 899 | aws-sdk-core (~> 3, >= 3.216.0) 900 | aws-sigv4 (~> 1.5) 901 | aws-sdk-pinpoint (1.104.0) 902 | aws-sdk-core (~> 3, >= 3.216.0) 903 | aws-sigv4 (~> 1.5) 904 | aws-sdk-pinpointemail (1.62.0) 905 | aws-sdk-core (~> 3, >= 3.216.0) 906 | aws-sigv4 (~> 1.5) 907 | aws-sdk-pinpointsmsvoice (1.58.0) 908 | aws-sdk-core (~> 3, >= 3.216.0) 909 | aws-sigv4 (~> 1.1) 910 | aws-sdk-pinpointsmsvoicev2 (1.32.0) 911 | aws-sdk-core (~> 3, >= 3.216.0) 912 | aws-sigv4 (~> 1.5) 913 | aws-sdk-pipes (1.34.0) 914 | aws-sdk-core (~> 3, >= 3.216.0) 915 | aws-sigv4 (~> 1.5) 916 | aws-sdk-polly (1.101.0) 917 | aws-sdk-core (~> 3, >= 3.216.0) 918 | aws-sigv4 (~> 1.5) 919 | aws-sdk-pricing (1.71.0) 920 | aws-sdk-core (~> 3, >= 3.216.0) 921 | aws-sigv4 (~> 1.5) 922 | aws-sdk-privatenetworks (1.28.0) 923 | aws-sdk-core (~> 3, >= 3.216.0) 924 | aws-sigv4 (~> 1.1) 925 | aws-sdk-prometheusservice (1.45.0) 926 | aws-sdk-core (~> 3, >= 3.216.0) 927 | aws-sigv4 (~> 1.5) 928 | aws-sdk-proton (1.50.0) 929 | aws-sdk-core (~> 3, >= 3.216.0) 930 | aws-sigv4 (~> 1.1) 931 | aws-sdk-qapps (1.12.0) 932 | aws-sdk-core (~> 3, >= 3.216.0) 933 | aws-sigv4 (~> 1.5) 934 | aws-sdk-qbusiness (1.26.0) 935 | aws-sdk-core (~> 3, >= 3.216.0) 936 | aws-sigv4 (~> 1.5) 937 | aws-sdk-qconnect (1.27.0) 938 | aws-sdk-core (~> 3, >= 3.216.0) 939 | aws-sigv4 (~> 1.5) 940 | aws-sdk-qldb (1.54.0) 941 | aws-sdk-core (~> 3, >= 3.216.0) 942 | aws-sigv4 (~> 1.5) 943 | aws-sdk-qldbsession (1.49.0) 944 | aws-sdk-core (~> 3, >= 3.216.0) 945 | aws-sigv4 (~> 1.5) 946 | aws-sdk-quicksight (1.142.0) 947 | aws-sdk-core (~> 3, >= 3.216.0) 948 | aws-sigv4 (~> 1.5) 949 | aws-sdk-ram (1.68.0) 950 | aws-sdk-core (~> 3, >= 3.216.0) 951 | aws-sigv4 (~> 1.5) 952 | aws-sdk-rds (1.266.0) 953 | aws-sdk-core (~> 3, >= 3.216.0) 954 | aws-sigv4 (~> 1.5) 955 | aws-sdk-rdsdataservice (1.67.0) 956 | aws-sdk-core (~> 3, >= 3.216.0) 957 | aws-sigv4 (~> 1.5) 958 | aws-sdk-recyclebin (1.35.0) 959 | aws-sdk-core (~> 3, >= 3.216.0) 960 | aws-sigv4 (~> 1.5) 961 | aws-sdk-redshift (1.135.0) 962 | aws-sdk-core (~> 3, >= 3.216.0) 963 | aws-sigv4 (~> 1.5) 964 | aws-sdk-redshiftdataapiservice (1.51.0) 965 | aws-sdk-core (~> 3, >= 3.216.0) 966 | aws-sigv4 (~> 1.5) 967 | aws-sdk-redshiftserverless (1.44.0) 968 | aws-sdk-core (~> 3, >= 3.216.0) 969 | aws-sigv4 (~> 1.5) 970 | aws-sdk-rekognition (1.111.0) 971 | aws-sdk-core (~> 3, >= 3.216.0) 972 | aws-sigv4 (~> 1.5) 973 | aws-sdk-repostspace (1.17.0) 974 | aws-sdk-core (~> 3, >= 3.216.0) 975 | aws-sigv4 (~> 1.5) 976 | aws-sdk-resiliencehub (1.46.0) 977 | aws-sdk-core (~> 3, >= 3.216.0) 978 | aws-sigv4 (~> 1.5) 979 | aws-sdk-resourceexplorer2 (1.31.0) 980 | aws-sdk-core (~> 3, >= 3.216.0) 981 | aws-sigv4 (~> 1.5) 982 | aws-sdk-resourcegroups (1.77.0) 983 | aws-sdk-core (~> 3, >= 3.216.0) 984 | aws-sigv4 (~> 1.5) 985 | aws-sdk-resourcegroupstaggingapi (1.75.0) 986 | aws-sdk-core (~> 3, >= 3.216.0) 987 | aws-sigv4 (~> 1.5) 988 | aws-sdk-resources (3.222.0) 989 | aws-sdk-accessanalyzer (~> 1) 990 | aws-sdk-account (~> 1) 991 | aws-sdk-acm (~> 1) 992 | aws-sdk-acmpca (~> 1) 993 | aws-sdk-amplify (~> 1) 994 | aws-sdk-amplifybackend (~> 1) 995 | aws-sdk-amplifyuibuilder (~> 1) 996 | aws-sdk-apigateway (~> 1) 997 | aws-sdk-apigatewaymanagementapi (~> 1) 998 | aws-sdk-apigatewayv2 (~> 1) 999 | aws-sdk-appconfig (~> 1) 1000 | aws-sdk-appconfigdata (~> 1) 1001 | aws-sdk-appfabric (~> 1) 1002 | aws-sdk-appflow (~> 1) 1003 | aws-sdk-appintegrationsservice (~> 1) 1004 | aws-sdk-applicationautoscaling (~> 1) 1005 | aws-sdk-applicationcostprofiler (~> 1) 1006 | aws-sdk-applicationdiscoveryservice (~> 1) 1007 | aws-sdk-applicationinsights (~> 1) 1008 | aws-sdk-applicationsignals (~> 1) 1009 | aws-sdk-appmesh (~> 1) 1010 | aws-sdk-appregistry (~> 1) 1011 | aws-sdk-apprunner (~> 1) 1012 | aws-sdk-appstream (~> 1) 1013 | aws-sdk-appsync (~> 1) 1014 | aws-sdk-apptest (~> 1) 1015 | aws-sdk-arczonalshift (~> 1) 1016 | aws-sdk-artifact (~> 1) 1017 | aws-sdk-athena (~> 1) 1018 | aws-sdk-auditmanager (~> 1) 1019 | aws-sdk-augmentedairuntime (~> 1) 1020 | aws-sdk-autoscaling (~> 1) 1021 | aws-sdk-autoscalingplans (~> 1) 1022 | aws-sdk-b2bi (~> 1) 1023 | aws-sdk-backup (~> 1) 1024 | aws-sdk-backupgateway (~> 1) 1025 | aws-sdk-backupsearch (~> 1) 1026 | aws-sdk-batch (~> 1) 1027 | aws-sdk-bcmdataexports (~> 1) 1028 | aws-sdk-bcmpricingcalculator (~> 1) 1029 | aws-sdk-bedrock (~> 1) 1030 | aws-sdk-bedrockagent (~> 1) 1031 | aws-sdk-bedrockagentruntime (~> 1) 1032 | aws-sdk-bedrockdataautomation (~> 1) 1033 | aws-sdk-bedrockdataautomationruntime (~> 1) 1034 | aws-sdk-bedrockruntime (~> 1) 1035 | aws-sdk-billing (~> 1) 1036 | aws-sdk-billingconductor (~> 1) 1037 | aws-sdk-braket (~> 1) 1038 | aws-sdk-budgets (~> 1) 1039 | aws-sdk-chatbot (~> 1) 1040 | aws-sdk-chime (~> 1) 1041 | aws-sdk-chimesdkidentity (~> 1) 1042 | aws-sdk-chimesdkmediapipelines (~> 1) 1043 | aws-sdk-chimesdkmeetings (~> 1) 1044 | aws-sdk-chimesdkmessaging (~> 1) 1045 | aws-sdk-chimesdkvoice (~> 1) 1046 | aws-sdk-cleanrooms (~> 1) 1047 | aws-sdk-cleanroomsml (~> 1) 1048 | aws-sdk-cloud9 (~> 1) 1049 | aws-sdk-cloudcontrolapi (~> 1) 1050 | aws-sdk-clouddirectory (~> 1) 1051 | aws-sdk-cloudformation (~> 1) 1052 | aws-sdk-cloudfront (~> 1) 1053 | aws-sdk-cloudfrontkeyvaluestore (~> 1) 1054 | aws-sdk-cloudhsm (~> 1) 1055 | aws-sdk-cloudhsmv2 (~> 1) 1056 | aws-sdk-cloudsearch (~> 1) 1057 | aws-sdk-cloudsearchdomain (~> 1) 1058 | aws-sdk-cloudtrail (~> 1) 1059 | aws-sdk-cloudtraildata (~> 1) 1060 | aws-sdk-cloudwatch (~> 1) 1061 | aws-sdk-cloudwatchevents (~> 1) 1062 | aws-sdk-cloudwatchevidently (~> 1) 1063 | aws-sdk-cloudwatchlogs (~> 1) 1064 | aws-sdk-cloudwatchrum (~> 1) 1065 | aws-sdk-codeartifact (~> 1) 1066 | aws-sdk-codebuild (~> 1) 1067 | aws-sdk-codecatalyst (~> 1) 1068 | aws-sdk-codecommit (~> 1) 1069 | aws-sdk-codeconnections (~> 1) 1070 | aws-sdk-codedeploy (~> 1) 1071 | aws-sdk-codeguruprofiler (~> 1) 1072 | aws-sdk-codegurureviewer (~> 1) 1073 | aws-sdk-codegurusecurity (~> 1) 1074 | aws-sdk-codepipeline (~> 1) 1075 | aws-sdk-codestarconnections (~> 1) 1076 | aws-sdk-codestarnotifications (~> 1) 1077 | aws-sdk-cognitoidentity (~> 1) 1078 | aws-sdk-cognitoidentityprovider (~> 1) 1079 | aws-sdk-cognitosync (~> 1) 1080 | aws-sdk-comprehend (~> 1) 1081 | aws-sdk-comprehendmedical (~> 1) 1082 | aws-sdk-computeoptimizer (~> 1) 1083 | aws-sdk-configservice (~> 1) 1084 | aws-sdk-connect (~> 1) 1085 | aws-sdk-connectcampaignservice (~> 1) 1086 | aws-sdk-connectcampaignsv2 (~> 1) 1087 | aws-sdk-connectcases (~> 1) 1088 | aws-sdk-connectcontactlens (~> 1) 1089 | aws-sdk-connectparticipant (~> 1) 1090 | aws-sdk-connectwisdomservice (~> 1) 1091 | aws-sdk-controlcatalog (~> 1) 1092 | aws-sdk-controltower (~> 1) 1093 | aws-sdk-costandusagereportservice (~> 1) 1094 | aws-sdk-costexplorer (~> 1) 1095 | aws-sdk-costoptimizationhub (~> 1) 1096 | aws-sdk-customerprofiles (~> 1) 1097 | aws-sdk-databasemigrationservice (~> 1) 1098 | aws-sdk-dataexchange (~> 1) 1099 | aws-sdk-datapipeline (~> 1) 1100 | aws-sdk-datasync (~> 1) 1101 | aws-sdk-datazone (~> 1) 1102 | aws-sdk-dax (~> 1) 1103 | aws-sdk-deadline (~> 1) 1104 | aws-sdk-detective (~> 1) 1105 | aws-sdk-devicefarm (~> 1) 1106 | aws-sdk-devopsguru (~> 1) 1107 | aws-sdk-directconnect (~> 1) 1108 | aws-sdk-directoryservice (~> 1) 1109 | aws-sdk-directoryservicedata (~> 1) 1110 | aws-sdk-dlm (~> 1) 1111 | aws-sdk-docdb (~> 1) 1112 | aws-sdk-docdbelastic (~> 1) 1113 | aws-sdk-drs (~> 1) 1114 | aws-sdk-dsql (~> 1) 1115 | aws-sdk-dynamodb (~> 1) 1116 | aws-sdk-dynamodbstreams (~> 1) 1117 | aws-sdk-ebs (~> 1) 1118 | aws-sdk-ec2 (~> 1) 1119 | aws-sdk-ec2instanceconnect (~> 1) 1120 | aws-sdk-ecr (~> 1) 1121 | aws-sdk-ecrpublic (~> 1) 1122 | aws-sdk-ecs (~> 1) 1123 | aws-sdk-efs (~> 1) 1124 | aws-sdk-eks (~> 1) 1125 | aws-sdk-eksauth (~> 1) 1126 | aws-sdk-elasticache (~> 1) 1127 | aws-sdk-elasticbeanstalk (~> 1) 1128 | aws-sdk-elasticinference (~> 1) 1129 | aws-sdk-elasticloadbalancing (~> 1) 1130 | aws-sdk-elasticloadbalancingv2 (~> 1) 1131 | aws-sdk-elasticsearchservice (~> 1) 1132 | aws-sdk-elastictranscoder (~> 1) 1133 | aws-sdk-emr (~> 1) 1134 | aws-sdk-emrcontainers (~> 1) 1135 | aws-sdk-emrserverless (~> 1) 1136 | aws-sdk-entityresolution (~> 1) 1137 | aws-sdk-eventbridge (~> 1) 1138 | aws-sdk-finspace (~> 1) 1139 | aws-sdk-finspacedata (~> 1) 1140 | aws-sdk-firehose (~> 1) 1141 | aws-sdk-fis (~> 1) 1142 | aws-sdk-fms (~> 1) 1143 | aws-sdk-forecastqueryservice (~> 1) 1144 | aws-sdk-forecastservice (~> 1) 1145 | aws-sdk-frauddetector (~> 1) 1146 | aws-sdk-freetier (~> 1) 1147 | aws-sdk-fsx (~> 1) 1148 | aws-sdk-gamelift (~> 1) 1149 | aws-sdk-geomaps (~> 1) 1150 | aws-sdk-geoplaces (~> 1) 1151 | aws-sdk-georoutes (~> 1) 1152 | aws-sdk-glacier (~> 1) 1153 | aws-sdk-globalaccelerator (~> 1) 1154 | aws-sdk-glue (~> 1) 1155 | aws-sdk-gluedatabrew (~> 1) 1156 | aws-sdk-greengrass (~> 1) 1157 | aws-sdk-greengrassv2 (~> 1) 1158 | aws-sdk-groundstation (~> 1) 1159 | aws-sdk-guardduty (~> 1) 1160 | aws-sdk-health (~> 1) 1161 | aws-sdk-healthlake (~> 1) 1162 | aws-sdk-iam (~> 1) 1163 | aws-sdk-identitystore (~> 1) 1164 | aws-sdk-imagebuilder (~> 1) 1165 | aws-sdk-importexport (~> 1) 1166 | aws-sdk-inspector (~> 1) 1167 | aws-sdk-inspector2 (~> 1) 1168 | aws-sdk-inspectorscan (~> 1) 1169 | aws-sdk-internetmonitor (~> 1) 1170 | aws-sdk-invoicing (~> 1) 1171 | aws-sdk-iot (~> 1) 1172 | aws-sdk-iotanalytics (~> 1) 1173 | aws-sdk-iotdataplane (~> 1) 1174 | aws-sdk-iotdeviceadvisor (~> 1) 1175 | aws-sdk-iotevents (~> 1) 1176 | aws-sdk-ioteventsdata (~> 1) 1177 | aws-sdk-iotfleethub (~> 1) 1178 | aws-sdk-iotfleetwise (~> 1) 1179 | aws-sdk-iotjobsdataplane (~> 1) 1180 | aws-sdk-iotsecuretunneling (~> 1) 1181 | aws-sdk-iotsitewise (~> 1) 1182 | aws-sdk-iotthingsgraph (~> 1) 1183 | aws-sdk-iottwinmaker (~> 1) 1184 | aws-sdk-iotwireless (~> 1) 1185 | aws-sdk-ivs (~> 1) 1186 | aws-sdk-ivschat (~> 1) 1187 | aws-sdk-ivsrealtime (~> 1) 1188 | aws-sdk-kafka (~> 1) 1189 | aws-sdk-kafkaconnect (~> 1) 1190 | aws-sdk-kendra (~> 1) 1191 | aws-sdk-kendraranking (~> 1) 1192 | aws-sdk-keyspaces (~> 1) 1193 | aws-sdk-kinesis (~> 1) 1194 | aws-sdk-kinesisanalytics (~> 1) 1195 | aws-sdk-kinesisanalyticsv2 (~> 1) 1196 | aws-sdk-kinesisvideo (~> 1) 1197 | aws-sdk-kinesisvideoarchivedmedia (~> 1) 1198 | aws-sdk-kinesisvideomedia (~> 1) 1199 | aws-sdk-kinesisvideosignalingchannels (~> 1) 1200 | aws-sdk-kinesisvideowebrtcstorage (~> 1) 1201 | aws-sdk-kms (~> 1) 1202 | aws-sdk-lakeformation (~> 1) 1203 | aws-sdk-lambda (~> 1) 1204 | aws-sdk-launchwizard (~> 1) 1205 | aws-sdk-lex (~> 1) 1206 | aws-sdk-lexmodelbuildingservice (~> 1) 1207 | aws-sdk-lexmodelsv2 (~> 1) 1208 | aws-sdk-lexruntimev2 (~> 1) 1209 | aws-sdk-licensemanager (~> 1) 1210 | aws-sdk-licensemanagerlinuxsubscriptions (~> 1) 1211 | aws-sdk-licensemanagerusersubscriptions (~> 1) 1212 | aws-sdk-lightsail (~> 1) 1213 | aws-sdk-locationservice (~> 1) 1214 | aws-sdk-lookoutequipment (~> 1) 1215 | aws-sdk-lookoutforvision (~> 1) 1216 | aws-sdk-lookoutmetrics (~> 1) 1217 | aws-sdk-machinelearning (~> 1) 1218 | aws-sdk-macie2 (~> 1) 1219 | aws-sdk-mailmanager (~> 1) 1220 | aws-sdk-mainframemodernization (~> 1) 1221 | aws-sdk-managedblockchain (~> 1) 1222 | aws-sdk-managedblockchainquery (~> 1) 1223 | aws-sdk-managedgrafana (~> 1) 1224 | aws-sdk-marketplaceagreement (~> 1) 1225 | aws-sdk-marketplacecatalog (~> 1) 1226 | aws-sdk-marketplacecommerceanalytics (~> 1) 1227 | aws-sdk-marketplacedeployment (~> 1) 1228 | aws-sdk-marketplaceentitlementservice (~> 1) 1229 | aws-sdk-marketplacemetering (~> 1) 1230 | aws-sdk-marketplacereporting (~> 1) 1231 | aws-sdk-mediaconnect (~> 1) 1232 | aws-sdk-mediaconvert (~> 1) 1233 | aws-sdk-medialive (~> 1) 1234 | aws-sdk-mediapackage (~> 1) 1235 | aws-sdk-mediapackagev2 (~> 1) 1236 | aws-sdk-mediapackagevod (~> 1) 1237 | aws-sdk-mediastore (~> 1) 1238 | aws-sdk-mediastoredata (~> 1) 1239 | aws-sdk-mediatailor (~> 1) 1240 | aws-sdk-medicalimaging (~> 1) 1241 | aws-sdk-memorydb (~> 1) 1242 | aws-sdk-mgn (~> 1) 1243 | aws-sdk-migrationhub (~> 1) 1244 | aws-sdk-migrationhubconfig (~> 1) 1245 | aws-sdk-migrationhuborchestrator (~> 1) 1246 | aws-sdk-migrationhubrefactorspaces (~> 1) 1247 | aws-sdk-migrationhubstrategyrecommendations (~> 1) 1248 | aws-sdk-mq (~> 1) 1249 | aws-sdk-mturk (~> 1) 1250 | aws-sdk-mwaa (~> 1) 1251 | aws-sdk-neptune (~> 1) 1252 | aws-sdk-neptunedata (~> 1) 1253 | aws-sdk-neptunegraph (~> 1) 1254 | aws-sdk-networkfirewall (~> 1) 1255 | aws-sdk-networkflowmonitor (~> 1) 1256 | aws-sdk-networkmanager (~> 1) 1257 | aws-sdk-networkmonitor (~> 1) 1258 | aws-sdk-notifications (~> 1) 1259 | aws-sdk-notificationscontacts (~> 1) 1260 | aws-sdk-oam (~> 1) 1261 | aws-sdk-observabilityadmin (~> 1) 1262 | aws-sdk-omics (~> 1) 1263 | aws-sdk-opensearchserverless (~> 1) 1264 | aws-sdk-opensearchservice (~> 1) 1265 | aws-sdk-opsworks (~> 1) 1266 | aws-sdk-opsworkscm (~> 1) 1267 | aws-sdk-organizations (~> 1) 1268 | aws-sdk-osis (~> 1) 1269 | aws-sdk-outposts (~> 1) 1270 | aws-sdk-panorama (~> 1) 1271 | aws-sdk-partnercentralselling (~> 1) 1272 | aws-sdk-paymentcryptography (~> 1) 1273 | aws-sdk-paymentcryptographydata (~> 1) 1274 | aws-sdk-pcaconnectorad (~> 1) 1275 | aws-sdk-pcaconnectorscep (~> 1) 1276 | aws-sdk-pcs (~> 1) 1277 | aws-sdk-personalize (~> 1) 1278 | aws-sdk-personalizeevents (~> 1) 1279 | aws-sdk-personalizeruntime (~> 1) 1280 | aws-sdk-pi (~> 1) 1281 | aws-sdk-pinpoint (~> 1) 1282 | aws-sdk-pinpointemail (~> 1) 1283 | aws-sdk-pinpointsmsvoice (~> 1) 1284 | aws-sdk-pinpointsmsvoicev2 (~> 1) 1285 | aws-sdk-pipes (~> 1) 1286 | aws-sdk-polly (~> 1) 1287 | aws-sdk-pricing (~> 1) 1288 | aws-sdk-privatenetworks (~> 1) 1289 | aws-sdk-prometheusservice (~> 1) 1290 | aws-sdk-proton (~> 1) 1291 | aws-sdk-qapps (~> 1) 1292 | aws-sdk-qbusiness (~> 1) 1293 | aws-sdk-qconnect (~> 1) 1294 | aws-sdk-qldb (~> 1) 1295 | aws-sdk-qldbsession (~> 1) 1296 | aws-sdk-quicksight (~> 1) 1297 | aws-sdk-ram (~> 1) 1298 | aws-sdk-rds (~> 1) 1299 | aws-sdk-rdsdataservice (~> 1) 1300 | aws-sdk-recyclebin (~> 1) 1301 | aws-sdk-redshift (~> 1) 1302 | aws-sdk-redshiftdataapiservice (~> 1) 1303 | aws-sdk-redshiftserverless (~> 1) 1304 | aws-sdk-rekognition (~> 1) 1305 | aws-sdk-repostspace (~> 1) 1306 | aws-sdk-resiliencehub (~> 1) 1307 | aws-sdk-resourceexplorer2 (~> 1) 1308 | aws-sdk-resourcegroups (~> 1) 1309 | aws-sdk-resourcegroupstaggingapi (~> 1) 1310 | aws-sdk-robomaker (~> 1) 1311 | aws-sdk-rolesanywhere (~> 1) 1312 | aws-sdk-route53 (~> 1) 1313 | aws-sdk-route53domains (~> 1) 1314 | aws-sdk-route53profiles (~> 1) 1315 | aws-sdk-route53recoverycluster (~> 1) 1316 | aws-sdk-route53recoverycontrolconfig (~> 1) 1317 | aws-sdk-route53recoveryreadiness (~> 1) 1318 | aws-sdk-route53resolver (~> 1) 1319 | aws-sdk-s3 (~> 1) 1320 | aws-sdk-s3control (~> 1) 1321 | aws-sdk-s3outposts (~> 1) 1322 | aws-sdk-s3tables (~> 1) 1323 | aws-sdk-sagemaker (~> 1) 1324 | aws-sdk-sagemakeredgemanager (~> 1) 1325 | aws-sdk-sagemakerfeaturestoreruntime (~> 1) 1326 | aws-sdk-sagemakergeospatial (~> 1) 1327 | aws-sdk-sagemakermetrics (~> 1) 1328 | aws-sdk-sagemakerruntime (~> 1) 1329 | aws-sdk-savingsplans (~> 1) 1330 | aws-sdk-scheduler (~> 1) 1331 | aws-sdk-schemas (~> 1) 1332 | aws-sdk-secretsmanager (~> 1) 1333 | aws-sdk-securityhub (~> 1) 1334 | aws-sdk-securityir (~> 1) 1335 | aws-sdk-securitylake (~> 1) 1336 | aws-sdk-serverlessapplicationrepository (~> 1) 1337 | aws-sdk-servicecatalog (~> 1) 1338 | aws-sdk-servicediscovery (~> 1) 1339 | aws-sdk-servicequotas (~> 1) 1340 | aws-sdk-ses (~> 1) 1341 | aws-sdk-sesv2 (~> 1) 1342 | aws-sdk-shield (~> 1) 1343 | aws-sdk-signer (~> 1) 1344 | aws-sdk-simpledb (~> 1) 1345 | aws-sdk-simspaceweaver (~> 1) 1346 | aws-sdk-sms (~> 1) 1347 | aws-sdk-snowball (~> 1) 1348 | aws-sdk-snowdevicemanagement (~> 1) 1349 | aws-sdk-sns (~> 1) 1350 | aws-sdk-socialmessaging (~> 1) 1351 | aws-sdk-sqs (~> 1) 1352 | aws-sdk-ssm (~> 1) 1353 | aws-sdk-ssmcontacts (~> 1) 1354 | aws-sdk-ssmincidents (~> 1) 1355 | aws-sdk-ssmquicksetup (~> 1) 1356 | aws-sdk-ssmsap (~> 1) 1357 | aws-sdk-ssoadmin (~> 1) 1358 | aws-sdk-states (~> 1) 1359 | aws-sdk-storagegateway (~> 1) 1360 | aws-sdk-supplychain (~> 1) 1361 | aws-sdk-support (~> 1) 1362 | aws-sdk-supportapp (~> 1) 1363 | aws-sdk-swf (~> 1) 1364 | aws-sdk-synthetics (~> 1) 1365 | aws-sdk-taxsettings (~> 1) 1366 | aws-sdk-textract (~> 1) 1367 | aws-sdk-timestreaminfluxdb (~> 1) 1368 | aws-sdk-timestreamquery (~> 1) 1369 | aws-sdk-timestreamwrite (~> 1) 1370 | aws-sdk-tnb (~> 1) 1371 | aws-sdk-transcribeservice (~> 1) 1372 | aws-sdk-transcribestreamingservice (~> 1) 1373 | aws-sdk-transfer (~> 1) 1374 | aws-sdk-translate (~> 1) 1375 | aws-sdk-trustedadvisor (~> 1) 1376 | aws-sdk-verifiedpermissions (~> 1) 1377 | aws-sdk-voiceid (~> 1) 1378 | aws-sdk-vpclattice (~> 1) 1379 | aws-sdk-waf (~> 1) 1380 | aws-sdk-wafregional (~> 1) 1381 | aws-sdk-wafv2 (~> 1) 1382 | aws-sdk-wellarchitected (~> 1) 1383 | aws-sdk-workdocs (~> 1) 1384 | aws-sdk-workmail (~> 1) 1385 | aws-sdk-workmailmessageflow (~> 1) 1386 | aws-sdk-workspaces (~> 1) 1387 | aws-sdk-workspacesthinclient (~> 1) 1388 | aws-sdk-workspacesweb (~> 1) 1389 | aws-sdk-xray (~> 1) 1390 | aws-sdk-robomaker (1.79.0) 1391 | aws-sdk-core (~> 3, >= 3.216.0) 1392 | aws-sigv4 (~> 1.5) 1393 | aws-sdk-rolesanywhere (1.31.0) 1394 | aws-sdk-core (~> 3, >= 3.216.0) 1395 | aws-sigv4 (~> 1.5) 1396 | aws-sdk-route53 (1.108.0) 1397 | aws-sdk-core (~> 3, >= 3.216.0) 1398 | aws-sigv4 (~> 1.5) 1399 | aws-sdk-route53domains (1.74.0) 1400 | aws-sdk-core (~> 3, >= 3.216.0) 1401 | aws-sigv4 (~> 1.5) 1402 | aws-sdk-route53profiles (1.15.0) 1403 | aws-sdk-core (~> 3, >= 3.216.0) 1404 | aws-sigv4 (~> 1.1) 1405 | aws-sdk-route53recoverycluster (1.39.0) 1406 | aws-sdk-core (~> 3, >= 3.216.0) 1407 | aws-sigv4 (~> 1.5) 1408 | aws-sdk-route53recoverycontrolconfig (1.38.0) 1409 | aws-sdk-core (~> 3, >= 3.216.0) 1410 | aws-sigv4 (~> 1.1) 1411 | aws-sdk-route53recoveryreadiness (1.36.0) 1412 | aws-sdk-core (~> 3, >= 3.216.0) 1413 | aws-sigv4 (~> 1.1) 1414 | aws-sdk-route53resolver (1.75.0) 1415 | aws-sdk-core (~> 3, >= 3.216.0) 1416 | aws-sigv4 (~> 1.5) 1417 | aws-sdk-s3 (1.178.0) 1418 | aws-sdk-core (~> 3, >= 3.216.0) 1419 | aws-sdk-kms (~> 1) 1420 | aws-sigv4 (~> 1.5) 1421 | aws-sdk-s3control (1.101.0) 1422 | aws-sdk-core (~> 3, >= 3.216.0) 1423 | aws-sigv4 (~> 1.5) 1424 | aws-sdk-s3outposts (1.43.0) 1425 | aws-sdk-core (~> 3, >= 3.216.0) 1426 | aws-sigv4 (~> 1.5) 1427 | aws-sdk-s3tables (1.1.0) 1428 | aws-sdk-core (~> 3, >= 3.216.0) 1429 | aws-sigv4 (~> 1.5) 1430 | aws-sdk-sagemaker (1.283.0) 1431 | aws-sdk-core (~> 3, >= 3.216.0) 1432 | aws-sigv4 (~> 1.5) 1433 | aws-sdk-sagemakeredgemanager (1.39.0) 1434 | aws-sdk-core (~> 3, >= 3.216.0) 1435 | aws-sigv4 (~> 1.5) 1436 | aws-sdk-sagemakerfeaturestoreruntime (1.44.0) 1437 | aws-sdk-core (~> 3, >= 3.216.0) 1438 | aws-sigv4 (~> 1.5) 1439 | aws-sdk-sagemakergeospatial (1.27.0) 1440 | aws-sdk-core (~> 3, >= 3.216.0) 1441 | aws-sigv4 (~> 1.1) 1442 | aws-sdk-sagemakermetrics (1.27.0) 1443 | aws-sdk-core (~> 3, >= 3.216.0) 1444 | aws-sigv4 (~> 1.5) 1445 | aws-sdk-sagemakerruntime (1.77.0) 1446 | aws-sdk-core (~> 3, >= 3.216.0) 1447 | aws-sigv4 (~> 1.5) 1448 | aws-sdk-savingsplans (1.55.0) 1449 | aws-sdk-core (~> 3, >= 3.216.0) 1450 | aws-sigv4 (~> 1.5) 1451 | aws-sdk-scheduler (1.27.0) 1452 | aws-sdk-core (~> 3, >= 3.216.0) 1453 | aws-sigv4 (~> 1.1) 1454 | aws-sdk-schemas (1.49.0) 1455 | aws-sdk-core (~> 3, >= 3.216.0) 1456 | aws-sigv4 (~> 1.1) 1457 | aws-sdk-secretsmanager (1.111.0) 1458 | aws-sdk-core (~> 3, >= 3.216.0) 1459 | aws-sigv4 (~> 1.5) 1460 | aws-sdk-securityhub (1.127.0) 1461 | aws-sdk-core (~> 3, >= 3.216.0) 1462 | aws-sigv4 (~> 1.5) 1463 | aws-sdk-securityir (1.1.0) 1464 | aws-sdk-core (~> 3, >= 3.216.0) 1465 | aws-sigv4 (~> 1.5) 1466 | aws-sdk-securitylake (1.35.0) 1467 | aws-sdk-core (~> 3, >= 3.216.0) 1468 | aws-sigv4 (~> 1.5) 1469 | aws-sdk-serverlessapplicationrepository (1.72.0) 1470 | aws-sdk-core (~> 3, >= 3.216.0) 1471 | aws-sigv4 (~> 1.1) 1472 | aws-sdk-servicecatalog (1.108.0) 1473 | aws-sdk-core (~> 3, >= 3.216.0) 1474 | aws-sigv4 (~> 1.5) 1475 | aws-sdk-servicediscovery (1.80.0) 1476 | aws-sdk-core (~> 3, >= 3.216.0) 1477 | aws-sigv4 (~> 1.5) 1478 | aws-sdk-servicequotas (1.50.0) 1479 | aws-sdk-core (~> 3, >= 3.216.0) 1480 | aws-sigv4 (~> 1.5) 1481 | aws-sdk-ses (1.79.0) 1482 | aws-sdk-core (~> 3, >= 3.216.0) 1483 | aws-sigv4 (~> 1.5) 1484 | aws-sdk-sesv2 (1.69.0) 1485 | aws-sdk-core (~> 3, >= 3.216.0) 1486 | aws-sigv4 (~> 1.5) 1487 | aws-sdk-shield (1.77.0) 1488 | aws-sdk-core (~> 3, >= 3.216.0) 1489 | aws-sigv4 (~> 1.5) 1490 | aws-sdk-signer (1.67.0) 1491 | aws-sdk-core (~> 3, >= 3.216.0) 1492 | aws-sigv4 (~> 1.5) 1493 | aws-sdk-simpledb (1.60.0) 1494 | aws-sdk-core (~> 3, >= 3.216.0) 1495 | aws-sigv2 (~> 1.0) 1496 | aws-sdk-simspaceweaver (1.28.0) 1497 | aws-sdk-core (~> 3, >= 3.216.0) 1498 | aws-sigv4 (~> 1.1) 1499 | aws-sdk-sms (1.67.0) 1500 | aws-sdk-core (~> 3, >= 3.216.0) 1501 | aws-sigv4 (~> 1.1) 1502 | aws-sdk-snowball (1.82.0) 1503 | aws-sdk-core (~> 3, >= 3.216.0) 1504 | aws-sigv4 (~> 1.5) 1505 | aws-sdk-snowdevicemanagement (1.33.0) 1506 | aws-sdk-core (~> 3, >= 3.216.0) 1507 | aws-sigv4 (~> 1.1) 1508 | aws-sdk-sns (1.94.0) 1509 | aws-sdk-core (~> 3, >= 3.216.0) 1510 | aws-sigv4 (~> 1.5) 1511 | aws-sdk-socialmessaging (1.4.0) 1512 | aws-sdk-core (~> 3, >= 3.216.0) 1513 | aws-sigv4 (~> 1.5) 1514 | aws-sdk-sqs (1.91.0) 1515 | aws-sdk-core (~> 3, >= 3.216.0) 1516 | aws-sigv4 (~> 1.5) 1517 | aws-sdk-ssm (1.188.0) 1518 | aws-sdk-core (~> 3, >= 3.216.0) 1519 | aws-sigv4 (~> 1.5) 1520 | aws-sdk-ssmcontacts (1.42.0) 1521 | aws-sdk-core (~> 3, >= 3.216.0) 1522 | aws-sigv4 (~> 1.5) 1523 | aws-sdk-ssmincidents (1.47.0) 1524 | aws-sdk-core (~> 3, >= 3.216.0) 1525 | aws-sigv4 (~> 1.1) 1526 | aws-sdk-ssmquicksetup (1.10.0) 1527 | aws-sdk-core (~> 3, >= 3.216.0) 1528 | aws-sigv4 (~> 1.5) 1529 | aws-sdk-ssmsap (1.33.0) 1530 | aws-sdk-core (~> 3, >= 3.216.0) 1531 | aws-sigv4 (~> 1.5) 1532 | aws-sdk-ssoadmin (1.49.0) 1533 | aws-sdk-core (~> 3, >= 3.216.0) 1534 | aws-sigv4 (~> 1.1) 1535 | aws-sdk-states (1.85.0) 1536 | aws-sdk-core (~> 3, >= 3.216.0) 1537 | aws-sigv4 (~> 1.5) 1538 | aws-sdk-storagegateway (1.102.0) 1539 | aws-sdk-core (~> 3, >= 3.216.0) 1540 | aws-sigv4 (~> 1.5) 1541 | aws-sdk-supplychain (1.21.0) 1542 | aws-sdk-core (~> 3, >= 3.216.0) 1543 | aws-sigv4 (~> 1.5) 1544 | aws-sdk-support (1.73.0) 1545 | aws-sdk-core (~> 3, >= 3.216.0) 1546 | aws-sigv4 (~> 1.5) 1547 | aws-sdk-supportapp (1.28.0) 1548 | aws-sdk-core (~> 3, >= 3.216.0) 1549 | aws-sigv4 (~> 1.1) 1550 | aws-sdk-swf (1.67.0) 1551 | aws-sdk-core (~> 3, >= 3.216.0) 1552 | aws-sigv4 (~> 1.5) 1553 | aws-sdk-synthetics (1.59.0) 1554 | aws-sdk-core (~> 3, >= 3.216.0) 1555 | aws-sigv4 (~> 1.5) 1556 | aws-sdk-taxsettings (1.16.0) 1557 | aws-sdk-core (~> 3, >= 3.216.0) 1558 | aws-sigv4 (~> 1.5) 1559 | aws-sdk-textract (1.72.0) 1560 | aws-sdk-core (~> 3, >= 3.216.0) 1561 | aws-sigv4 (~> 1.5) 1562 | aws-sdk-timestreaminfluxdb (1.18.0) 1563 | aws-sdk-core (~> 3, >= 3.216.0) 1564 | aws-sigv4 (~> 1.1) 1565 | aws-sdk-timestreamquery (1.48.0) 1566 | aws-sdk-core (~> 3, >= 3.216.0) 1567 | aws-sigv4 (~> 1.5) 1568 | aws-sdk-timestreamwrite (1.43.0) 1569 | aws-sdk-core (~> 3, >= 3.216.0) 1570 | aws-sigv4 (~> 1.1) 1571 | aws-sdk-tnb (1.26.0) 1572 | aws-sdk-core (~> 3, >= 3.216.0) 1573 | aws-sigv4 (~> 1.5) 1574 | aws-sdk-transcribeservice (1.112.0) 1575 | aws-sdk-core (~> 3, >= 3.216.0) 1576 | aws-sigv4 (~> 1.5) 1577 | aws-sdk-transcribestreamingservice (1.73.0) 1578 | aws-sdk-core (~> 3, >= 3.216.0) 1579 | aws-sigv4 (~> 1.5) 1580 | aws-sdk-transfer (1.111.0) 1581 | aws-sdk-core (~> 3, >= 3.216.0) 1582 | aws-sigv4 (~> 1.5) 1583 | aws-sdk-translate (1.78.0) 1584 | aws-sdk-core (~> 3, >= 3.216.0) 1585 | aws-sigv4 (~> 1.5) 1586 | aws-sdk-trustedadvisor (1.18.0) 1587 | aws-sdk-core (~> 3, >= 3.216.0) 1588 | aws-sigv4 (~> 1.1) 1589 | aws-sdk-verifiedpermissions (1.39.0) 1590 | aws-sdk-core (~> 3, >= 3.216.0) 1591 | aws-sigv4 (~> 1.5) 1592 | aws-sdk-voiceid (1.38.0) 1593 | aws-sdk-core (~> 3, >= 3.216.0) 1594 | aws-sigv4 (~> 1.1) 1595 | aws-sdk-vpclattice (1.26.0) 1596 | aws-sdk-core (~> 3, >= 3.216.0) 1597 | aws-sigv4 (~> 1.5) 1598 | aws-sdk-waf (1.74.0) 1599 | aws-sdk-core (~> 3, >= 3.216.0) 1600 | aws-sigv4 (~> 1.5) 1601 | aws-sdk-wafregional (1.76.0) 1602 | aws-sdk-core (~> 3, >= 3.216.0) 1603 | aws-sigv4 (~> 1.5) 1604 | aws-sdk-wafv2 (1.100.0) 1605 | aws-sdk-core (~> 3, >= 3.216.0) 1606 | aws-sigv4 (~> 1.5) 1607 | aws-sdk-wellarchitected (1.49.0) 1608 | aws-sdk-core (~> 3, >= 3.216.0) 1609 | aws-sigv4 (~> 1.5) 1610 | aws-sdk-workdocs (1.70.0) 1611 | aws-sdk-core (~> 3, >= 3.216.0) 1612 | aws-sigv4 (~> 1.5) 1613 | aws-sdk-workmail (1.79.0) 1614 | aws-sdk-core (~> 3, >= 3.216.0) 1615 | aws-sigv4 (~> 1.5) 1616 | aws-sdk-workmailmessageflow (1.48.0) 1617 | aws-sdk-core (~> 3, >= 3.216.0) 1618 | aws-sigv4 (~> 1.5) 1619 | aws-sdk-workspaces (1.129.0) 1620 | aws-sdk-core (~> 3, >= 3.216.0) 1621 | aws-sigv4 (~> 1.5) 1622 | aws-sdk-workspacesthinclient (1.20.0) 1623 | aws-sdk-core (~> 3, >= 3.216.0) 1624 | aws-sigv4 (~> 1.5) 1625 | aws-sdk-workspacesweb (1.37.0) 1626 | aws-sdk-core (~> 3, >= 3.216.0) 1627 | aws-sigv4 (~> 1.5) 1628 | aws-sdk-xray (1.79.0) 1629 | aws-sdk-core (~> 3, >= 3.216.0) 1630 | aws-sigv4 (~> 1.5) 1631 | aws-sigv2 (1.2.0) 1632 | aws-sigv4 (1.11.0) 1633 | aws-eventstream (~> 1, >= 1.0.2) 1634 | aws_config (0.1.1) 1635 | awsecrets (1.15.1) 1636 | aws-sdk (>= 2, < 4) 1637 | aws_config (~> 0.1.0) 1638 | awspec (1.32.0) 1639 | addressable 1640 | aws-sdk (~> 3) 1641 | awsecrets (~> 1) 1642 | base64 (~> 0.1.0) 1643 | dry-inflector 1644 | ipaddress 1645 | ostruct (~> 0.6.1) 1646 | rspec (~> 3.0) 1647 | rspec-its 1648 | term-ansicolor 1649 | thor 1650 | base64 (0.1.2) 1651 | bigdecimal (3.1.9) 1652 | colored2 (3.1.2) 1653 | concurrent-ruby (1.3.3) 1654 | confidante (0.28.0) 1655 | activesupport (>= 4) 1656 | hiera (~> 3.3) 1657 | shikashi (~> 0.6) 1658 | vault (~> 0.17) 1659 | connection_pool (2.4.1) 1660 | diff-lcs (1.6.2) 1661 | down (5.4.1) 1662 | addressable (~> 2.8) 1663 | drb (2.2.1) 1664 | dry-inflector (1.2.0) 1665 | evalhook (0.6.0) 1666 | partialruby (~> 0.3) 1667 | sexp_processor (~> 4.0) 1668 | excon (0.111.0) 1669 | faraday (2.10.0) 1670 | faraday-net_http (>= 2.0, < 3.2) 1671 | logger 1672 | faraday-net_http (3.1.1) 1673 | net-http 1674 | getsource (0.2.2) 1675 | git (1.19.1) 1676 | addressable (~> 2.8) 1677 | rchardet (~> 1.8) 1678 | hamster (3.0.0) 1679 | concurrent-ruby (~> 1.0) 1680 | hiera (3.12.0) 1681 | i18n (1.14.5) 1682 | concurrent-ruby (~> 1.0) 1683 | immutable-struct (2.4.1) 1684 | ipaddress (0.8.3) 1685 | jmespath (1.6.2) 1686 | json (2.12.2) 1687 | language_server-protocol (3.17.0.5) 1688 | lino (3.1.0) 1689 | hamster (~> 3.0) 1690 | open4 (~> 1.3) 1691 | lint_roller (1.1.0) 1692 | logger (1.6.0) 1693 | mini_portile2 (2.8.8) 1694 | minitar (0.9) 1695 | minitest (5.24.1) 1696 | mutex_m (0.2.0) 1697 | net-http (0.4.1) 1698 | uri 1699 | nokogiri (1.18.8) 1700 | mini_portile2 (~> 2.8.2) 1701 | racc (~> 1.4) 1702 | nokogiri (1.18.8-x86_64-darwin) 1703 | racc (~> 1.4) 1704 | octokit (8.1.0) 1705 | base64 1706 | faraday (>= 1, < 3) 1707 | sawyer (~> 0.9) 1708 | open4 (1.3.4) 1709 | ostruct (0.6.1) 1710 | parallel (1.27.0) 1711 | parser (3.3.8.0) 1712 | ast (~> 2.4.1) 1713 | racc 1714 | partialruby (0.3.0) 1715 | ruby2ruby (~> 2) 1716 | ruby_parser (~> 3) 1717 | prism (1.4.0) 1718 | public_suffix (6.0.1) 1719 | racc (1.8.1) 1720 | rainbow (3.1.1) 1721 | rake (13.3.0) 1722 | rake_circle_ci (0.13.0) 1723 | colored2 (~> 3.1) 1724 | excon (~> 0.72) 1725 | rake_factory (~> 0.33) 1726 | sshkey (~> 2.0) 1727 | rake_dependencies (3.5.0) 1728 | down (~> 5.3) 1729 | hamster (~> 3.0) 1730 | minitar (~> 0.9) 1731 | rake_factory (~> 0.23) 1732 | rubyzip (>= 1.3) 1733 | rake_factory (0.34.0.pre.2) 1734 | activesupport (>= 4) 1735 | rake (~> 13.0) 1736 | rake_git (0.3.0.pre.2) 1737 | colored2 (~> 3.1) 1738 | git (~> 1.13, >= 1.13.2) 1739 | rake_factory (~> 0.33) 1740 | rake_git_crypt (0.1.0.pre.33) 1741 | colored2 (~> 3.1) 1742 | rake_factory (>= 0.32.0.pre.2) 1743 | ruby_git_crypt (>= 0.1.0.pre.8) 1744 | ruby_gpg2 (>= 0.11.0.pre.6) 1745 | rake_github (0.15.0) 1746 | colored2 (~> 3.1) 1747 | octokit (>= 4.16, < 9.0) 1748 | rake_factory (~> 0.33) 1749 | sshkey (~> 2.0) 1750 | rake_gpg (0.18.0) 1751 | rake_factory (~> 0.23) 1752 | ruby_gpg2 (~> 0.6) 1753 | rake_ssh (0.12.0) 1754 | colored2 (~> 3.1) 1755 | rake_factory (~> 0.33) 1756 | sshkey (~> 2.0) 1757 | rake_terraform (1.23.0) 1758 | colored2 (~> 3.1) 1759 | rake_dependencies (~> 3.1) 1760 | rake_factory (~> 0.23) 1761 | ruby-terraform (~> 1.4) 1762 | rchardet (1.8.0) 1763 | regexp_parser (2.10.0) 1764 | rspec (3.13.1) 1765 | rspec-core (~> 3.13.0) 1766 | rspec-expectations (~> 3.13.0) 1767 | rspec-mocks (~> 3.13.0) 1768 | rspec-core (3.13.4) 1769 | rspec-support (~> 3.13.0) 1770 | rspec-expectations (3.13.5) 1771 | diff-lcs (>= 1.2.0, < 2.0) 1772 | rspec-support (~> 3.13.0) 1773 | rspec-its (2.0.0) 1774 | rspec-core (>= 3.13.0) 1775 | rspec-expectations (>= 3.13.0) 1776 | rspec-mocks (3.13.5) 1777 | diff-lcs (>= 1.2.0, < 2.0) 1778 | rspec-support (~> 3.13.0) 1779 | rspec-support (3.13.4) 1780 | rspec-terraform (0.4.0) 1781 | confidante (>= 0.27) 1782 | rspec (>= 3.0) 1783 | ruby-terraform (= 1.7.0.pre.18) 1784 | rubocop (1.76.0) 1785 | json (~> 2.3) 1786 | language_server-protocol (~> 3.17.0.2) 1787 | lint_roller (~> 1.1.0) 1788 | parallel (~> 1.10) 1789 | parser (>= 3.3.0.2) 1790 | rainbow (>= 2.2.2, < 4.0) 1791 | regexp_parser (>= 2.9.3, < 3.0) 1792 | rubocop-ast (>= 1.45.0, < 2.0) 1793 | ruby-progressbar (~> 1.7) 1794 | unicode-display_width (>= 2.4.0, < 4.0) 1795 | rubocop-ast (1.45.0) 1796 | parser (>= 3.3.7.2) 1797 | prism (~> 1.4) 1798 | rubocop-rake (0.7.1) 1799 | lint_roller (~> 1.1) 1800 | rubocop (>= 1.72.1) 1801 | rubocop-rspec (3.6.0) 1802 | lint_roller (~> 1.1) 1803 | rubocop (~> 1.72, >= 1.72.1) 1804 | ruby-progressbar (1.13.0) 1805 | ruby-terraform (1.7.0.pre.18) 1806 | immutable-struct (~> 2.4) 1807 | lino (~> 3.0) 1808 | ruby2ruby (2.5.0) 1809 | ruby_parser (~> 3.1) 1810 | sexp_processor (~> 4.6) 1811 | ruby_git_crypt (0.1.0.pre.8) 1812 | immutable-struct (~> 2.4) 1813 | lino (>= 3.1) 1814 | ruby_gpg2 (0.11.0.pre.6) 1815 | lino (>= 3.1) 1816 | ruby_parser (3.20.3) 1817 | sexp_processor (~> 4.16) 1818 | rubyzip (2.4.1) 1819 | sawyer (0.9.2) 1820 | addressable (>= 2.3.5) 1821 | faraday (>= 0.17.3, < 3) 1822 | semantic (1.6.1) 1823 | sexp_processor (4.17.0) 1824 | shikashi (0.6.0) 1825 | evalhook (>= 0.6.0) 1826 | getsource (>= 0.1.0) 1827 | sshkey (2.0.0) 1828 | sync (0.5.0) 1829 | term-ansicolor (1.11.2) 1830 | tins (~> 1.0) 1831 | thor (1.3.2) 1832 | tins (1.38.0) 1833 | bigdecimal 1834 | sync 1835 | tzinfo (2.0.6) 1836 | concurrent-ruby (~> 1.0) 1837 | unicode-display_width (3.1.4) 1838 | unicode-emoji (~> 4.0, >= 4.0.4) 1839 | unicode-emoji (4.0.4) 1840 | uri (0.13.2) 1841 | vault (0.18.1) 1842 | aws-sigv4 1843 | 1844 | PLATFORMS 1845 | ruby 1846 | x86_64-darwin-19 1847 | 1848 | DEPENDENCIES 1849 | awspec 1850 | confidante 1851 | git 1852 | nokogiri 1853 | rake 1854 | rake_circle_ci 1855 | rake_git 1856 | rake_git_crypt 1857 | rake_github 1858 | rake_gpg 1859 | rake_ssh 1860 | rake_terraform 1861 | rspec 1862 | rspec-terraform 1863 | rubocop 1864 | rubocop-rake 1865 | rubocop-rspec 1866 | rubyzip 1867 | semantic 1868 | 1869 | BUNDLED WITH 1870 | 2.3.7 1871 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 InfraBlocks Maintainers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Terraform AWS Organisation 2 | ========================== 3 | 4 | [![CircleCI](https://circleci.com/gh/infrablocks/terraform-aws-organization.svg?style=svg)](https://circleci.com/gh/infrablocks/terraform-aws-organization) 5 | 6 | A Terraform module for managing an AWS Organisation. 7 | 8 | The Organisation deployment has no requirements. 9 | 10 | The Organisation deployment consists of: 11 | 12 | * an AWS organisation 13 | * with a hierarchy of organisational units 14 | * with a set of accounts placed in that hierarchy 15 | 16 | Usage 17 | ----- 18 | 19 | To use the module, include something like the following in your Terraform 20 | configuration: 21 | 22 | ```hcl-terraform 23 | module "organisation" { 24 | source = "infrablocks/organization/aws" 25 | version = "2.0.0" 26 | 27 | feature_set = "ALL" 28 | aws_service_access_principals = [ 29 | "cloudtrail.amazonaws.com", 30 | "config.amazonaws.com" 31 | ] 32 | enabled_policy_types = [ 33 | "SERVICE_CONTROL_POLICY", 34 | "TAG_POLICY" 35 | ] 36 | 37 | organization = { 38 | accounts = [ 39 | { 40 | name = "Default" 41 | key = "mycompany-default" 42 | email = "root@company.com" 43 | } 44 | ] 45 | units = [ 46 | { 47 | name = "MyProduct", 48 | key = "mycompany-myproduct" 49 | units = [ 50 | { 51 | name = "Development", 52 | key = "mycompany-myproduct-development" 53 | accounts = [ 54 | { 55 | name = "Blue" 56 | key = "mycompany-myproduct-development-blue" 57 | email = "development@company.com" 58 | } 59 | ] 60 | }, 61 | { 62 | name = "Production", 63 | key = "mycompany-myproduct-production" 64 | accounts = [ 65 | { 66 | name = "Blue" 67 | key = "mycompany-myproduct-production-blue" 68 | email = "production@company.com" 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | } 77 | ``` 78 | 79 | Note: `organization` can be nested up to 5 levels deep. Levels 1 through 4 may 80 | include 81 | a `units` property, although it can be an empty array. Level 5 must not include 82 | a `units` property. 83 | 84 | See the 85 | [Terraform registry entry](https://registry.terraform.io/modules/infrablocks/organization/aws/latest) 86 | for more details. 87 | 88 | ### Inputs 89 | 90 | | Name | Description | Default | Required | 91 | |-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|:-------:|:--------:| 92 | | feature_set | The feature set to enable for the organization (one of "ALL" or "CONSOLIDATED_BILLING") | ALL | no | 93 | | aws_service_access_principals | A list of AWS service principal names for which you want to enable integration with your organization. | [] | no | 94 | | organization | The tree of organizational units and accounts to construct. Defaults to an empty tree. | [] | no | 95 | | enabled_policy_types | The list of Organizations policy types to enable in the Organization Root. The organization must have `feature_set` set to `\"ALL\"`. | [] | no | 96 | 97 | ### Outputs 98 | 99 | | Name | Description | 100 | |----------------------|-----------------------------------------------| 101 | | organization_arn | The ARN of the resulting organization | 102 | | organizational_units | Details of the resulting organizational units | 103 | | accounts | Details of the resulting accounts | 104 | 105 | ### Compatibility 106 | 107 | This module is compatible with Terraform versions greater than or equal to 108 | Terraform 1.3. 109 | 110 | Development 111 | ----------- 112 | 113 | ### Machine Requirements 114 | 115 | In order for the build to run correctly, a few tools will need to be installed 116 | on your development machine: 117 | 118 | * Ruby (3.1.1) 119 | * Bundler 120 | * git 121 | * git-crypt 122 | * gnupg 123 | * direnv 124 | * aws-vault 125 | 126 | #### Mac OS X Setup 127 | 128 | Installing the required tools is best managed by [homebrew](http://brew.sh). 129 | 130 | To install homebrew: 131 | 132 | ``` 133 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 134 | ``` 135 | 136 | Then, to install the required tools: 137 | 138 | ``` 139 | # ruby 140 | brew install rbenv 141 | brew install ruby-build 142 | echo 'eval "$(rbenv init - bash)"' >> ~/.bash_profile 143 | echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc 144 | eval "$(rbenv init -)" 145 | rbenv install 3.1.1 146 | rbenv rehash 147 | rbenv local 3.1.1 148 | gem install bundler 149 | 150 | # git, git-crypt, gnupg 151 | brew install git 152 | brew install git-crypt 153 | brew install gnupg 154 | 155 | # aws-vault 156 | brew cask install 157 | 158 | # direnv 159 | brew install direnv 160 | echo "$(direnv hook bash)" >> ~/.bash_profile 161 | echo "$(direnv hook zsh)" >> ~/.zshrc 162 | eval "$(direnv hook $SHELL)" 163 | 164 | direnv allow 165 | ``` 166 | 167 | ### Running the build 168 | 169 | Running the build requires an AWS account and AWS credentials. You are free to 170 | configure credentials however you like as long as an access key ID and secret 171 | access key are available. These instructions utilise 172 | [aws-vault](https://github.com/99designs/aws-vault) which makes credential 173 | management easy and secure. 174 | 175 | To provision module infrastructure, run tests and then destroy that 176 | infrastructure, execute: 177 | 178 | ```bash 179 | aws-vault exec -- ./go 180 | ``` 181 | 182 | To provision the module prerequisites: 183 | 184 | ```bash 185 | aws-vault exec -- ./go deployment:prerequisites:provision[] 186 | ``` 187 | 188 | To provision the module contents: 189 | 190 | ```bash 191 | aws-vault exec -- ./go deployment:root:provision[] 192 | ``` 193 | 194 | To destroy the module contents: 195 | 196 | ```bash 197 | aws-vault exec -- ./go deployment:root:destroy[] 198 | ``` 199 | 200 | To destroy the module prerequisites: 201 | 202 | ```bash 203 | aws-vault exec -- ./go deployment:prerequisites:destroy[] 204 | ``` 205 | 206 | Configuration parameters can be overridden via environment variables: 207 | 208 | ```bash 209 | DEPLOYMENT_IDENTIFIER=testing aws-vault exec -- ./go 210 | ``` 211 | 212 | When a deployment identifier is provided via an environment variable, 213 | infrastructure will not be destroyed at the end of test execution. This can 214 | be useful during development to avoid lengthy provision and destroy cycles. 215 | 216 | By default, providers will be downloaded for each terraform execution. To 217 | cache providers between calls: 218 | 219 | ```bash 220 | TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" aws-vault exec -- ./go 221 | ``` 222 | 223 | ### Common Tasks 224 | 225 | #### Generating an SSH key pair 226 | 227 | To generate an SSH key pair: 228 | 229 | ``` 230 | ssh-keygen -m PEM -t rsa -b 4096 -C integration-test@example.com -N '' -f config/secrets/keys/bastion/ssh 231 | ``` 232 | 233 | #### Generating a self-signed certificate 234 | 235 | To generate a self signed certificate: 236 | 237 | ``` 238 | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 239 | ``` 240 | 241 | To decrypt the resulting key: 242 | 243 | ``` 244 | openssl rsa -in key.pem -out ssl.key 245 | ``` 246 | 247 | #### Managing CircleCI keys 248 | 249 | To encrypt a GPG key for use by CircleCI: 250 | 251 | ```bash 252 | openssl aes-256-cbc \ 253 | -e \ 254 | -md sha1 \ 255 | -in ./config/secrets/ci/gpg.private \ 256 | -out ./.circleci/gpg.private.enc \ 257 | -k "" 258 | ``` 259 | 260 | To check decryption is working correctly: 261 | 262 | ```bash 263 | openssl aes-256-cbc \ 264 | -d \ 265 | -md sha1 \ 266 | -in ./.circleci/gpg.private.enc \ 267 | -k "" 268 | ``` 269 | 270 | Contributing 271 | ------------ 272 | 273 | Bug reports and pull requests are welcome on GitHub at 274 | https://github.com/infrablocks/terraform-aws-organisation. 275 | This project is intended to be a safe, welcoming space for collaboration, and 276 | contributors are expected to adhere to 277 | the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 278 | 279 | License 280 | ------- 281 | 282 | The library is available as open source under the terms of the 283 | [MIT License](http://opensource.org/licenses/MIT). 284 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'confidante' 4 | require 'git' 5 | require 'rake_circle_ci' 6 | require 'rake_git' 7 | require 'rake_git_crypt' 8 | require 'rake_github' 9 | require 'rake_gpg' 10 | require 'rake_ssh' 11 | require 'rake_terraform' 12 | require 'rspec/core/rake_task' 13 | require 'rubocop/rake_task' 14 | require 'securerandom' 15 | require 'semantic' 16 | require 'yaml' 17 | 18 | require_relative 'lib/paths' 19 | require_relative 'lib/version' 20 | 21 | configuration = Confidante.configuration 22 | 23 | def repo 24 | Git.open(Pathname.new('.')) 25 | end 26 | 27 | def latest_tag 28 | repo.tags.map do |tag| 29 | Semantic::Version.new(tag.name) 30 | end.max 31 | end 32 | 33 | task default: %i[ 34 | test:code:fix 35 | test:unit 36 | ] 37 | 38 | RakeTerraform.define_installation_tasks( 39 | path: File.join(Dir.pwd, 'vendor', 'terraform'), 40 | version: '1.3.1' 41 | ) 42 | 43 | RakeGitCrypt.define_standard_tasks( 44 | namespace: :git_crypt, 45 | 46 | provision_secrets_task_name: :'secrets:provision', 47 | destroy_secrets_task_name: :'secrets:destroy', 48 | 49 | install_commit_task_name: :'git:commit', 50 | uninstall_commit_task_name: :'git:commit', 51 | 52 | gpg_user_key_paths: %w[ 53 | config/gpg 54 | config/secrets/ci/gpg.public 55 | ] 56 | ) 57 | 58 | namespace :git do 59 | RakeGit.define_commit_task( 60 | argument_names: [:message] 61 | ) do |t, args| 62 | t.message = args.message 63 | end 64 | end 65 | 66 | namespace :encryption do 67 | namespace :directory do 68 | desc 'Ensure CI secrets directory exists.' 69 | task :ensure do 70 | FileUtils.mkdir_p('config/secrets/ci') 71 | end 72 | end 73 | 74 | namespace :passphrase do 75 | desc 'Generate encryption passphrase for CI GPG key' 76 | task generate: ['directory:ensure'] do 77 | File.write( 78 | 'config/secrets/ci/encryption.passphrase', 79 | SecureRandom.base64(36) 80 | ) 81 | end 82 | end 83 | end 84 | 85 | namespace :keys do 86 | namespace :deploy do 87 | RakeSSH.define_key_tasks( 88 | path: 'config/secrets/ci/', 89 | comment: 'maintainers@infrablocks.io' 90 | ) 91 | end 92 | 93 | namespace :secrets do 94 | namespace :gpg do 95 | RakeGPG.define_generate_key_task( 96 | output_directory: 'config/secrets/ci', 97 | name_prefix: 'gpg', 98 | owner_name: 'InfraBlocks Maintainers', 99 | owner_email: 'maintainers@infrablocks.io', 100 | owner_comment: 'terraform-aws-organization CI Key' 101 | ) 102 | end 103 | 104 | task generate: ['gpg:generate'] 105 | end 106 | end 107 | 108 | namespace :secrets do 109 | namespace :directory do 110 | desc 'Ensure secrets directory exists and is set up correctly' 111 | task :ensure do 112 | FileUtils.mkdir_p('config/secrets') 113 | unless File.exist?('config/secrets/.unlocked') 114 | File.write('config/secrets/.unlocked', 'true') 115 | end 116 | end 117 | end 118 | 119 | desc 'Generate all generatable secrets.' 120 | task generate: %w[ 121 | directory:ensure 122 | encryption:passphrase:generate 123 | keys:deploy:generate 124 | keys:secrets:generate 125 | ] 126 | 127 | desc 'Provision all secrets.' 128 | task provision: [:generate] 129 | 130 | desc 'Delete all secrets.' 131 | task :destroy do 132 | rm_rf 'config/secrets' 133 | end 134 | 135 | desc 'Rotate all secrets.' 136 | task rotate: [:'git_crypt:reinstall'] 137 | end 138 | 139 | RakeCircleCI.define_project_tasks( 140 | namespace: :circle_ci, 141 | project_slug: 'github/infrablocks/terraform-aws-organization' 142 | ) do |t| 143 | circle_ci_config = 144 | YAML.load_file('config/secrets/circle_ci/config.yaml') 145 | 146 | t.api_token = circle_ci_config['circle_ci_api_token'] 147 | t.environment_variables = { 148 | ENCRYPTION_PASSPHRASE: 149 | File.read('config/secrets/ci/encryption.passphrase') 150 | .chomp, 151 | CIRCLECI_API_KEY: 152 | YAML.load_file( 153 | 'config/secrets/circle_ci/config.yaml' 154 | )['circle_ci_api_token'] 155 | } 156 | t.checkout_keys = [] 157 | t.ssh_keys = [ 158 | { 159 | hostname: 'github.com', 160 | private_key: File.read('config/secrets/ci/ssh.private') 161 | } 162 | ] 163 | end 164 | 165 | RakeGithub.define_repository_tasks( 166 | namespace: :github, 167 | repository: 'infrablocks/terraform-aws-organization' 168 | ) do |t| 169 | github_config = 170 | YAML.load_file('config/secrets/github/config.yaml') 171 | 172 | t.access_token = github_config['github_personal_access_token'] 173 | t.deploy_keys = [ 174 | { 175 | title: 'CircleCI', 176 | public_key: File.read('config/secrets/ci/ssh.public') 177 | } 178 | ] 179 | end 180 | 181 | namespace :pipeline do 182 | desc 'Prepare CircleCI Pipeline' 183 | task prepare: %i[ 184 | circle_ci:env_vars:ensure 185 | circle_ci:checkout_keys:ensure 186 | circle_ci:ssh_keys:ensure 187 | github:deploy_keys:ensure 188 | ] 189 | end 190 | 191 | RuboCop::RakeTask.new 192 | 193 | namespace :test do 194 | namespace :code do 195 | desc 'Run all checks on the test code' 196 | task check: [:rubocop] 197 | 198 | desc 'Attempt to automatically fix issues with the test code' 199 | task fix: [:'rubocop:autocorrect_all'] 200 | end 201 | 202 | desc 'Run module unit tests' 203 | RSpec::Core::RakeTask.new(unit: ['terraform:ensure']) do |t| 204 | t.pattern = 'spec/unit/**{,/*/**}/*_spec.rb' 205 | t.rspec_opts = '-I spec/unit' 206 | 207 | plugin_cache_directory = 208 | "#{Paths.project_root_directory}/vendor/terraform/plugins" 209 | 210 | mkdir_p(plugin_cache_directory) 211 | 212 | ENV['AWS_REGION'] = configuration.region 213 | end 214 | end 215 | 216 | namespace :deployment do 217 | namespace :prerequisites do 218 | RakeTerraform.define_command_tasks( 219 | configuration_name: 'prerequisites', 220 | argument_names: [:seed] 221 | ) do |t, args| 222 | deployment_configuration = 223 | configuration 224 | .for_scope(role: :prerequisites) 225 | .for_overrides(args.to_h) 226 | 227 | t.source_directory = 'spec/unit/infra/prerequisites' 228 | t.work_directory = 'build/infra' 229 | 230 | t.state_file = deployment_configuration.state_file 231 | t.vars = deployment_configuration.vars 232 | end 233 | end 234 | 235 | namespace :root do 236 | RakeTerraform.define_command_tasks( 237 | configuration_name: 'root', 238 | argument_names: [:seed] 239 | ) do |t, args| 240 | deployment_configuration = 241 | configuration 242 | .for_scope(role: :root) 243 | .for_overrides(args.to_h) 244 | 245 | t.source_directory = 'spec/unit/infra/root' 246 | t.work_directory = 'build/infra' 247 | 248 | t.state_file = deployment_configuration.state_file 249 | t.vars = deployment_configuration.vars 250 | end 251 | end 252 | end 253 | 254 | namespace :version do 255 | desc 'Bump version for specified type (pre, major, minor, patch)' 256 | task :bump, [:type] do |_, args| 257 | next_tag = latest_tag.send("#{args.type}!") 258 | repo.add_tag(next_tag.to_s) 259 | repo.push('origin', 'main', tags: true) 260 | puts "Bumped version to #{next_tag}." 261 | end 262 | 263 | desc 'Release module' 264 | task :release do 265 | next_tag = latest_tag.release! 266 | repo.add_tag(next_tag.to_s) 267 | repo.push('origin', 'main', tags: true) 268 | puts "Released version #{next_tag}." 269 | end 270 | end 271 | -------------------------------------------------------------------------------- /accounts.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | level_root_account_arguments = [ 3 | for level_root_account in var.organization.accounts : 4 | { 5 | parent : aws_organizations_organization.organization.roots[0], 6 | key : level_root_account.key, 7 | name : level_root_account.name, 8 | email : level_root_account.email 9 | allow_iam_users_access_to_billing : level_root_account.allow_iam_users_access_to_billing 10 | } 11 | ] 12 | level_1_account_arguments = flatten([ 13 | for level_1_ou in var.organization.units : 14 | [ 15 | for level_1_account in level_1_ou.accounts : 16 | { 17 | parent : [for ou in local.level_1_ou_attributes : ou if level_1_ou.name == ou.name][0], 18 | key : level_1_account.key, 19 | name : level_1_account.name, 20 | email : level_1_account.email 21 | allow_iam_users_access_to_billing : level_1_account.allow_iam_users_access_to_billing 22 | } 23 | ] 24 | ]) 25 | level_2_account_arguments = flatten([ 26 | for level_1_ou in var.organization.units : 27 | [ 28 | for level_2_ou in level_1_ou.units : 29 | [ 30 | for level_2_account in level_2_ou.accounts : 31 | { 32 | parent : [for ou in local.level_2_ou_attributes : ou if level_2_ou.name == ou.name][0], 33 | key : level_2_account.key, 34 | name : level_2_account.name, 35 | email : level_2_account.email 36 | allow_iam_users_access_to_billing : level_2_account.allow_iam_users_access_to_billing 37 | } 38 | ] 39 | ] 40 | ]) 41 | level_3_account_arguments = flatten([ 42 | for level_1_ou in var.organization.units : 43 | [ 44 | for level_2_ou in level_1_ou.units : 45 | [ 46 | for level_3_ou in level_2_ou.units : 47 | [ 48 | for level_3_account in level_3_ou.accounts : 49 | { 50 | parent : [for ou in local.level_3_ou_attributes : ou if level_3_ou.name == ou.name][0], 51 | key : level_3_account.key, 52 | name : level_3_account.name, 53 | email : level_3_account.email 54 | allow_iam_users_access_to_billing : level_3_account.allow_iam_users_access_to_billing 55 | } 56 | ] 57 | ] 58 | ] 59 | ]) 60 | level_4_account_arguments = flatten([ 61 | for level_1_ou in var.organization.units : 62 | [ 63 | for level_2_ou in level_1_ou.units : 64 | [ 65 | for level_3_ou in level_2_ou.units : 66 | [ 67 | for level_4_ou in level_3_ou.units : 68 | [ 69 | for level_4_account in level_4_ou.accounts : 70 | { 71 | parent : [for ou in local.level_4_ou_attributes : ou if level_4_ou.name == ou.name][0], 72 | key : level_4_account.key, 73 | name : level_4_account.name, 74 | email : level_4_account.email 75 | allow_iam_users_access_to_billing : level_4_account.allow_iam_users_access_to_billing 76 | } 77 | ] 78 | ] 79 | ] 80 | ] 81 | ]) 82 | level_5_account_arguments = flatten([ 83 | for level_1_ou in var.organization.units : 84 | [ 85 | for level_2_ou in level_1_ou.units : 86 | [ 87 | for level_3_ou in level_2_ou.units : 88 | [ 89 | for level_4_ou in level_3_ou.units : 90 | [ 91 | for level_5_ou in level_4_ou.units : 92 | [ 93 | for level_5_account in level_5_ou.accounts : 94 | { 95 | parent : [for ou in local.level_5_ou_attributes : ou if level_5_ou.name == ou.name][0], 96 | key : level_5_account.key, 97 | name : level_5_account.name, 98 | email : level_5_account.email 99 | allow_iam_users_access_to_billing : level_5_account.allow_iam_users_access_to_billing 100 | } 101 | ] 102 | ] 103 | ] 104 | ] 105 | ] 106 | ]) 107 | all_accounts = concat( 108 | local.level_root_account_arguments, 109 | local.level_1_account_arguments, 110 | local.level_2_account_arguments, 111 | local.level_3_account_arguments, 112 | local.level_4_account_arguments, 113 | local.level_5_account_arguments 114 | ) 115 | } 116 | 117 | resource "aws_organizations_account" "account" { 118 | for_each = {for record in local.all_accounts : record.key => record} 119 | 120 | name = each.value.name 121 | email = each.value.email 122 | 123 | iam_user_access_to_billing = each.value.allow_iam_users_access_to_billing ? "ALLOW" : "DENY" 124 | 125 | parent_id = each.value.parent.id 126 | } 127 | 128 | locals { 129 | all_account_attributes = { 130 | for account in local.all_accounts : 131 | account.key => { 132 | id = aws_organizations_account.account[account.key].id, 133 | arn = aws_organizations_account.account[account.key].arn, 134 | name = aws_organizations_account.account[account.key].name 135 | email = aws_organizations_account.account[account.key].email 136 | parent_id = aws_organizations_account.account[account.key].parent_id, 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /config/defaults.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | region: 'us-east-1' 3 | 4 | component: 'test' 5 | deployment_identifier: "%{hiera('seed')}" 6 | -------------------------------------------------------------------------------- /config/gpg/jonas.gpg.public: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | 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 59 | =e5EY 60 | -----END PGP PUBLIC KEY BLOCK----- -------------------------------------------------------------------------------- /config/gpg/liam.gpg.public: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mQGNBGH39r4BDADfCcY6rEDhN1uxj4kgr/xTclNJM0kzDJIv7veMmKylNlw+ePhj 4 | dl9IXIFxd/Sc8NPx/xOCYIbALd8SvDVW9Qfe0Mqq41HbWmAGgoWKN6BfY4UBqKgM 5 | 2lIGAUzdkwsF+ubXMwLooLSDL38homebBG+I/NG1uu1rO9B0c8G/cHz4jBuqYJXj 6 | FrBwDgcoBrJEI2oNpN68qezdzGvB3AJO9oE4rrhIkbqkQouqqxvvZbuqb+FHRxIH 7 | LiAV6zqnZ/3sDq0L90V36auH7rsz4cYxOWl4S6jFzNty5UviIvqJ/zz+g7ouaC+N 8 | qpG3g2Qjk6h7A9fy+wwO0G04oKkYMT3Qi8moqVrlm89atVenvFVI6tNVSnzh0vFG 9 | ycvE5UUXqjw1b+Bwq2GINHmUGBz1u0aw2TbPaETzPJQbMLWxrPPz9ck99+UqXj57 10 | ZY4xk5gfP/FcAZIOeTxp1l5FQzxRmFIM523MnKdkbaJ+Qhm44chnRGRatz9PiJnv 11 | 5eMESRNpOY2lC1EAEQEAAbQnTGlhbSBHcmlmZmluLUpvd2V0dCA8bGlhbUBnby1h 12 | dG9taWMuaW8+iQHYBBMBCABCFiEEkz45lGhtwVyZ0TaYRANzma7bHY0FAmH39r4C 13 | GwMFCQPCZwAFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJEEQDc5mu2x2N 14 | 9QkL/i2UALrzcFZazgBOx5Pkng6BLt2pKKv9zE58ZNu2u8hq8QaNHUA7Gwf7qZlL 15 | A5arZ4K8KJ2zuR9BBzQIbjdVbwqsSpOz0wKXzF6Jt4Cas2gxdBob4m2hv9W7E1wz 16 | hFUjZk4GixCp8who4/FUGrBun+COo/b1UkJ/E9DisgIiXyM78AO6HhhVOb/2M+cf 17 | 1vq6OjuN3Cr5p0LnvrEsOsz2sdB6qBarrN3ragd6M2+T7HmkUPbZDf5UIxVzUeWm 18 | I0YXhECSqahNhlyIR24e6CsEAJkILxijU3mvj09DO7gHYKXZsBiAX9Peo+D5qywc 19 | q4TCV9oZuDB1Rbuzmrb/jTCrQMBaYt0kosMo0OTWSGrUFg+Ymwl/cnoZU89ZPYp6 20 | ZvctRHaw3f3eP1AJ1WG+oE1X7e/g4q7Or8z5O8EYoBHVXTjwGi621WTodr5a/gPY 21 | oGYRr68afTsq13KuiMC3lCWfHPFTmo5/Os66fvZHIuxles0Oxy3iHQseZKlCdXhd 22 | ylJu6rkBjQRh9/a+AQwAnFqV8e7RTz47mIK4r+WLh82XnAbMuefyOBajavWOSD1J 23 | YrO29qL/UKD5Td7I9iqCHLwfHr0HNSXZ8MXRW71teOtEwwtNRtntSCkATdBsvgUW 24 | xwwpvB+OpKBR3wv5Q8/7fmDN8bAz1TBaYLxu+Q2q7ziHC6cB+lBfgdPE3b/y0LfK 25 | Ia26+jy+gqA4l/Xlio+WU2SKSVy+usJrNg58rStgND/E8btm+uCXq2VBhhZ+dLqi 26 | Oo3IblTvDcG6BRN/NN9g3YJaOaSdjxNeZp3V6xwtnOEdZ85pEdBsvkRgnpZ0eyHp 27 | yYm1xE2H5Idwtugs4wVC9u33p8P9QgDJ7hS5B+5kowjwiHuSquo1cXrj8a4NL8L+ 28 | duJrRb9lP/fXjjcGk4uaDhIjKTWoGWTAra9/tRdLZpjBh9Y+d70cdQfrzeVGH7ac 29 | VTyvjL9+h17dbP6pYMf42zeB0n667WRyG97L1nD48rUqWf2l38m8S639Q5x9t1L+ 30 | kvOUEISYXtMuv/I15qk3ABEBAAGJAbwEGAEIACYWIQSTPjmUaG3BXJnRNphEA3OZ 31 | rtsdjQUCYff2vgIbDAUJA8JnAAAKCRBEA3OZrtsdjdAPC/sH1zQIUm60bn0N3gHt 32 | E5dW2BBAULA6vxnkWTVNWBYuZm5AHR1wPEB8GvheWIiU0ASIuGbC/vbn0mB23FVz 33 | oxGQhOB4b2QNHVhaHtmr+0m+FQborpoeamnblc1SNtMNLN4a2dgAxhCHA97NMWKr 34 | NrUuyN+qz//Xh44jPyRo04bEkYbCmTk/fca0tb/WCBQHLq8JJy1ZfgWZfj3iC092 35 | wT5MpDL2NvItXBX8mDXZWf7NG+o1yUEm1mA6ZE3ZZPgwP0Uy8myhTLz1EN1aVoqG 36 | 7lUH2fuw0dmSEwPytl9IPqZIYRzzSRWcAiho0BazfKdpubh9hY4AEtPVFR54I9Z9 37 | JiezgHCilIo7haAFTi0rgXMfoQIIXlFRPL8a4QfWvPBmRd/Vm0DKSUOaF7wJtflC 38 | AdYBEuibOElrD9+e3wwBC2qr1zSNmvoGA5o7T3Eq31oZkZmfzm4a4z0558Y7UMZ3 39 | 3rbVfQYlC4lv1cLV+bFV3jEGIOW3H1ueTUv/ClTwB+xCZv8= 40 | =0Zai 41 | -----END PGP PUBLIC KEY BLOCK----- 42 | -------------------------------------------------------------------------------- /config/gpg/toby.gpg.public: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | 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 105 | VryshT5m6VKxVqJv 106 | =vHmq 107 | -----END PGP PUBLIC KEY BLOCK----- 108 | -------------------------------------------------------------------------------- /config/hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | :backends: 3 | - "env" 4 | - "overrides" 5 | - "yaml" 6 | :logger: "noop" 7 | :yaml: 8 | :datadir: "config" 9 | :hierarchy: 10 | - "roles/%{role}" 11 | - "defaults" 12 | -------------------------------------------------------------------------------- /config/roles/basic.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | configuration_directory: "%{cwd}/examples/basic" 3 | state_file: "%{cwd}/state/basic.tfstate" 4 | vars: 5 | region: "%{hiera('region')}" 6 | -------------------------------------------------------------------------------- /config/roles/prerequisites.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | configuration_directory: "%{cwd}/spec/unit/infra/prerequisites" 3 | state_file: "%{cwd}/state/prerequisites.tfstate" 4 | vars: 5 | region: "%{hiera('region')}" 6 | -------------------------------------------------------------------------------- /config/roles/root.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | configuration_directory: "%{cwd}/spec/unit/infra/root" 3 | state_file: "%{cwd}/state/root.tfstate" 4 | vars: 5 | region: "%{hiera('region')}" 6 | -------------------------------------------------------------------------------- /config/secrets/.unlocked: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/.unlocked -------------------------------------------------------------------------------- /config/secrets/ci/aws-credentials.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/ci/aws-credentials.sh -------------------------------------------------------------------------------- /config/secrets/ci/encryption.passphrase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/ci/encryption.passphrase -------------------------------------------------------------------------------- /config/secrets/ci/gpg.private: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/ci/gpg.private -------------------------------------------------------------------------------- /config/secrets/ci/gpg.public: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/ci/gpg.public -------------------------------------------------------------------------------- /config/secrets/ci/ssh.private: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/ci/ssh.private -------------------------------------------------------------------------------- /config/secrets/ci/ssh.public: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/ci/ssh.public -------------------------------------------------------------------------------- /config/secrets/circle_ci/config.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/circle_ci/config.yaml -------------------------------------------------------------------------------- /config/secrets/github/config.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/config/secrets/github/config.yaml -------------------------------------------------------------------------------- /examples/basic/.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/aws" { 5 | version = "4.33.0" 6 | constraints = ">= 3.29.0, 4.33.0" 7 | hashes = [ 8 | "h1:0S9ZXYg6K0CTOJUTQnoH94YrKuOYyJYEcc+hN5qGafA=", 9 | "h1:rLRYOeKvU17Tky5dleZwTPRoWtbdFTG/jOF/fTP2otY=", 10 | "zh:421b24e21d7fac4d65d97438d2c0a4effe71d3a1bd15820d6fde2879e49fe817", 11 | "zh:4378a84ca8e2a6990f47abc24367b801e884be928671b37ad7b8e7b656f73e48", 12 | "zh:54e0d7884edf3cefd096715794d32b6532138dca905f0b2fe84fb2117594293c", 13 | "zh:6269a7d0312057db5ded669e9f7f9bd80fb6dcb549b50d8d7f3f3b2a0361b8a5", 14 | "zh:67f57d16aa3db493a3174c3c5f30385c7af9767c4e3cdca14e5a4bf384ff59d9", 15 | "zh:7d4d4a1d963e431ffdc3348e3a578d3ba0fa782b1f4bf55fd5c0e527d24fed81", 16 | "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", 17 | "zh:cd8e3d32485acb49c1b06f63916fec8e73a4caa6cf88ae9c4bf236d6f5d9b914", 18 | "zh:d586fd01195bd3775346495e61806e79b6012e745dc05e31a30b958acf968abe", 19 | "zh:d76122060f25ab87887a743096a42d47ba091c2c019ac13ce6b3973b2babe5a3", 20 | "zh:e917d36fe18eddc42ec743b3152b4dcb4853b75ea7a679abd19bdf271bc48221", 21 | "zh:eb780860d5c04f43a018aef564e76a2d84e9aa68984fa1f968ca8c09d23a611a", 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /examples/basic/organization.tf: -------------------------------------------------------------------------------- 1 | module "organization" { 2 | source = "../../" 3 | 4 | feature_set = "ALL" 5 | 6 | organization = { 7 | accounts = [ 8 | { 9 | name = "Default" 10 | key = "mycompany-default" 11 | email = "root@company.com" 12 | } 13 | ] 14 | units = [ 15 | { 16 | name = "MyProduct", 17 | key = "mycompany-myproduct" 18 | units = [ 19 | { 20 | name = "Development", 21 | key = "mycompany-myproduct-development" 22 | accounts = [ 23 | { 24 | name = "Blue" 25 | key = "mycompany-myproduct-development-blue" 26 | email = "development@company.com" 27 | } 28 | ] 29 | }, 30 | { 31 | name = "Production", 32 | key = "mycompany-myproduct-production" 33 | accounts = [ 34 | { 35 | name = "Blue" 36 | key = "mycompany-myproduct-production-blue" 37 | email = "production@company.com" 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/basic/outputs.tf: -------------------------------------------------------------------------------- 1 | output "organization_arn" { 2 | value = module.organization.organization_arn 3 | } 4 | 5 | output "organizational_units" { 6 | value = module.organization.organizational_units 7 | } 8 | -------------------------------------------------------------------------------- /examples/basic/prerequisites.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/examples/basic/prerequisites.tf -------------------------------------------------------------------------------- /examples/basic/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | } 4 | -------------------------------------------------------------------------------- /examples/basic/terraform.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.3" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = "4.33" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/basic/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" {} 2 | -------------------------------------------------------------------------------- /go: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$GO_DEBUG" ] && set -x 4 | set -e 5 | 6 | project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 7 | 8 | verbose="no" 9 | offline="no" 10 | skip_checks="no" 11 | 12 | missing_dependency="no" 13 | 14 | [ -n "$GO_DEBUG" ] && verbose="yes" 15 | [ -n "$GO_SKIP_CHECKS" ] && skip_checks="yes" 16 | [ -n "$GO_OFFLINE" ] && offline="yes" 17 | 18 | function loose_version() { 19 | local version="$1" 20 | 21 | IFS="." read -r -a version_parts <<<"$version" 22 | 23 | echo "${version_parts[0]}.${version_parts[1]}" 24 | } 25 | 26 | ruby_full_version="$(cat "$project_dir"/.ruby-version)" 27 | ruby_loose_version="$(loose_version "$ruby_full_version")" 28 | 29 | if [[ "$skip_checks" == "no" ]]; then 30 | echo "Checking for system dependencies." 31 | if ! type ruby >/dev/null 2>&1 || ! ruby -v | grep -q "$ruby_loose_version"; then 32 | echo "This codebase requires Ruby $ruby_loose_version." 33 | missing_dependency="yes" 34 | fi 35 | 36 | if ! type bundler >/dev/null 2>&1; then 37 | echo "This codebase requires Bundler." 38 | missing_dependency="yes" 39 | fi 40 | 41 | if [[ "$missing_dependency" = "yes" ]]; then 42 | echo "Please install missing dependencies to continue." 43 | exit 1 44 | fi 45 | 46 | echo "All system dependencies present. Continuing." 47 | fi 48 | 49 | if [[ "$offline" == "no" ]]; then 50 | echo "Installing bundler." 51 | if [[ "$verbose" == "yes" ]]; then 52 | gem install --no-document bundler 53 | else 54 | gem install --no-document bundler >/dev/null 55 | fi 56 | 57 | echo "Installing ruby dependencies." 58 | if [[ "$verbose" == "yes" ]]; then 59 | bundle install 60 | else 61 | bundle install >/dev/null 62 | fi 63 | fi 64 | 65 | echo "Starting rake." 66 | if [[ "$verbose" == "yes" ]]; then 67 | time bundle exec rake --verbose "$@" 68 | else 69 | time bundle exec rake "$@" 70 | fi 71 | -------------------------------------------------------------------------------- /lib/paths.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Paths 4 | class << self 5 | def project_root_directory 6 | join_and_expand(self_directory, '..') 7 | end 8 | 9 | def from_project_root_directory(*segments) 10 | join_and_expand(project_root_directory, *segments) 11 | end 12 | 13 | def join_and_expand(*segments) 14 | File.expand_path(join(*segments)) 15 | end 16 | 17 | def join(*segments) 18 | File.join(*segments.compact) 19 | end 20 | 21 | def self_directory 22 | File.dirname(__FILE__) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Semantic 4 | module Extensions 5 | def release! 6 | unless prerelease? 7 | raise 'Error: no pre segment, ' \ 8 | 'this version is not a pre-release version.' 9 | end 10 | 11 | new_version = clone 12 | new_version.build = new_version.pre = nil 13 | new_version 14 | end 15 | 16 | def rc! 17 | return start_rc if release? 18 | return increment_rc if rc? 19 | 20 | raise "Error: pre segment '#{pre}' does not look like 'rc.n'." 21 | end 22 | 23 | private 24 | 25 | def start_rc 26 | new_version = clone 27 | new_version = new_version.increment!(:minor) 28 | new_version.pre = 'rc.1' 29 | new_version 30 | end 31 | 32 | def increment_rc 33 | new_version = clone 34 | new_version.pre = "rc.#{Integer(new_version.pre.delete('rc.')) + 1}" 35 | new_version 36 | end 37 | 38 | def release? 39 | pre.nil? 40 | end 41 | 42 | def prerelease? 43 | !release? 44 | end 45 | 46 | def rc? 47 | pre =~ /^rc\.\d+$/ 48 | end 49 | end 50 | 51 | class Version 52 | prepend Extensions 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/main.tf -------------------------------------------------------------------------------- /organization.tf: -------------------------------------------------------------------------------- 1 | resource "aws_organizations_organization" "organization" { 2 | feature_set = var.feature_set 3 | aws_service_access_principals = var.aws_service_access_principals 4 | enabled_policy_types = var.enabled_policy_types 5 | } 6 | -------------------------------------------------------------------------------- /organizational_units.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | level_1_ou_arguments = [ 3 | for ou in var.organization.units : 4 | { 5 | name : ou.name, 6 | key : ou.key, 7 | } 8 | ] 9 | level_2_ou_arguments = flatten([ 10 | for level_1_ou in var.organization.units : 11 | [ 12 | for level_2_ou in level_1_ou.units : 13 | { 14 | name : level_2_ou.name, 15 | key : level_2_ou.key, 16 | parent : level_1_ou.key 17 | } 18 | ] 19 | ]) 20 | level_3_ou_arguments = flatten([ 21 | for level_1_ou in var.organization.units : 22 | [ 23 | for level_2_ou in level_1_ou.units : 24 | [ 25 | for level_3_ou in level_2_ou.units : 26 | { 27 | name : level_3_ou.name, 28 | key : level_3_ou.key, 29 | parent : level_2_ou.key 30 | } 31 | ] 32 | ] 33 | ]) 34 | level_4_ou_arguments = flatten([ 35 | for level_1_ou in var.organization.units : 36 | [ 37 | for level_2_ou in level_1_ou.units : 38 | [ 39 | for level_3_ou in level_2_ou.units : 40 | [ 41 | for level_4_ou in level_3_ou.units : 42 | { 43 | name : level_4_ou.name, 44 | key : level_4_ou.key, 45 | parent : level_3_ou.key 46 | } 47 | ] 48 | ] 49 | ] 50 | ]) 51 | level_5_ou_arguments = flatten([ 52 | for level_1_ou in var.organization.units : 53 | [ 54 | for level_2_ou in level_1_ou.units : 55 | [ 56 | for level_3_ou in level_2_ou.units : 57 | [ 58 | for level_4_ou in level_3_ou.units : 59 | [ 60 | for level_5_ou in level_4_ou.units : 61 | { 62 | name : level_5_ou.name, 63 | key : level_5_ou.key, 64 | parent : level_4_ou.key 65 | } 66 | ] 67 | ] 68 | ] 69 | ] 70 | ]) 71 | } 72 | 73 | resource "aws_organizations_organizational_unit" "level_1_ous" { 74 | for_each = {for record in local.level_1_ou_arguments : record.key => record} 75 | name = each.value.name 76 | parent_id = aws_organizations_organization.organization.roots[0].id 77 | } 78 | 79 | resource "aws_organizations_organizational_unit" "level_2_ous" { 80 | for_each = {for record in local.level_2_ou_arguments : record.key => record} 81 | name = each.value.name 82 | parent_id = aws_organizations_organizational_unit.level_1_ous[each.value.parent].id 83 | } 84 | 85 | resource "aws_organizations_organizational_unit" "level_3_ous" { 86 | for_each = {for record in local.level_3_ou_arguments : record.key => record} 87 | name = each.value.name 88 | parent_id = aws_organizations_organizational_unit.level_2_ous[each.value.parent].id 89 | } 90 | 91 | resource "aws_organizations_organizational_unit" "level_4_ous" { 92 | for_each = {for record in local.level_4_ou_arguments : record.key => record} 93 | name = each.value.name 94 | parent_id = aws_organizations_organizational_unit.level_3_ous[each.value.parent].id 95 | } 96 | 97 | resource "aws_organizations_organizational_unit" "level_5_ous" { 98 | for_each = {for record in local.level_5_ou_arguments : record.key => record} 99 | name = each.value.name 100 | parent_id = aws_organizations_organizational_unit.level_4_ous[each.value.parent].id 101 | } 102 | 103 | locals { 104 | level_1_ou_attributes = [ 105 | for ou in local.level_1_ou_arguments : 106 | { 107 | key = ou.key 108 | id = aws_organizations_organizational_unit.level_1_ous[ou.key].id, 109 | arn = aws_organizations_organizational_unit.level_1_ous[ou.key].arn, 110 | parent_id = aws_organizations_organizational_unit.level_1_ous[ou.key].parent_id, 111 | name = aws_organizations_organizational_unit.level_1_ous[ou.key].name, 112 | } 113 | ] 114 | level_2_ou_attributes = [ 115 | for ou in local.level_2_ou_arguments : 116 | { 117 | key = ou.key 118 | id = aws_organizations_organizational_unit.level_2_ous[ou.key].id, 119 | arn = aws_organizations_organizational_unit.level_2_ous[ou.key].arn, 120 | parent_id = aws_organizations_organizational_unit.level_2_ous[ou.key].parent_id, 121 | name = aws_organizations_organizational_unit.level_2_ous[ou.key].name, 122 | } 123 | ] 124 | level_3_ou_attributes = [ 125 | for ou in local.level_3_ou_arguments : 126 | { 127 | key = ou.key 128 | id = aws_organizations_organizational_unit.level_3_ous[ou.key].id, 129 | arn = aws_organizations_organizational_unit.level_3_ous[ou.key].arn, 130 | parent_id = aws_organizations_organizational_unit.level_3_ous[ou.key].parent_id, 131 | name = aws_organizations_organizational_unit.level_3_ous[ou.key].name, 132 | } 133 | ] 134 | level_4_ou_attributes = [ 135 | for ou in local.level_4_ou_arguments : 136 | { 137 | key = ou.key 138 | id = aws_organizations_organizational_unit.level_4_ous[ou.key].id, 139 | arn = aws_organizations_organizational_unit.level_4_ous[ou.key].arn, 140 | parent_id = aws_organizations_organizational_unit.level_4_ous[ou.key].parent_id, 141 | name = aws_organizations_organizational_unit.level_4_ous[ou.key].name, 142 | } 143 | ] 144 | level_5_ou_attributes = [ 145 | for ou in local.level_5_ou_arguments : 146 | { 147 | key = ou.key 148 | id = aws_organizations_organizational_unit.level_5_ous[ou.key].id, 149 | arn = aws_organizations_organizational_unit.level_5_ous[ou.key].arn, 150 | parent_id = aws_organizations_organizational_unit.level_5_ous[ou.key].parent_id, 151 | name = aws_organizations_organizational_unit.level_5_ous[ou.key].name, 152 | } 153 | ] 154 | all_ou_attributes = { 155 | for ou in concat( 156 | local.level_1_ou_attributes, 157 | local.level_2_ou_attributes, 158 | local.level_3_ou_attributes, 159 | local.level_4_ou_attributes, 160 | local.level_5_ou_attributes 161 | ) : 162 | ou.key => ou 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "organization_arn" { 2 | value = aws_organizations_organization.organization.arn 3 | } 4 | 5 | output "organizational_units" { 6 | value = local.all_ou_attributes 7 | } 8 | 9 | output "accounts" { 10 | value = local.all_account_attributes 11 | } 12 | -------------------------------------------------------------------------------- /scripts/ci/common/configure-git.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | git config --global user.email "circleci@infrablocks.io" 8 | git config --global user.name "Circle CI" 9 | -------------------------------------------------------------------------------- /scripts/ci/common/install-git-crypt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | apt-get update 8 | apt-get install -y --no-install-recommends git ssh git-crypt 9 | -------------------------------------------------------------------------------- /scripts/ci/common/install-gpg-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | PROJECT_DIR="$( cd "$SCRIPT_DIR/../../.." && pwd )" 9 | 10 | cd "$PROJECT_DIR" 11 | 12 | set +e 13 | openssl version 14 | openssl aes-256-cbc \ 15 | -d \ 16 | -md sha1 \ 17 | -in ./.circleci/gpg.private.enc \ 18 | -k "${ENCRYPTION_PASSPHRASE}" | gpg --import - 19 | set -e 20 | -------------------------------------------------------------------------------- /scripts/ci/common/install-orb-deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | apt-get update 8 | apt-get install -y --no-install-recommends jq 9 | -------------------------------------------------------------------------------- /scripts/ci/steps/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | PROJECT_DIR="$( cd "$SCRIPT_DIR/../../.." && pwd )" 9 | 10 | cd "$PROJECT_DIR" 11 | 12 | ./go test:code:check 13 | -------------------------------------------------------------------------------- /scripts/ci/steps/merge-pull-request.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | PROJECT_DIR="$( cd "$SCRIPT_DIR/../../.." && pwd )" 9 | 10 | cd "$PROJECT_DIR" 11 | 12 | git-crypt unlock 13 | 14 | CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) 15 | 16 | ./go github:pull_requests:merge["$CURRENT_BRANCH","%s [skip ci]"] 17 | -------------------------------------------------------------------------------- /scripts/ci/steps/prerelease.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | PROJECT_DIR="$( cd "$SCRIPT_DIR/../../.." && pwd )" 9 | 10 | cd "$PROJECT_DIR" 11 | 12 | set +e 13 | openssl version 14 | openssl aes-256-cbc \ 15 | -d \ 16 | -md sha1 \ 17 | -in ./.circleci/gpg.private.enc \ 18 | -k "${ENCRYPTION_PASSPHRASE}" | gpg --import - 19 | set -e 20 | 21 | git crypt unlock 22 | 23 | ./go version:bump[rc] 24 | -------------------------------------------------------------------------------- /scripts/ci/steps/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | PROJECT_DIR="$( cd "$SCRIPT_DIR/../../.." && pwd )" 9 | 10 | cd "$PROJECT_DIR" 11 | 12 | set +e 13 | openssl version 14 | openssl aes-256-cbc \ 15 | -d \ 16 | -md sha1 \ 17 | -in ./.circleci/gpg.private.enc \ 18 | -k "${ENCRYPTION_PASSPHRASE}" | gpg --import - 19 | set -e 20 | 21 | git crypt unlock 22 | 23 | ./go version:release 24 | -------------------------------------------------------------------------------- /scripts/ci/steps/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ -n "$DEBUG" ] && set -x 4 | set -e 5 | set -o pipefail 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | PROJECT_DIR="$( cd "$SCRIPT_DIR/../../.." && pwd )" 9 | 10 | cd "$PROJECT_DIR" 11 | 12 | set +e 13 | openssl version 14 | openssl aes-256-cbc \ 15 | -d \ 16 | -md sha1 \ 17 | -in ./.circleci/gpg.private.enc \ 18 | -k "${ENCRYPTION_PASSPHRASE}" | gpg --import - 19 | set -e 20 | 21 | git crypt unlock 22 | 23 | source config/secrets/ci/aws-credentials.sh 24 | 25 | ./go test:unit 26 | -------------------------------------------------------------------------------- /spec/unit/accounts_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'accounts' do 6 | describe 'by default' do 7 | before(:context) do 8 | @plan = plan(role: :root) 9 | end 10 | 11 | it 'outputs an empty map of accounts' do 12 | expect(@plan) 13 | .to(include_output_creation(name: 'accounts') 14 | .with_value({})) 15 | end 16 | 17 | it 'does not create any accounts' do 18 | expect(@plan) 19 | .not_to(include_resource_creation( 20 | type: 'aws_organizations_account' 21 | )) 22 | end 23 | end 24 | 25 | context 'when no accounts specified' do 26 | before(:context) do 27 | @plan = plan(role: :root) do |vars| 28 | vars.organization = {} 29 | end 30 | end 31 | 32 | it 'outputs an empty map of accounts' do 33 | expect(@plan) 34 | .to(include_output_creation(name: 'accounts') 35 | .with_value({})) 36 | end 37 | 38 | it 'does not create any accounts' do 39 | expect(@plan) 40 | .not_to(include_resource_creation( 41 | type: 'aws_organizations_account' 42 | )) 43 | end 44 | end 45 | 46 | context 'when one account specified within root organizational unit' do 47 | before(:context) do 48 | @account_name = 'Finance' 49 | @account_email = 'finance@example.com' 50 | 51 | @plan = plan(role: :root) do |vars| 52 | vars.organization = { 53 | accounts: [ 54 | account(name: @account_name, 55 | email: @account_email, 56 | key: 'finance_key') 57 | ] 58 | } 59 | end 60 | end 61 | 62 | it 'outputs details of the account' do 63 | expect(@plan) 64 | .to(include_output_creation(name: 'accounts') 65 | .with_value( 66 | a_hash_including( 67 | finance_key: a_hash_including( 68 | name: @account_name, 69 | email: @account_email 70 | ) 71 | ) 72 | )) 73 | end 74 | 75 | it 'creates the account' do 76 | expect(@plan) 77 | .to(include_resource_creation( 78 | type: 'aws_organizations_account' 79 | ) 80 | .with_attribute_value(:name, @account_name)) 81 | end 82 | 83 | it 'uses the supplied email address' do 84 | expect(@plan) 85 | .to(include_resource_creation( 86 | type: 'aws_organizations_account' 87 | ) 88 | .with_attribute_value(:name, @account_name) 89 | .with_attribute_value(:email, @account_email)) 90 | end 91 | end 92 | 93 | context 'when one account specified within layered organizational unit' do 94 | describe 'by default' do 95 | before(:context) do 96 | @account_name = 'Fulfillment' 97 | @account_email = 'fulfillment@example.com' 98 | @account_organizational_unit = 'Fulfillment' 99 | 100 | @plan = plan(role: :root) do |vars| 101 | vars.organization = { 102 | units: [{ 103 | name: @account_organizational_unit, 104 | key: @account_organizational_unit, 105 | units: [], 106 | accounts: [ 107 | account(name: @account_name, 108 | email: @account_email, 109 | key: 'fulfillment_key') 110 | ] 111 | }] 112 | } 113 | end 114 | end 115 | 116 | it 'outputs details of the account' do 117 | expect(@plan) 118 | .to(include_output_creation(name: 'accounts') 119 | .with_value( 120 | a_hash_including( 121 | fulfillment_key: a_hash_including( 122 | name: @account_name, 123 | email: @account_email 124 | ) 125 | ) 126 | )) 127 | end 128 | 129 | it 'creates the account' do 130 | expect(@plan) 131 | .to(include_resource_creation( 132 | type: 'aws_organizations_account' 133 | ) 134 | .with_attribute_value(:name, @account_name)) 135 | end 136 | 137 | it 'uses the supplied email address' do 138 | expect(@plan) 139 | .to(include_resource_creation( 140 | type: 'aws_organizations_account' 141 | ) 142 | .with_attribute_value(:name, @account_name) 143 | .with_attribute_value(:email, @account_email)) 144 | end 145 | end 146 | 147 | context 'when allow_iam_users_access_to_billing is true' do 148 | before(:context) do 149 | @account_name = 'Fulfillment' 150 | @account_organizational_unit = 'Fulfillment' 151 | 152 | @plan = plan(role: :root) do |vars| 153 | vars.organization = { 154 | units: [ 155 | { 156 | name: @account_organizational_unit, 157 | key: @account_organizational_unit, 158 | units: [], 159 | accounts: [ 160 | account(name: @account_name, 161 | allow_iam_users_access_to_billing: true) 162 | ] 163 | } 164 | ] 165 | } 166 | end 167 | end 168 | 169 | it 'allows IAM user access to billing' do 170 | expect(@plan) 171 | .to(include_resource_creation( 172 | type: 'aws_organizations_account' 173 | ) 174 | .with_attribute_value(:name, @account_name) 175 | .with_attribute_value(:iam_user_access_to_billing, 'ALLOW')) 176 | end 177 | end 178 | 179 | context 'when allow_iam_users_access_to_billing is false' do 180 | before(:context) do 181 | @account_name = 'Fulfillment' 182 | @account_organizational_unit = 'Fulfillment' 183 | 184 | @plan = plan(role: :root) do |vars| 185 | vars.organization = { 186 | units: [ 187 | { 188 | name: @account_organizational_unit, 189 | key: @account_organizational_unit, 190 | units: [], 191 | accounts: [ 192 | account(name: @account_name, 193 | allow_iam_users_access_to_billing: false) 194 | ] 195 | } 196 | ] 197 | } 198 | end 199 | end 200 | 201 | it 'does not allow IAM user access to billing' do 202 | expect(@plan) 203 | .to(include_resource_creation( 204 | type: 'aws_organizations_account' 205 | ) 206 | .with_attribute_value(:name, @account_name) 207 | .with_attribute_value(:iam_user_access_to_billing, 'DENY')) 208 | end 209 | end 210 | end 211 | 212 | context 'when many accounts specified' do 213 | before(:context) do 214 | @account1_name = 'Fulfillment' 215 | @account1_email = 'fulfillment@example.com' 216 | @account1_organizational_unit = 'Fulfillment' 217 | 218 | @account2_name = 'Billing' 219 | @account2_email = 'billing@example.com' 220 | @account2_organizational_unit = 'Billing' 221 | 222 | @account3_name = 'Online' 223 | @account3_email = 'online@example.com' 224 | @account3_organizational_unit = 'Online' 225 | 226 | @account1 = account(name: @account1_name, 227 | email: @account1_email, 228 | allow_iam_users_access_to_billing: true, 229 | key: 'fulfillment_key') 230 | @account2 = account(name: @account2_name, 231 | email: @account2_email, 232 | allow_iam_users_access_to_billing: false, 233 | key: 'billing_key') 234 | @account3 = account(name: @account3_name, 235 | email: @account3_email, 236 | allow_iam_users_access_to_billing: true, 237 | key: 'online_key') 238 | 239 | @accounts = [@account1, @account2, @account3] 240 | 241 | @accounts_with_billing_access = [@account1, @account3] 242 | @accounts_without_billing_access = [@account2] 243 | 244 | @plan = plan(role: :root) do |vars| 245 | vars.organization = { 246 | units: [ 247 | { 248 | name: @account1_organizational_unit, 249 | key: @account1_organizational_unit, 250 | units: [], 251 | accounts: [@account1] 252 | }, 253 | { 254 | name: @account2_organizational_unit, 255 | key: @account2_organizational_unit, 256 | units: [], 257 | accounts: [@account2] 258 | }, 259 | { 260 | name: @account3_organizational_unit, 261 | key: @account3_organizational_unit, 262 | units: [], 263 | accounts: [@account3] 264 | } 265 | ] 266 | } 267 | end 268 | end 269 | 270 | it 'outputs details of the accounts' do 271 | expect(@plan) 272 | .to(include_output_creation(name: 'accounts') 273 | .with_value( 274 | a_hash_including( 275 | fulfillment_key: a_hash_including(name: @account1_name), 276 | billing_key: a_hash_including(name: @account2_name), 277 | online_key: a_hash_including(name: @account3_name) 278 | ) 279 | )) 280 | end 281 | 282 | it 'creates the accounts' do 283 | @accounts.each do |account| 284 | expect(@plan) 285 | .to(include_resource_creation( 286 | type: 'aws_organizations_account' 287 | ) 288 | .with_attribute_value(:name, account[:name])) 289 | end 290 | end 291 | 292 | it 'uses the supplied email addresses' do 293 | @accounts.each do |account| 294 | expect(@plan) 295 | .to(include_resource_creation( 296 | type: 'aws_organizations_account' 297 | ) 298 | .with_attribute_value(:name, account[:name]) 299 | .with_attribute_value(:email, account[:email])) 300 | end 301 | end 302 | 303 | it 'allows IAM user billing access when requested' do 304 | @accounts_with_billing_access.each do |account| 305 | expect(@plan) 306 | .to(include_resource_creation( 307 | type: 'aws_organizations_account' 308 | ) 309 | .with_attribute_value(:name, account[:name]) 310 | .with_attribute_value(:iam_user_access_to_billing, 'ALLOW')) 311 | end 312 | end 313 | 314 | it 'denies IAM user billing access when requested' do 315 | @accounts_without_billing_access.each do |account| 316 | expect(@plan) 317 | .to(include_resource_creation( 318 | type: 'aws_organizations_account' 319 | ) 320 | .with_attribute_value(:name, account[:name]) 321 | .with_attribute_value(:iam_user_access_to_billing, 'DENY')) 322 | end 323 | end 324 | end 325 | 326 | context 'when deeply nested account specified' do 327 | before(:context) do 328 | @account_name = 'Fulfillment' 329 | @account = account(name: @account_name, 330 | key: 'fulfillment_key') 331 | 332 | @plan = plan(role: :root) do |vars| 333 | vars.organization = { 334 | units: [{ 335 | name: 'Level 1', 336 | key: 'level-1', 337 | units: [{ 338 | name: 'Level 2', 339 | key: 'level-2', 340 | units: [{ 341 | name: 'Level 3', 342 | key: 'level-3', 343 | units: [{ 344 | name: 'Level 4', 345 | key: 'level-4', 346 | units: [{ 347 | name: 'Level 5', 348 | key: 'level-5', 349 | accounts: [@account] 350 | }] 351 | }] 352 | }] 353 | }] 354 | }] 355 | } 356 | end 357 | end 358 | 359 | it 'outputs details of the accounts' do 360 | expect(@plan) 361 | .to(include_output_creation(name: 'accounts') 362 | .with_value( 363 | a_hash_including( 364 | fulfillment_key: a_hash_including(name: @account_name) 365 | ) 366 | )) 367 | end 368 | 369 | it 'creates the accounts' do 370 | expect(@plan) 371 | .to(include_resource_creation( 372 | type: 'aws_organizations_account' 373 | ).with_attribute_value(:name, @account_name)) 374 | end 375 | end 376 | 377 | context 'when allow_iam_users_access_to_billing not specified on account' do 378 | before(:context) do 379 | @account_name = 'Finance' 380 | @account_email = 'finance@example.com' 381 | 382 | @plan = plan(role: :root) do |vars| 383 | vars.organization = { 384 | accounts: [ 385 | { 386 | name: @account_name, 387 | email: @account_email, 388 | key: 'finance_key' 389 | } 390 | ] 391 | } 392 | end 393 | end 394 | 395 | it 'allows IAM users access to billing' do 396 | expect(@plan) 397 | .to(include_resource_creation( 398 | type: 'aws_organizations_account' 399 | ) 400 | .with_attribute_value(:name, @account_name) 401 | .with_attribute_value(:iam_user_access_to_billing, 'ALLOW')) 402 | end 403 | end 404 | 405 | def account(overrides = {}) 406 | id = SecureRandom.alphanumeric(4) 407 | { 408 | name: "test-#{id}", 409 | key: "test-#{id}", 410 | email: "test-#{id}@example.com", 411 | allow_iam_users_access_to_billing: false 412 | }.merge(overrides) 413 | end 414 | end 415 | -------------------------------------------------------------------------------- /spec/unit/infra/prerequisites/.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/aws" { 5 | version = "4.33.0" 6 | constraints = "4.33.0" 7 | hashes = [ 8 | "h1:0S9ZXYg6K0CTOJUTQnoH94YrKuOYyJYEcc+hN5qGafA=", 9 | "h1:rLRYOeKvU17Tky5dleZwTPRoWtbdFTG/jOF/fTP2otY=", 10 | "zh:421b24e21d7fac4d65d97438d2c0a4effe71d3a1bd15820d6fde2879e49fe817", 11 | "zh:4378a84ca8e2a6990f47abc24367b801e884be928671b37ad7b8e7b656f73e48", 12 | "zh:54e0d7884edf3cefd096715794d32b6532138dca905f0b2fe84fb2117594293c", 13 | "zh:6269a7d0312057db5ded669e9f7f9bd80fb6dcb549b50d8d7f3f3b2a0361b8a5", 14 | "zh:67f57d16aa3db493a3174c3c5f30385c7af9767c4e3cdca14e5a4bf384ff59d9", 15 | "zh:7d4d4a1d963e431ffdc3348e3a578d3ba0fa782b1f4bf55fd5c0e527d24fed81", 16 | "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", 17 | "zh:cd8e3d32485acb49c1b06f63916fec8e73a4caa6cf88ae9c4bf236d6f5d9b914", 18 | "zh:d586fd01195bd3775346495e61806e79b6012e745dc05e31a30b958acf968abe", 19 | "zh:d76122060f25ab87887a743096a42d47ba091c2c019ac13ce6b3973b2babe5a3", 20 | "zh:e917d36fe18eddc42ec743b3152b4dcb4853b75ea7a679abd19bdf271bc48221", 21 | "zh:eb780860d5c04f43a018aef564e76a2d84e9aa68984fa1f968ca8c09d23a611a", 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /spec/unit/infra/prerequisites/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/spec/unit/infra/prerequisites/main.tf -------------------------------------------------------------------------------- /spec/unit/infra/prerequisites/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infrablocks/terraform-aws-organization/a8dc4373f2ab9389c59fbd0c05f5f916a3c1b16c/spec/unit/infra/prerequisites/outputs.tf -------------------------------------------------------------------------------- /spec/unit/infra/prerequisites/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | } 4 | -------------------------------------------------------------------------------- /spec/unit/infra/prerequisites/terraform.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.3" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = "4.33" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/unit/infra/prerequisites/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" {} 2 | -------------------------------------------------------------------------------- /spec/unit/infra/root/.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/aws" { 5 | version = "4.33.0" 6 | constraints = ">= 3.29.0, 4.33.0" 7 | hashes = [ 8 | "h1:0S9ZXYg6K0CTOJUTQnoH94YrKuOYyJYEcc+hN5qGafA=", 9 | "h1:rLRYOeKvU17Tky5dleZwTPRoWtbdFTG/jOF/fTP2otY=", 10 | "zh:421b24e21d7fac4d65d97438d2c0a4effe71d3a1bd15820d6fde2879e49fe817", 11 | "zh:4378a84ca8e2a6990f47abc24367b801e884be928671b37ad7b8e7b656f73e48", 12 | "zh:54e0d7884edf3cefd096715794d32b6532138dca905f0b2fe84fb2117594293c", 13 | "zh:6269a7d0312057db5ded669e9f7f9bd80fb6dcb549b50d8d7f3f3b2a0361b8a5", 14 | "zh:67f57d16aa3db493a3174c3c5f30385c7af9767c4e3cdca14e5a4bf384ff59d9", 15 | "zh:7d4d4a1d963e431ffdc3348e3a578d3ba0fa782b1f4bf55fd5c0e527d24fed81", 16 | "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", 17 | "zh:cd8e3d32485acb49c1b06f63916fec8e73a4caa6cf88ae9c4bf236d6f5d9b914", 18 | "zh:d586fd01195bd3775346495e61806e79b6012e745dc05e31a30b958acf968abe", 19 | "zh:d76122060f25ab87887a743096a42d47ba091c2c019ac13ce6b3973b2babe5a3", 20 | "zh:e917d36fe18eddc42ec743b3152b4dcb4853b75ea7a679abd19bdf271bc48221", 21 | "zh:eb780860d5c04f43a018aef564e76a2d84e9aa68984fa1f968ca8c09d23a611a", 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /spec/unit/infra/root/main.tf: -------------------------------------------------------------------------------- 1 | data "terraform_remote_state" "prerequisites" { 2 | backend = "local" 3 | 4 | config = { 5 | path = "${path.module}/../../../../state/prerequisites.tfstate" 6 | } 7 | } 8 | 9 | module "organization" { 10 | source = "../../../.." 11 | 12 | feature_set = var.feature_set 13 | aws_service_access_principals = var.aws_service_access_principals 14 | enabled_policy_types = var.enabled_policy_types 15 | organization = var.organization 16 | } 17 | -------------------------------------------------------------------------------- /spec/unit/infra/root/outputs.tf: -------------------------------------------------------------------------------- 1 | output "organization_arn" { 2 | value = module.organization.organization_arn 3 | } 4 | 5 | output "organizational_units" { 6 | value = module.organization.organizational_units 7 | } 8 | 9 | output "accounts" { 10 | value = module.organization.accounts 11 | } 12 | -------------------------------------------------------------------------------- /spec/unit/infra/root/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | } 4 | -------------------------------------------------------------------------------- /spec/unit/infra/root/terraform.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.3" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = "4.33" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /spec/unit/infra/root/variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" {} 2 | 3 | variable "feature_set" { 4 | type = string 5 | default = null 6 | } 7 | 8 | variable "aws_service_access_principals" { 9 | type = list(string) 10 | default = null 11 | } 12 | 13 | variable "enabled_policy_types" { 14 | type = list(string) 15 | default = null 16 | } 17 | 18 | variable "organization" { 19 | type = object({ 20 | accounts = optional(list(object({ 21 | name = string, 22 | key = string, 23 | email = string, 24 | allow_iam_users_access_to_billing = optional(bool, null), 25 | })), []) 26 | units = optional(list(object({ 27 | name = string, 28 | key = string, 29 | accounts = optional(list(object({ 30 | name = string, 31 | key = string, 32 | email = string, 33 | allow_iam_users_access_to_billing = optional(bool, null), 34 | })), []) 35 | units = optional(list(object({ 36 | name = string, 37 | key = string, 38 | accounts = optional(list(object({ 39 | name = string, 40 | key = string, 41 | email = string, 42 | allow_iam_users_access_to_billing = optional(bool, null), 43 | })), []) 44 | units = optional(list(object({ 45 | name = string, 46 | key = string, 47 | accounts = optional(list(object({ 48 | name = string, 49 | key = string, 50 | email = string, 51 | allow_iam_users_access_to_billing = optional(bool, null), 52 | })), []) 53 | units = optional(list(object({ 54 | name = string, 55 | key = string, 56 | accounts = optional(list(object({ 57 | name = string, 58 | key = string, 59 | email = string, 60 | allow_iam_users_access_to_billing = optional(bool, null), 61 | })), []) 62 | units = optional(list(object({ 63 | name = string, 64 | key = string, 65 | accounts = optional(list(object({ 66 | name = string, 67 | key = string, 68 | email = string, 69 | allow_iam_users_access_to_billing = optional(bool, null), 70 | })), []) 71 | })), []) 72 | })), []) 73 | })), []) 74 | })), []) 75 | })), []) 76 | }) 77 | default = null 78 | } 79 | -------------------------------------------------------------------------------- /spec/unit/organization_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'organization' do 6 | let(:organization_arn) do 7 | output(role: :root, name: 'organization_arn') 8 | end 9 | 10 | describe 'by default' do 11 | before(:context) do 12 | @plan = plan(role: :root) 13 | end 14 | 15 | it 'has a feature set of "ALL"' do 16 | expect(@plan) 17 | .to(include_resource_creation(type: 'aws_organizations_organization') 18 | .with_attribute_value(:feature_set, 'ALL')) 19 | end 20 | 21 | it 'has no AWS service access principals' do 22 | expect(@plan) 23 | .to(include_resource_creation(type: 'aws_organizations_organization') 24 | .with_attribute_value(:aws_service_access_principals, nil)) 25 | end 26 | 27 | it 'has no enabled policy types' do 28 | expect(@plan) 29 | .to(include_resource_creation(type: 'aws_organizations_organization') 30 | .with_attribute_value(:enabled_policy_types, nil)) 31 | end 32 | 33 | it 'outputs the organization ARN' do 34 | expect(@plan) 35 | .to(include_output_creation(name: 'organization_arn')) 36 | end 37 | end 38 | 39 | context 'when AWS service access principals are provided' do 40 | before(:context) do 41 | @aws_service_access_principals = %w[ 42 | cloudtrail.amazonaws.com 43 | config.amazonaws.com 44 | ] 45 | 46 | @plan = plan(role: :root) do |vars| 47 | vars.aws_service_access_principals = @aws_service_access_principals 48 | end 49 | end 50 | 51 | it 'has the provided AWS service access principals' do 52 | expect(@plan) 53 | .to(include_resource_creation(type: 'aws_organizations_organization') 54 | .with_attribute_value(:aws_service_access_principals, 55 | @aws_service_access_principals)) 56 | end 57 | end 58 | 59 | context 'when AWS service access principals is an empty list' do 60 | before(:context) do 61 | @plan = plan(role: :root) do |vars| 62 | vars.aws_service_access_principals = [] 63 | end 64 | end 65 | 66 | it 'has no AWS service access principals' do 67 | expect(@plan) 68 | .to(include_resource_creation(type: 'aws_organizations_organization') 69 | .with_attribute_value(:aws_service_access_principals, nil)) 70 | end 71 | end 72 | 73 | context 'when enabled policy types are provided' do 74 | before(:context) do 75 | @enabled_policy_types = %w[ 76 | SERVICE_CONTROL_POLICY 77 | TAG_POLICY 78 | ] 79 | 80 | @plan = plan(role: :root) do |vars| 81 | vars.enabled_policy_types = @enabled_policy_types 82 | end 83 | end 84 | 85 | it 'has the provided enabled policy types' do 86 | expect(@plan) 87 | .to(include_resource_creation(type: 'aws_organizations_organization') 88 | .with_attribute_value( 89 | :enabled_policy_types, @enabled_policy_types 90 | )) 91 | end 92 | end 93 | 94 | context 'when enabled policy types is an empty list' do 95 | before(:context) do 96 | @plan = plan(role: :root) do |vars| 97 | vars.enabled_policy_types = [] 98 | end 99 | end 100 | 101 | it 'has no enabled policy types' do 102 | expect(@plan) 103 | .to(include_resource_creation(type: 'aws_organizations_organization') 104 | .with_attribute_value(:enabled_policy_types, nil)) 105 | end 106 | end 107 | 108 | context 'when a feature set of "CONSOLIDATED_BILLING" is specified' do 109 | before(:context) do 110 | @plan = plan(role: :root) do |vars| 111 | vars.feature_set = 'CONSOLIDATED_BILLING' 112 | end 113 | end 114 | 115 | it 'has a feature set of "CONSOLIDATED_BILLING"' do 116 | expect(@plan) 117 | .to(include_resource_creation(type: 'aws_organizations_organization') 118 | .with_attribute_value(:feature_set, 'CONSOLIDATED_BILLING')) 119 | end 120 | end 121 | 122 | context 'when a feature set of ALL is specified' do 123 | before(:context) do 124 | @plan = plan(role: :root) do |vars| 125 | vars.feature_set = 'ALL' 126 | end 127 | end 128 | 129 | it 'has a feature set of "ALL"' do 130 | expect(@plan) 131 | .to(include_resource_creation(type: 'aws_organizations_organization') 132 | .with_attribute_value(:feature_set, 'ALL')) 133 | end 134 | end 135 | end 136 | -------------------------------------------------------------------------------- /spec/unit/organizational_units_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'organizational units' do 6 | describe 'by default' do 7 | before(:context) do 8 | @plan = plan(role: :root) 9 | end 10 | 11 | it 'outputs details of the the organizational units' do 12 | expect(@plan) 13 | .to(include_output_creation(name: 'organizational_units') 14 | .with_value({})) 15 | end 16 | 17 | it 'does not create any organizational units' do 18 | expect(@plan) 19 | .not_to(include_resource_creation( 20 | type: 'aws_organizations_organizational_unit' 21 | )) 22 | end 23 | end 24 | 25 | # TODO: work out how to check that the level one organizational units are 26 | # under the organization root. 27 | describe 'when organizational units is one level deep' do 28 | before(:context) do 29 | @plan = plan(role: :root) do |vars| 30 | vars.organization = { 31 | units: [ 32 | { 33 | name: 'Fulfillment', 34 | key: 'fulfillment', 35 | units: [] 36 | }, 37 | { 38 | name: 'Online', 39 | key: 'online', 40 | units: [] 41 | } 42 | ] 43 | } 44 | end 45 | end 46 | 47 | it 'creates organizational units for the first level' do 48 | %w[Fulfillment Online].each do |unit_name| 49 | expect(@plan) 50 | .to(include_resource_creation( 51 | type: 'aws_organizations_organizational_unit' 52 | ) 53 | .with_attribute_value(:name, unit_name)) 54 | end 55 | end 56 | 57 | it 'outputs details on each organizational unit' do 58 | expect(@plan) 59 | .to(include_output_creation(name: 'organizational_units') 60 | .with_value( 61 | a_hash_including( 62 | fulfillment: a_hash_including(name: 'Fulfillment'), 63 | online: a_hash_including(name: 'Online') 64 | ) 65 | )) 66 | end 67 | end 68 | 69 | # TODO: work out how to check that the level one organizational units are 70 | # under the organization root and level two organizational units are 71 | # under the corresponding level one organizational units. 72 | context 'when organizational units is two levels deep' do 73 | before(:context) do 74 | @plan = plan(role: :root) do |vars| 75 | vars.organization = { 76 | units: [ 77 | { 78 | name: 'Fulfillment', 79 | key: 'fulfillment', 80 | units: [ 81 | { 82 | name: 'Warehouse', 83 | key: 'warehouse', 84 | units: [] 85 | }, 86 | { 87 | name: 'Collections', 88 | key: 'collections', 89 | units: [] 90 | } 91 | ] 92 | } 93 | ] 94 | } 95 | end 96 | end 97 | 98 | it 'creates organizational units for the first level' do 99 | expect(@plan) 100 | .to(include_resource_creation( 101 | type: 'aws_organizations_organizational_unit' 102 | ) 103 | .with_attribute_value(:name, 'Fulfillment')) 104 | end 105 | 106 | it 'creates organizational units for the second level' do 107 | %w[Warehouse Collections].each do |unit_name| 108 | expect(@plan) 109 | .to(include_resource_creation( 110 | type: 'aws_organizations_organizational_unit' 111 | ) 112 | .with_attribute_value(:name, unit_name)) 113 | end 114 | end 115 | 116 | it 'outputs details on each organizational unit' do 117 | expect(@plan) 118 | .to(include_output_creation(name: 'organizational_units') 119 | .with_value( 120 | a_hash_including( 121 | fulfillment: a_hash_including(name: 'Fulfillment'), 122 | warehouse: a_hash_including(name: 'Warehouse'), 123 | collections: a_hash_including(name: 'Collections') 124 | ) 125 | )) 126 | end 127 | end 128 | 129 | # TODO: work out how to check that the level one organizational units are 130 | # under the organization root and level two organizational units are 131 | # under the corresponding level one organizational units and level 132 | # three organizational units are under the corresponding level two 133 | # organizational units. 134 | context 'when organizational units is three levels deep' do 135 | before(:context) do 136 | @plan = plan(role: :root) do |vars| 137 | vars.organization = { 138 | units: [ 139 | { 140 | name: 'Fulfillment', 141 | key: 'fulfillment', 142 | units: [ 143 | { 144 | name: 'Warehouse', 145 | key: 'warehouse', 146 | units: [ 147 | { 148 | name: 'London', 149 | key: 'london', 150 | units: [] 151 | }, 152 | { 153 | name: 'Edinburgh', 154 | key: 'edinburgh', 155 | units: [] 156 | } 157 | ] 158 | } 159 | ] 160 | } 161 | ] 162 | } 163 | end 164 | end 165 | 166 | it 'creates organizational units for the first level' do 167 | expect(@plan) 168 | .to(include_resource_creation( 169 | type: 'aws_organizations_organizational_unit' 170 | ) 171 | .with_attribute_value(:name, 'Fulfillment')) 172 | end 173 | 174 | it 'creates organizational units for the second level' do 175 | expect(@plan) 176 | .to(include_resource_creation( 177 | type: 'aws_organizations_organizational_unit' 178 | ) 179 | .with_attribute_value(:name, 'Warehouse')) 180 | end 181 | 182 | it 'creates organizational units for the third level' do 183 | %w[London Edinburgh].each do |unit_name| 184 | expect(@plan) 185 | .to(include_resource_creation( 186 | type: 'aws_organizations_organizational_unit' 187 | ) 188 | .with_attribute_value(:name, unit_name)) 189 | end 190 | end 191 | 192 | it 'outputs details on each organizational unit' do 193 | expect(@plan) 194 | .to(include_output_creation(name: 'organizational_units') 195 | .with_value( 196 | a_hash_including( 197 | fulfillment: a_hash_including(name: 'Fulfillment'), 198 | warehouse: a_hash_including(name: 'Warehouse'), 199 | london: a_hash_including(name: 'London'), 200 | edinburgh: a_hash_including(name: 'Edinburgh') 201 | ) 202 | )) 203 | end 204 | end 205 | 206 | context 'when organizational units is four levels deep' do 207 | before(:context) do 208 | @plan = plan(role: :root) do |vars| 209 | vars.organization = { 210 | units: [ 211 | { 212 | name: 'Fulfillment', 213 | key: 'fulfillment', 214 | units: [ 215 | { 216 | name: 'Warehouse', 217 | key: 'warehouse', 218 | units: [ 219 | { 220 | name: 'London', 221 | key: 'london', 222 | units: [ 223 | { 224 | name: 'Hackney', 225 | key: 'hackney', 226 | units: [] 227 | } 228 | ] 229 | } 230 | ] 231 | } 232 | ] 233 | } 234 | ] 235 | } 236 | end 237 | end 238 | 239 | it 'creates organizational units for the first level' do 240 | expect(@plan) 241 | .to(include_resource_creation( 242 | type: 'aws_organizations_organizational_unit' 243 | ) 244 | .with_attribute_value(:name, 'Fulfillment')) 245 | end 246 | 247 | it 'creates organizational units for the second level' do 248 | expect(@plan) 249 | .to(include_resource_creation( 250 | type: 'aws_organizations_organizational_unit' 251 | ) 252 | .with_attribute_value(:name, 'Warehouse')) 253 | end 254 | 255 | it 'creates organizational units for the third level' do 256 | expect(@plan) 257 | .to(include_resource_creation( 258 | type: 'aws_organizations_organizational_unit' 259 | ) 260 | .with_attribute_value(:name, 'London')) 261 | end 262 | 263 | it 'creates organizational units for the fourth level' do 264 | expect(@plan) 265 | .to(include_resource_creation( 266 | type: 'aws_organizations_organizational_unit' 267 | ) 268 | .with_attribute_value(:name, 'Hackney')) 269 | end 270 | 271 | it 'outputs details on each organizational unit' do 272 | expect(@plan) 273 | .to(include_output_creation(name: 'organizational_units') 274 | .with_value( 275 | a_hash_including( 276 | fulfillment: a_hash_including(name: 'Fulfillment'), 277 | warehouse: a_hash_including(name: 'Warehouse'), 278 | london: a_hash_including(name: 'London'), 279 | hackney: a_hash_including(name: 'Hackney') 280 | ) 281 | )) 282 | end 283 | end 284 | 285 | context 'when organizational units is five levels deep' do 286 | before(:context) do 287 | @plan = plan(role: :root) do |vars| 288 | vars.organization = { 289 | units: [ 290 | { 291 | name: 'Fulfillment', 292 | key: 'fulfillment', 293 | units: [ 294 | { 295 | name: 'Warehouse', 296 | key: 'warehouse', 297 | units: [ 298 | { 299 | name: 'London', 300 | key: 'london', 301 | units: [ 302 | { 303 | name: 'Hackney', 304 | key: 'hackney', 305 | units: [ 306 | { 307 | name: 'Shoreditch', 308 | key: 'shoreditch' 309 | } 310 | ] 311 | } 312 | ] 313 | } 314 | ] 315 | } 316 | ] 317 | } 318 | ] 319 | } 320 | end 321 | end 322 | 323 | it 'creates organizational units for the first level' do 324 | expect(@plan) 325 | .to(include_resource_creation( 326 | type: 'aws_organizations_organizational_unit' 327 | ) 328 | .with_attribute_value(:name, 'Fulfillment')) 329 | end 330 | 331 | it 'creates organizational units for the second level' do 332 | expect(@plan) 333 | .to(include_resource_creation( 334 | type: 'aws_organizations_organizational_unit' 335 | ) 336 | .with_attribute_value(:name, 'Warehouse')) 337 | end 338 | 339 | it 'creates organizational units for the third level' do 340 | expect(@plan) 341 | .to(include_resource_creation( 342 | type: 'aws_organizations_organizational_unit' 343 | ) 344 | .with_attribute_value(:name, 'London')) 345 | end 346 | 347 | it 'creates organizational units for the fourth level' do 348 | expect(@plan) 349 | .to(include_resource_creation( 350 | type: 'aws_organizations_organizational_unit' 351 | ) 352 | .with_attribute_value(:name, 'Hackney')) 353 | end 354 | 355 | it 'creates organizational units for the fifth level' do 356 | expect(@plan) 357 | .to(include_resource_creation( 358 | type: 'aws_organizations_organizational_unit' 359 | ) 360 | .with_attribute_value(:name, 'Shoreditch')) 361 | end 362 | 363 | it 'outputs details on each organizational unit' do 364 | expect(@plan) 365 | .to(include_output_creation(name: 'organizational_units') 366 | .with_value( 367 | a_hash_including( 368 | fulfillment: a_hash_including(name: 'Fulfillment'), 369 | warehouse: a_hash_including(name: 'Warehouse'), 370 | london: a_hash_including(name: 'London'), 371 | hackney: a_hash_including(name: 'Hackney'), 372 | shoreditch: a_hash_including(name: 'Shoreditch') 373 | ) 374 | )) 375 | end 376 | end 377 | end 378 | -------------------------------------------------------------------------------- /spec/unit/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/setup' 4 | 5 | require 'aws-sdk' 6 | require 'rspec' 7 | require 'ruby_terraform' 8 | require 'rspec/terraform' 9 | 10 | Dir[File.join(__dir__, 'support', '**', '*.rb')] 11 | .each { |f| require f } 12 | 13 | RSpec.configure do |config| 14 | config.filter_run_when_matching :focus 15 | config.example_status_persistence_file_path = '.rspec_status' 16 | config.expect_with(:rspec) { |c| c.syntax = :expect } 17 | 18 | config.terraform_binary = 'vendor/terraform/bin/terraform' 19 | config.terraform_log_file_path = 'build/logs/unit.log' 20 | config.terraform_log_streams = [:file] 21 | config.terraform_configuration_provider = 22 | RSpec::Terraform::Configuration.chain_provider( 23 | providers: [ 24 | RSpec::Terraform::Configuration.seed_provider, 25 | RSpec::Terraform::Configuration.in_memory_provider( 26 | no_color: true 27 | ), 28 | RSpec::Terraform::Configuration.confidante_provider( 29 | parameters: %i[ 30 | configuration_directory 31 | state_file 32 | vars 33 | ], 34 | scope_selector: ->(o) { o.slice(:role) } 35 | ) 36 | ] 37 | ) 38 | 39 | config.before(:suite) do 40 | apply( 41 | role: :prerequisites 42 | ) 43 | end 44 | config.after(:suite) do 45 | destroy( 46 | role: :prerequisites, 47 | only_if: -> { ENV['SEED'].nil? } 48 | ) 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /terraform.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.3" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 3.29" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "feature_set" { 2 | description = "The feature set of the organization. One of 'ALL' or 'CONSOLIDATED_BILLING'." 3 | type = string 4 | default = "ALL" 5 | nullable = false 6 | } 7 | 8 | variable "aws_service_access_principals" { 9 | description = "A list of AWS service principal names for which you want to enable integration with your organization." 10 | type = list(string) 11 | default = [] 12 | nullable = false 13 | } 14 | 15 | variable "enabled_policy_types" { 16 | description = "The list of Organizations policy types to enable in the Organization Root. The organization must have `feature_set` set to `\"ALL\"`." 17 | type = list(string) 18 | default = [] 19 | nullable = false 20 | } 21 | 22 | variable "organization" { 23 | description = "The organization with the tree of organizational units and accounts to construct. Defaults to an object with an empty list of units and accounts" 24 | type = object({ 25 | accounts = optional(list(object({ 26 | name = string, 27 | key = string, 28 | email = string, 29 | allow_iam_users_access_to_billing = optional(bool, true), 30 | })), []) 31 | units = optional(list(object({ 32 | name = string, 33 | key = string, 34 | accounts = optional(list(object({ 35 | name = string, 36 | key = string, 37 | email = string, 38 | allow_iam_users_access_to_billing = optional(bool, true), 39 | })), []) 40 | units = optional(list(object({ 41 | name = string, 42 | key = string, 43 | accounts = optional(list(object({ 44 | name = string, 45 | key = string, 46 | email = string, 47 | allow_iam_users_access_to_billing = optional(bool, true), 48 | })), []) 49 | units = optional(list(object({ 50 | name = string, 51 | key = string, 52 | accounts = optional(list(object({ 53 | name = string, 54 | key = string, 55 | email = string, 56 | allow_iam_users_access_to_billing = optional(bool, true), 57 | })), []) 58 | units = optional(list(object({ 59 | name = string, 60 | key = string, 61 | accounts = optional(list(object({ 62 | name = string, 63 | key = string, 64 | email = string, 65 | allow_iam_users_access_to_billing = optional(bool, true), 66 | })), []) 67 | units = optional(list(object({ 68 | name = string, 69 | key = string, 70 | accounts = optional(list(object({ 71 | name = string, 72 | key = string, 73 | email = string, 74 | allow_iam_users_access_to_billing = optional(bool, true), 75 | })), []) 76 | })), []) 77 | })), []) 78 | })), []) 79 | })), []) 80 | })), []) 81 | }) 82 | default = {} 83 | nullable = false 84 | } 85 | --------------------------------------------------------------------------------