見出し画像

System Managerを使ってCircleCIでEC2のセキュリティGを動的に変更してみる

はじめに

こんにちは、自動化アーキテクトの森川です。

本日はCircleCIのパイプラインに関するTipsです。

やりたいこと

CircleCIのクラウド環境でE2Eテストをまわすとき、VMからテスト対象へのアクセスが必要となります。

開発環境にIPアドレス制限がかかっていることは「あるある」です。

IPホワイトリストのオプション契約をしていれば万事解決ですが、POCフェイズではそのようなリッチな環境は望めません。

CircleCIで開示されているIPアドレスリストを使うのはセキュリティ的に難しい場合もあるでしょう。

IP アドレスの範囲 - CircleCI

Note: Jobs can use any of the address ranges above. また、このアドレス リストは、本機能を有効化しているすべての CircleCI ユーザーと共有されることに注意してください。

そこで、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をふりだす、というプラクティスが推奨されているようです。

AWS CLI を使用して 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 & 自動テストライフを!


執筆者プロフィール:森川 知雄
中堅SIerでテスト管理と業務ツール、テスト自動化ツール開発を10数年経験。
SHIFTでは、GUIテストの自動化ツールRacine(ラシーヌ)の開発を担当。
GUIテストに限らず、なんでも自動化することを好むが、ルンバが掃除しているところを眺めるのは好まないタイプ。
さまざま案件で自動化、効率化によるお客様への価値創出を日々模索している。
2021年からは技術イベントSHIFT EVOLVEの運営を主担当。好きな食べ物、第2位はペンネ・リガーテ

お問合せはお気軽に
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/