Configuring Workload Identity Federation for GitHub Actions
This guide explains how to configure workload identity federation for GitHub Actions, allowing your GitHub workflows to authenticate with Thalassa Cloud without storing long-lived credentials.
Prerequisites
Before configuring workload identity federation for GitHub Actions, ensure you have:
- A GitHub repository with Actions enabled
- Access to your Thalassa Cloud organisation
- A service account created in Thalassa Cloud with appropriate IAM roles
- Permissions to create identity providers and federated identities
Step 1: Create Identity Provider for GitHub Actions
Step 1: Navigate to Identity Providers
Navigate to IAM → Identity Providers in your Thalassa Cloud Console.
Step 2: Create GitHub Actions Identity Provider
Click “Create Identity Provider” and configure:
Basic Information:
- Name:
github-actions(or a descriptive name) - Description: Optional description, e.g., “GitHub Actions OIDC provider”
OIDC Configuration:
- OIDC Issuer URL:
https://token.actions.githubusercontent.com- This is GitHub’s OIDC issuer endpoint
JWKS Configuration:
- Use Automatic Discovery (recommended)
- Leave the JWKS endpoint blank
- Thalassa Cloud will automatically discover the JWKS endpoint from GitHub’s well-known configuration at
https://token.actions.githubusercontent.com/.well-known/openid-configuration
Step 3: Save Identity Provider
Click “Create Identity Provider” to save the configuration.
Step 2: Create Federated Identity
Step 1: Navigate to Service Accounts
Navigate to IAM → Service Accounts in your Thalassa Cloud Console.
Step 2: Select Service Account
Select the service account you want to configure for GitHub Actions federation.
Step 3: Create Federated Identity
Click “Add Federated Identity” or “Workload Identity Federation”.
Step 4: Configure Token Matching
Configure how tokens from GitHub Actions are matched:
Identity Provider:
- Select the GitHub Actions identity provider you created in Step 1
Token Matching:
GitHub Actions OIDC tokens include several claims that you can use for matching:
Subject Claim (
sub): The most important claim for matching. Format:repo:OWNER/REPO:ref:refs/heads/BRANCHorrepo:OWNER/REPO:environment:ENVIRONMENT_NAME- Example for main branch:
repo:myorg/myrepo:ref:refs/heads/main - Example for environment:
repo:myorg/myrepo:environment:production - Example for pull requests:
repo:myorg/myrepo:pull_request
- Example for main branch:
Additional Claims (optional):
repository: The repository name (e.g.,myorg/myrepo)repository_owner: The repository owner (e.g.,myorg)ref: The git reference (e.g.,refs/heads/main)environment: The environment name if using GitHub Environments
Recommended Matching Patterns:
For maximum security, use specific subject claims:
- Match specific repository and branch:
repo:myorg/myrepo:ref:refs/heads/main - Match production environment:
repo:myorg/myrepo:environment:production - Match pull requests:
repo:myorg/myrepo:pull_request
You can use wildcards for more flexibility:
- Match all branches in a repository:
repo:myorg/myrepo:ref:refs/heads/* - Match all repositories in an organisation:
repo:myorg/*:ref:refs/heads/main
API Scopes:
- Select the API scopes your workflow needs (e.g.,
read,write) - Follow the principle of least privilege—only grant necessary scopes
Expiry (Optional):
- Set an expiry date if this is a temporary federation
Step 5: Save Federated Identity
Click “Create Federated Identity” to complete the setup.
Step 3: Configure GitHub Actions Workflow
Now configure your GitHub Actions workflow to use workload identity federation.
Basic Workflow Example
name: Deploy to Thalassa Cloud
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC token
contents: read # Required for repository access
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get OIDC Token
id: oidc
uses: actions/github-script@v7
with:
script: |
const token = await core.getIDToken();
core.setOutput('token', token);
- name: Exchange OIDC Token
id: auth
run: |
# Exchange GitHub OIDC token for Thalassa Cloud bearer token
RESPONSE=$(curl -X POST https://api.thalassa.cloud/oidc/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=${{ steps.oidc.outputs.token }}" \
-d "subject_token_type=urn:ietf:params:oauth:token-type:id_token" \
-d "organisation_id=${{ vars.THALASSA_ORGANISATION_ID }}" \
-d "service_account_id=${{ vars.THALASSA_SERVICE_ACCOUNT_ID }}")
BEARER_TOKEN=$(echo "$RESPONSE" | jq -r '.access_token')
echo "token=$BEARER_TOKEN" >> $GITHUB_OUTPUT
- name: Deploy with Terraform
env:
THALASSA_TOKEN: ${{ steps.auth.outputs.token }}
run: |
terraform init
terraform plan
terraform apply -auto-approveUsing GitHub Variables
Store your organisation ID and service account ID as GitHub repository or organisation variables:
- Navigate to your repository settings
- Go to Secrets and variables → Actions
- Add repository variables:
THALASSA_ORGANISATION_ID: Your Thalassa Cloud organisation IDTHALASSA_SERVICE_ACCOUNT_ID: Your service account ID
Using GitHub Environments
For better security and control, you can use GitHub Environments to restrict which workflows can use your federated identity:
name: Deploy to Production
on:
workflow_dispatch:
inputs:
environment:
type: choice
options:
- production
- staging
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment }}
permissions:
id-token: write
contents: read
steps:
# ... same steps as aboveWhen using environments, your subject claim should match the environment pattern: repo:OWNER/REPO:environment:ENVIRONMENT_NAME
Testing the Configuration
- Push to your repository to trigger the workflow
- Monitor the workflow to verify the OIDC token exchange succeeds
- Check logs to ensure the bearer token is being used correctly
- Verify permissions by testing API calls or Terraform operations
Troubleshooting
OIDC Token Exchange Fails
- Verify the subject claim in your federated identity matches the actual token claims
- Check that the identity provider issuer URL is correct
- Ensure the service account ID and organisation ID are correct
Token Matching Fails
- Decode your OIDC token to inspect the actual claims:
# In GitHub Actions, add a debug step - name: Debug Token Claims run: | echo "${{ steps.oidc.outputs.token }}" | cut -d. -f2 | base64 -d | jq - Compare the actual claims with your federated identity matching rules
- Adjust your subject claim or additional claims to match the token
Permission Denied
- Verify the service account has the required IAM roles
- Check that the API scopes configured in the federated identity match your needs
- Review the service account’s role bindings
Best Practices
- Use Specific Subject Claims: Match specific repositories and branches rather than using broad wildcards
- Use GitHub Environments: Leverage GitHub Environments for better security and workflow control
- Least Privilege: Grant only the minimum required API scopes
- Monitor Usage: Regularly review federated identity usage through audit logs
- Rotate Regularly: Set expiry dates and rotate federated identities periodically
Related Documentation
- Workload Identity Federation Overview: General overview of workload identity federation
- GitLab Configuration: Configure federation for GitLab CI
- Generic OIDC Configuration: Configure federation for generic OIDC providers
- Service Accounts: Learn about service accounts