AZ-400: Designing and Implementing Microsoft DevOps Solutions

Design and Implement a Strategy for Managing Sensitive Information in Automation

Exploring GitHub Secrets

In this lesson, we delve into GitHub Secrets and learn how to manage them securely. We will explore secure secret management practices, demonstrate the integration of secrets within GitHub workflows, and discuss their use with external tools. By the end of this guide, you will be equipped to leverage GitHub Secrets in your projects effectively.

GitHub Secrets are encrypted environment variables that allow you to store sensitive information—such as API keys, access tokens, or other confidential data—without exposing them in your code. This encryption ensures that sensitive data remains protected from unauthorized access, even in collaborative development environments.

GitHub offers three primary types of secrets:

  • Repository Secrets: Scoped to a specific repository, these are ideal for workflows that are confined to a single project.
  • Environment Secrets: Tied to specific environments (e.g., staging or production) within a repository, offering fine-grained access control over secret usage.
  • Organizational Secrets: Shared across multiple repositories within an organization, perfect for common secrets used across various projects.

To manage your secrets, navigate to your repository's Settings and scroll down to Secrets and Variables. Within this section, you will find tabs for Actions, Codespaces, Dependabot, etc. For example, if you click on the Actions tab, you might see a secret such as AZURE_WEBAPP_PUBLISH_PROFILE:

The image shows a GitHub repository settings page for "Actions secrets and variables," displaying a repository secret named "AZURE_WEBAPP_PUBLISH_PROFILE."

Note

When editing a secret, its value is hidden to prevent unauthorized retrieval directly from the UI.

Secrets vs. Variables

In addition to secrets, GitHub allows you to define repository variables. Unlike secrets, variables are not encrypted and should only be used for non-sensitive information, such as server names. They offer an efficient way to update values across different parts of your project from a single location.

The image shows a GitHub repository settings page focused on "Actions secrets and variables," with options to manage secrets and repository variables. A cursor is hovering over the "Variables" tab, and there are no variables currently set.

Creating a Repository Secret

Follow these steps to create a new repository secret in a project, for example, "My Cool Project":

  1. Navigate to Settings > Secrets and Variables > Actions.
  2. Click on “New repository secret.”
  3. Enter the secret name (e.g., API_KEY) and assign it a corresponding value (e.g., ABC123).

The image shows a GitHub interface where a user is adding a new secret under "Actions secrets" in the settings of a project. The user is prompted to enter a name and a secret value.

Remember, once the secret is added, its value is only visible during creation. To update, click Edit, modify the value (for example, change it to ABC234), and confirm using your password.

Using GitHub Secrets in Workflows

Integrating secrets into your GitHub Actions is straightforward. To set up a workflow:

  1. Go to the Actions tab.
  2. Click Set Up a Workflow Yourself to generate a basic workflow template.

For instance, consider the following workflow that makes a cURL request using the secret stored under API_KEY:

on:
  workflow_dispatch:
jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    steps:
      - name: Hello World Action
        run: |
          curl -H "Authorization: Bearer ${{ secrets.API_KEY }}" https://en12e6i3tq18hk.x.pipedream.net

This workflow is manually triggered using workflow_dispatch and sends a cURL request with the bearer token from GitHub Secrets. When executed, the endpoint (often a request bin) will display the authorization header containing the secret value (ABC234).

After committing your workflow file, the process should complete with a success message:

The image shows a GitHub Actions page for a project named "My-cool-project," displaying a workflow run for a file named "main.yml" in the ".github/workflows" directory.

To verify secret usage, you might run a GET request like the following:

curl -H "Authorization: ****" https://en1z6g31tq18hk.x.pipedream.net

A successful response might look like this:

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
0     0    0     0    0     0   0      0 --:--:-- --:--:-- --:--:--     0
100   16  100   16    0    74 --:--:-- --:--:-- --:--:--    74
{"success": true}

This confirms that the secret value (ABC234) was successfully transmitted as an authorization header.

Important Security Considerations

