はじめに
IBM Cloud CodeEngineを利用してCISの送信元IPアドレス変更を定期的にメール通知する方法を紹介します。
コンテナ実行環境サービスであるサーバーレスCode Engineのジョブを用いて定期実行する例です。
スクリプト(bash)で実行した例を下記記事で紹介しておりますのでご参照ください。
IBM Cloud CISの送信元IPアドレス変更を検知する
https://qiita.com/aktech/items/f6cf0a9771c26c117825
IBM Cloud Functionsを利用した例を下記記事で紹介していますが、2023/10/26 Cloud Functionsは非推奨の発表がされています。
IBM Cloud Functionsを利用してCISの送信元IPアドレス変更をSlackへ通知する
https://qiita.com/aktech/items/85334f23b4e071249ad8
IBM Cloud Functions 非推奨の概要
https://cloud.ibm.com/docs/openwhisk?topic=openwhisk-dep-overview
主な手順
1. Code Engineにデプロイするコンテナのアクションの作成
2. GitHubへPush
3. Code Engine用のレジストリの準備
4. Code Engine プロジェクトの作成
5. Code Engine シークレットの作成
6. Code Engine ジョブの作成
7. Code Engine ジョブの実行
8. Code Engine ログ監視
9. Code Engine イベント設定(定期実行)
1. Code Engineにデプロイするコンテナのアクションの作成
今回は実行環境にPythonを利用
用意する物
・Dockerfile
・cis-ip-check.py
FROM python:slim
ADD ./cis-ip-check.py /root/cis-ip-check.py
WORKDIR /root
RUN apt update
RUN pip install sdcclient
RUN pip install sendgrid
CMD ["python","/root/cis-ip-check.py"]
import os
import json
import requests
from requests.exceptions import Timeout
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
# Secect the value (0 = False, 1 = True)
MAIL_CUSTOM = os.getenv('MAIL_CUSTOM')
MAIL_SEND_EVERY_TIME = os.getenv('MAIL_SEND_EVERY_TIME')
MAIL_TO_ADDRESS_HIDE = os.getenv('MAIL_TO_ADDRESS_HIDE')
if MAIL_CUSTOM == "1":
MAIL_SUBJECT = os.getenv('MAIL_SUBJECT')
MAIL_BODY_HTML = os.getenv('MAIL_BODY_HTML')
MAIL_BODY_TEXT = os.getenv('MAIL_BODY_TEXT')
MAIL_SUBJECT_NOT_CHANGED = os.getenv('MAIL_SUBJECT_NOT_CHANGED')
MAIL_BODY_HTML_NOT_CHANGED = os.getenv('MAIL_BODY_HTML_NOT_CHANGED')
MAIL_BODY_TEXT_NOT_CHANGED = os.getenv('MAIL_BODY_TEXT_NOT_CHANGED')
else:
MAIL_SUBJECT = "CIS IPS Changed."
MAIL_BODY_HTML = "<strong>CIS IPS has been changed.</strong><br>Please check your access-lists."
MAIL_BODY_TEXT = "CIS IPS has been changed.\nPlease check your access-lists.\nThis is a text mail."
MAIL_SUBJECT_NOT_CHANGED = "CIS IPS not Changed."
MAIL_BODY_HTML_NOT_CHANGED = "This is a user-edited mail."
MAIL_BODY_TEXT_NOT_CHANGED = "This is a user-edited mail.\nThis is a text mail."
if MAIL_TO_ADDRESS_HIDE == "1":
address_hide = True
else:
address_hide = False
MAIL_ADDRESS_TO = [m.strip() for m in os.getenv('MAIL_ADDRESS_TO').split(',')]
print(MAIL_ADDRESS_TO)
print("MAIL_ADDRESS_FROM : ",os.getenv('MAIL_ADDRESS_FROM'))
print("MAIL_ADDRESS_TO : ",os.getenv('MAIL_ADDRESS_TO'))
print("MAIL_CUSTOM : ",MAIL_CUSTOM)
print("MAIL_SEND_EVERY_TIME : ",MAIL_SEND_EVERY_TIME)
print("MAIL_TO_ADDRESS_HIDE : ",MAIL_TO_ADDRESS_HIDE,address_hide)
message = Mail(
from_email=os.getenv('MAIL_ADDRESS_FROM'),
to_emails=MAIL_ADDRESS_TO,
subject=MAIL_SUBJECT,
html_content=MAIL_BODY_HTML,
plain_text_content=MAIL_BODY_TEXT,
is_multiple=address_hide)
message_not_changed = Mail(
from_email=os.getenv('MAIL_ADDRESS_FROM'),
to_emails=MAIL_ADDRESS_TO,
subject=MAIL_SUBJECT_NOT_CHANGED,
html_content=MAIL_BODY_HTML_NOT_CHANGED,
plain_text_content=MAIL_BODY_TEXT_NOT_CHANGED,
is_multiple=address_hide)
try:
url = "https://api.cis.cloud.ibm.com/v1/ips"
r = requests.get(url, timeout=3.0)
if r.status_code != 200:
print("status_code from cis-ips was not 200.")
elif r.json()["result"]["etag"] == os.getenv('ETAG'):
print("There is no difference.")
if MAIL_SEND_EVERY_TIME == "1":
sg = SendGridAPIClient(os.getenv('SENDGRID_API_KEY'))
response = sg.send(message_not_changed)
print(response.status_code)
print(response.body)
print(response.headers)
else:
print("There is difference. CIS IPS has been changed.")
sg = SendGridAPIClient(os.getenv('SENDGRID_API_KEY'))
response = sg.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
except Timeout:
print("timeout.")
pass
環境変数はCode Engineのシークレットとして登録
ジョブ動作概要
・CIS (Cloudflare) の送信元アドレス情報を公開しているURL(API)へアクセス
・応答のETAGが異なる場合は変更ありと判断
・変更がある場合にメール送付
・オプション指定(シークレット)により変更がない場合でもメール送付
・変更がある場合のメール内容はカスタマイズ可能(Subject/Bodyはシークレットに事前登録)
・変更がない場合のメール内容はカスタマイズ可能(Subject/Bodyはシークレットに事前登録)
・宛先(TO)は複数指定可能
・オプション指定(シークレット)により複数指定した場合に他アドレスを隠す
・コードの編集は行わず、Code Engine シークレット入力によりオプション変更
・URL(API)からの応答がTimeout(3秒)した場合は"timeout"という文字列をログ出力
(※Timeout時に再送したり、メール送付を希望の場合はコード修正をご検討ください)
2. GitHubへPush
上記ファイルをGitHubへpushする(手順は省略)
GitHub URLに公開(public)しています
https://github.com/akd8/ibmcloud-cis-ip-check.git
3. Code Engine用のレジストリの準備
Code Engine用にContainer Registoryの名前空間を作成する
項目 | 入力内容 |
---|---|
リソースグループ | rg-xxx |
名前 | cr-code-engine |
4. Code Engine プロジェクトの作成
項目 | 入力内容 |
---|---|
ロケーション | 東京(jp-tok) 大阪(jp-osa) |
リソースグループ | rg-xxx |
名前 | CodeEngine |
5. Code Engine シークレットの作成
プロジェクト > シークレットおよびConfigmap > 作成
項目 | 入力内容 |
---|---|
タイプ | シークレット |
名前 | cisipcheck |
シークレット
キー | 値(入力例) | 説明 |
---|---|---|
ETAG | 38f79d050aa027e3be3865e495dcc9bc | 最新のETAGを入力(変更があれば更新する) |
SENDGRID_API_KEY | Sendgridを利用するユーザのAPI KEY API KEYの入手方法は参考URLへ |
|
MAIL_ADDRESS_FROM | xxx@test.com | 送信元アドレスを指定(Sendgridを利用するユーザメールアドレス) |
MAIL_ADDRESS_TO | aaa@test.com,bbb@test.com,ccc@test.com | 複数宛先を指定する場合は「,」区切りで指定 |
MAIL_CUSTOM | 0 or 1 | 1の場合はシークレットに設定したSubject/Bodyを応答する |
MAIL_SEND_EVERY_TIME | 0 or 1 | 1の場合はETAGに変更がなくともメールする |
MAIL_TO_ADDRESS_HIDE | 0 or 1 | 1の場合はTOに複数指定しても送信時に他のアドレスを隠す |
MAIL_SUBJECT | CIS IPS Changed. | メールタイトル文面 |
MAIL_BODY_HTML | This is a user-edited mail.<br>You can edit this mail. | メール文面(HTML形式) |
MAIL_BODY_TEXT | This is a user-edited mail.\nYou can edit this mail.\nThis is a text mail. | メール文章(TEXT形式) |
MAIL_SUBJECT_NOT_CHANGED | CIS IPS not Changed. | ETAGに変更がない場合のメールタイトル文面 |
MAIL_BODY_HTML_NOT_CHANGED | ETAGに変更がない場合のメール文面(HTML形式) | |
MAIL_BODY_TEXT_NOT_CHANGED | ETAGに変更がない場合のメール文章(TEXT形式) |
6. Code Engine ジョブの作成
一般
項目 | 入力内容 |
---|---|
名前 | ce-job-cis-ip-check |
実行するコードの選択
項目 | 入力内容 |
---|---|
実行するコードの選択 | ソース・コード |
コード・リポジトリー URL | https://github.com/akd8/ibmcloud-cis-ip-check.git |
コード・リポジトリー・アクセス | なし |
ブランチ名 | main |
コンテキスト・ディレクトリー | 指定なし(ブランク) |
Dockerfile | Dockerfile |
タイムアウト | 10m |
ブランチ名 | main |
ビルド用のリソース | 小 (0.5 vCPU / 2GB) |
レジストリー・サーバー | private.jp1.icr.io(IBM レジストリー東京) もしくは、private.jp2.icr.io(IBM レジストリー大阪) |
レジストリー・アクセス・シークレット | ce-cisip-ras |
名前空間 | cr-code-engine |
リポジトリー (イメージ名) | codeengine-ce1.git-xx(名前は任意) |
ビルド用のリソース | 小 (0.5 vCPU / 2GB) |
リソースおよびスケーリング
項目 | 入力内容 |
---|---|
インスタンス数 | 1 |
インスタインス・リソース | 0.125個のvCPU / 0.25 GB |
一時ストレージ(GB) | 0.4 |
ジョブの再試行回数 | 3 |
ジョブ・タイムアウト (秒) | 7200 |
環境変数(オプション)
項目 | 入力内容 |
---|---|
シークレット | cisipcheck |
上記値を入力して「作成」を実施すると、githubのコンテナ・アクション情報を元にしてコンテナイメージがレジストリに作成され、ビルドが完了する。
7. Code Engine ジョブの実行
作成したジョブ画面右上の「ジョブの実行依頼」より単発でのジョブ実行が可能
ジョブの実行依頼
項目 | 入力内容 |
---|---|
インスタンスの数 | 1 |
8. Code Engine ログ監視
ジョブ画面の「ロギングの起動」より、IBM Log Analysis with LogDNA (事前に要作成) を起動する
自動的に「_platform:'Code Engine' label.Project:'CodeEngine' app:ce-job-cis-ip-check」(例)のようなフィルタリングされた画面が表示される。
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 ['aaa@test.com', 'bbb@test.com', 'ccc@test.com']
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 MAIL_ADDRESS_FROM : xxx@test.com
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 MAIL_ADDRESS_TO : aaa@test.com, bbb@test.com, ccc@test.com
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 MAIL_CUSTOM : 0
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 MAIL_SEND_EVERY_TIME : 0
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 MAIL_TO_ADDRESS_HIDE : 0 False
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 There is no difference.
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 202
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 b''
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 Server: nginx
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 Date: Thu, 16 Nov 2023 04:31:15 GMT
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 Content-Length: 0
Nov 16 13:31:25 Code Engine ce-job-cis-ip-check-jobrun-12xyz-0-0 Connection: close
9. Code Engine イベント設定(定期実行)
イベント・サブスクリプションの作成
定期実行する間隔を指定する(下記は毎分の実行の例)
作成したジョブを選択する
実行されたジョブの時刻と状況(成功/失敗)は、ジョブの「ジョブ実行」タブから確認可能
参考URL
IBM Cloudのメール配信サービス(SendGrid)を使ってNode.js、Pythonからメール配信してみた!
https://qiita.com/strada/items/f4e6536b6e973b5ca2e9
Twilio SendGridとPythonでメールを一斉送信する方法
https://sendgrid.kke.co.jp/blog/?p=12510