Workflow Security

Manage access and security in GitHub workflows

Workflow Security

12 December 2024

sha

In CI/CD cycles, GitHub actions and workflows may need access to resources and services on GitHub or outside GitHub. Also, the outside services may need access to our resources on GitHub. It is very important to understand how to securely stitch together services and resources (public or private) in the CI/CD workflows.

!IMPORTANT Even if not passed explicitly, GITHUB_TOKEN is available, through github context, to all the actions called in a workflow. Always set restrictive default permissions for the token (in the organization or repository settings) and elevate them using permissions key at specific locations in the workflow.

!TIP When calling actions created by other people or organizations, use full length commit SHA of the called action. Use actions from trusted sources (GitHub, or GitHub verified). visit GitHub docs for information about script injection and cross repo access.

1. GitHub Token

Visit GitHub docs for further reading, main points:

1.1 Examples:

This needs more work, the following examples are copy-paste from GitHub docs.

Provide access to github CLI in workflow (example picked from GitHub docs):

name: Open new issue
on: workflow_dispatch

jobs:
  open-issue:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
    steps:
      - run: |
          gh issue --repo ${{ github.repository }} \
            create --title "Issue title" --body "Issue body"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  1. Use the api:
name: Create issue on commit

on: [ push ]

jobs:
  create_issue:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Create issue using REST API
        run: |
          curl --request POST \
          --url https://api.github.com/repos/${{ github.repository }}/issues \
          --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
          --header 'content-type: application/json' \
          --data '{
            "title": "Automated issue for commit: ${{ github.sha }}",
            "body": "This issue was automatically created by the GitHub Action workflow **${{ github.workflow }}**. \n\n The commit hash was: _${{ github.sha }}_."
            }' \
          --fail

2. Personal Access Token (PAT)

4. Deploy keys

3. GitHub OpenID Connect for AWS

This is one of the methods to define access interface between AWS and GitHub. This is needed to provision resources on AWS.

The aws official action aws-actions/configure-aws-credentials supports five methods for fetching credentials from AWS, OpenID Connect is the recommended one as it gets short-lived credentials, good enough for actions and workflows. Visit configure-aws-credentials action docs and GitHub docs for further reading. The AWS provided action also allows to limit access using inline policies as inputs.

To configure GitHub as OPENID Connect identity provider, visit IAM console on aws:

Here is an example trust policy for the IAM role to allow access from all repos under the org YOUR_ORG_NAME:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::************:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:YOUR_ORG_NAME/*"
                }
            }
        }
    ]
}

Aknowledgments and References

The following resources were very helpful in writing the document:

  1. Secuirty for GitHub actions
  2. Create a role for OpenID Connect federation
  3. aws-actions/configure-aws-credentials