System Managerを使ってCircleCIでEC2のセキュリティGを動的に変更してみる
はじめに
こんにちは、自動化アーキテクトの森川です。
本日はCircleCIのパイプラインに関するTipsです。
やりたいこと
CircleCIのクラウド環境でE2Eテストをまわすとき、VMからテスト対象へのアクセスが必要となります。
開発環境にIPアドレス制限がかかっていることは「あるある」です。
IPホワイトリストのオプション契約をしていれば万事解決ですが、POCフェイズではそのようなリッチな環境は望めません。
CircleCIで開示されているIPアドレスリストを使うのはセキュリティ的に難しい場合もあるでしょう。
そこで、EC2のセキュリティグループで許可するIPアドレスを動的に変える方法を試してみます。
理由は後述しますが、この手法は非推奨です。プラクティスではなく一つの試行としていただけると幸いです。
使ったもの
CI: CircieCI
テスト対象アプリ: AWS EC2
IAM Role: テスト実行用
IAM ユーザ: System Manager用
IAM RoleをSystem Managerでふりだす
IAMのアカウント情報はCircleCIの環境変数に登録しますが、テスト実行のためのリソースへのアクセスポリシーを持ったIAMを設定するのはセキュリテイ的によろしくない気がします。
そこで、CircleCIにはAWSのSystem Managerのみに絞ったIAMを登録しておき、これを用いてパイプライン上でテスト実行のTokenつきIAMをふりだす、というプラクティスが推奨されているようです。
こんなイメージでしょうか。
準備するIAMリソースは2つです。
System ManagerでIAMロールをふりだすためのIAMユーザ
テスト実行のためのリソース操作ポリシーがつけられたIAMロール
作成手順については下記の記事にならいました。
CloudFormationから作成する手順を紹介されているので大変参考になります。
参考: CircleCIで AWS CLI v2 を使ってみた | DevelopersIO
お試しの際は片付け上手のCloudFormationが良いですよね。
EC2のセキュリティグループを動的に変更
こちらも先人がすでにいくつも良い記事をあげてくださっていました。
EC2のセキュリティ設定変更にはAWS CLIのOrbsとしてcircleci/aws-cli@3.1.1を用います。
steps:
- aws-cli/install
- run:
name: authorize-security-group-ingress
command: |
IP=`curl -s ifconfig.me`
echo "#!/bin/bash" > ./sg.sh
echo "aws configure set region ${AWS_DEFAULT_REGION}" >> ./sg.sh
echo "aws ec2 authorize-security-group-ingress --group-id $EC2_SECURITY_GROUP_ID \ 👈 これ
--ip-permissions IpProtocol=tcp,FromPort=80,ToPort=80, \
IpRanges='[{CidrIp=${IP}/32,Description="circleci-vm"}]'" >> ./sg.sh
bash ./sg.sh
これでセキュリティグループにインバウンドのIPアドレス許可を追加できます。
セキュリティグループIDは事前に取得して環境変数に登録しています。
削除するときはAPIをrevoke-security-group-ingressにするだけです。
アクセスをテスト
steps:
- run:
name: access to sut
command: |
url=http://sut-web.xxx.com/
curl ${url}
EC2のテスト対象にcurlでアクセスします。
パイプライン
パイプライン全体はこんな感じになりました。
検証ということでセキュリティGの追加・削除を別のステップにしていますが、一緒にしても良いと思います。
# .circleci/config.yml
version: 2.1
executors:
my-executor:
docker:
- image: circleci/openjdk:11-jdk-buster-browsers
orbs:
aws-cli: circleci/aws-cli@1.3.2
commands:
update-sg:
steps:
- aws-cli/install
- run:
name: authorize-security-group-ingress
command: |
./assume_role.sh
source aws-env.sh
IP=`curl -s ifconfig.me`
echo "#!/bin/bash" > ./sg.sh
echo "aws configure set region ${AWS_DEFAULT_REGION}" >> ./sg.sh
echo "aws ec2 authorize-security-group-ingress --group-id $EC2_SECURITY_GROUP_ID \
--ip-permissions IpProtocol=tcp,FromPort=80,ToPort=80,IpRanges='[{CidrIp=${IP}/32,Description="circleci"}]'" >> ./sg.sh
bash ./sg.sh
access-sut:
steps:
- run:
name: access to sut
command: |
url=http://sut-web.xxx.com/
curl ${url}
remove-sg:
steps:
- aws-cli/install
- run:
name: revoke-security-group-ingress
command: |
./assume_role.sh
source aws-env.sh
IP=`curl -s ifconfig.me`
echo "#!/bin/bash" > ./sg.sh
echo "aws configure set region ${AWS_DEFAULT_REGION}" >> ./sg.sh
echo "aws ec2 revoke-security-group-ingress --group-id $EC2_SECURITY_GROUP_ID \
--ip-permissions IpProtocol=tcp,FromPort=80,ToPort=80,IpRanges='[{CidrIp=${IP}/32,Description=circleci}]'" >> ./sg.sh
bash ./sg.sh
jobs:
aws_access:
executor: my-executor
environment:
EC2_SECURITY_GROUP_ID : $SECURITY_GROUP_ID
steps:
- checkout
- update-sg
- access-sut
- remove-sg
workflows:
version: 2.1
aws-test-workflow:
jobs:
- aws_access:
filters:
branches:
only:
- main
動かしてみる
Successしています。
アクセスも無事にできています。
CloudTrailでログを確認
セキュリティGが本当に設定変更されているか気になりますよね。
CloudTrailで確認してみましょう。
ログに出力されていますね。
感想
テスト対象へのアクセスのためだけに、この手間をかけるのはやはりちょっと抵抗があります。
また数秒・数分とはいえFWに穴をあけることになりますので、セキュリティ的に問題がないことを証明するのは難しいため手法としては非推奨ですね。
CircleCIのSelf-Hosted-Runnerをテスト対象と同じVPCに立ててVPC内で成立させるほうがシンプルで安全だなぁ、と思ったときにはこの記事をほぼ書き終えていました。
CircleCI セルフホストランナーの概要 - CircleCI
一方でAWSのAPIを経由してインフラ設定をパイプライン上で自在に変更することが実現可能であることは伺えたと思います。CI/CD基盤の設計時には積極的に取り入れたいものです。
それではみなさん、楽しいCI/CD & 自動テストライフを!
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/