GitHub Secrets are safeguarded by a strict security policy: secrets are not passed to workflows triggered by pull requests from forks. This measure prevents untrusted code from being used to reveal sensitive information.

For example, consider a workflow in a forked repository:

on:
  workflow_dispatch:
jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    steps:
      - name: Hello World Action
        run: |
          curl -H "Authorization: Bearer ${{ secrets.API_KEY }}" https://en1263itql8hk.x.pipedream.net

In this case, the secret would not be passed, ensuring its safety even when workflows are executed by external contributors.

Using Multiple Secrets in a Workflow

You might encounter workflows that require several secrets for authentication and deployment tasks, such as deploying an application to Azure. Here’s an example:

name: Deploy to Azure
on:
  push:
    branches:
      - main
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Azure Login
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Deploy to Azure Web App
        uses: azure/webapps-deploy@v2
        with:
          app-name: ${{ secrets.AZURE_WEBAPP_NAME }}
          publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}

GitHub automatically masks secret values in logs by replacing them with asterisks. However, be cautious: users with write access might inadvertently expose secrets in workflows. Therefore, it is essential to manage repository access and employ environment protection rules that require approval before secrets are used.

Regular Secret Rotation

Regularly rotating secrets minimizes the risk of compromised credentials. Although you might not control external API tokens, you should routinely rotate internal tokens and API keys. Consider the workflow below that runs on a monthly schedule to rotate an API key:

name: Rotate API Key
on:
  schedule:
    - cron: "0 1 * * *" # Run monthly
jobs:
  rotate-key:
    runs-on: ubuntu-latest
    steps:
      - name: Generate new API key
        run: |
          NEW_KEY=$(openssl rand -base64 32)
          echo "NEW_KEY=$NEW_KEY" >> $GITHUB_ENV
      - name: Update API key in external service
        run: |
          curl -X POST https://api.example.com/rotate-key \
          -H "Authorization: Bearer ${{ secrets.CURRENT_API_KEY }}" \
          -d "{\"new_key\": \"$NEW_KEY\"}"
      - name: Update GitHub Secret
        uses: hmanzur/[email protected]
        with:
          name: 'CURRENT_API_KEY'
          value: ${{ env.NEW_KEY }}
          repository: ${{ github.repository }}
          token: ${{ secrets.REPO_ACCESS_TOKEN }}

This workflow generates a new API key, uses it to update an external service, and then refreshes the GitHub secret accordingly.

Logging Secret Usage

Monitoring secret usage can be critical for security audits. You can log secret usage by creating an entry each time a secret (e.g., DEPLOY_KEY) is utilized in a workflow:

steps:
  - name: Log secret usage
    run: |
      echo "Secret DEPLOY_KEY used at $(date)" >> $GITHUB_WORKSPACE/secret_usage.log
  - name: Use secret
    env:
      DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
    run: ./deploy.sh

This log enables you to monitor when and how secrets are accessed, helping you detect and address any unusual activity.

Best Practices for Secret Management

  • Limit Exposure: Grant access to secrets only to personnel who absolutely need them. Utilize short-lived tokens whenever possible.
  • Never Hard Code Secrets: Avoid embedding secrets within your codebase—in scripts or compiled binaries.
  • Use Environment Secrets: For higher security, store production credentials as environment secrets and require manual approvals.
  • Regularly Audit and Rotate Secrets: Continuously monitor, audit, and rotate your secrets to reduce risk if a secret is compromised.
  • Enable Secret Scanning: Utilize GitHub’s secret scanning feature to automatically detect accidental secret exposure.
  • Educate Your Team: Ensure that all team members are aware of the importance of secret management protocols.

The image shows a list of best practices for managing secrets in code, including limiting exposure, using short-lived tokens, avoiding hardcoding, and regularly auditing access.

GitHub Secrets provide a robust mechanism for protecting sensitive information in your workflows. By following these best practices, you can ensure a secure development environment while leveraging seamless automation and external system integration.

Happy coding!

Watch Video

Watch video content

Previous
Exploring Azure Pipelines Secrets with Azure Key Vault