Take a “new step” Achieved by Value Engineering tech.digitalexperience.co.jp

Teamsからセキュリティグループの設定を一括変更したい

こんにちは。SREの井上です

Teamsからセキュリティグループの設定を一括変更できるようにしてみました。

目次

ざっくりと構成図

仕組みとしては

1.TeamsでAWS Systems Managerコマンドを実行する
2.Amazon Q Developer in chat applicationsが走る
3.Amazon Q Developer in chat applicationsがAWS Systems ManagerのDocument(※1)を基にRunCommandを走らせる

※1 AWS Systems ManagerのDocumentには、「指定したEC2インスタンスに置いてある.shファイル(※2)を実行する」という設定がされている。
※2 .shファイルにはセキュリティグループ変更関連のスクリプトが記載されている。

という感じです。

主に使用しているツール

AWS

●Amazon Q Developer in chat applications (旧称: AWS Chatbot)
 ⇒名称が長いのでこの先はChatbotと記述します。

●EC2インスタンス

●AWS Systems Manager:Document、RunCommand
 ⇒名称が長いのでこの先はSSMと記述します。

●IAMロール、ポリシー

AWS外

●Teams(Slackでもできると思います)
 

できること

セキュリティグループに設定されている特定のIPアドレスを一括変更
使用例:1.1.1.1というIPアドレスを2.2.2.2に上書きしたい場合
※変更前のIPアドレス(上記だと1.1.1.1)を失念した場合、このツールは使えない

できないこと

既存セキュリティグループへのIPアドレス新規追加
理由:セキュリティグループのIDを指定する必要があるため、SRE以外には管理が難しい

ALBリスナールールで設定されているIPアドレスの変更
理由:なんとなく実装はできそうだが管理が煩雑になる気がする

セキュリティグループに設定されている特定のIPアドレスを0.0.0.0/0へ変更、及び0.0.0.0/0からの変更、もしくは会社IP関連の変更
理由:一歩間違えると重大インシデントになりかねないため

作ってみよう

1.事前準備

AWS CLI v2入りのEC2インスタンスを用意し、SSMが使えるようにしておく必要があります。
SSMの設定に関しては公式ドキュメントを参考にしてください。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-setting-up-ec2.html

同じEC2インスタンスの適当な場所に、以下リポジトリにある.shファイルをアップしてください。実行権限はec2-userを想定して進めます。
https://github.com/sp-inoue/shellscript-sg

.shファイルについてちょっと説明

SSMコマンド実行時に引数として変更前のIPを入力します(使用方法は後述します)。その変更前のIPが設定上あるかどうか、をまずは確認しています。
あったら当該のセキュリティグループに設定されている変更前のIPを変更後のIPに変更、なかったらエラーを返すようにしています。
Port、Descriptionの設定内容は引き継がれます。


2.IAMポリシーの作成

ポリシーは4つ作成します。それぞれのポリシーに設定しているjsonの中身を以下に記載します。

ポリシー①:Chatbotチャネルのガイドラインに付与するポリシー


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:Describe*",
                "cloudwatch:Get*",
                "cloudwatch:List*",
                "logs:PutLogEvents",
                "logs:CreateLogStream",
                "logs:CreateLogGroup"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:SendCommand",
                "ssm:GetCommandInvocation",
                "ssm:ListCommandInvocations"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "arn:aws:iam::アカウントID:role/後述する「ロール①」
        }
    ]
}

ポリシー②:後述する「ロール①」に付与するためのポリシー


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:SendCommand",
                "ssm:GetCommandInvocation",
                "ssm:ListCommandInvocations"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::アカウントID:role/後述する「ロール①」",
            ]
        }
    ]
}

ポリシー③:Chatbotのチャネルロールとユーザーロールに設定するためのポリシー


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": [
                "arn:aws:iam::アカウントID:role/後述する「ロール①」",
            ]
        }
    ]
}

ポリシー④:後述するIAMロール①とロール②共通設定
※アカウント内全てのEC2インスタンスに対する許可設定が入っていますが、必要に応じてインスタンスIDを指定してください。


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:SendCommand",
                "ssm:GetCommandInvocation",
                "ssm:ListCommandInvocations",
                "ssm:DescribeDocument",
                "ssm:ListDocuments",
                "ssm:DescribeInstanceInformation"
            ],
            "Resource": [
                "arn:aws:ssm:ap-northeast-1:アカウントID:document/この後作成するSSMドキュメント名",
                "arn:aws:ec2:ap-northeast-1:アカウントID:instance/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": [
                "arn:aws:iam::アカウントID:role/後述する「ロール①」",
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*"
            ],
            "Resource": "*"
        }
    ]
}

