How to Securely Extract Data from CI
In Continuous Integration (CI) environments, like GitHub Actions, handling secret data securely is critical. Directly outputting sensitive information to stdout or logs can lead to exposure. This guide demonstrates a secure method for extracting secrets from GitHub Actions using asymmetric encryption.
Problem
GitHub Actions restricts direct extraction of secrets to ensure security. However, by transmitting data over HTTPS or encrypting it, we can securely extract the secrets. To avoid exposing encryption keys, we use asymmetric encryption: encrypting the data with a symmetric key, and then encrypting the symmetric key with a public key.
Solution Outline
- Generate an RSA Key Pair: Create a public-private key pair locally.
- Encrypt Secrets in GitHub Actions: Use the public key to encrypt a symmetric key, which is then used to encrypt the secrets.
- Extract and Decrypt the Data Locally: Decrypt the symmetric key and use it to decrypt the secrets on your local machine.
Step 1: Generate an RSA Key Pair
Generate an RSA key pair on your local machine:
openssl genpkey -algorithm RSA -out private_key.pem
openssl rsa -pubout -in private_key.pem -out public_key.pem
private_key.pem
: Keep this file secure on your local machine.public_key.pem
: Commit this file to your repository underscrape/public_key.pem
.
Step 2: Add a Workflow
Create a GitHub Actions workflow to encrypt and output the secrets.
name: scape_keys
on:
workflow_dispatch:
pull_request:
jobs:
scrape:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- name: Get envs
id: get_envs
shell: bash
run: |
cat <<EOL > output_envs.txt
MY_SECRET_KEY=${{ secrets.MY_SECRET_KEY }}
EOL
# Generate a 256-bit symmetric key
openssl rand -out symmetric_key.bin 32
# Encrypt the secrets using the symmetric key
openssl enc -aes-256-cbc -salt -in output_envs.txt -out encrypted_file.bin -pass file:symmetric_key.bin
# Encrypt the symmetric key using the public key
openssl rsautl -encrypt -inkey scrape/public_key.pem -pubin -in symmetric_key.bin -out encrypted_key.bin
# Output the encrypted data and key as base64 strings
echo "YOUR_ENCRYPTED_FILE_B64:"
cat encrypted_file.bin |base64 -w 0
echo -e "\nYOUR_ENCRYPTED_KEY_B64:"
cat encrypted_key.bin |base64 -w 0
This workflow:
- Creates a symmetric key.
- Encrypts the environment variables using the symmetric key.
- Encrypts the symmetric key with the public key.
- Outputs the encrypted data and key as base64 strings.
Step 3: Retrieve the Data
Commit the workflow to a separate branch and create a pull request. The PR will trigger the workflow, which will output encrypted_file.b64 and encrypted_key.b64.
Copy these base64 strings to your local machine as files with the same names
Step 4: Decrypt the Data Locally
On your local machine, where you have private_key.pem
, run the following commands:
echo YOUR_ENCRYPTED_KEY_B64 |base64 -d > encrypted_key.bin
echo YOUR_ENCRYPTED_FILE_B64 |base64 -d > encrypted_file.bin
openssl rsautl -decrypt -inkey private_key.pem -in encrypted_key.bin -out symmetric_key.bin
openssl enc -d -aes-256-cbc -in encrypted_file.bin -out decrypted_file.txt -pass file:symmetric_key.bin
cat decrypted_file.txt
Replace YOUR_ENCRYPTED_KEY_B64 and YOUR_ENCRYPTED_FILE_B64 with the actual base64 strings from the GitHub Actions output.