How to send passphrase for ssh-add with GitHub Actions?

Viewed 1766

My goal is to store private key with passphrase in GitHub secrets, but I don't know how to enter the passphrase through GitHub actions.

What I've tried:

  1. I created a private key without passphrase and store it in GitHub secrets.

.github/workflows/docker-build.yml

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. 
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Runs a set of commands using the runners shell
      - name: Run a multi-line script
        run: |
          eval $(ssh-agent -s)
          echo "${{ secrets.SSH_PRIVATE_KEY }}" |  ssh-add -
          ssh -o StrictHostKeyChecking=no root@${{ secrets.HOSTNAME }} "rm -rf be-bankaccount; git clone https://github.com/kidfrom/be-bankaccount.git; cd be-bankaccount; docker build -t be-bankaccount .; docker-compose up -d;"
2 Answers

I finally figured this out because I didn't want to go to the trouble of updating all my servers with a passphrase-less authorized key. Ironically, it probably took me longer to do this but now I can save you the time.

The two magic ingredients are: using SSH_AUTH_SOCK to share between GH action steps and using ssh-add with DISPLAY=None and SSH_ASKPASS set to an executable script that sends your passphrase via stdin.

For your question specifically, you do not need SSH_AUTH_SOCK because all your commands run within a single job step. However, for more complex workflows, you'll need it set.

Here's an example workflow:

name: ssh with passphrase example

env:
  # Use the same ssh-agent socket value across all jobs
  # Useful when a GH action is using SSH behind-the-scenes
  SSH_AUTH_SOCK: /tmp/ssh_agent.sock

jobs:
  job1:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2
      
    # Start ssh-agent but set it to use the same ssh_auth_sock value.
    # The agent will be running in all steps after this, so it
    # should be one of the first.
    - name: Setup SSH passphrase
      env:
        SSH_PASSPHRASE: ${{secrets.SSH_PASSPHRASE}}
        SSH_PRIVATE_KEY: ${{secrets.SSH_PRIVATE_KEY}}
      run: |
        ssh-agent -a $SSH_AUTH_SOCK > /dev/null
        echo 'echo $SSH_PASSPHRASE' > ~/.ssh_askpass && chmod +x ~/.ssh_askpass
        echo "$SSH_PRIVATE_KEY" | tr -d '\r' | DISPLAY=None SSH_ASKPASS=~/.ssh_askpass ssh-add - >/dev/null

    # Debug print out the added identities. This will prove SSH_AUTH_SOCK
    # is persisted across job steps
    - name: Print ssh-add identities
      runs: ssh-add -l

  job2:

    # NOTE: SSH_AUTH_SOCK will be set, but the agent itself is not
    # shared across jobs, each job is a new container sandbox
    # so you still need to setup the passphrase again
    steps: ...

Resources I referenced:

You could try and use actions/webfactory-ssh-agent, which comes from the study done in "Using a SSH deploy key in GitHub Actions to access private repositories" done by Matthias Pigulla

GitHub Actions only have access to the repository they run for. So, in order to access additional private repositories, create an SSH key with sufficient access privileges.
Then, use this action to make the key available with ssh-agent on the Action worker node. Once this has been set up, git clone commands using ssh URLs will just work.

# .github/workflows/my-workflow.yml
jobs:
    my_job:
        ...
        steps:
            - actions/checkout@v1
            # Make sure the @v0.4.1 matches the current version of the
            # action 
            - uses: webfactory/ssh-agent@v0.4.1
              with:
                  ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
            - ... other steps
Related