背景
SSHして何かやる定形/不定形業務を廃止するのは、なかなか困難が伴います。
- SSH接続を許可するか許可しないか、くらいしかできない
- いやまあ、Linux側でがんばってユーザー/グループを組めばいいんですけど
- 極少数のメンバーしか、保安上の理由から、許可できない
- 極少数のメンバーは、能力高しで多忙なのに、たいしたことないSSH作業に忙殺される
以前は、SSH定形業務をJenkinsジョブとして形式知化していましたが、
- JenkinsのEC2インスタンスが
- SPOFとなる。単純に台数を増やせばいいものでもない。
- 闇のダンジョンとなりがち
- だからといって、今からJenkinsfileとかすごく頑張るのは、あまりに低い山の頂上を目指しているのではないか
- Jenkinsおじさんの雇用が生まれてしまう
など問題がありました。このうち一部の問題について、CodeBuildジョブにすることで上手く扱えそうな感触が得られたので、まとめます。
ちなみに、ユニットテストやデプロイの類は、CircleCIやCodeBuildに移植済みで、Jenkinsには本当に「ポチるとSSHして何かするジョブ」だけが残っています。
作る
CodeBuildからEC2にSSHで何かさせてみます。
EC2 SSH Keypair、EC2インスタンスを作り、SSHできることを確認する
これは何も躓くところ無いですね。Keypair名は「hoge」で作ります。hoge.pemがダウンロードできてるものとして記述します。お手元から接続できることまで確認してください。
EC2 SSH KeypairのSSH秘密鍵をSSMパラメータストアに保管する
先程のSSH秘密鍵をSSMパラメータストアに暗号化保管します。
https://console.aws.amazon.com/systems-manager/parameters でパラメータの作成して、
先程のSSH秘密鍵をまるっとコピーして、
cat hoge.pem | pbcopy
AWS System Managerのパラメータストアの「値」にベタッとして、暗号化保管するので「安全な文字列」で、パラメータの作成。
AWSのEC2 SSH Keypairで作成した鍵なら1700文字くらいなので大丈夫ですが、手元のsshコマンドで生成した場合は、SSH秘密鍵の文字数に注意してください。4096文字までです。
CodeBuildジョブを作る
ジョブの組み立ては以下を参考に。ところかまわずSSHできるのはマズいでしょうから、VPC内でCodeBuildが起動するよう組むのが望ましいかと思います。
ポイントは以下。
- CodeBuildの環境変数で、プレーンテキストではなくパラメータとして、SSMパラメータストアから読むようにする
- 作例では、CodeBuildの環境変数「SSH_PRIV_KEY」に、SSMパラメータストアの「ssh_private_key」を読み込ませています
- CodeBuildジョブに付けるIAMロールに、SSMパラメータストアを読む権限を付けてあげる
- sshコマンドをインストール済みのコンテナを使うと面倒が少ないです。たとえば https://hub.docker.com/r/ansible/ansible-runner とか。
buildspec.yaml は以下のように。sshコマンドで、初回アクセス時の(yes/no?)に答えようがないので抑止したりしてます。
version: 0.2
phases:
pre_build:
commands:
- mkdir ~/.ssh
- echo "${SSH_PRIV_KEY}" > ~/.ssh/id_rsa
- chmod 0700 ~/.ssh
- chmod 0600 ~/.ssh/id_rsa
build:
commands:
- ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ec2-user@172.16.0.6 -p 22 "pwd;ls -alF;hostname"
見てのとおりで、buildspec.yaml でシェル芸を極めたコマンドラインをsshに流し込むのはまあまあ大変です。
接続先のEC2内にシェルスクリプトの類を設置して、CodeBuildはそれを呼ぶだけにするのが良いんじゃないかと思っています。
そのシェルスクリプトは、AnsibleのGitHubリポジトリか、アプリケーションコードのGitHubリポジトリのどちらかで管理して。など。
CodeBuildの権限制御をどうするか
SSHに比べると、いくらか制御しやすいんじゃないでしょうか。
Jenkinsなら Jenkinsでユーザーに権限を付与してアクションを制限する - Qiita の手法で権限制御できました。
AWS なら、
- IAMで権限制御する
- IAMグループを作成し、どのIAMグループは、CodeBuildジョブ定義を作成/編集/削除できる、実行/中断できる、などを構成する
- 誰が、いつ、どのジョブに、何をしたか、の
- 雑なトラッキングは、CodeBuildのジョブのログで見る
- 詳細なトラッキングは、AWS CloudTrailでやる
SSHの不定形業務はどうすんの
不定形だと思ってる業務も、Excel手順書(w)に書き出して、何度かやれば、これが定形業務で、ここは人間による条件分岐判断があって、その先は定形業務で、などと見えてくるはずなので、定形業務の部分をCodeBuildに切り出していくといいんじゃないですかね。
SSMセッションマネージャーもあるじゃん
これとかですね。非常に良いと思っていて、技術指針に従って、どちらでも使ったらいいのではないかと。