Orchestrating AWS Deployments via GitHub Actions and OpenID Connect

The integration of GitHub Actions with Amazon Web Services (AWS) represents a shift toward modern DevSecOps practices, moving away from the precarious reliance on long-lived access keys toward a dynamic, identity-based trust model. By leveraging GitHub Actions as the orchestration engine and AWS as the infrastructure provider, developers can establish a robust Continuous Integration and Continuous Deployment (CI/CD) pipeline that automates the lifecycle of an application from the initial commit to the final deployment on Amazon EC2 or AWS Lambda. The core of this synergy is the transition to OpenID Connect (OIDC), which allows GitHub to communicate directly with AWS Identity and Access Management (IAM) to assume short-lived roles, thereby eliminating the security risks associated with storing static AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY within GitHub repository secrets.

The Architecture of OIDC Authentication

OpenID Connect (OIDC) serves as the critical authentication bridge between the GitHub Actions runner and the AWS environment. Traditionally, CI/CD pipelines required the manual creation of IAM users with permanent credentials. In the OIDC model, GitHub acts as the Identity Provider (IdP), and AWS acts as the Relying Party. When a workflow is triggered, GitHub issues a temporary OIDC token. AWS validates this token against the configured OIDC provider and, if the trust policy is satisfied, issues short-lived credentials via the Security Token Service (STS).

The real-world impact of this architecture is a drastic reduction in the attack surface. If a repository is compromised, there are no long-lived secrets to steal that would grant permanent access to the AWS account. Instead, the access is scoped to a specific role and a specific GitHub repository, ensuring that only the intended workflow can modify infrastructure.

To implement this, an IAM Identity Provider must be created in the AWS account for token.actions.githubusercontent.com. This provider establishes the trust relationship. Following the creation of the provider, an IAM Role must be defined with a specific trust policy.

The following JSON represents the mandatory Trust Policy for the IAM Role:

json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", "token.actions.githubusercontent.com:sub": "repo:<GITHUB_ORG>/<GITHUB_REPOSITORY>:ref:refs/heads/<GITHUB_BRANCH>" } } } ] }

This policy ensures that only a specific branch of a specific repository within a specific organization can assume the role, providing granular control over who can trigger deployments.

Deploying Web Applications to Amazon EC2

Deploying a complex web application to Amazon EC2 instances within an Auto Scaling Group (ASG) requires a coordinated effort between GitHub Actions, Amazon S3, and AWS CodeDeploy. This pipeline is designed to handle the build, packaging, and deployment phases systematically.

The workflow begins when a GitHub Action is triggered, either manually or automatically via a push event. The initial stage is the Build and Package phase. In this stage, the GitHub runner builds the application—for example, a SpringBoot application—and generates a deployable artifact, such as a .war file.

Once the artifact is generated, the GitHub Action uploads it to an Amazon S3 bucket. S3 acts as the intermediary storage, ensuring that the deployment artifact is centrally available and versioned before being distributed to the target instances.

After the artifact is safely stored in S3, the GitHub Action invokes AWS CodeDeploy. CodeDeploy then takes over the orchestration, targeting the Amazon EC2 instances residing in the predefined Auto Scaling group. CodeDeploy downloads the artifact from S3 and executes the deployment scripts to install and start the application on the EC2 instances.

To facilitate this, the following prerequisites must be met:

  • An AWS account with administrative permissions to create IAM roles, S3 buckets, and EC2 instances.
  • A GitHub account with permissions to manage repositories, configure secrets, and write YAML workflow files.
  • A local Git client to clone the necessary source code.

The implementation sequence for an EC2 deployment is as follows:

  • Clone the project from the AWS samples repository: git clone https://github.com/aws-samples/aws-codedeploy-github-actions-deployment.git.
  • Deploy the AWS CloudFormation template to provision the required infrastructure.
  • Update the application source code.
  • Configure GitHub Secrets for the IAM Role ARN.
  • Integrate the CodeDeploy application with GitHub to allow the execution of scripts stored in the repository.
  • Trigger the GitHub Action workflow located in .github/workflows/deploy.yml.
  • Verify the deployment through the AWS CodeDeploy console by selecting the application name and deployment group.

Configuration of GitHub Secrets for IAM Roles

While OIDC removes the need for long-lived access keys, the GitHub workflow still needs to know which IAM Role to assume. This Role ARN is stored as a GitHub Secret to keep the account ID and role name hidden from the public repository.

To configure these secrets:

  • Navigate to the GitHub repository and select the Settings tab.
  • Select Secrets from the left-hand menu.
  • Choose New repository secret.
  • Under the Secrets category, select Actions.
  • Name the secret IAMROLE_GITHUB.
  • Paste the ARN of the GitHubIAMRole obtained from the CloudFormation output section.

This mechanism allows the workflow to dynamically reference the role using ${{ secrets.IAMROLE_GITHUB }}, maintaining a secure separation between the workflow logic and the identity configuration.

Serverless Deployments with AWS Lambda

GitHub Actions can also be utilized for serverless architectures, specifically for deploying AWS Lambda functions. This process is more streamlined than EC2 deployments as it does not require the overhead of Auto Scaling groups or CodeDeploy orchestration.

