Manage Secrets in GitHub Actions

An important core part of working with CI builds is the capability to store and manage secrets, which are necessary to access protected systems and for example sign apps.

Handling the secrets correctly can quickly become tricky, as not everything is a simple key (string).

How to store secrets

GitHub offers repo maintainers to define secrets via the repo settings.

One very important detail for repositories with collaborators is, that you fully trust everybody with collaborator access, as secrets added for public repositories will also be available to collaborators.

You don't have to worry about pull requests, as secrets are not available for these.

GitHub Actions Secrets
GitHub Actions Secrets
GitHub Actions Add Secret
GitHub Actions Add Secret

When naming secrets please keep in mind that GITHUB_ as prefix is not allowed as it is protected to be only used by GitHub itself.

Also there's a hard limit of 100 secrets, which you can't exceed.

When working as part of an organisation GitHub offers the additional possibility to define organization secrets which will be available to all or selected repositories.

Which can be overwritten on a per repo base again.

GitHub Organization Secrets
GitHub Organization Secrets

Use secrets

After a secret gets defined for the repository, they can be directly used in workflows. For this the environment object secrets exists in the workflows.

${{ secrets.MY_ORG_USER }}

Special secret

There's one special secret, which is available to every workflow.

${{ secrets.GITHUB_TOKEN }}

This special token, can be used to execute operations on the repository this action is executed on. Like commenting, ...

Store complex secrets

Not all secrets can be simplified to a plain string token or user and password, but are far more complex. For example files.

One usecase of being required to store a file in the secrets would for example be the Android keystore.

GitHub Actions has a 64 KB limit, which has to be met.

Luckily we can use gpg which allows us to encrypt any file to ASCII format, which can then be stored as a secret.

1.) Encrypt file

gpg --symmetric --armor --cipher-algo AES256 myapp.keystore

2.) Define password

Executing this, will require to provide a passphrase to encrypt the keystore with.

3.) Specify in GitHub

As a result you will get a myapp.keystore.asc file, which we read in and then specify in GitHub as secret.

cat  myapp.keystore.asc
Encrypted KeyStore secret
Encrypted KeyStore secret
GitHub Actions KeyStore secrets
GitHub Actions KeyStore secrets

4.) Use in Workflow

The last step is to retrieve and decrypt the secret to a file again.

- name: Prepare Keystore and Local.
  run: |
     echo "${{ secrets.KEYSTORE }}" > app.keystore.asc
     gpg -d --passphrase "${{ secrets.KEYSTORE_PASS }}" --batch "app.keystore.asc" > "app/app.keystore"

After this the keystore is available as app/app.keystore, and allows you to sign the app for release.

Secure your secrets

As highlighted in the previous article about staying secure with GitHub Actions.

Please always try to prefer to provide secrets only to the smallest scope in your build as possible.

Prefer to provide secrets only to steps. If this is not possible consider to provide them only for jobs. Only in the rarest situations it is ok to define secrets globally to your whole workflow.

This will ensure that no actions or part of your build could potentially leak or steal the secrets, or keys you maintain.


Got thoughts, feedback, improvements, suggestions, or comments?

Let me know @mike_penz