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.
Navigating and Managing Secrets
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
:
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.
Creating a Repository Secret
Follow these steps to create a new repository secret in a project, for example, "My Cool Project":
- Navigate to Settings > Secrets and Variables > Actions.
- Click on “New repository secret.”
- Enter the secret name (e.g.,
API_KEY
) and assign it a corresponding value (e.g.,ABC123
).
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:
- Go to the Actions tab.
- 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:
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.
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