From a1014f9419e5e30f3d1b35b095ea998349926a18 Mon Sep 17 00:00:00 2001 From: Krzysztof Banasiak Date: Wed, 27 Dec 2023 16:59:17 +0100 Subject: [PATCH] feat: GitHub OIDC provider feat: GitHub Action --- .github/workflows/cdk-deploy.yaml | 28 ++++++++++++ Makefile | 9 +++- app.py | 7 +-- base/github_trust_stack.py | 74 +++++++++++++++++++++++++++++++ base/vpc_stack.py | 15 +++---- 5 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/cdk-deploy.yaml create mode 100644 base/github_trust_stack.py diff --git a/.github/workflows/cdk-deploy.yaml b/.github/workflows/cdk-deploy.yaml new file mode 100644 index 0000000..b9ac49e --- /dev/null +++ b/.github/workflows/cdk-deploy.yaml @@ -0,0 +1,28 @@ +name: Deploy Chatbot AWS Infra + +on: + push: + branches: + - main + +jobs: + cdk-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ vars.AWS_GITHUB_ACTIONS_ROLE }} + aws-region: ${{ vars.AWS_REGION }} + role-session-name: "github-actions-cdk-deploy-chatbot" + + - name: Deploy Chatbot Vpc + uses: youyo/aws-cdk-github-actions@v2 + with: + cdk_subcommand: deploy + cdk_stack: ChatbotVpcStack + cdk_args: "--require-approval never" + actions_comment: false diff --git a/Makefile b/Makefile index e6a37b8..2bf41c6 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,9 @@ cdk-bootstrap: - cdk bootstrap \ No newline at end of file + cdk bootstrap + +github-trust-stack: + cdk deploy ChatbotGithubTrustStack \ + --parameters GitHubOrg=krzysiekb \ + --parameters GitHubRepo=aws-chatbot-infra + +.PHONY: cdk-bootstrap github-trust-stack \ No newline at end of file diff --git a/app.py b/app.py index db9b1bc..e2421a1 100644 --- a/app.py +++ b/app.py @@ -1,13 +1,14 @@ #!/usr/bin/env python3 -import os import aws_cdk as cdk +from base.github_trust_stack import GitHubTrustStack from base.vpc_stack import VpcStack - app = cdk.App() -VpcStack(scope=app, id="ChatbotVpcStack") +# Create the GitHub trust stack in AWS account. +GitHubTrustStack(app, "ChatbotGithubTrustStack") +VpcStack(app, "ChatbotVpcStack") app.synth() diff --git a/base/github_trust_stack.py b/base/github_trust_stack.py new file mode 100644 index 0000000..76b4e2d --- /dev/null +++ b/base/github_trust_stack.py @@ -0,0 +1,74 @@ +from aws_cdk import Stack, CfnParameter, CfnOutput +from aws_cdk.aws_iam import CfnOIDCProvider, Role, FederatedPrincipal, PolicyStatement, Effect +from constructs import Construct + + +class GitHubTrustStack(Stack): + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # parameters + github_org = CfnParameter(scope=self, id="GitHubOrg", type="String") + github_repo = CfnParameter(scope=self, id="GitHubRepo", type="String") + + # GitHub OIDC provider + # https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#creating-an-oidc-provider + # + # Thumbprints are from: + # https://github.blog/changelog/2022-01-13-github-actions-update-on-oidc-based-deployments-to-aws/ + + github_provider = CfnOIDCProvider( + scope=self, + id="GitHubOIDCProvider", + thumbprint_list=["6938fd4d98bab03faadb97b34396831e3780aea1"], + url="https://token.actions.githubusercontent.com", + client_id_list=["sts.amazonaws.com"], + ) + + github_actions_role = Role( + scope=self, + id="GitHubActionsRole", + assumed_by=FederatedPrincipal( + federated=github_provider.attr_arn, + conditions={ + "StringEquals": { + # audience is sts.amazonaws.com (must be set to sts.amazonaws.com) + "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" + }, + "StringLike": { + # subscriber is main branch of the defined repository + "token.actions.githubusercontent.com:sub": + f"repo:{github_org.value_as_string}/{github_repo.value_as_string}:ref:refs/heads/main" + } + }, + assume_role_action="sts:AssumeRoleWithWebIdentity" + ) + ) + + # this policy allows GitHub Actions to assume the roles for: + # file publishing, lookup and deploy created by CDK bootstrap + # https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html + accume_cdk_deployments_role_policy = PolicyStatement( + effect=Effect.ALLOW, + actions=["sts:AssumeRole"], + resources=["arn:aws:iam::*:role/cdk-*"], + conditions={ + "StringEquals": { + "aws:ResourceTag/aws-cdk:bootstrap-role": [ + "file-publishing", + "lookup", + "deploy", + ] + } + }, + ) + + github_actions_role.add_to_policy(accume_cdk_deployments_role_policy) + + # outputs + CfnOutput( + scope=self, + id="GitHubActionsRoleArn", + value=github_actions_role.role_arn, + description="GitHub Actions role ARN", + ) diff --git a/base/vpc_stack.py b/base/vpc_stack.py index 2c7dec7..1631c70 100644 --- a/base/vpc_stack.py +++ b/base/vpc_stack.py @@ -1,24 +1,23 @@ -import aws_cdk as cdk +from aws_cdk import aws_ec2, Stack +from constructs import Construct -from aws_cdk import aws_ec2 - -class VpcStack(cdk.Stack): - def __init__(self, scope, id, **kwargs): +class VpcStack(Stack): + def __init__(self, scope: Construct, id: str, **kwargs): super().__init__(scope, id, **kwargs) - vpc = cdk.aws_ec2.Vpc( + vpc = aws_ec2.Vpc( self, "ChatbotVpc", cidr="10.0.0.0/16", max_azs=3, subnet_configuration=[ - cdk.aws_ec2.SubnetConfiguration( + aws_ec2.SubnetConfiguration( name="ChatbotPublicSubnet", subnet_type=aws_ec2.SubnetType.PUBLIC, cidr_mask=24 ), - cdk.aws_ec2.SubnetConfiguration( + aws_ec2.SubnetConfiguration( name="ChatbotPrivateSubnet", subnet_type=aws_ec2.SubnetType.PRIVATE_WITH_EGRESS, cidr_mask=24