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