Advent CalendarAWSEvent

AWSのACMで発行した証明書を自動で承認するPythonスクリプトを書いてみた

この記事はPython Advent Calendar 2016の記事です。 AWS使ってますか? AWSにはAmazon Certificate Managerという無料で証明書を発行できるサービスがあります。 で、そ […]

広告ここから
広告ここまで

この記事はPython Advent Calendar 2016の記事です。

AWS使ってますか?

AWSにはAmazon Certificate Managerという無料で証明書を発行できるサービスがあります。

で、それの証明書を発行する際の認証方法がEmailオンリーなわけですが、いちいちメール開いて承認ボタンを押すのがめんどくさいなと思いました。

と、言うことでAWS Lambdaで認証メールを読み込んで承認ボタンクリックする作業を自動化してみました。

免責

思いっきりHTMLをパースしてるので、AWS側から送られるメールや承認ページのマークアップが変わった瞬間に死にます。

事前準備

Route53とSESとS3を使って承認メールをインターセプトします。
インターセプトするための設定については、下のスライドを参考にしてください。
https://speakerdeck.com/amimoto/ri-ben-yu-amazon-cloudfront-with-aws-certificate-manager

AWS Lambdaのコード

Route53 -> SES -> S3で受信したメールをAWS Lambdaで処理します。
コードはだいたいこんな感じ。

from __future__ import print_function

import json
import urllib
import urllib2
import boto3

print('Loading function')

s3 = boto3.client('s3')
acmUrl = "https://certificates.amazon.com/approvals"


def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))

    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key']).decode('utf8')
    print(bucket)
    print(key)
    try:
        response = s3.get_object(Bucket=bucket, Key=key)
        body = response['Body'].read()
        mail = body.decode('utf-8')
        startNum = mail.find( acmUrl )
        endNum = startNum + mail[startNum:].index( "\n" )
        crtUrl = mail[startNum:endNum]
        print( crtUrl )
        req = urllib2.Request(crtUrl)
        result = urllib2.urlopen(req).read()
        
        # Get Valivation Token
        validationTokenStartNum = result.find( "validation_token" )
        validationTokenStartNum = validationTokenStartNum + result[validationTokenStartNum:].find( 'value=' )
        validationTokenEndNum = validationTokenStartNum + result[validationTokenStartNum:].find( '/>' )
        validationToken = result[validationTokenStartNum:validationTokenEndNum]
        validationToken = validationToken[validationToken.find('"') + 1: -2 ]
        print('Validation Token is',validationToken)
        
        # Get Context
        contextTokenStartNum = validationTokenStartNum + result[validationTokenStartNum:].find( "context" )
        contextTokenStartNum = contextTokenStartNum + result[contextTokenStartNum:].find( 'value=' )
        contextTokenEndNum = contextTokenStartNum + result[contextTokenStartNum:].find( '/>' )
        contextToken = result[contextTokenStartNum:contextTokenEndNum]
        contextToken = contextToken[contextToken.find('"') + 1: -2 ]
        print( "Context is", contextToken )

        params = {
            "validation_token": validationToken,
            "context": contextToken
        }
        params = urllib.urlencode(params)
        req2 = urllib2.Request(crtUrl)
        req2.add_data(params)
        result = urllib2.urlopen(req2)
        
        print(result)
        
        return mail
    except Exception as e:
        print(e)
        print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
        raise e

LambdaとS3を連携させる

最後にLambdaのイベントをS3へのオブジェクト作成に設定して完了です。

動かしてみて

2つ3つほど動かしていますが、ACMで証明書作成した後2〜3分待つと勝手に証明書が利用可能になってるのは非常に楽しいです。

AWS SDKかCloudFormationと組み合わせて、ACM設定済みのCloudFront立ち上げを自動化するとか面白そうかもです。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts