やること
CloudWatch Logsのフィルタリング後(filter pattern)入力後のURLを生成
環境
python 3.8
aws
背景
CISベンチマークに関するアラート通知を作った。
AWS公式ドキュメントに記載のある、フィルタリング条件で、CloudWatch Logsでフィルタリング後のURLを通知したかった。
https://docs.aws.amazon.com/ja_jp/securityhub/latest/userguide/securityhub-cis-controls.html
やってみた
実際にCIS3.1を例にやってみる。
CloudWatchLogsには検索文字列、開始日時、終了日時の3つを指定できるため、それぞれ作成して最後にくっつける。
フィルタリング条件
{($.errorCode="*UnauthorizedOperation") || ($.errorCode="AccessDenied*")}
下記手順でできる。
- 2回URLエンコードする。
-
%2520
(エンコード後の空白)を+
に変換する。 -
%
を$
に変換する
import urllib.parse
# safe=''を指定しているのは、デフォルトが`/`を除外するから。
filter = urllib.parse.quote(urllib.parse.quote(filter, safe=''), safe='').replace('%2520', '+').replace('%', '$')
日時
UNIXTIME指定のため、datetime
型やdate
型等は変換する。
変換した後は少数点以下3桁があるfloat
型になるため、1000倍する。 -> これをしないと URLの日付の値が小さすぎるため、1970年が指定される。
ex.)1615820400000
の13桁
import datetime
# dtより30分前から
start_time = int((dt- datetime.timedelta(minutes=30)).timestamp() * 1000)
# dtまで。
end_time = int(dt.timestamp() * 1000)
url生成
# 他ロググループ、ストリーム、リージョンは変更しないため、固定値にした。
# `CloudTrail/logs`ロググループ
# `{*****アカウントID*****}_CloudTrail_us-east-1`ログストリーム
url = 'https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/CloudTrail$252Flogs/log-events/{*****アカウントID*****}_CloudTrail_us-east-1'
url += '$3FfilterPattern$3D' + filter + '$26start$3D' + str(start_time) + '$26end$3D' + str(end_time)
ex.)生成されたURL
https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/CloudTrail$252Flogs/log-events/{*****アカウントID*****}_CloudTrail_us-east-1$3FfilterPattern$3D$257B+$2528$2524.errorCode+$253D+$2522$252AUnauthorizedOperation$2522$2529+$257C$257C+$2528$2524.errorCode+$253D+$2522AccessDenied$252A$2522$2529+$257D$26start$3D1615881063411$26end$3D1615882863411
気をつけるところとしてはCloudTrail$252Flogs
をみてわかる通り、URLで使われている/
以外の/
もURLエンコードしないといけない。
フィルタリング条件と同様にURLエンコードにひとクセある感じ。
所感
わかってしまえばなんてことはないんですが、URLエンコードするだけでなく、文字列変換のロジック組まないといけないのは、ちょっと面倒くさいですね。
また、フィルタリング時に文字列検索なら"
で囲うのも意外と忘れがち。