Skip to content

Commit

Permalink
feat: 🚀 Created cloudformation-stackset workflow and readme (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tanveer143s authored Oct 30, 2023
1 parent ba5eb58 commit 9e9106e
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 3 deletions.
188 changes: 188 additions & 0 deletions .github/workflows/deploy-cloudformation-stackset.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
name: Cloudformation stack-set & stack-set-instances
on:
workflow_call:
inputs:
aws-region:
description: 'Aws region (in this region stackset enabled)'
required: false
default: 'us-east-2'
type: string
stackset-instance-region:
description: 'Stackset-instance regions where you need cloudformation stacks'
required: false
default: 'us-east-2'
type: string
stack-set-name:
description: 'Stack-set name defined here'
required: true
type: string
template-url:
description: 'Cloudformation template path add here (S3 Object URL)'
required: true
type: string
OrganizationalUnitIds:
description: 'Organization unit ID for deployment in target accounts when service_managed permission added'
required: false
type: string
account-ids:
description: 'account ids for self_managed permission added'
required: false
type: string
parameter-overrides:
description: 'The parameters to override in the stack inputs. You can pass a comma-delimited list or a file URL. The comma-delimited list has each entry formatted as <ParameterName>=<ParameterValue> or <ParameterName>="<ParameterValue>,<ParameterValue>".'
required: false
type: string
permission-model:
description: 'IAM role permission SERVICE_MANAGED/SELF_MANAGED choose one'
required: false
type: string
auto-deployment-enabled:
description: 'true or false (true when Service_managed policy enable else false for Self_managed)'
required: true
type: string
RetainStacksOnAccountRemoval:
description: 'true or false (true when Service_managed policy enable else false for Self_managed)'
required: true
type: string
administration-role-arn:
description: 'Administrator role arn add here for trust relation on admin and child account'
required: false
type: string
execution-role-name:
description: 'execution-role-name add here for trust relation in child account'
required: false
type: string
secrets:
AWS_ACCESS_KEY_ID:
required: false
description: 'AWS Access Key ID to install AWS CLI.'
AWS_SECRET_ACCESS_KEY:
required: false
description: 'AWS Secret access key to install AWS CLI'
AWS_SESSION_TOKEN:
required: false
description: 'AWS Session Token to install AWS CLI'
AWS_ROLE_TO_ASSUME:
required: false
description: 'AWS Role ARN defined'
GITHUB:
required: false
description: 'GitHub token'

jobs:
deploy-cf-stackset:
runs-on: ubuntu-latest
steps:
- name: Checkout code from master branch
uses: actions/checkout@v4

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID}}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }}
aws-region: ${{ inputs.aws-region }}
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}

- name: Check if StackSet exists or not-exist then create/update stack-set
id: check-stackset
run: |
set +e
result=$(aws cloudformation describe-stack-set --stack-set-name "${{ inputs.stack-set-name }}" 2>&1)
RC=$?
set -e
if [ "${{ inputs.permission-model }}" = "SERVICE_MANAGED" ]; then
if [ $RC -eq 0 ]; then
echo "StackSet exists, updating..."
aws cloudformation update-stack-set \
--stack-set-name ${{ inputs.stack-set-name }} \
--template-url ${{ inputs.template-url }} \
--parameters ${{ inputs.parameter-overrides }} \
--capabilities CAPABILITY_NAMED_IAM \
--permission-model ${{ inputs.permission-model }} \
--auto-deployment Enabled=${{ inputs.auto-deployment-enabled }},RetainStacksOnAccountRemoval=${{ inputs.RetainStacksOnAccountRemoval }}
elif [ $RC -eq 254 ]; then
if echo "$result" | grep -q "StackSetNotFoundException"; then
echo "StackSet does not exist, creating..."
aws cloudformation create-stack-set \
--stack-set-name ${{ inputs.stack-set-name }} \
--template-url ${{ inputs.template-url }} \
--parameters ${{ inputs.parameter-overrides }} \
--capabilities CAPABILITY_NAMED_IAM \
--permission-model ${{ inputs.permission-model }} \
--auto-deployment Enabled=${{ inputs.auto-deployment-enabled }},RetainStacksOnAccountRemoval=${{ inputs.RetainStacksOnAccountRemoval }}
else
exit $RC
fi
else
exit $RC
fi
else
if [ $RC -eq 0 ]; then
echo "StackSet exists, updating..."
aws cloudformation update-stack-set \
--stack-set-name ${{ inputs.stack-set-name }} \
--template-url ${{ inputs.template-url }} \
--capabilities CAPABILITY_NAMED_IAM \
--parameters ${{ inputs.parameter-overrides }} \
--administration-role-arn ${{ inputs.administration-role-arn }}
elif [ $RC -eq 254 ]; then
if echo "$result" | grep -q "StackSetNotFoundException"; then
echo "StackSet does not exist, creating..."
aws cloudformation create-stack-set \
--stack-set-name ${{ inputs.stack-set-name }} \
--template-url ${{ inputs.template-url }} \
--capabilities CAPABILITY_NAMED_IAM \
--parameters ${{ inputs.parameter-overrides }} \
--administration-role-arn ${{ inputs.administration-role-arn }} \
--execution-role-name AWSControlTowerExecution
else
exit $RC
fi
else
exit $RC
fi
sleep 50s
fi
- name: Create or Update StackSet-instance
run: |
stack_instance_list=$(aws cloudformation list-stack-instances --region ${{ inputs.stackset-instance-region }} --stack-set-name ${{ inputs.stack-set-name }})
if [ "${{ inputs.permission-model }}" == "SERVICE_MANAGED" ]; then
if [[ "$stack_instance_list" == *'"Summaries": []'* ]]; then
echo "StackSet-instance, creating..."
aws cloudformation create-stack-instances \
--stack-set-name ${{ inputs.stack-set-name }} \
--deployment-targets OrganizationalUnitIds='["${{ inputs.OrganizationalUnitIds }}"]' \
--parameter-overrides ${{ inputs.parameter-overrides }} \
--regions ${{ inputs.stackset-instance-region }}
else
echo "StackSet-instance, updating..."
aws cloudformation update-stack-instances \
--stack-set-name ${{ inputs.stack-set-name }} \
--deployment-targets OrganizationalUnitIds='["${{ inputs.OrganizationalUnitIds }}"]' \
--parameter-overrides ${{ inputs.parameter-overrides }} \
--regions ${{ inputs.stackset-instance-region }}
fi
else
if [[ "$stack_instance_list" == *'"Summaries": []'* ]]; then
echo "StackSet-instance, creating..."
aws cloudformation create-stack-instances \
--stack-set-name ${{ inputs.stack-set-name }} \
--parameter-overrides ${{ inputs.parameter-overrides }} \
--accounts ${{ inputs.account-ids }} \
--regions ${{ inputs.stackset-instance-region }} \
--operation-preferences FailureToleranceCount=1,MaxConcurrentCount=2
else
echo "StackSet-instance, updating..."
aws cloudformation update-stack-instances \
--stack-set-name ${{ inputs.stack-set-name }} \
--parameter-overrides ${{ inputs.parameter-overrides }} \
--accounts ${{ inputs.account-ids }} \
--regions ${{ inputs.stackset-instance-region }} \
--operation-preferences MaxConcurrentPercentage=1
fi
fi
...
9 changes: 8 additions & 1 deletion .github/workflows/deploy-cloudformation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ on:
description: 'The parameters to override in the stack inputs. You can pass a comma-delimited list or a file URL. The comma-delimited list has each entry formatted as <ParameterName>=<ParameterValue> or <ParameterName>="<ParameterValue>,<ParameterValue>".'
required: false
type: string
capabilities:
description: "The comma-delimited list of stack template capabilities to acknowledge. Defaults to 'CAPABILITY_IAM'"
required: false
default: "CAPABILITY_IAM"
type: string

