-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
03da8fb
commit f30681d
Showing
21 changed files
with
2,202 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
name: Terragrunt AWS Execute | ||
description: "Authenticates to AWS then invokes terragrunt" | ||
inputs: | ||
PIPELINES_READ_TOKEN: | ||
description: "The PIPELINES_READ_TOKEN secret" | ||
required: true | ||
working_directory: | ||
description: "" | ||
required: true | ||
account_id: | ||
description: "" | ||
required: true | ||
account_role_name: | ||
description: "" | ||
required: true | ||
role_session_name: | ||
description: "" | ||
required: true | ||
gruntwork_context: | ||
description: "" | ||
required: true | ||
|
||
|
||
outputs: | ||
execute_stdout: | ||
description: "The output of the Pipelines Execute command" | ||
value: ${{ steps.execute.outputs.execute_stdout }} | ||
plan_folder: | ||
description: "A folder with plan files (if any)" | ||
value: ${{ steps.execute.outputs.plan_folder }} | ||
formatted_plan_output: | ||
description: "A string, formatted in GitHub Markdown, rendering human readable output of the plan" | ||
value: ${{ steps.execute.outputs.formatted_plan_output }} | ||
|
||
runs: | ||
using: composite | ||
steps: | ||
- name: "Read in Gruntwork context" | ||
id: gruntwork_context | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
cache: ${{ inputs.gruntwork_context }} | ||
|
||
- name: Authenticate to AWS | ||
id: aws_auth | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
# We can authenticate to any valid region, the IaC configured provider determines what region resources are created | ||
# in. As a result we can pass the default aws region. | ||
aws-region: ${{ steps.gruntwork_context.outputs.default_aws_region }} | ||
role-to-assume: "arn:aws:iam::${{ inputs.account_id }}:role/${{ inputs.account_role_name }}" | ||
role-duration-seconds: 3600 | ||
role-session-name: ${{ inputs.role_session_name }} | ||
|
||
- name: "Get Auth Failure Reason" | ||
shell: bash | ||
id: auth_failure_reason | ||
if: ${{ failure() }} | ||
env: | ||
ACCOUNT_ID: ${{ inputs.account_id }} | ||
ACCOUNT_ROLE_NAME: ${{ inputs.account_role_name }} | ||
run: | | ||
# if the role_name begins with 'delegate' the role may not have been created yet | ||
if [[ $ACCOUNT_ROLE_NAME == delegate* ]]; then | ||
reason="Failed to authenticate to AWS. The role($ACCOUNT_ROLE_NAME) may not have been created yet. Contact your account administrator to ensure that access-control Pull Request for this account($ACCOUNT_ID) has been merged." | ||
else | ||
reason="Failed to authenticate to AWS. Verify that the role($ACCOUNT_ROLE_NAME) and account ID($ACCOUNT_ID) are correct." | ||
fi | ||
echo "auth_failure_reason=$reason" >> $GITHUB_OUTPUT | ||
- name: "Add Auth Failure Notice if AWS Auth Fails" | ||
uses: gruntwork-io/[email protected] | ||
if: ${{ failure() }} | ||
with: | ||
step_name: "AWS Authentication" | ||
step_status: "failed" | ||
step_details: ${{ steps.auth_failure_reason.outputs.auth_failure_reason }} | ||
pull_request_number: ${{ steps.gruntwork_context.outputs.pr_number }} | ||
|
||
- name: "[Terragrunt Execute] Confirm Account Access" | ||
if: ${{ steps.aws_auth.outcome == 'success' }} | ||
shell: bash | ||
env: | ||
ACCOUNT: ${{ inputs.account_id }} | ||
WORKING_DIRECTORY: ${{ inputs.working_directory }} | ||
run: echo "::notice ::Running in account $ACCOUNT and planning in $WORKING_DIRECTORY" | ||
|
||
- name: "[Terragrunt Execute] Run terragrunt ${{ inputs.terragrunt_command }} in ${{ inputs.working_directory }}" | ||
if: ${{ steps.aws_auth.outcome == 'success' }} | ||
id: execute | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
token: ${{ inputs.PIPELINES_READ_TOKEN }} | ||
tf_binary: ${{ steps.gruntwork_context.outputs.tf_binary }} | ||
working_directory: ${{ inputs.working_directory }} | ||
pipelines_cli_version: ${{ steps.gruntwork_context.outputs.pipelines_cli_version }} | ||
terragrunt_command: ${{ steps.gruntwork_context.outputs.terragrunt_command }} | ||
infra_live_repo_branch: ${{ steps.gruntwork_context.outputs.branch }} | ||
gruntwork_config_file: ${{ steps.gruntwork_context.outputs.gruntwork_config_file }} | ||
infra_live_repo: "." | ||
infra_live_directory: "." | ||
deploy_branch_name: ${{ steps.gruntwork_context.outputs.deploy_branch_name }} |
60 changes: 60 additions & 0 deletions
60
.github/actions/pipelines-baseline-account-action/action.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
name: Bootstrap a new account in access-control repo | ||
description: "Sets up a new AWS account and basic roles inside the access control repo" | ||
inputs: | ||
PIPELINES_READ_TOKEN: | ||
description: "The PIPELINES_READ_TOKEN secret" | ||
required: true | ||
gruntwork_context: | ||
description: "Gruntwork Context from the Gruntwork Bootstrap step" | ||
required: true | ||
|
||
runs: | ||
using: composite | ||
steps: | ||
- name: "[Baseline]: Read account request" | ||
id: gruntwork_context | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
cache: ${{ inputs.gruntwork_context }} | ||
|
||
- name: "[Baseline]: Run terragrunt ${{ steps.gruntwork_context.outputs.terragrunt_command }} in security account" | ||
id: terragrunt-apply-security | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
PIPELINES_READ_TOKEN: ${{ inputs.PIPELINES_READ_TOKEN }} | ||
account_id: ${{ steps.gruntwork_context.outputs.security_account_id }} | ||
account_role_name: ${{ steps.gruntwork_context.outputs.role_name }} | ||
role_session_name: ${{ steps.gruntwork_context.outputs.role_session_name }} | ||
working_directory: security/_global/account-baseline | ||
gruntwork_context: ${{ inputs.gruntwork_context }} | ||
|
||
- name: "[Baseline]: Run terragrunt ${{ steps.gruntwork_context.outputs.terragrunt_command }} in logs account" | ||
id: terragrunt-apply-logs | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
PIPELINES_READ_TOKEN: ${{ inputs.PIPELINES_READ_TOKEN }} | ||
account_id: ${{ steps.gruntwork_context.outputs.logs_account_id }} | ||
account_role_name: ${{ steps.gruntwork_context.outputs.role_name }} | ||
role_session_name: ${{ steps.gruntwork_context.outputs.role_session_name }} | ||
working_directory: logs/_global/account-baseline | ||
gruntwork_context: ${{ inputs.gruntwork_context }} | ||
|
||
- name: "[Baseline]: Run terragrunt ${{ steps.gruntwork_context.outputs.terragrunt_command }} in shared account" | ||
id: terragrunt-apply-shared | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
PIPELINES_READ_TOKEN: ${{ inputs.PIPELINES_READ_TOKEN }} | ||
account_id: ${{ steps.gruntwork_context.outputs.shared_account_id }} | ||
account_role_name: ${{ steps.gruntwork_context.outputs.role_name }} | ||
role_session_name: ${{ steps.gruntwork_context.outputs.role_session_name }} | ||
working_directory: shared/_global/account-baseline | ||
gruntwork_context: ${{ inputs.gruntwork_context }} | ||
|
||
# Finally, auth to the mgmt account so we can assume a role in the child account | ||
- name: "[Baseline]: Authenticate to AWS" | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
aws-region: ${{ steps.gruntwork_context.outputs.default_aws_region }} | ||
role-to-assume: "arn:aws:iam::${{ steps.gruntwork_context.outputs.account_id }}:role/${{ steps.gruntwork_context.outputs.role_name }}" | ||
role-duration-seconds: 3600 | ||
role-session-name: ${{ steps.gruntwork_context.outputs.role_session_name }} |
115 changes: 115 additions & 0 deletions
115
.github/actions/pipelines-baseline-child-account-action/action.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
name: Bootstrap Workflow | ||
description: "Bootstrap workflows with common requirements" | ||
inputs: | ||
PIPELINES_READ_TOKEN: | ||
description: "The GitHub token to use for checking out the infrastructure-live repo" | ||
required: true | ||
account_id: | ||
description: "Child Account ID to operate on" | ||
required: true | ||
account_name: | ||
description: "Child Account Name to operate on" | ||
required: true | ||
job: | ||
description: "JSON of pipelines orchestrate job" | ||
required: true | ||
|
||
runs: | ||
using: composite | ||
steps: | ||
- name: Check out repo code | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: Bootstrap Workflow | ||
id: gruntwork_context | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
token: ${{ inputs.PIPELINES_READ_TOKEN }} | ||
change_type: ${{ fromJson(inputs.job).ChangeType }} | ||
branch: ${{ fromJson(inputs.job).Ref }} | ||
working_directory: ${{ fromJson(inputs.job).WorkingDirectory }} | ||
account_id: ${{ fromJson(inputs.job).AccountId }} | ||
terragrunt_command: ${{ fromJson(inputs.job).Action.Command }} ${{ fromJson(inputs.job).Action.Args }} | ||
additional_data: ${{ toJson(fromJson(inputs.job).AdditionalData) }} | ||
account_names: ${{ fromJson(inputs.job).AdditionalData.AccountNames }} | ||
child_account_id: ${{ inputs.account_id }} | ||
new_account_name: ${{ inputs.account_name }} | ||
|
||
# Finally, auth to the mgmt account so we can assume a role in the child account | ||
- name: "[Baseline]: Authenticate to AWS" | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
aws-region: ${{ steps.gruntwork_context.outputs.default_aws_region }} | ||
role-to-assume: "arn:aws:iam::${{ steps.gruntwork_context.outputs.account_id }}:role/${{ steps.gruntwork_context.outputs.role_name }}" | ||
role-duration-seconds: 3600 | ||
role-session-name: ${{ steps.gruntwork_context.outputs.role_session_name }} | ||
|
||
# Auth to child account | ||
# THIS RETRIEVES PERMISSIONS TO BE ABLE TO RUN A PLAN/APPLY IN THE NEWLY CREATED CHILD ACCOUNT | ||
# The "AWSControlTowerExecution" role being assumed here is created by Control Tower in each account it provisions | ||
# and it can be assumed by a role in the management account. | ||
- name: "[Baseline]: Assume role new child account" | ||
shell: bash | ||
env: | ||
SESSION_NAME: ${{ steps.gruntwork_context.outputs.role_session_name }} | ||
CHILD_ACCOUNT_ID: ${{ inputs.account_id }} | ||
run: | | ||
echo "Assuming AWSControlTowerExecution Role -- arn:aws:iam::$CHILD_ACCOUNT_ID:role/AWSControlTowerExecution" | ||
RESPONSE="$(aws sts assume-role --role-arn "arn:aws:iam::$CHILD_ACCOUNT_ID:role/AWSControlTowerExecution" --role-session-name "$SESSION_NAME")" | ||
ASSUMED_ROLE_CREDS="$(echo "$RESPONSE" | jq -r '.Credentials')" | ||
AWS_ACCESS_KEY_ID="$(echo "$ASSUMED_ROLE_CREDS" | jq -r '.AccessKeyId')" | ||
echo "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" >> "$GITHUB_ENV" | ||
echo "::add-mask::$AWS_ACCESS_KEY_ID" | ||
AWS_SECRET_ACCESS_KEY="$(echo "$ASSUMED_ROLE_CREDS" | jq -r '.SecretAccessKey')" | ||
echo AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY" >> "$GITHUB_ENV" | ||
echo "::add-mask::$AWS_SECRET_ACCESS_KEY" | ||
AWS_SESSION_TOKEN="$(echo "$ASSUMED_ROLE_CREDS" | jq -r '.SessionToken')" | ||
echo AWS_SESSION_TOKEN="$AWS_SESSION_TOKEN" >> "$GITHUB_ENV" | ||
echo "::add-mask::$AWS_SESSION_TOKEN" | ||
- name: "[Baseline]: Confirm Account Access" | ||
shell: bash | ||
run: aws sts get-caller-identity | ||
|
||
# This Bootstrap step is a workaround for the error that happens when running plan-all for the first time in a | ||
# new account with multiple modules. The error is: | ||
# | ||
# OperationAborted: A conflicting conditional operation is currently in progress against this resource. Please try again. | ||
# BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it. | ||
# | ||
# This happens because each module is trying to create buckets for state and logs when they do not exist. | ||
# Setting Terragrunt Parallelism to 1 does NOT prevent this error from happening. So we'll instead run an init in | ||
# a single module first to create the buckets so that subsequent run-all commands do not fail. | ||
- name: "[Baseline]: Bootstrap child account with state & logs S3 buckets" | ||
if: ${{ contains(steps.gruntwork_context.outputs.terragrunt_command, 'plan') }} | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
token: ${{ inputs.PIPELINES_READ_TOKEN }} | ||
pipelines_cli_version: ${{ steps.gruntwork_context.outputs.pipelines_cli_version }} | ||
working_directory: "${{ inputs.account_name }}/_global/account-baseline" | ||
terragrunt_command: "init" | ||
infra_live_repo: '.' | ||
infra_live_directory: '.' | ||
infra_live_repo_branch: ${{ steps.gruntwork_context.outputs.branch }} | ||
gruntwork_config: "${{ steps.gruntwork_context.outputs.gruntwork_config }}" | ||
gruntwork_config_file: "${{ steps.gruntwork_context.outputs.gruntwork_config_file }}" | ||
deploy_branch_name: ${{ steps.gruntwork_context.outputs.deploy_branch_name }} | ||
tf_binary: ${{ steps.gruntwork_context.outputs.tf_binary }} | ||
|
||
# Apply Access Control Roles and Baseline in Delegated Account | ||
- name: "[Baseline]: Bootstrap child account with access control roles, state & logs S3 buckets" | ||
uses: gruntwork-io/[email protected] | ||
with: | ||
token: ${{ inputs.PIPELINES_READ_TOKEN }} | ||
pipelines_cli_version: ${{ steps.gruntwork_context.outputs.pipelines_cli_version }} | ||
working_directory: "${{ inputs.account_name }}" | ||
terragrunt_command: ${{ steps.gruntwork_context.outputs.terragrunt_command }} | ||
infra_live_repo: '.' | ||
infra_live_directory: '.' | ||
infra_live_repo_branch: ${{ steps.gruntwork_context.outputs.branch }} | ||
gruntwork_config: "${{ steps.gruntwork_context.outputs.gruntwork_config }}" | ||
gruntwork_config_file: "${{ steps.gruntwork_context.outputs.gruntwork_config_file }}" | ||
deploy_branch_name: ${{ steps.gruntwork_context.outputs.deploy_branch_name }} | ||
tf_binary: ${{ steps.gruntwork_context.outputs.tf_binary }} |
Empty file.
Oops, something went wrong.