diff options
Diffstat (limited to 'doc/ci/ssh_keys/README.md')
-rw-r--r-- | doc/ci/ssh_keys/README.md | 249 |
1 files changed, 169 insertions, 80 deletions
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md index e5a2bbd1773..df0e1521150 100644 --- a/doc/ci/ssh_keys/README.md +++ b/doc/ci/ssh_keys/README.md @@ -1,84 +1,106 @@ -# Using SSH keys +--- +last_updated: 2017-12-13 +--- + +# Using SSH keys with GitLab CI/CD GitLab currently doesn't have built-in support for managing SSH keys in a build -environment. +environment (where the GitLab Runner runs). The SSH keys can be useful when: 1. You want to checkout internal submodules -2. You want to download private packages using your package manager (eg. bundler) -3. You want to deploy your application to eg. Heroku or your own server -4. You want to execute SSH commands from the build server to the remote server -5. You want to rsync files from your build server to the remote server +1. You want to download private packages using your package manager (e.g., Bundler) +1. You want to deploy your application to your own server, or, for example, Heroku +1. You want to execute SSH commands from the build environment to a remote server +1. You want to rsync files from the build environment to a remote server If anything of the above rings a bell, then you most likely need an SSH key. -## Inject keys in your build server - The most widely supported method is to inject an SSH key into your build -environment by extending your `.gitlab-ci.yml`. - -This is the universal solution which works with any type of executor -(docker, shell, etc.). - -### How it works - -1. Create a new SSH key pair with [ssh-keygen][] -2. Add the private key as a **Secret Variable** to the project -3. Run the [ssh-agent][] during job to load the private key. +environment by extending your `.gitlab-ci.yml`, and it's a solution which works +with any type of [executor](https://docs.gitlab.com/runner/executors/) +(Docker, shell, etc.). + +## How it works + +1. Create a new SSH key pair locally with [ssh-keygen](http://linux.die.net/man/1/ssh-keygen) +1. Add the private key as a [secret variable](../variables/README.md) to + your project +1. Run the [ssh-agent](http://linux.die.net/man/1/ssh-agent) during job to load + the private key. +1. Copy the public key to the servers you want to have access to (usually in + `~/.ssh/authorized_keys`) or add it as a [deploy key](../../ssh/README.md#deploy-keys) + if you are accessing a private GitLab repository. + +NOTE: **Note:** +The private key will not be displayed in the job trace, unless you enable +[debug tracing](../variables/README.md#debug-tracing). You might also want to +check the [visibility of your pipelines](../../user/project/pipelines/settings.md#visibility-of-pipelines). ## SSH keys when using the Docker executor -You will first need to create an SSH key pair. For more information, follow the -instructions to [generate an SSH key](../../ssh/README.md). Do not add a -passphrase to the SSH key, or the `before_script` will prompt for it. - -Then, create a new **Secret Variable** in your project settings on GitLab -following **Settings > CI/CD** and look for the "Secret Variables" section. -As **Key** add the name `SSH_PRIVATE_KEY` and in the **Value** field paste the -content of your _private_ key that you created earlier. - -It is also good practice to check the server's own public key to make sure you -are not being targeted by a man-in-the-middle attack. To do this, add another -variable named `SSH_SERVER_HOSTKEYS`. To find out the hostkeys of your server, run -the `ssh-keyscan YOUR_SERVER` command from a trusted network (ideally, from the -server itself), and paste its output into the `SSH_SERVER_HOSTKEYS` variable. If -you need to connect to multiple servers, concatenate all the server public keys -that you collected into the **Value** of the variable. There must be one key per -line. - -Next you need to modify your `.gitlab-ci.yml` with a `before_script` action. -Add it to the top: - -``` -before_script: - # Install ssh-agent if not already installed, it is required by Docker. - # (change apt-get to yum if you use a CentOS-based image) - - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' - - # Run ssh-agent (inside the build environment) - - eval $(ssh-agent -s) - - # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store - - ssh-add <(echo "$SSH_PRIVATE_KEY") - - # For Docker builds disable host key checking. Be aware that by adding that - # you are suspectible to man-in-the-middle attacks. - # WARNING: Use this only with the Docker executor, if you use it with shell - # you will overwrite your user's SSH config. - - mkdir -p ~/.ssh - - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' - # In order to properly check the server's host key, assuming you created the - # SSH_SERVER_HOSTKEYS variable previously, uncomment the following two lines - # instead. - # - mkdir -p ~/.ssh - # - '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts' -``` - -As a final step, add the _public_ key from the one you created earlier to the -services that you want to have an access to from within the build environment. -If you are accessing a private GitLab repository you need to add it as a -[deploy key](../../ssh/README.md#deploy-keys). +When your CI/CD jobs run inside Docker containers (meaning the environment is +contained) and you want to deploy your code in a private server, you need a way +to access it. This is where an SSH key pair comes in handy. + +1. You will first need to create an SSH key pair. For more information, follow + the instructions to [generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair). + **Do not** add a passphrase to the SSH key, or the `before_script` will\ + prompt for it. + +1. Create a new [secret variable](../variables/README.md#secret-variables). + As **Key** enter the name `SSH_PRIVATE_KEY` and in the **Value** field paste + the content of your _private_ key that you created earlier. + +1. Modify your `.gitlab-ci.yml` with a `before_script` action. In the following + example, a Debian based image is assumed. Edit to your needs: + + ```yaml + before_script: + ## + ## Install ssh-agent if not already installed, it is required by Docker. + ## (change apt-get to yum if you use an RPM-based image) + ## + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + + ## + ## Run ssh-agent (inside the build environment) + ## + - eval $(ssh-agent -s) + + ## + ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store + ## We're using tr to fix line endings which makes ed25519 keys work + ## without extra base64 encoding. + ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556 + ## + - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null + + ## + ## Create the SSH directory and give it the right permissions + ## + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + + ## + ## Optionally, if you will be using any Git commands, set the user name and + ## and email. + ## + #- git config --global user.email "user@example.com" + #- git config --global user.name "User name" + ``` + + NOTE: **Note:** + The [`before_script`](../yaml/README.md#before-script) can be set globally + or per-job. + +1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys). + +1. As a final step, add the _public_ key from the one you created in the first + step to the services that you want to have an access to from within the build + environment. If you are accessing a private GitLab repository you need to add + it as a [deploy key](../../ssh/README.md#deploy-keys). That's it! You can now have access to private servers or repositories in your build environment. @@ -91,24 +113,93 @@ SSH key. You can generate the SSH key from the machine that GitLab Runner is installed on, and use that key for all projects that are run on this machine. -First, you need to login to the server that runs your jobs. +1. First, you need to login to the server that runs your jobs. + +1. Then from the terminal login as the `gitlab-runner` user: -Then from the terminal login as the `gitlab-runner` user and generate the SSH -key pair as described in the [SSH keys documentation](../../ssh/README.md). + ``` + sudo su - gitlab-runner + ``` -As a final step, add the _public_ key from the one you created earlier to the -services that you want to have an access to from within the build environment. -If you are accessing a private GitLab repository you need to add it as a -[deploy key](../../ssh/README.md#deploy-keys). +1. Generate the SSH key pair as described in the instructions to + [generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair). + **Do not** add a passphrase to the SSH key, or the `before_script` will + prompt for it. + +1. As a final step, add the _public_ key from the one you created earlier to the + services that you want to have an access to from within the build environment. + If you are accessing a private GitLab repository you need to add it as a + [deploy key](../../ssh/README.md#deploy-keys). Once done, try to login to the remote server in order to accept the fingerprint: ```bash -ssh <address-of-my-server> +ssh example.com +``` + +For accessing repositories on GitLab.com, you would use `git@gitlab.com`. + +## Verifying the SSH host keys + +It is a good practice to check the private server's own public key to make sure +you are not being targeted by a man-in-the-middle attack. In case anything +suspicious happens, you will notice it since the job would fail (the SSH +connection would fail if the public keys would not match). + +To find out the host keys of your server, run the `ssh-keyscan` command from a +trusted network (ideally, from the private server itself): + +```sh +## Use the domain name +ssh-keyscan example.com + +## Or use an IP +ssh-keyscan 1.2.3.4 ``` -For accessing repositories on GitLab.com, the `<address-of-my-server>` would be -`git@gitlab.com`. +Create a new [secret variable](../variables/README.md#secret-variables) with +`SSH_KNOWN_HOSTS` as "Key", and as a "Value" add the output of `ssh-keyscan`. + +NOTE: **Note:** +If you need to connect to multiple servers, all the server host keys +need to be collected in the **Value** of the variable, one key per line. + +TIP: **Tip:** +By using a secret variable instead of `ssh-keyscan` directly inside +`.gitlab-ci.yml`, it has the benefit that you don't have to change `.gitlab-ci.yml` +if the host domain name changes for some reason. Also, the values are predefined +by you, meaning that if the host keys suddenly change, the CI/CD job will fail, +and you'll know there's something wrong with the server or the network. + +Now that the `SSH_KNOWN_HOSTS` variable is created, in addition to the +[content of `.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor) +above, here's what more you need to add: + + ```yaml +before_script: + ## + ## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the + ## following two lines. + ## + - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts' + - chmod 644 ~/.ssh/known_hosts + + ## + ## Alternatively, use ssh-keyscan to scan the keys of your private server. + ## Replace example.com with your private server's domain name. Repeat that + ## command if you have more than one server to connect to. + ## + #- ssh-keyscan example.com >> ~/.ssh/known_hosts + #- chmod 644 ~/.ssh/known_hosts + + ## + ## You can optionally disable host key checking. Be aware that by adding that + ## you are suspectible to man-in-the-middle attacks. + ## WARNING: Use this only with the Docker executor, if you use it with shell + ## you will overwrite your user's SSH config. + ## + #- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config' +``` ## Example project @@ -119,6 +210,4 @@ that runs on [GitLab.com](https://gitlab.com) using our publicly available Want to hack on it? Simply fork it, commit and push your changes. Within a few moments the changes will be picked by a public runner and the job will begin. -[ssh-keygen]: http://linux.die.net/man/1/ssh-keygen -[ssh-agent]: http://linux.die.net/man/1/ssh-agent [ssh-example-repo]: https://gitlab.com/gitlab-examples/ssh-private-key/ |