This tutorial shows how to set up OpenID Connect (OIDC) authentication between GitHub Actions and AWS, enabling secure, passwordless deployments to multiple AWS environments.
- How to set up OIDC authentication between GitHub Actions and AWS
- How to manage multiple environments (dev/prod) securely
- How to handle Terraform state management across environments
- Best practices for secure CI/CD with AWS
- AWS CLI installed locally
- AWS accounts for dev and prod environments
- AWS SSO access configured
- Terraform installed locally (v1.7.0 or later)
- A GitHub repository where you'll deploy infrastructure
- Configure AWS SSO Profiles
# Configure AWS SSO for development account
aws configure sso
# Enter:
# - SSO start URL: your-sso-url
# - SSO Region: your-region
# - Profile name: dev-myproject
# Choose the development account and appropriate role
# Repeat for production account
aws configure sso
# Use profile name: prod-myproject
- Clone and Configure Repository
git clone git@github.com:your-username/github-oidc-setup.git
cd github-oidc-setup
- Update Configuration
In projects/myproject.tfvars
, update:
projects = {
myproject = {
github_repo = "YourGitHubUsername/your-project-name" # Update this
additional_tags = {
Project = "MyProject"
}
# Rest of the configuration remains the same
}
}
# Login to AWS SSO
aws sso login --profile dev-myproject
# Verify correct account
aws sts get-caller-identity --profile dev-myproject
# Set profile
export AWS_PROFILE=dev-myproject
# Initialize and apply
terraform init
terraform apply -var-file=environments/dev.tfvars -var-file=projects/myproject.tfvars
# Remove state files to avoid conflicts
rm -rf .terraform* terraform.tfstate*
# Login to AWS SSO for prod
aws sso login --profile prod-myproject
# Verify correct account
aws sts get-caller-identity --profile prod-myproject
# Set profile
export AWS_PROFILE=prod-myproject
# Initialize and apply
terraform init
terraform apply -var-file=environments/prod.tfvars -var-file=projects/myproject.tfvars
After completing the OIDC setup, you'll need to create GitHub Actions workflows in your main project repository where you'll be deploying infrastructure.
Check the example-workflow-files
directory in this repository for complete examples of:
terraform-plan.yml
- Runs Terraform plan on pull requeststerraform-apply.yml
- Applies Terraform changes on merge
- Create Workflow Directory in Your Project
mkdir -p .github/workflows
- Copy and Configure Workflows
# Copy example workflow files
cp example-workflow-files/*.yml .github/workflows/
# Update the following in both files:
- YOUR_DEV_ACCOUNT_ID with your dev AWS account ID
- YOUR_PROD_ACCOUNT_ID with your prod AWS account ID
- myproject with your actual project name
- Directory Structure Your project repository should look like this:
your-project/
├── .github/
│ └── workflows/
│ ├── terraform-plan.yml
│ └── terraform-apply.yml
└── terraform/
├── environments/
│ ├── dev.tfvars
│ └── prod.tfvars
├── main.tf
└── [other terraform files]
- Workflow Behavior
- Pull requests to
develop
→ Terraform plan for dev environment - Pull requests to
main
→ Terraform plan for prod environment - Merge to
develop
→ Terraform apply to dev environment - Merge to
main
→ Terraform apply to prod environment
- Required GitHub Setup
- Create environments:
dev
andprod
- Set up branch protection rules
- Configure environment protection rules
- Add required reviewers for production
- Test Development Workflow
# Create feature branch
git checkout -b feature/test-infrastructure
# Make changes to terraform files
git add .
git commit -m "test: add test infrastructure"
git push origin feature/test-infrastructure
# Create PR to develop branch
- Test Production Workflow
# Create release branch from develop
git checkout develop
git pull
git checkout -b release/test-infrastructure
# Create PR to main branch
- Ensure role trust relationships are correct
- OIDC Provider Already Exists
# List providers
aws iam list-open-id-connect-providers
# Delete if needed
aws iam delete-open-id-connect-provider --open-id-connect-provider-arn PROVIDER_ARN
- State File Conflicts
# Always clean state when switching accounts
rm -rf .terraform* terraform.tfstate*
- Access Denied Errors
- Verify correct AWS profile
- Check SSO session validity
- Confirm admin permissions
- Verify OIDC Provider
aws iam list-open-id-connect-providers
- Check IAM Roles
aws iam get-role --role-name github-actions-myproject-dev
aws iam get-role --role-name github-actions-myproject-prod
- Check S3 Buckets
aws s3 ls | grep myproject-terraform-state
This setup creates in each account:
- OIDC Provider for GitHub Actions
- IAM Role for GitHub Actions
- S3 Bucket for Terraform state
- DynamoDB Table for state locking
After deployment:
- Get the Role ARNs:
# Development Role ARN
aws iam get-role --role-name github-actions-myproject-dev --query 'Role.Arn' --output text
# Production Role ARN
aws iam get-role --role-name github-actions-myproject-prod --query 'Role.Arn' --output text
- Use these ARNs in your GitHub Actions workflows
- Always remove state files when switching accounts
- Verify AWS SSO session before running Terraform
- Double-check AWS profile before applying
- OIDC provider is unique per AWS account
- S3 bucket names must be globally unique
- OIDC is more secure than storing AWS credentials in GitHub
- IAM roles are restricted to specific repositories
- State files are stored in environment-specific S3 buckets
- DynamoDB provides state locking
When using this tutorial, update these files with your project name:
projects/myproject.tfvars
- Update GitHub repository name.github/workflows/*.yml
- Update role names and bucket namesenvironments/*.tfvars
- Update environment-specific variables
If you encounter issues:
- Check the Troubleshooting Guide above
- Verify AWS credentials and permissions
- Check GitHub Actions logs
- Ensure all placeholders are replaced with your actual values
Would you like me to also provide the updated versions of all the other files in the repository?