GitLab CI/CDでSSHキーを使う

GitLabには現在、ビルド環境(GitLab Runnerが動作する環境)でSSHキーを管理するためのビルトインサポートがありません。

SSHキーを使いたいときに使ってください:

  • 内部サブモジュールのチェックアウト。
  • パッケージマネージャを使って非公開パッケージをダウンロードします。例えば、Bundler。
  • アプリケーションを自分のサーバーやHerokuなどにデプロイします。
  • ビルド環境からリモートサーバーにSSHコマンドを実行します。
  • ビルド環境からリモートサーバーへのファイルのRsync。

上記に心当たりがある場合は、SSHキーが必要な可能性が高いです。

最も広くサポートされている方法は、.gitlab-ci.yml を拡張することで、ビルド環境にSSHキーを注入することです。これはどんなタイプのExecutor(例えばDockerやShellなど)でも動作するソリューションです。

どのように動作するか

  1. で新しいSSHキー・ペアをローカルに作成します。ssh-keygen
  2. 秘密鍵をファイルタイプのCI/CD変数としてプロジェクトに追加します。
  3. ssh-agent during jobを実行して秘密鍵をロードします。
  4. 公開鍵をアクセスしたいサーバーにコピーするか(通常は~/.ssh/authorized_keys )、非公開の GitLab リポジトリにアクセスする場合はデプロイ鍵として追加します。

以下の例では、ssh-add - コマンドは$SSH_PRIVATE_KEY の値をジョブログに表示しませんが、デバッグログを有効にすれば表示される可能性があります。パイプラインの可視性も確認しておきましょう。

Dockerエクゼキュータ使用時のSSHキー

CI/CDジョブがDockerコンテナ内で実行され(環境が封じ込められていることを意味します)、コードを非公開サーバにデプロイしたい場合、それにアクセスする方法が必要です。この場合、SSHキーペアを使うことができます。

  1. まずSSHキーペアを作成する必要があります。詳しくは、SSHキーを生成する手順を参照してください。SSH キーにパスフレーズを追加しないでください。before_script がパスフレーズを要求します。

  2. 新しいファイルタイプのCI/CD変数を作成します。Keyとして SSH_PRIVATE_KEY という名前を入力し、Valueフィールドに先ほど作成した_秘密_鍵の内容を貼り付けます。

  3. before_script アクションで.gitlab-ci.yml を変更します。以下の例では Debian ベースのイメージを想定しています。必要に応じて編集してください:

    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)
      ##
      - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
       
      ##
      ## Run ssh-agent (inside the build environment)
      ##
      - eval $(ssh-agent -s)
       
      ##
      ## Give the right permissions, otherwise ssh-add will refuse to add files
      ## Add the SSH key stored in SSH_PRIVATE_KEY file type CI/CD variable to the agent store
      ##
      - chmod 400 "$SSH_PRIVATE_KEY"
      - ssh-add "$SSH_PRIVATE_KEY"
       
      ##
      ## 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"
    

    before_script はデフォルトまたはジョブごとに設定できます。

  4. 非公開サーバーのSSHホスト鍵が検証されていることを確認してください。

  5. 最後のステップとして、最初のステップで作成した_公開_鍵をビルド環境内からアクセスしたいサービスに追加します。GitLab の非公開リポジトリにアクセスする場合は、それをデプロイ鍵として追加する必要があります。

これで完了です!これで、ビルド環境で非公開サーバーやリポジトリにアクセスできるようになりました。

Shellエクゼキュータ使用時のSSHキー

DockerではなくShell Executorを使う場合は、SSHキーを設定する方が簡単です。

GitLab RunnerがインストールされているマシンからSSHキーを生成し、このマシンで実行されるすべてのプロジェクトにそのキーを使うことができます。

  1. まず、ジョブを実行するサーバーにサインインします。

  2. 次に、ターミナルからgitlab-runner ユーザーとしてサインインします:

    sudo su - gitlab-runner
    
  3. SSHキーを生成する手順に従って、SSHキーペアを生成します。SSH キーにパスフレーズを追加しないでください。before_script がパスフレーズを要求します。

  4. 最後のステップとして、先ほど作成した_公開_鍵をビルド環境からアクセスしたいサービスに追加します。GitLab の非公開リポジトリにアクセスする場合は、デプロイ鍵として追加する必要があります。

鍵を生成したら、リモートサーバーにサインインしてフィンガープリントを受け取ります:

ssh example.com

GitLab.com のリポジトリにアクセスするには、git@gitlab.com を使います。

SSH ホストキーの検証

中間者攻撃(man-in-the-middle attack)に狙われていないことを確認するために、非公開サーバ自身の秘密鍵を確認するのは良い習慣です。もし何か不審なことが起きたら、ジョブが失敗するのでそれに気づくでしょう(公開キーが一致しないとSSH接続は失敗します)。

サーバーのホスト鍵を調べるには、信頼できるネットワークから(理想的には非公開サーバー自身から)ssh-keyscan コマンドを実行します:

## Use the domain name
ssh-keyscan example.com

## Or use an IP
ssh-keyscan 10.0.2.2

新しいファイルタイプのCI/CD変数を作成し、SSH_KNOWN_HOSTS を “Key “とし、ssh-keyscan の出力を “Value “として追加します。

複数のサーバーに接続する必要がある場合は、すべてのサーバーのホスト・キーを1行に1つずつ、変数のValueに集めなければなりません。

note
内部で直接ssh-keyscan ssh-keyscanssh-keyscan代わりにファイル型のCI/CD変数を使用することで、何らかの理由でホストドメイン名が変更されてもssh-keyscan変更する必要がないという利点が ssh-keyscanあります。また、値はあらかじめ定義されているので、ホストキーが突然変わってもCI/CDジョブが失敗することはありません。

SSH_KNOWN_HOSTS 変数が作成されたので、上記の.gitlab-ci.yml](#ssh-keys-when-using-the-docker-executor) の[の内容に加えて、 を追加してください:

before_script:
  ##
  ## Assuming you created the SSH_KNOWN_HOSTS file type CI/CD variable, uncomment the
  ## following two lines.
  ##
  - cp "$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 susceptible 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'

プロジェクトの例

GitLab.comで公開されている共有Runnerを使ったSSHプロジェクトの例を用意しました。

ハックしたいですか?フォークしてコミットし、変更をプッシュしてください。数瞬で公開 Runner によって変更が選択され、ジョブが開始されます。