How to mask environment variables created in Github when running a workflow?
Question:
I created a Github workflow that runs a python script with a cron schedule. On every run of the workflow an access_token is generated, which is required during the next run.
To save the token the python script writes the token to the GITHUB_ENV
file. In the next step, I use the hmanzur/[email protected]
action to save the token to a Github secret. All works fine.
My only problem is, that the token gets displayed in the logs of the second step as an environment variable.
Here is a minimal version of the workflow file:
name: Tests
on:
schedule:
- cron: "0 1 * * *"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: ['3.9']
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
working-directory: ./src
run: python -m unittest
env:
ACCESS_TOKEN: ${{secrets.ACCESS_TOKEN}}
- uses: hmanzur/[email protected]
with:
name: 'ACCESS_TOKEN'
value: ${{env.ACCESS_TOKEN}}
repository: Me/MyRepository
token: ${{ secrets.REPO_ACCESS_TOKEN }}
I tried applying ::add-mask::
. Adding echo "ACCESS_TOKEN=::add-mask::$ACCESS_TOKEN" >> $GITHUB_ENV
only added ::add-mask::
to the string.
Is there a way of masking all environment variables in the GITHUB_ENV
file I can apply in the first step? Can I apply the masking to the variable while writing to the GITHUB_ENV
file in python? Or is there a way to disable the display of the environment variables during the workflow?
Answers:
My solution, if someone is having the same problem.
There seems to be no direct solution. As a workaround I use the cryptocode
library to encode and decode the access token in the python script. Only the encrypted token is send to the workflow environment and saved in the repos secret.
Here a minimal working example:
workflow.yml
:
name: Test
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: ['3.9']
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
working-directory: ./
run: python encrypt-secret.py
env:
ENCRYPTED_ACCESS_TOKEN: ${{secrets.ENCRYPTED_ACCESS_TOKEN}}
INITIAL_ACCESS_TOKEN: ${{secrets.INITIAL_ACCESS_TOKEN}}
PASS_KEY: ${{secrets.REPO_ACCESS_TOKEN}}
- uses: hmanzur/[email protected]
with:
name: 'ENCRYPTED_ACCESS_TOKEN'
value: ${{env.ENCRYPTED_NEW_ACCESS_TOKEN}}
repository: Der-Henning/test-workflows
token: ${{ secrets.REPO_ACCESS_TOKEN }}
encrypt-secret.py
:
from os import environ
from random import random
import cryptocode
def main():
## Get Github environment file
## Only run this part when GITHUB_ENV is set -> workflow detection
env_file = environ.get('GITHUB_ENV', None)
if env_file:
## PASS_KEY to encrypt the secret
passkey = environ.get("PASS_KEY", None)
access_token = environ.get("INITIAL_ACCESS_TOKEN")
## get the encrypted token and decrypt with passkey
encrypted_old_access_token = environ.get("ENCRYPTED_ACCESS_TOKEN", None)
if encrypted_old_access_token and passkey:
old_access_token = cryptocode.decrypt(encrypted_old_access_token, passkey)
if old_access_token:
print("Access Token from secret: {}".format(old_access_token))
print("Correct Token: {}".format(old_access_token.startswith('ThisIsASecret')))
access_token = old_access_token
else:
print("No encrypted Access Token provided!")
######
#
# Do stuff here
# Use old_access_token to access an API ...
#
#####
## Encrypt new access token from API for next run
## Save encrypted token to GITHUB_ENV
new_access_token = "ThisIsASecret{}".format(random())
print("New Token: {}".format(new_access_token))
if passkey:
encrypted_new_access_token = cryptocode.encrypt(new_access_token, passkey)
with open(env_file, "a") as file:
file.write("ENCRYPTED_NEW_ACCESS_TOKEN={}n".format(encrypted_new_access_token))
if __name__ == "__main__":
main()
Your usage of "::add-mask::" is wrong (not your fault, I hate GHA doc).
What you need to do is:
echo "::add-mask::$ACCESS_TOKEN"
echo "ACCESS_TOKEN=$ACCESS_TOKEN" >> $GITHUB_ENV
I created a Github workflow that runs a python script with a cron schedule. On every run of the workflow an access_token is generated, which is required during the next run.
To save the token the python script writes the token to the GITHUB_ENV
file. In the next step, I use the hmanzur/[email protected]
action to save the token to a Github secret. All works fine.
My only problem is, that the token gets displayed in the logs of the second step as an environment variable.
Here is a minimal version of the workflow file:
name: Tests
on:
schedule:
- cron: "0 1 * * *"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: ['3.9']
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
working-directory: ./src
run: python -m unittest
env:
ACCESS_TOKEN: ${{secrets.ACCESS_TOKEN}}
- uses: hmanzur/[email protected]
with:
name: 'ACCESS_TOKEN'
value: ${{env.ACCESS_TOKEN}}
repository: Me/MyRepository
token: ${{ secrets.REPO_ACCESS_TOKEN }}
I tried applying ::add-mask::
. Adding echo "ACCESS_TOKEN=::add-mask::$ACCESS_TOKEN" >> $GITHUB_ENV
only added ::add-mask::
to the string.
Is there a way of masking all environment variables in the GITHUB_ENV
file I can apply in the first step? Can I apply the masking to the variable while writing to the GITHUB_ENV
file in python? Or is there a way to disable the display of the environment variables during the workflow?
My solution, if someone is having the same problem.
There seems to be no direct solution. As a workaround I use the cryptocode
library to encode and decode the access token in the python script. Only the encrypted token is send to the workflow environment and saved in the repos secret.
Here a minimal working example:
workflow.yml
:
name: Test
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: ['3.9']
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
working-directory: ./
run: python encrypt-secret.py
env:
ENCRYPTED_ACCESS_TOKEN: ${{secrets.ENCRYPTED_ACCESS_TOKEN}}
INITIAL_ACCESS_TOKEN: ${{secrets.INITIAL_ACCESS_TOKEN}}
PASS_KEY: ${{secrets.REPO_ACCESS_TOKEN}}
- uses: hmanzur/[email protected]
with:
name: 'ENCRYPTED_ACCESS_TOKEN'
value: ${{env.ENCRYPTED_NEW_ACCESS_TOKEN}}
repository: Der-Henning/test-workflows
token: ${{ secrets.REPO_ACCESS_TOKEN }}
encrypt-secret.py
:
from os import environ
from random import random
import cryptocode
def main():
## Get Github environment file
## Only run this part when GITHUB_ENV is set -> workflow detection
env_file = environ.get('GITHUB_ENV', None)
if env_file:
## PASS_KEY to encrypt the secret
passkey = environ.get("PASS_KEY", None)
access_token = environ.get("INITIAL_ACCESS_TOKEN")
## get the encrypted token and decrypt with passkey
encrypted_old_access_token = environ.get("ENCRYPTED_ACCESS_TOKEN", None)
if encrypted_old_access_token and passkey:
old_access_token = cryptocode.decrypt(encrypted_old_access_token, passkey)
if old_access_token:
print("Access Token from secret: {}".format(old_access_token))
print("Correct Token: {}".format(old_access_token.startswith('ThisIsASecret')))
access_token = old_access_token
else:
print("No encrypted Access Token provided!")
######
#
# Do stuff here
# Use old_access_token to access an API ...
#
#####
## Encrypt new access token from API for next run
## Save encrypted token to GITHUB_ENV
new_access_token = "ThisIsASecret{}".format(random())
print("New Token: {}".format(new_access_token))
if passkey:
encrypted_new_access_token = cryptocode.encrypt(new_access_token, passkey)
with open(env_file, "a") as file:
file.write("ENCRYPTED_NEW_ACCESS_TOKEN={}n".format(encrypted_new_access_token))
if __name__ == "__main__":
main()
Your usage of "::add-mask::" is wrong (not your fault, I hate GHA doc).
What you need to do is:
echo "::add-mask::$ACCESS_TOKEN"
echo "ACCESS_TOKEN=$ACCESS_TOKEN" >> $GITHUB_ENV