secrets:
AWS_ACCESS_KEY_ID:
required: false
Expand Down Expand Up @@ -107,5 +113,6 @@ jobs:
name: ${{ inputs.stack-name }}
template: ${{ inputs.template-path }}
no-fail-on-empty-changeset: "1"
parameter-overrides: ${{ inputs.parameter-overrides}}
parameter-overrides: ${{ inputs.parameter-overrides }}
capabilities: ${{ inputs.capabilities }}
...
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ Above example is just a simple example to call workflow from github shared workf
7. [Checkov Workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/checkov.md)
8. [Terraform Workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/terraform_workflow.md)
9. [Infracost workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/infracost.md)
10. [ Deploy Cloudformation workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/deploy-cloudformation.md)
10. [ Deploy Cloudformation Stack workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/deploy-cloudformation.md)
11. [ Deploy Cloudformation Stackset workflow](https://github.com/clouddrove/github-shared-workflows/blob/master/docs/deploy-cloudformation-stackset.md)
## Feedback
If you come accross a bug or have any feedback, please log it in our [issue tracker](https://github.com/clouddrove/github-shared-workflows/issues), or feel free to drop us an email at [[email protected]](mailto:[email protected]).
Expand Down
53 changes: 53 additions & 0 deletions docs/deploy-cloudformation-stackset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
## [Deploy Cloudformation Stacket & Stackset-instances](https://github.com/clouddrove/github-shared-workflows/blob/master/.github/workflows/deploy-cloudformation-stackset.yml)
The process starts with the creation of a shared workflow template. This template contains CloudFormation resource definitions, parameter declarations, and other configuration settings that are commonly used across multiple projects or environments. It serves as a blueprint for the infrastructure you want to create. `.github/workflows/deploy-cloudformation-stackset.yml`

#### Usage

- In this workflow we added multiple parameters like S3 bucket for source code, stack-parameters, account-ids, stackset-name using parameters we overrides from called.yml as we defined below.
- In this workflow we provide S3 Object URL where your code & template file located and deploy stackset and stackset-instances
- Most important thing is we centrally manage stacks of every account's using stackset

#### Key Points:
In this workflow we added steps like for the below conditions:

- If stackset are not-Exists then Create a new **stackset**
- If stackset are Exist then Updating a **stackset**
- If stackset-instance is not-Exist then Create a new **stackset-instance**
- If stackset-instance is Exist then Updating a **stackset-instance**

#### Example

```yaml
name: Cloudformation stack-set
on:
push:
branches: main
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
deploy-cf-stackset:
uses: clouddrove/github-shared-workflows/.github/workflows/deploy-cloudformation-stackset.yml@master
with:
aws-region: # aws-configure region add, where you need stackset
stackset-instance-region: # region add where you need stacks
stack-set-name: # name of stack-set ( same name apply for stackset & instances )
template-url: # S3 bucket Object URL add where template file is located
OrganizationalUnitIds: "" # deployment targets OrganizationalUnitIds
account-ids: # deployment targets add master account ids where you deploying stacksets
parameter-overrides: # use this format (ParameterKey=ABC,ParameterValue=XXX ParameterKey=XYZ,ParameterValue=XXX)
permission-model: # SELF_MANAGED & SERVICE_MANAGED add here
auto-deployment-enabled: false # for SELF_MANAGED-false & SERVICE_MANAGED-true
RetainStacksOnAccountRemoval: false # for SELF_MANAGED-false & SERVICE_MANAGED-true
administration-role-arn: # administration AWSControlTowerStackSetRole ARN add here
execution-role-name: # child account AWSControlTowerExecution role name add here

secrets:
AWS_ROLE_TO_ASSUME: # Add AWS OIDC role ARN
AWS_ACCESS_KEY_ID: # Add AWS credentials
AWS_SECRET_ACCESS_KEY:
AWS_SESSION_TOKEN:
```
2 changes: 1 addition & 1 deletion docs/deploy-cloudformation.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## [Deploy Cloudformation Stack](https://github.com/clouddrove/github-shared-workflows/blob/master/.github/workflows/infracost.yml)
## [Deploy Cloudformation Stack](https://github.com/clouddrove/github-shared-workflows/blob/master/.github/workflows/deploy-cloudformation.yml)
The process starts with the creation of a shared workflow template. This template contains CloudFormation resource definitions, parameter declarations, and other configuration settings that are commonly used across multiple projects or environments. It serves as a blueprint for the infrastructure you want to create. `.github/workflows/deploy-cloudformation.yml`

#### Usage
Expand Down

0 comments on commit 9e9106e

Please sign in to comment.