🔑 Key points
- You must authorize GitHub to have access to your AWS account.
- You can use a GitHub Action workflow to execute AWS CLI commands.
- You will create a workflow that uploads a file to your S3 bucket.
In order to use CI to deploy our static frontend content to S3 you need to create a trust relationship between GitHub and AWS. This is done by using the Open ID Connection (OIDC) protocol to dynamically obtain an authentication token whenever you want to call the S3 endpoints for copying files. Using OIDC to authenticate with AWS makes it so that you don't ever have to store credentials in your CI pipeline.
Important
Make sure you are using the us-east-1 AWS region for all your work in this course.
You establish a trust relationship between GitHub and AWS by configuring AWS to use GitHub as an OIDC identity provider, associating a OIDC identity with an AWS IAM role that allows access to S3, and configuring a GitHub Actions workflow to use the identity.
First you need to set up AWS to use GitHub as an OIDC provider.
-
Open the AWS IAM service console
-
Choose
Identity providers -
Press
Add provider -
Choose the provider type of
OpenID Connect -
Give the GitHub URL for the provider URL, and allow AWS Security Token Service as the audience.
- provider URL:
https://token.actions.githubusercontent.com - Audience:
sts.amazonaws.com
- provider URL:
-
Press
Add provider -
Click on the newly created identity provider to display its properties.
-
You will reference the identity provider ARN when you create the IAM role.
We want to be careful which AWS services and resources we expose through the credentials we are creating, so we need to create an AWS IAM policy that only provides what is necessary to update your S3 deployment bucket and invalidate the files that the CloudFront distribution is hosting.
- Open the AWS IAM service console.
- Choose
Policies. - Press
Create policy. - Press
JSONin order to define the policy with JSON. - Paste the following policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListObjectsInBucket",
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::BUCKET_NAME_HERE"]
},
{
"Sid": "UpdateS3Bucket",
"Effect": "Allow",
"Action": ["s3:*Object"],
"Resource": ["arn:aws:s3:::BUCKET_NAME_HERE/*"]
},
{
"Sid": "InvalidateCloudFront",
"Effect": "Allow",
"Action": ["cloudfront:CreateInvalidation"],
"Resource": ["arn:aws:cloudfront::AWS_ACCOUNT_HERE:distribution/DISTRIBUTION_HERE"]
}
]
}- Replace
BUCKET_NAME_HEREwith the name of the S3 bucket you created (e.g. pizza.yourhostname). - Replace
AWS_ACCOUNT_HEREwith your AWS account ID number (e.g. 882352824274). - Replace
DISTRIBUTION_HEREwith the CloudFront distribution ID (e.g. F3A3ZL6IF7XCE1). - Press
Next. - Name the policy
jwt-pizza-ci-deployment. - Press
Create policy.
Now we can create the AWS IAM role that allows access to S3.
-
Open the AWS IAM service console.
-
Choose
Roles. -
Press
Create role. -
Choose
Web identity. -
Select the identity provider that you just created for GitHub.
-
Add the
Audienceto be sts.amazonaws.com from the dropdown. -
Add the
GitHub organizationto be your GitHub account name. -
Add the
GitHub repositoryfor your fork of thejwt-pizzarepository. -
Add the
GitHub branchto be main. -
Press
Next. -
Add permissions by entering the name of the policy you created (e.g.
jwt-pizza-ci-deployment). -
Press
Next. -
Name the role
github-ci. -
Press
Create role.
The final step is to create a GitHub Actions workflow that deploys to the S3 bucket using the OIDC credentials that you just created.
Your repository is public and so you want to make sure that you keep secret anything that would give an advantage to a nefarious party. This includes your AWS Account ID, IAM role, S3 Bucket name, and the CloudFront distribution ID.
You can hide these secrets by creating repository secrets and then referencing the secrets in your workflow.
Go ahead and create the following secrets.
| Secret | Description | Example |
|---|---|---|
| AWS_ACCOUNT | Your AWS account ID number | 343243424 |
| CI_IAM_ROLE | The IAM user with rights to deploy your application | github-ci |
| APP_BUCKET | The S3 bucket hosting your static deployment files | pizza.ilovebyu.click |
| DISTRIBUTION_ID | The CloudFront Distribution ID for your frontend deployment | F3GRFXFEBQ8EEU |
-
In the repository that you specified when you created your identity provider, create a GitHub Actions workflow file named
testS3Deploy.ymlin your project's.github/workflowsdirectory. This will contain the workflow to copy files to your S3 bucket. -
Paste the following template into the
testS3Deploy.ymlfile.name: Test S3 Deploy on: push: branches: - main workflow_dispatch: permissions: id-token: write jobs: deploy-s3: runs-on: ubuntu-latest steps: - name: Create OIDC token to AWS uses: aws-actions/configure-aws-credentials@v4 with: audience: sts.amazonaws.com aws-region: us-east-1 role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT }}:role/${{ secrets.CI_IAM_ROLE }} - name: Push to AWS S3 run: | mkdir dist printf "<h1>CloudFront deployment with GitHub Actions</h1>" > dist/index.html aws s3 cp dist s3://${{ secrets.APP_BUCKET }} --recursive aws cloudfront create-invalidation --distribution-id ${{ secrets.DISTRIBUTION_ID }} --paths "/*"
-
Save the file, commit, and push.
The interesting pieces of the workflow include the request for OIDC authorization using the supplied role.
- name: Create OIDC token to AWS
uses: aws-actions/configure-aws-credentials@v4
with:
audience: sts.amazonaws.com
aws-region: us-east-1
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT }}:role/${{ secrets.CI_IAM_ROLE }}If this is successful then you can execute any AWS CLI commands that the role allows. In our case it allows the commands to copy the dist directory to our S3 bucket and invalidate the CloudFront distribution cache. If we didn't invalidate the cache then your new files would not show up until the cache expired 24 hours later.
aws s3 cp dist s3://${{ secrets.APP_BUCKET }} --recursive
aws cloudfront create-invalidation --distribution-id ${{ secrets.DISTRIBUTION_ID }} --paths "/*"After following the above steps you should see the resulting index.html page when you view your website.
Once you are done, you can disable this workflow on the GitHub Actions page, or simply delete it since you repeat what you have done here with the JWT Pizza frontend code in a future assignment, and you don't want this to run every time you commit your code.







