LoginSignup
1
0

More than 1 year has passed since last update.

Amazon SNS に設定されている iOS アプリの APNs 証明書の有効期限についてアラートを通知する

Last updated at Posted at 2020-12-23

0.はじめに

unnamed.png

iOS アプリの通知について、Amazon SNS を利用しており、以下の記事を参考にして、先日 iOS アプリの APNs 証明書の更新したんですが…、

Bitrise の設定は更新したものの、Amazon SNS を忘れてしまって、通知が届かなくなるというトラブルが発生してしいました…。

😱😱😱

iOS アプリの APNs 証明書の有効期限は、Apple から警告メールが届くので良いんですが、Amazon SNS の設定状況についても、検知する仕組みが必要だな、と思い、作ってみました。

1. 全体の構成

構成としては、こんな感じです。

Qiita_03_960x320.001.jpeg

  1. Amazon CloudWatch Events から、日時で AWS Lambda を実行。
  2. AWS Lambda で、Amazon SNS に登録されている APNs プラットフォームアプリケーションの有効期限をチェック。
  3. 有効期限に近いものが確認された場合、Amazon SNS のトピックにパブリッシュして、メールを通知。

2. Python @ AWS Lambda のコード

#!/usr/bin/env python
# -*- coding: utf-8-unix; -*-
"""AWS Lambda Function - Maintenance SNS Check to Expire
"""
from __future__ import print_function

import os
import math
import boto3

# 「Python 3 で少しだけ便利になった datetime の新機能 - Qiita」
# <https://qiita.com/methane/items/d7ac3c9af5a2c659bc51>
from datetime import datetime, timezone, timedelta
TimeZone = timezone(timedelta(hours=+9), 'JST')

ClientSNS = boto3.client('sns')

# ------------------------------------------------------------------------------
# Function
# ------------------------------------------------------------------------------

# 「【Python】Lambdaからメールを送信 | ハックノート」
# https://hacknote.jp/archives/35679/
def MailSend(prmSubject, prmMessage):
    result = -1
    try:
        response = ClientSNS.publish(
            TopicArn = '[送信先トピックのARN]',
            Message = prmMessage,
            Subject = prmSubject
        )
    except Exception as e:
        print(e)
        result = -1
        raise
    else:
        pass
    finally:
        pass
    return result

def lambda_handler(event, context):
    try:
        print(event)
        print(context.__dict__)
        now_datetime = datetime.now(TimeZone)
        print(now_datetime)
        logdata = ""
        list_platform_applications_paginator = ClientSNS.get_paginator('list_platform_applications')
        #print(list_platform_applications_paginator)
        list_platform_applications_pageiterator = list_platform_applications_paginator.paginate()
        #print(list_platform_applications_pageiterator)
        for list_platform_applications_page in list_platform_applications_pageiterator:
            #print(list_platform_applications_page)
            platform_applications = list_platform_applications_page.get('PlatformApplications', [])
            for platform_application in platform_applications:
                print(platform_application)
                platform_application_arn = platform_application.get('PlatformApplicationArn', '')
                platform_application_arn_split = platform_application_arn.split('/')
                #print(platform_application_arn_split)
                if len(platform_application_arn_split) < 3:
                    continue
                platform_application_type = platform_application_arn_split[1]
                #print(platform_application_type)
                if platform_application_type != 'APNS':
                    continue
                platform_application_attributes = platform_application.get('Attributes', {})
                platform_application_enabled = platform_application_attributes.get('Enabled', '')
                #print(platform_application_enabled)
                if platform_application_enabled != 'true':
                    continue
                platform_application_expiration_date = platform_application_attributes.get('AppleCertificateExpirationDate', '').replace('Z', '+00:00')
                print(platform_application_expiration_date)
                platform_application_expiration_date_timestamp = 0
                try:
                    platform_application_expiration_date_timestamp = datetime.fromisoformat(platform_application_expiration_date).timestamp()
                except Exception as e:
                    print(e)
                #print(platform_application_expiration_date_timestamp)
                now_datetime_timestamp = now_datetime.timestamp()
                #print(now_datetime_timestamp)
                diff_timestamp = platform_application_expiration_date_timestamp - now_datetime_timestamp
                diff_day = math.floor(diff_timestamp/(60*60*24))
                print(diff_day)
                if diff_day < 1:
                    pass
                elif diff_day in [30,60,90]:
                    pass
                else:
                    continue
                logdata += """\
- Last %d Days !!! - %s
""" % (diff_day, platform_application_arn)
        #
        #print(logdata)
        if len(logdata) > 0:
            subject = """[%s] SNS Check to Expire !!!""" % (now_datetime.isoformat(' ', 'seconds'))
            msg = """\
----

【有効期限注意】

%s
""" % (logdata)
            print(subject)
            print(msg)
            MailSend(subject, msg)
    except Exception as e:
        print(e)
    else:
        pass
    finally:
        pass
    #
    return "normal end"

このコードでは、警告の判断は、以下としていますが、状況に合わせて変更して頂ければよろしいかと。

  • 有効期限が 14 日以内
  • 有効期限が、90 or 60 or 30 日前

AWS Lambda に割り当てる IAM Role については、こんな感じです。

  • Amazon SNS からのプラットフォームアプリケーションの情報の取得
    • sns:ListPlatformApplications
  • Amazon SNS のトピックへのパブリッシュ
    • sns:Publish
  • AWS LambdaCloudWatch Logs へのログの出力
    • logs:CreateLogGroup
    • logs:CreateLogStream
    • logs:PutLogEvents

99.ハマりポイント

  • 今回は、特にハマることはありませんでしたが…

  • ただ、よくよく考えてみると、Bitrise にしても、Amazon SNS にしても、Apple Developer で証明書を更新したら、自動でそちらも更新されると非常に便利だなぁ、と思ったりもしますので、先々その辺の自動化の仕組みも検討しても良いかもしれません。

  • それによっては、使うサービスを変えても良いかなとも思ったりします。

unnamed.gif

XX.まとめ

ご参考になれば ♪♪♪

👋👋👋

【2021.05.07 追記】

因みに、証明書の更新手順は、以下。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0