Open24

セッションマネージャでshellログインしたときにslack通知するやつ手元メモ

inomotoinomoto

AWSネタなのでやはりクラメソブログには記事がある
https://dev.classmethod.jp/articles/ssm-sessionmanager-notification/

Chatbotでいい感じにできないとかCloudtrail経由でとか書いてあるが、今どうなのか知りたいので試す。

また最近Chatbotの通知カスタムがサポートされたとか見たので、ついでにそっちも試したい。
https://dev.classmethod.jp/articles/aws-chatbot-custom-notification/

inomotoinomoto

まずはサンプル用にEC2を生やす。

雑にセッションマネージャで入れるための雑な起動テンプレートを持っていたのだが、最終更新が2021-06-13と古すぎる。せっかくだし作り直すか。

inomotoinomoto

適当に新規作成から

  • AmazonLinux 2023 (arm) 適当に最新のやつ
    • もう2023とかになってたのか...時代...
    • armにしたのはインスタンスタイプを最新にしたかったから
  • t4g.nanoを指定
  • IAMロールは AmazonSSMManagedInstanceCore だけ指定したやつ
  • ユーザデータのスクリプトに下記を指定
    • 前に使ってたやつをそのまま持ってきた。動くかな...?
#!/bin/bash

passwd -d ec2-user

sed -i /etc/ssh/sshd_config -e 's/^#PermitEmptyPasswords.*$/PermitEmptyPasswords yes/g'
sed -i /etc/ssh/sshd_config -e 's/^PasswordAuthentication no$/#PasswordAuthentication no/g'
sed -i /etc/ssh/sshd_config -e 's/^UsePAM yes$/#UsePAM yes/g'
systemctl reload sshd
inomotoinomoto

いやsshの設定のやつ入れたけど、別に令和の時代に手元からsshコマンドでsshしないな。別にマネコンから 接続 のやつでいいわ。

inomotoinomoto

手元にセッションマネージャのssh設定がなかったのでsshは試してない。が、この設定で起動はしたし、マネコンから接続で入れた。

あと sudo systemctl status sshd しても特に怪しげなログはないので、多分sshの方も大丈夫じゃないかな。

inomotoinomoto

EventBrdigeのルールを作っていく。

2023/10/30現在でも、EventBridgeネイティブ?でセッションマネージャのイベントを直接取ることはできないっぽい。
AWS API Call via CloudTrailをとることになりそう。

inomotoinomoto

EventBridgeって直接Chatbotに配信できないのか。そのためSNSトピックを経由しないといけないのも変わってない。
適当にトピックを生やして割り当てる。

inomotoinomoto

思考を止めて最速でトピックを生やしたところ、FIFOになってしまったが、EventBridgeのターゲットにFIFOはサポートされていないとのことだった。
スタンダードで作り直す。

inomotoinomoto

ちなみにCloudtrailの事前準備が必要なのかはわからない。使っているアカウントはなんらか有効にはなっている?からか、特に何もせずとも使えた。

inomotoinomoto

イベントタイプはこれ

{
  "source": ["aws.ssm"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["ssm.amazonaws.com"],
    "eventName": ["StartSession", "ResumeSession", "TerminateSession"]
  }
}

冒頭にあげたクラメソの記事と結局同じ。

inomotoinomoto

ChatBotのチャンネルを適当に作る。

なんか昔にテストしていたのが残っていたので、そこに今回のSNSトピックを足すことにした。
設定をあんま覚えていないけど、多分特別なことはしてない。

inomotoinomoto

EC2画面にもどり 接続 してみたところ、なんかきた。

inomotoinomoto

あとは通知をカスタムしてみる。

inomotoinomoto

EventBridge側で入力トランスフォーマーでゴニョゴニョすればいいらしい。
が、そもそもオリジナルのイベントのデータ構造がわからん。

調べればわかるのかもだけど、めんどくさいのでイベントのターゲットにcwlogsを足す。

inomotoinomoto

想定通り、ログのjsonが出てきた。マスクがめんどうなので貼らない。

inomotoinomoto

入力トランスフォーマー

入力パス

{
  "user": "$.detail.userIdentity.arn",
  "target": "$.detail.requestParameters.target",
  "event": "$.detail.eventName"
}

テンプレート

{
    "version": "1.0",
    "source": "custom",
    "content": {
        "title": "セッションマネージャが利用されました: <event>",
        "description": "ユーザ: <user>\nターゲット: <target>"
    }
}

テンプレートに指定するスキーマのドキュメント https://docs.aws.amazon.com/chatbot/latest/adminguide/custom-notifs.html

inomotoinomoto

トランスフォーマー設定画面にてcwlogsのログを実際に貼り付けて出力テストしたところ、TerminateSessionの場合に $.detail.requestParameters.target が存在しないのが問題だったもよう。

消したら出た。

のだけど、それだとStartSessionの通知も出なかった理由にならんのだけどな。

inomotoinomoto

一応、EventBridgeルール側でStartSessionのみ受け付けるようにしたところ、意図通りに出た。

イベントパターン

{
  "source": ["aws.ssm"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["ssm.amazonaws.com"],
    "eventName": ["StartSession"]
  }
}

入力パスとテンプレートは↑のと同じ

slack

inomotoinomoto

そういや適当に入れた改行もちゃんとはいってる。よい。

inomotoinomoto

ちなみに、対象EC2に関する情報はインスタンスID ( i-xxxx みたいなやつ) しかとれない。Nameタグとかはここからは取れないので、取りたかったら諦めてlambdaにするしかない。

また(↓にも別途書いているが)分岐の類が全く使えないので、インスタンスIDとnameのマッピングを設定内に持つこともできない。

「どのインスタンスに入ったか」がぱっと見レベルで重要なユースケースには耐えないな。「なんかしらんけどログインしたっぽい」が分かれば十分(EC2が非常に少ないとか、頻度が非常に少ないとか、都度人間も周知するのでそれでわかるとか)であれば問題ないであろう。

inomotoinomoto

Chatbotのメッセージカスタムのやつだと、lambdaとかいらないので良い。

ただ分岐はできないので、今回だと「StartSessionの場合はターゲットを出す、Terminateでは出さない」とかはできない。
この場合でいえば、それぞれEventBridgeのルールを分けて作ることになろう。SNSトピックとかChatBotチャンネルは同じでいいかな。

inomotoinomoto

一応実験した。SNSトピックとChatBotチャンネルは同じで良かった。

一応、ミニマルかつぼちぼち使えそうな動いたテンプレを貼る

start側

入力パス

{
  "event": "$.detail.eventName",
  "sessionId": "$.detail.responseElements.sessionId",
  "target": "$.detail.requestParameters.target",
  "user": "$.detail.userIdentity.arn"
}

テンプレ

{
    "version": "1.0",
    "source": "custom",
    "content": {
        "title": "セッションマネージャが利用されました: <event>",
        "description": "ユーザ: <user>\nターゲット: <target>\nセッションID: <sessionId>"
    }
}

terminate側

入力パス

{
  "sessionId": "$.detail.requestParameters.sessionId",
  "user": "$.detail.userIdentity.arn"
}

テンプレ

{
    "version": "1.0",
    "source": "custom",
    "content": {
        "title": "セッションマネージャが終了しました :done:",
        "description": "ユーザ: <user>\nセッションID: <sessionId>"
    }
}
inomotoinomoto

あとResumeもあったほうがいいのかもしれん。それは実導入時にテストかな。