GitLab CI/CDでSSHキーを使う
GitLabは現在、ビルド環境(GitLab Runnerが実行される環境)でのSSHキーの管理をビルトインでサポートしていません。
SSHキーは次のような場合に役立ちます:
- 内部サブモジュールをチェックアウトしたい場合
- パッケージマネージャー(Bundlerなど)を使って非公開パッケージをダウンロードしたい場合
- アプリケーションを自分のサーバーや、例えばHerokuにデプロイしたい場合
- ビルド環境からリモートサーバーにSSHコマンドを実行したい場合
- ビルド環境からリモートサーバーにファイルをrsyncしたい場合
上記に心当たりのある方は、SSHキーが必要な可能性が高いです。
最も広くサポートされている方法は、.gitlab-ci.yml
を拡張することで、SSHキーをビルド環境に注入することです。これは、どのタイプのexecutor(Docker、shellなど)でも動作するソリューションです。
どのように動作するか
- でローカルに新しいSSHキーペアを作成します。
ssh-keygen
- プロジェクトに秘密鍵を変数として追加します。
-
ssh-agent
をジョブ中に実行し、秘密鍵をロードします。 - 公開鍵をアクセスしたいサーバーにコピーするか(通常は
~/.ssh/authorized_keys
)、非公開の GitLab リポジトリにアクセスする場合はデプロイ鍵として追加します。
Docker executor使用時のSSHキー
CI/CDジョブがDockerコンテナ内で実行され(つまり環境が封じ込められている)、コードを非公開サーバにデプロイしたい場合、それにアクセスする方法が必要です。 そこでSSHキーペアが役に立ちます。
-
まず、SSH キーペアを作成する必要があります。詳しくは、SSH キーを生成する手順に従ってください。 SSH キーにパスフレーズを追加しないでください。さもないと、
before_script
がパスフレーズの入力を要求します。 -
新しい変数を作成します。Keyとして
SSH_PRIVATE_KEY
と入力し、Valueフィールドに先ほど作成した秘密_鍵の_内容を貼り付けます。 -
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) ## - '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 - ## ## 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
before_script
はグローバルまたはジョブごとに設定できます。 -
非公開サーバーのSSHホスト鍵が検証されていることを確認してください。
-
最後のステップとして、最初のステップで作成した_公開_鍵を、ビルド環境内からアクセスしたいサービスに追加します。 GitLabの非公開リポジトリにアクセスする場合は、デプロイ鍵として追加する必要があります。
これでビルド環境で非公開サーバーやリポジトリにアクセスできるようになりました。
SSHキー(executor使用時
DockerではなくShell executorを使う場合は、SSHキーを設定する方が簡単です。
GitLab RunnerがインストールされているマシンからSSHキーを生成し、このマシンで実行されるすべてのプロジェクトにそのキーを使うことができます。
-
まず、ジョブを実行するサーバーにログインしてください。
-
次に、ターミナルから
gitlab-runner
ユーザーとしてログインします:sudo su - gitlab-runner
-
SSHキーを生成する手順の説明に従って、SSH キーペアを生成します。 SSH キーにパスフレーズを追加しないでください。さもないと、
before_script
がパスフレーズを要求します。 -
最後のステップとして、先ほど作成した_公開_鍵をビルド環境からアクセスしたいサービスに追加します。 GitLabの非公開リポジトリにアクセスする場合は、デプロイ鍵として追加する必要があります。
完了したら、フィンガープリントを受け入れるためにリモートサーバーへのログインを試みます:
ssh example.com
GitLab.com のリポジトリにアクセスするには、git@gitlab.com
を使います。
SSHホストキーの検証
中間者攻撃に狙われていないことを確認するために、非公開サーバー自身の公開鍵をチェックするのは良い習慣です。 不審なことが起きた場合、ジョブが失敗する(公開鍵が一致しないとSSH接続が失敗する)ので、それに気づくでしょう。
サーバーのホスト鍵を調べるには、信頼できるネットワークから(理想的には非公開サーバー自体から)ssh-keyscan
コマンドを実行します:
## Use the domain name
ssh-keyscan example.com
## Or use an IP
ssh-keyscan 1.2.3.4
新しい変数を作成し、SSH_KNOWN_HOSTS
を “キー “とし、ssh-keyscan
の出力を “値 “として追加します。
ssh-keyscan
の内部で直接変数を使用する代わりにssh-keyscan
、 ssh-keyscan
変数を使用することで、ホストドメイン名が何らかの理由で変更された場合に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 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 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で公開されている共有ランナーを使ったSSHプロジェクトの例を用意しました。
ハックしたいのであれば、フォークしてコミットし、変更をプッシュするだけです。 数瞬のうちに公開ランナーによって変更が選択され、ジョブが開始されます。