20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CircleCI から AWS VPC の private subnet に private repo を git clone

Last updated at Posted at 2016-01-30

この記事はCircleCI Advent Calendar 2015の7日目の為に考えていた記事です。

あまりに時間が立ってしまったので、元記事から切り離して再投稿。

やりたいこと

  1. AWS VPC上に組んだプライベートサブネット上に
  2. CircleCIからVagrantでインスタンスを生成して
  3. GitHubのプライベートリポジトリをクローンする

図にするとこう。

image

動機

インターネットむき出しじゃないインスタンスに対して、SSHの鍵をばら撒かずにデプロイしたい

前提知識

プライベートサブネット構成

以下の図のように、ユーザからのアクセスをELB経由に限定してアプリケーションサーバ自体は直接インターネットに接続できないプライベートサブネットに置く構成。

アプリケーションサーバを直接インターネットに晒したくない人向け。

ただ、全ての通信を遮断してしまうと、リリースもできない。時刻同期もできない。となってしまうので、そういった管理上必要な通信は別途用意するNATサーバ経由で行う。

image

プライベートサブネットに置かれたサーバからの通信は全てNAT経由になるので、
一枚目の画像についても正しくはこういうなる。
image

参考:classmethod - Amazon VPCでELBとNATを使ってよりセキュアな環境を作る【5日目】

2015年の年末にマネージドNATゲートウェイが新機能としてリリースされたので、今後NATサーバを別に立てる必要はないのかも。

本題

こちらのリポジトリにまとめました。内容そのままでプライベートリポジトリに変更してCircleCIでビルドすると動くと思います。
https://github.com/kotatsu360/private-repo-deploy-sample

サンプルでは、VagrantとChefを使っています。

その1:プライベートサブネットのインスタンスへアクセスするための記述

まず、プライベートサブネットに踏み台(NATサーバ)経由でアクセスしてやる必要があります。
重要なのは2箇所です。

pre.sh
echo "Host nat" >> ~/.ssh/config
echo "  Hostname ${AWS_NAT_SERVER_IP_ADDRESS}" >> ~/.ssh/config
echo "  User ec2-user" >> ~/.ssh/config
Vagrantfile
    override.ssh.username = "ubuntu"
    override.ssh.proxy_command = "ssh -A nat -W %h:%p"

ここでは、NATサーバがAmazonLinux, アプリケーションサーバがUbuntuの想定です。
まずpre.shの中でCircleCIの.ssh/configにNATの情報を書き込んでやります。

Vagrantでアクセスするときは、そのHostを使ってプロキシします。

また、この記事の範囲からは外れますが、pre.shはデプロイ前後で自分自身からのSSHを許可して、また閉じています。これは「普段はSSHを不許可、デプロイ時のみ許可」という運用をしたいためです。

※環境変数は最後に設定します

その2:プライベートリポジトリにへアクセスするための記述

Vagrantfile
  config.ssh.forward_agent = true
  # ...

    override.ssh.private_key_path = [ENV['GITHUB_CLONE_SSH_KEY_PATH'], ENV['AWS_LOGIN_SSH_KEY_PATH']]

default.rb
file "/etc/sudoers.d/root_ssh_agent" do
  mode 0440
  owner 'root'
  group 'root'
  content "Defaults env_keep += \"SSH_AUTH_SOCK\"\n"
end

bash "add ssh_setting to .ssh/config" do
  not_if %!grep Host github.com /root/.ssh/config!

  code <<-EOC
    echo -e "Host github.com\n StrictHostKeyChecking no\n" >> /root/.ssh/config
  EOC
end

override.ssh.private_key_path

VagrantでSSHのAgentForwardを有効にしています。
また、

  • GitHubへアクセスするための鍵
  • Chefがインスタンスへアクセスするための鍵

を指定しています。ここで指定した鍵がAgent Forwardで転送されます。

content "Defaults env_keep += "SSH_AUTH_SOCK"\n"

EC2インスタンスへSSHしているユーザはubuntu
Chefはrootで動作する。ここではrootへ引き継ぐ環境変数にssh-agentを追加

echo -e "Host github.com\n StrictHostKeyChecking no\n" >> /root/.ssh/config

GitHubからはsshでgit cloneする。git cloneするときにfingerprintの確認で止まるのを防ぐためにStrictHostKeyChecking noを追加

その3:CircleCI

最後にCircleCIの「Environment variables」で環境変数を設定してやります。

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
についてはCircleCIの「AWS Permission」から設定してもいいかも。
変数名 概要 サンプル
AWS_ACCESS_KEY_ID AWSのアクセスキー xxxxCIBA
AWS_DEFAULT_REGION AWS EC2のデフォルトリージョン xxxxst-2
AWS_DEPLOY_MACHINE_SECURITY_GROUP EC2インスタンスに割り当てるセキュリティグループ xxxx228c
AWS_DEPLOY_SUBNET EC2インスタンスを立てるサブネット xxxxbc2c
AWS_KEYPAIR AWSで作成するEC2インスタンスにSSHする時用keypair名 xxxxpair
AWS_LOGIN_SSH_KEY_PATH ※1
AWS_NAT_SECURITY_GROUP デプロイに使うNATのセキュリティグループ xxxx11db
AWS_NAT_SERVER_IP_ADDRESS デプロイに使うNATのEIP xxxx9.71
AWS_SECRET_ACCESS_KEY AWSのシークレットアクセスキー xxxx1muU
GITHUB_CLONE_SSH_KEY_PATH ※2

AWS_LOGIN_SSH_KEY_PATH

AWS_KEYPAIRで設定したkeypairの秘密鍵をCircleCIの「SSH Permission」からHostnameを空にして登録する。
スクリーンショット 2016-01-30 15.56.27.png

スクリーンショット 2016-01-30 15.56.54.png

Hostnameが空の場合、CircleCIはfingerprintに従って鍵を作成するので、そのパスを指定する。

~/.ssh/id_xxxxxxxxxxxx3044

GITHUB_CLONE_SSH_KEY_PATH

CircleCIに一度SSHする。~/.ssh/id_github.comという鍵(CircleCIがリポジトリをCheckoutするための鍵, GitHubでいうDeployKey)があるのでこれの中身を「SSH Permission」にHostname=github.comで登録する。

スクリーンショット 2016-01-30 16.14.15.png

スクリーンショット 2016-01-30 16.14.59.png

Hostnameが空でない場合、CircleCIはHostnameに従って鍵を作成するので、そのパスを指定する。

~/.ssh/id_github.com

制約

https://github.com/kotatsu360/private-repo-deploy-sample
このリポジトリのやり方だと、毎回Vagrantで新しいインスタンスを立ててしまうので
古いインスタンスは削除されるようにdeploy.shで設定しています。

EC2インスタンスの中にデータを入れておくと漏れ無く消えます。

振り返ってみて

「GitHubからクローンしたいリポジトリ」 = 「CircleCIでテストしているリポジトリ」の場合、シンプルにSCPで送るという手段もあったような。。

参考

怠け者のためのVagrant+Chef入門 - Qiita
CircleCIからサーバへのSSH接続確立時間を高速化する

20
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?