DEV Community

CiCube for CICube

Posted on • Edited on • Originally published at cicube.io

How to Use Secrets in GitHub Actions Workflows


cicube.io

Introduction

I would like to go through some thoughts on how you can better maintain and make use of secrets with your GitHub Actions workflows. Once I had read through the GitHub documentation, I did a simple breakdown of the core activities before giving a number of recommendations:

Overview of Secrets

In GitHub, these are called secrets, which are stored-sensitive data at the organization, repository, or environment level. Secrets might be used within workflows but would remain accessible only when they have explicitly been mentioned in a workflow file to protect API tokens, credentials, and other sensitive data.

How to Define Secrets in GitHub

First of all, to get started with secrets in GitHub Actions, you have to define them at organization, repository, or environment levels. Here is how you can create and manage them:

A Secret Creation for a Repository:

  1. On GitHub, navigate to the homepage of your repository.
  2. Under the repository name, click Settings.
  3. In the left sidebar, click Secrets and variables, then select Actions.
  4. Click the Secrets tab.
  5. Click New repository secret.
  6. In the Name field give your secret a name like API_KEY.
  7. Under Secret, fill in the value of the secret, e.g., the actual API key or token.
  8. Click Add secret.

Once added, your secret will be stored securely and can be utilized within your workflows.

Creating Secrets for an Organization:

  1. On GitHub, navigate to your organization's main page.
  2. Click Settings under the organization name.
  3. In the left sidebar, click Secrets and variables, then select Actions.
  4. Click the Secrets tab.
  5. Click New organization secret.
  6. Type an appropriate name for your secret, and fill in its value.
  7. In the Repository access dropdown, select which repositories can access this secret.
  8. Click Add secret.

This allows you to share secrets between multiple repositories and reduces the duplication of it.

Creating Secrets for an Environment:

  1. Navigate to the main page of the repository on GitHub.
  2. Under the repository name, click Settings.
  3. Click Environments in the left sidebar.
  4. From the dropdown list, select the environment you would like to create a secret in.
  5. Under Environment secrets, click Add secret.
  6. Name your secret, and add its value, then click Add secret.

The environment-to-secrets support an extra layer of approval in that they will be covered under approval before access is granted to workflows.

Examples of Secrets:

Here are some robust pragmatic ways to apply secrets within a GitHub Actions workflow:

Example 1: Using Secrets as Environment Variables

The following example uses a secret as an environment variable in a step in a workflow:

name: Use secret as environment variable
on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run a command with a secret
        env:
          API_KEY: ${{ secrets.API_KEY }} # Use your secret here
        run: echo "Using secret in a command"
Enter fullscreen mode Exit fullscreen mode

In this example, environment variable API_KEY secret was used in the job. The secret is securely passed to the worflow and can be set in the script without showing sensitive data.

Example 2: Using Secrets as Workflow Inputs

This is how you can perform it in case you want to pass a secret as an input for an action:

name: Use secret as input
on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Use secret in an action
        uses: some-action/with-secrets@v1
        with:
          api_key: ${{ secrets.API_KEY }} # Set secret as input
Enter fullscreen mode Exit fullscreen mode

For this action, api_key is a required input; hence, we safely pass the API_KEY secret to satisfy this requirement.

Example 3: Decrypting Large Secrets

Another alternative, especially for large secrets bigger than 48KB, is the encryption of a file and its storage in a repository, then using a passphrase stored as a secret from GitHub to decrypt that particular file during workflow execution.

  1. encrypt the secret file:
gpg --symmetric --cipher-algo AES256 my_secret.json
Enter fullscreen mode Exit fullscreen mode

This command will create the encrypted file called my_secret.json.gpg.

  1. Store the passphrase as secret in GitHub. For example, LARGE_SECRET_PASSPHRASE.
  2. Add a workflow step to decrypt the file:
name: Decrypt large secret
on: push

jobs:
  decrypt-job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Decrypt large secret
        // higliht-next-line
        run: ./decrypt_secret.sh
        env:
          LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}
Enter fullscreen mode Exit fullscreen mode

This step uses that passphrase as stored in the secret LARGE_SECRET_PASSPHRASE to decrypt the my_secret.json.gpg file.

#!/bin/sh
gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" \
--output $HOME/secrets/my_secret.json my_secret.json.gpg
Enter fullscreen mode Exit fullscreen mode

Example 4: Base64 Encoding a Binary Blob

We can store binary blobs, such as certificates, as Base64-encoded strings. Here is how it's done :

  1. Encode your file to Base64:
base64 -i cert.der -o cert.base64
Enter fullscreen mode Exit fullscreen mode

This command takes the cert.der binary file and transforms it into a base64-encoded string, placing the output into cert.base64:.

  1. Store the Base64 string as a secret in GitHub.

  2. Decode a Base64 secret in a workflow:

name: Retrieve Base64 secret
on: push

jobs:
  decode-secret:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Decode Base64 secret
        env:
          CERTIFICATE_BASE64: ${{ secrets.CERTIFICATE_BASE64 }}
        run: |
          echo $CERTIFICATE_BASE64 | base64 --decode > cert.der
Enter fullscreen mode Exit fullscreen mode

In this example, a Base64-encoded certificate is stored as a secret and decoded back to its original binary form inside the workflow.

Example 5: Conditional Step with Secrets

Secrets cannot be used directly within conditional if statements. However, we can make a secret a job-level environment variable and then use that value for conditional logic:

name: Conditional secret usage
on: push

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      SECRET_FLAG: ${{ secrets.FLAG_SECRET }}
    steps:
      - name: Conditional step
        if: env.SECRET_FLAG == 'enabled'
        run: echo "The secret flag is enabled!"
Enter fullscreen mode Exit fullscreen mode

Besides the above example here the secret FLAG_SECRET is assigned to an environment variable SECRET_FLAG controlling via its existence whether or not a conditional step will be executed:

Conclusion

Secret usage within GitHub Actions workflows offers a layer of protection to sensitive data while efficiently automating. Setting these secrets across higher levels of granularity-organization, repository, and environment-will give you the flexibility of access control. Be it API keys, credentials, or encrypted files, this should give one a good basis for security and reliability within the workflow.

Top comments (1)

Collapse
 
martinbaun profile image
Martin Baun

Sweet! Github secrets are a blessing with actions.