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立ち上げを自動化するとか面白そうかもです。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark