Accessing GitHub from a build via SSH keys


This tutorial demonstrates how to use Secret Manager with Cloud Build to access private GitHub repositories from a build. Secret Manager is a Google Cloud service that securely stores API keys, passwords, and other sensitive data.

Objectives

  • Set up a GitHub SSH key.
  • Add the public SSH key to a private repository's deploy keys.
  • Store the private SSH key in Secret Manager.
  • Submit a build that accesses the key from Secret Manager and uses it to access the private repository.

Costs

In this document, you use the following billable components of Google Cloud:

  • Secret Manager
  • Cloud Build

To generate a cost estimate based on your projected usage, use the pricing calculator. New Google Cloud users might be eligible for a free trial.

Before you begin

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Cloud Build and Secret Manager APIs.

    Enable the APIs

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. Make sure that billing is enabled for your Google Cloud project.

  9. Enable the Cloud Build and Secret Manager APIs.

    Enable the APIs

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init
  12. Optional. Complete the Secret Manager quickstart to become familiar with this product.

Create a SSH key

  1. Open a terminal window.

  2. Create a new directory named workingdir and navigate into it:

    mkdir workingdir
    cd workingdir
    
  3. Create a new GitHub SSH key, where github-email is your GitHub email address:

    ssh-keygen -t rsa -b 4096 -N '' -f id_github -C github-email
    

    This command creates a new SSH key workingdir/id_github without a passphrase for your SSH key. Cloud Build cannot use your SSH key if it is protected with a passphrase.

Store the private SSH key in Secret Manager

When you create an SSH key, an id_github file is created in your environment. Because anyone can authenticate to your account with this file, you must store the file in Secret Manager before using it in a build.

  1. To store your SSH key in Secret Manager:

    1. Go to the Secret Manager page in the Google Cloud console:

      Go to the Secret Manager page

    2. On the Secret Manager page, click Create Secret.

    3. On the Create secret page, under Name, enter a name for the secret.

    4. In the Secret value field, click Upload and upload your workingdir/id_github file.

    5. Leave the Regions section unchanged.

    6. Click the Create secret button.

This will upload your id_github file to Secret Manager.

Add the public SSH key to your private repository's deploy keys

  1. Login to GitHub.

  2. In the upper-right corner, click your profile photo, then click Your profile.

  3. On your profile page, click Repositories, then click the name of your repository.

  4. From your repository, click Settings.

  5. In the sidebar, click Deploy Keys, then click Add deploy key.

  6. Provide a title, paste your public SSH key from workingdir/id_github.pub.

  7. Select Allow write access if you want this key to have write access to the repository. A deploy key with write access lets a deployment push to the repository.

  8. Click Add key.

  9. Delete the SSH key from your disk:

    rm id_github*
    

Grant permissions

You must grant permission to access Secret Manager to the service account you are using for the build.

  1. Open the Cloud Build Settings page:

    Open the Cloud Build Settings page

  2. From the drop-down list, select the service account whose roles you want to change.

  3. Set the status of the Secret Manager Secret Accessor role to Enable.

Add the public SSH key to known hosts

Most machines contain a file named known_hosts, which contains known keys for remote hosts. The keys are often collected from the remote hosts when connecting to them for the first time, but they can also be added manually. The keys in this file are used to verify the identity of the remote host and protect against impersonation.

For Cloud Build to connect to GitHub, you must add the public SSH key to the known_hosts file in Cloud Build's build environment. You can do this by adding the key to a temporary known_hosts.github file, and then copying the contents of known_hosts.github to the known_hosts file in Cloud Build's build environment.

In your workingdir directory, create a file named known_hosts.github and add the public SSH key to this file:

ssh-keyscan -t rsa github.com > known_hosts.github

In the next section when you configure the build, you'll add instructions in the Cloud Build config file to copy the contents of known_hosts.github to the known_hosts file in Cloud Build's build environment.

Configure the build

