友人から「AWSのコストレポートをメールで流すのって簡単にできる?」と聞かれ、「(コンソールの設定でできたかなー、と思い、)調べるから待っててねー。」と言ったのですが、それをすっかり忘れてしまい3週間ほど放置してしまいました。その贖罪として(:))、SAM でコストレポートをメールする仕組みを作ったので共有します(結局、コンソールで簡単な設定はありませんでした。)
IAM ロールの設定と、Lambda ファンクションの定義だけでできるので(後述しますが、SESの初期設定は Lambda ファンクション内でやっています。)、それほど難しくなく、SAM の練習にはもってこいだと思います。
また、実は SES をあまり使ったことがなく、その勉強を兼ねています。いったん、Gmail のアドレスを From にも To にも設定する形にしていますが、From 側を独自ドメインのものを使う場合は、別途設定が必要だと思っています。こちらについてもどこかで確認したいと思っています。
ソースコード
こちらで公開しています。
Lambda ファンクション(billing_mail.py
)
メールアドレスは環境変数から取得します。
import os import boto3 import datetime MAIL_FROM = os.environ['MAIL_FROM'] MAIL_TO = os.environ['MAIL_TO'] cloud_watch_client = boto3.client('cloudwatch', region_name='us-east-1') ses_client = boto3.client('ses', region_name='us-east-1') def lambda_handler(event, context): if not is_registerd_email_address(): register_email_address() return billing = getBilling() send_email(billing) return def is_registerd_email_address(): return len(ses_client.list_verified_email_addresses()["VerifiedEmailAddresses"]) == 1 def register_email_address(): return ses_client.verify_email_address( EmailAddress=MAIL_FROM ) def send_email(billing): return ses_client.send_email( Source=MAIL_FROM, Destination={ 'ToAddresses': [ MAIL_TO, ] }, Message={ 'Subject': { 'Data': '【システムメール】現在のAWS利用料金', }, 'Body': { 'Text': { 'Data': '現在のAWS利用料は、$' + str(billing) + ' です。' , }, } } ) def getBilling(): start_time = datetime.datetime.today() - datetime.timedelta(days=1) end_time = datetime.datetime.today() statistics = cloud_watch_client.get_metric_statistics( Namespace='AWS/Billing', MetricName='EstimatedCharges', Dimensions=[ { 'Name': 'Currency', 'Value': 'USD' } ], StartTime=start_time, EndTime=end_time, Period=3600*24, Statistics=['Maximum'] ) return statistics['Datapoints'][0]['Maximum']
template.yaml
MAIL_FROM
, MAIL_TO
については適宜修正してください。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Send AWS billing information. # SAM Globals Globals: Function: Environment: Variables: MAIL_FROM: '***@gmail.com' # Fix MAIL_TO: '***@gmail.com' # Fix # SAM Resources Resources: SamSampleLambda: Type: AWS::Serverless::Function Properties: CodeUri: functions/billing_mail/billing_mail.zip Handler: billing_mail.lambda_handler Runtime: python3.6 Role: !GetAtt BillingIamRole.Arn Timeout: 30 Events: Timer: Type: Schedule Properties: Schedule: cron(0 0 * * ? *) # JST AM9:00 BillingIamRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: "sts:AssumeRole" Policies: - PolicyName: "billing_mail_for_lambda" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: "cloudwatch:*" Resource: "*" - Effect: "Allow" Action: "ses:*" Resource: "*"
導入方法
README.md
にも書いていますが、SAM の初期設定は完了している前提となります。もし、設定が完了していない場合は、こちらも参考にしてみてください。
template.yaml
のMAIL_FROM
,MAIL_TO
を変更してください。(Gmailでしか動作確認しておりません。)sh deploy.sh
コマンドを実行してください。- 初回実行時にメールアドレスの verify が必要です。構築された Lambda Function を実行してください。2. で設定したメールアドレスに、verifyメールが送信されるので、承認してください。
- 以上で設定完了です。日次でコストレポートが送信されます。
イマイチなところ
最初のメールアドレスの verify 部分はライフサイクルが他と異なるのでどうしたものかと思ったのですが、いったん一つの Lambda ファンクションでやってしまっています。SAM(Cfn)ではできなそうに見える?(調べが甘いかもしれません。) deploy.sh
の中で AWS CLI を使って verify する方がまだマシな気もしています。うーむ。
まとめ
少々イマイチなところは残りましたが、当初の目的は達成しました。SAM についてはこちらでもまとめていますので、気になる方はチェックしてみてください。