Search code examples
githubgithub-actionscicd

Can I reference GitHub Organization Secrets from a repo's Environment Secrets?


Our organization has a bunch of repos on GitHub using GitHub Actions to deploy, some of which need access to the same secrets (token for our code coverage tool as one example). Organization-level secrets work great for this.

Individual repos also require secrets which differ based whether they are deploying to staging or production. Environment secrets work great for this by allowing the action to be generic and just reference AWS_KEY rather than conditionally use PROD_AWS_KEY or STAGING_AWS_KEY, for instance.

But I can't seem to find a way to use both features together. If two repos want to use environment secrets to change the value of the secret they are accessing, but have that underlying secret be shared to the repos from the organization level.

CircleCI had a feature called contexts which allowed us to share a prod and staging context to any repo that needed them but I can't seem to get analogous behaviour out of GitHub Actions. Does anyone know if this is possible, and if so how?


Solution

  • So after some messing around I found an answer to this that works, at least in my particular use case.

    It is possible to use a variable/secret value to access an organization secret. If I store the name of the organization secret in the value of an environment variable then I can use it to access the correct org secret at action runtime.

    Lets assume the repo has two environments setup; production and staging. Also assume the organization has a secret to access an AWS key for each of there corresponding AWS accounts, named AWS_KEY_PROD and AWS_KEY_STAGE for instance.

    In each GitHub Action environment lets create an environment variable named AWS_KEY where the value is the name of the org secret that makes sense for the environment we are working with. So the value of AWS_KEY for the production environment is AWS_KEY_PROD and for the staging environment its AWS_KEY_STAGE. Then we can use the value to access the corresponding org secret.

    jobs:
      staging-job:
        name: example staging job
        runs-on: ubuntu-latest
        environment: staging
        steps:
    
          #Should print 'AWS_KEY_STAGE' 
          - name: get secret name from environment vars
            run: echo "${{ vars.AWS_KEY }}"
    
          - name: get secret value using secret name
            run: someCommand "${{ secrets[vars.AWS_KEY] }}"
    
      production-job:
        name: example production job
        runs-on: ubuntu-latest
        environment: production
        steps:
    
          #Should print 'AWS_KEY_PROD' 
          - name: get secret name from environment vars
            run: echo "${{ vars.AWS_KEY }}"
    
          - name: get secret value using secret name
            run: someCommand "${{ secrets[vars.AWS_KEY] }}"
    

    As you can see the two different jobs use the exact same steps definition (except for the comment added here for clarity) to access the different secrets based on the environment.