To configure the build:

  1. Create a build config file named cloudbuild.yaml with two steps: the first gcloud step accesses the SSH key in Secret Manager and saves it as id_rsa in a volume named ssh, along with a copy of the known_hosts.github. The volume is used to persist files across the build steps. The second git step uses the key in id_rsa to connect to the repository at git@github.com:git-username/git-repository.

    # Access the id_github file from Secret Manager, and setup SSH
    steps:
    - name: 'gcr.io/cloud-builders/git'
      secretEnv: ['SSH_KEY']
      entrypoint: 'bash'
      args:
      - -c
      - |
        echo "$$SSH_KEY" >> /root/.ssh/id_rsa
        chmod 400 /root/.ssh/id_rsa
        cp known_hosts.github /root/.ssh/known_hosts
      volumes:
      - name: 'ssh'
        path: /root/.ssh
    
    # Clone the repository
    - name: 'gcr.io/cloud-builders/git'
      args:
      - clone
      - --recurse-submodules
      - git@github.com:GIT_USERNAME/GIT_REPOSITORY
      volumes:
      - name: 'ssh'
        path: /root/.ssh
    
    availableSecrets:
      secretManager:
      - versionName: projects/PROJECT_ID/secrets/SECRET_NAME/versions/latest
        env: 'SSH_KEY'
    

Replace the placeholder values in the above commands with the following:

  • GIT_USERNAME: The GitHub username of the repository owner.
  • GIT_REPOSITORY: The name of the GitHub repository you want to access.
  • PROJECT_ID: The ID of the Google Cloud project where you've stored your secrets.
  • SECRET_NAME: The name of the secret you created in Secret Manager.

To learn about YAML multiline strings used in the snippet above, see YAML multiline.

Submit the build

To submit the build, run the following command:

gcloud builds submit --config=cloudbuild.yaml .

The output is similar to the following:

Creating temporary tarball archive of 3 file(s) totalling 4.1 KiB before compression.
Uploading tarball of [.] to [gs://[PROJECT-ID]_cloudbuild/source/1504288639.02---.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/[PROJECT-ID]/builds/871b68bc---].
Logs are available at [https://console.cloud.google.com/cloud-build/builds/871b68bc---?project=[PROJECT-ID]].
----------------------------- REMOTE BUILD OUTPUT ------------------------------
starting build "871b68bc-cefc-4411-856c-2a2b7c7d2487"

FETCHSOURCE
Fetching storage object: gs://[PROJECT-ID]_cloudbuild/source/1504288639.02---.tgz#1504288640827178
Copying gs://[PROJECT-ID]_cloudbuild/source/1504288639.02---.tgz#1504288640827178...
/ [1 files][  3.9 KiB/  3.9 KiB]
Operation completed over 1 objects/3.9 KiB.
BUILD
Step #0: Already have image (with digest): gcr.io/cloud-builders/gcloud
Starting Step #0
Finished Step #0
Step #1: Already have image (with digest): gcr.io/cloud-builders/git
Starting Step #1
Step #1: # github.com SSH-2.0-libssh_0.7.0
Finished Step #1
Step #2: Already have image (with digest): gcr.io/cloud-builders/git
Starting Step #2
Step #2: Cloning into '[REPOSITORY-NAME]'...
Step #2: Warning: Permanently added the RSA host key for IP address 'XXX.XXX.XXX.XXX' to the list of known hosts.
Finished Step #2
PUSH
DONE
-----------------------------------------------------------------------------------------------------------------

ID                                    CREATE_TIME                DURATION  SOURCE                                                                              IMAGES  STATUS
871b68bc-cefc-4411-856c-2a2b7c7d2487  XXXX-XX-XXT17:57:21+00:00  13S       gs://[PROJECT-ID]_cloudbuild/source/1504288639.02---.tgz  -                                 SUCCESS

Clean up

To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.

Delete the project

The easiest way to eliminate billing is to delete the project that you created for the tutorial.

To delete the project:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Delete the deploy key from your repository

  1. On GitHub, navigate to the main page of the repository.

  2. Under your repository name, click Settings.

  3. In the left sidebar, click Deploy keys.

  4. On the Deploy keys page, look for the deploy keys associated with your repository and click Delete.

What's next