エンジニア

2022.11.10

AWS Certificate Manager 証明書の期限をSlackに通知するLambda(Python)作った

こんにちは。

うっかり証明書の期限過ぎてた・・!なんてことありませんか?
私はないのですが、そんなことがあったら困ると思いLambdaで作ってみました。

さっそく構成

すごく簡単な構成です。
AWS Certificate Manager(以下ACM)の証明書は東京とバージニアで作成。
Lambdaは東京リージョンに作成しました。

コードのご紹介

続いてコードです。Pythonを使っています。

import os
import boto3
import json
import urllib
from urllib import parse, request
from datetime import datetime, timedelta, date
from dateutil.relativedelta import relativedelta
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

WEB_HOOK_URL = os.environ['SLACK_WEBHOOK']

# ACM証明書期限取得
def get_acm_expired(region):
    
    acmclient = boto3.client('acm', region_name=region)
    
    #ACMの一覧を取得
    acm_list = acmclient.list_certificates()
    
    for list in acm_list['CertificateSummaryList']:
        acm_arn = list.get("CertificateArn", "")

        #証明書の詳細を取得
        acm_detail = acmclient.describe_certificate(
            CertificateArn=acm_arn
            )
        acm_domainname = acm_detail['Certificate']['DomainName']
        acm_expired = acm_detail['Certificate']['NotAfter'].strftime("%Y/%m/%d")
        nextmonth = (date.today() + relativedelta(months=1)).strftime("%Y/%m/%d")
    
        massage = acm_domainname + " " + str(acm_expired)
        post_slack(massage, nextmonth, acm_expired, region)

# Slack通知 
def post_slack(massage, nextmonth, acm_expired, region):
    
    send_data = {
        "username": 'ACM証明書期限(sandbox):' + region ,
        "icon_emoji": ":watermelon:"
    }
    
    # 期限まで1ヶ月以上
    if nextmonth < acm_expired:
        color = "#FFFFFF"
        
    # 期限まで1ヶ月未満
    else:
        color = "#FF0000"

    send_data["attachments"] = [{
        'fields': [
            {
                'value': massage,
                'short': False,
            }
        ],
        'color': color,
    }]

    send_text = "payload=" + json.dumps(send_data)

    request = urllib.request.Request(
        WEB_HOOK_URL,
        data=send_text.encode("utf-8"), 
        method="POST"
    )
    urllib.request.urlopen(request)
    
    print(massage)


def handler(event, context):
    
    regions = ["ap-northeast-1", "us-east-1"]
    
    for region in regions:
        try:
            get_acm_expired(region)
        except Exception as e:
            continue

関数や流れはこんな感じです。

  • def handler
    対象リージョンは、regions = [“ap-northeast-1”, “us-east-1”]。
    リージョン毎にdef get_acm_expiredを実行。

  • def get_acm_expired
    list_certificatesで証明書一覧からARNを取得。
    describe_certificate で期限を取得。

  • def post_slack
    証明書名と期限をSlackに通知。
    期限1ヶ月未満だったら左横に赤いバーを表示する。

いざ実行

実行すると、こんな感じでSlackに通知が届きます。
sandboxはアカウント名です。
アイコンがスイカなのはなんとなくです。

期限間近の証明書がなかったので、next_month=’2023/11/25’で実行(2023年10月25日に実行した場合)。
ちゃんと期限まで1ヶ月未満の証明書には赤いバーが付きました。

EventBridgeで定期実行すれば、証明書切れを回避できそうです。
開発に専念できるよう、運用はできるだけ自動化したいですね。
次は何やろうかなーと模索中です。
ではまた!

一覧に戻る