To automate Lambda deployments, a workflow file must be created in the .github/workflows/ directory. The workflow is typically triggered by a push to the main branch.

The critical components of a Lambda deployment workflow include the id-token: write permission, which is mandatory for the OIDC handshake, and the contents: read permission to allow the runner to check out the repository code.

An example deployment workflow for Lambda is structured as follows:

yaml name: Deploy AWS Lambda on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write # Required for OIDC authentication contents: read # Required to check out the repository steps: - uses: actions/checkout@v4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubActionRole aws-region: us-east-1 - name: Deploy Lambda Function uses: aws-actions/aws-lambda-deploy@v1 with: function-name: my-lambda-function code-artifacts-dir: ./dist

In this scenario, the workflow checks out the code, authenticates via OIDC, and uses the aws-actions/aws-lambda-deploy action to push the compiled code located in the ./dist directory to the specified Lambda function.

Deep Dive into the configure-aws-credentials Action

The aws-actions/configure-aws-credentials action is the primary tool for establishing the session between GitHub and AWS. It handles the complex process of exchanging the GitHub OIDC token for AWS temporary credentials.

One advanced feature of this action is the role-session-name. By default, the session is named "GitHubActions". However, for audit and logging purposes, it is highly recommended to set this to ${{ github.run_id }}. This ensures that every action performed in AWS can be traced back to a specific workflow run in GitHub, providing a clear audit trail for security compliance.

The action also applies a set of tags to the session to provide deeper context within the AWS environment. These tags include:

Key Value
GitHub "Actions"
Repository GITHUB_REPOSITORY
Workflow GITHUB_WORKFLOW
Action GITHUB_ACTION
Actor GITHUB_ACTOR
Branch GITHUB_REF
Commit GITHUB_SHA

Users should be aware that the GITHUB_WORKFLOW tag may be truncated if the name is excessively long, as it must conform to AWS tag requirements.

Furthermore, the action provides a special-characters-workaround option. When enabled, the action will continually retry fetching credentials until a set is received that does not contain special characters. While this is available, it is generally discouraged unless specifically required, as infinite retries are not considered a best practice in robust system design.

Security Scanning and Vulnerability Management

Beyond deployment, GitHub Actions can be used to ensure the security of the artifacts being deployed. AWS provides specialized actions to integrate security scanning directly into the pipeline.

A prominent example is the aws-actions/vulnerability-scan-github-action-for-amazon-inspector. This action allows developers to scan artifacts with Amazon Inspector before they are promoted to a production environment. By integrating this into the GitHub workflow, teams can implement a "security gate" where the deployment is automatically halted if the Inspector scan detects critical vulnerabilities in the application dependencies or container images.

Comparison of EC2 and Lambda Deployment Paths

The choice between deploying to EC2 via CodeDeploy versus deploying to Lambda depends on the architectural requirements of the application.

Feature EC2 Deployment Path Lambda Deployment Path
Orchestration Uses AWS CodeDeploy Direct deployment via Action
Artifact Storage Requires Amazon S3 Direct upload or S3
Scaling Managed via Auto Scaling Groups Native AWS Lambda scaling
Authentication OIDC via IAM Role OIDC via IAM Role
Complexity High (Build -> S3 -> CodeDeploy -> EC2) Low (Build -> Lambda)
State State-full/Long running Stateless/Event-driven

Comprehensive Troubleshooting and Verification

Verification of a successful deployment is a critical final step. For EC2 deployments, the verification process involves navigating to the AWS Management Console and accessing the CodeDeploy service. Users must select the specific Application name (e.g., CodeDeployAppNameWithASG) and the Deployment group (CodeDeployGroupName) to view the status of the rollout.

Common failure points in these pipelines include:

  • Missing id-token: write permissions in the YAML file, which leads to OIDC authentication failure.
  • Incorrectly configured Trust Policies in the IAM Role, specifically mismatched sub claims (e.g., wrong branch or repository name).
  • Failure to integrate CodeDeploy with GitHub, which prevents the service from accessing the deployment scripts stored in the repository.
  • Lack of proper S3 permissions for the IAM Role, preventing the upload or download of the .war or .zip artifacts.

Final Analysis of the AWS-GitHub Integration

The integration of GitHub Actions with AWS through OIDC represents a significant evolution in cloud native deployment strategies. By moving the trust anchor from static secrets to identity-based federation, organizations achieve a higher security posture and a more maintainable pipeline. The use of a multi-stage process—encompassing build, artifact storage in S3, and orchestrated deployment via CodeDeploy—ensures that large-scale EC2 deployments are handled with minimal downtime. Conversely, the streamlined approach to Lambda deployments demonstrates the flexibility of GitHub Actions in supporting both traditional and serverless paradigms. The ability to tag sessions with metadata like GITHUB_SHA and GITHUB_ACTOR further bridges the gap between the version control system and the infrastructure, enabling a transparent and accountable deployment lifecycle.

Sources

  1. Integrating with GitHub Actions CI/CD Pipeline to Deploy a Web App to Amazon EC2
  2. Configure AWS Credentials Action for GitHub Actions
  3. AWS Actions GitHub Organization
  4. Deploying Lambda functions using GitHub Actions

Related Posts