3.IAMロールの作成

IAMロールは2つ作成します。
ロール①:Teamsからssmコマンドを実行する為のロール
先程作成した「ポリシー②」と「ポリシー④」と、AWS管理の以下ポリシーをアタッチ

AmazonSSMFullAccess
AmazonSSMManagedInstanceCore
AWSResourceExplorerReadOnlyAccess

ロール②:AmazonQを使用する為のロール、Chatbotのチャネルロールとユーザーロールに設定する
先程作成した「ポリシー③」と「ポリシー④」をアタッチ


4.Chatbot(Amazon Q Developer in chat applications)とTeamsの紐づけ

AWSコンソールにてAmazon Q Developer in chat applicationsを開き、チャットクライアントをTeamsに設定します。

 
 
 
使用したいTeamsのチャネルアドレスを貼付します。

 
 
 
設定すると左メニューにチャネル名が表示されるので、そこから詳細画面へ移り、新しいチャネルを設定に移ります。

 
 
 
設定名やチャネルURLは適切なものを入力してください。
ロール設定のチャネルロールにて「既存のIAMロールを使用する」を選択し、先程作成した「ロール②」を指定します。
チャネルガードレールポリシーには先程作成した「ポリシー①」を指定して、ここでの設定は終わりです。


5.SSMドキュメントの作成

AWSコンソールにてSystemsManager>ドキュメントに移ります。
ドキュメントの作成>コマンドまたはセッションを選択します。

ターゲットタイプを「/AWS::EC2::Instance」とし、コンテンツはJSONを指定して以下のJSONを入力します。


{
  "schemaVersion": "2.2",
  "description": "Command Document Example JSON Template",
  "parameters": {
    "OLDIP": {
      "type": "String",
      "description": "Previous IP address",
      "default": "hoge"
    },
    "NEWIP": {
      "type": "String",
      "description": "New IP address",
      "default": "hoge"
    }
  },
  "mainSteps": [
    {
      "action": "aws:runShellScript",
      "name": "example",
      "inputs": {
        "runCommand": [
          "cd /home/ec2-user", #.shファイルををアップロードしたファイルパス
          "./ip_address_change.sh {{OLDIP}}/32 {{NEWIP}}/32"
        ]
      }
    }
  ]
}

今回はCIDRを/32で固定していますが、必要に応じて修正してください。

使ってみよう

設定ができたので動作確認します。

Chatbotと紐づけをしたTeamsのチャネルにて、@Amazon Qにメンションを付け、以下のコマンドを実行します。
変数の値は適宜ご変更ください。

ssm send-command --targets Key=InstanceIds,Values=インスタンスID --document-name 作成したドキュメント名 --cloud-watch-output-config CloudWatchOutputEnabled=true,CloudWatchLogGroupName="ログを出力するファイル" --parameters OLDIP=変更前IP,NEWIP=変更後IP --region ap-northeast-1

実際に使ってみるとこんな感じ

 
 
ログが不要の場合は以下の部分を除いて実行してください。

-cloud-watch-output-config CloudWatchOutputEnabled=true,CloudWatchLogGroupName="ログを出力するファイル"

 
コマンドの実行に成功したか失敗したかはSSMのRunCommandから確認できます。先程のキャプチャ赤枠部分にあるコマンドIDを控えておくと探しやすいです。

成功するとこんな感じ

上記のインスタンスIDを選択すると詳細を見ることができます。
成功した場合、変更されたセキュリティグループのIDがOutputに表示されます。

ちなみに失敗するとこんな感じ

インスタンスIDから出力先の詳細にいくと、Outputに失敗した理由が出力されています。
今回は変更前IPが設定上存在しなかったため、失敗となりました。
 
以下のパターンに該当すると失敗します。
●変更前IPが設定上存在しない場合
●0.0.0.0を変更前、変更後IPとして設定した場合
●会社の固定IPを変更前、変更後IPとして設定した場合

今後の課題

実はコマンドが成功したか失敗したかの確認が現状だとSSMのRunCommandでしかできません…。
CloudWatchLogsと紐づけるとSNS通知ができるっぽいので絶賛実装中です。できたら追記したいと思います。

参考にさせていただいたサイト

関連カテゴリ 最新記事一覧