Step FunctionsにLambdaからデータを渡してみた

eyecatch-step-functions

こんにちは、臼田です。

みなさんLambdaしてますか?

今日は、ちょっとしたwebページの更新チェックをしたくてLambdaを使おうと思ったのですが、せっかくなのでStep Functionsで分岐処理をしてみたいなーと思ったのでやってみました。

ちなみに、Step Functions初心者なので、これから始める人と同じ目線で説明していきます。

作りたいもの

最近脆弱性診断ができるAWS Inspectorを触っていたのですが、対応しているCVEのリストがこちらにあり、随時アップデートされています。

このファイルが更新されたことを通知する仕組みが作りたいと思って実装し始めました。

作りたいイメージ

だいたい下記のイメージです。※今後変更される可能性があります

  1. Step FunctionsからTargetのUpdateを確認するLambdaを実行してレスポンスを取得
  2. 更新があればTweet用LambdaからTweet
  3. 途中でエラーが発生したらSESで通知

CVE_Check

数回のブログに分けて実装していきます。

今回の範囲

まずはUpdate Checkerをサクッと作って、それをStep Functionsから呼び出してレスポンスを取得してみます。

Webページの更新をチェックするLambda作成

それでは作っていきましょう。

中身のアルゴリズムとしては、該当URLに対してリクエストしてレスポンスヘッダーの「Last-Modified」をチェックして判断する感じにします。

Python 3.6で書いていきます。

コード

import urllib.request
from datetime import datetime, timedelta

def lambda_handler(event, context):
	url = "https://s3-us-west-2.amazonaws.com/rules-engine/CVEList.txt"
	yesterday = datetime.now() - timedelta(1)
	with urllib.request.urlopen(url) as r:
		lm_header = r.info()['Last-Modified']
		last_modified = datetime.strptime(lm_header, '%a, %d %b %Y %H:%M:%S %Z')
		print(last_modified)
	if last_modified > yesterday:
		result = {"update": True}
	else:
		result = {"update": False}
	return result

URLをハードコーディングしていますが、最初はとりあえずこんな感じでいいでしょう。

Step Functionsでつなぐので、レスポンスはjsonで返すようにします。

動きとしては、デイリーでLast-Modifiedをチェックして、1日以内の更新であれば「update: True」を返します。

本当はタイムゾーンとか気にするべきですが、ターゲットがGMTで返してくれるのと、pytzを利用しないと(色んな意味で)面倒になるので今回は無視します。

外部ライブラリを利用するなら、Serverless Frameworkを使ったほうがいいでしょう。

それでは、Lambdaを作成します。

Lambda作成

マネジメントコンソールからLambda関数を作成します。

コードが既にあるので「Blank Function」を選択します。

01_lamnda

現状トリガーは無いのでそのまま「次へ」

02_lambda

名前を適当に入れ「Python 3.6」を選択します。

03_setting

Update_Checkerは外部へのアクセスのみなので、特にAWSリソースにアクセスする必要はないので適当なロール名でロールを作成して「次へ」進みます。

04_setting

確認画面で「関数の作成」を押します

05_create

作成できたら「テスト」してみます。

06_test

入力値は気にしないので「Hello World」のまま実行します。

07_test

Updateが無いためfalseが返ってきました。

08_false

とりあえず動いたので、画面右上のLambdaのARNを控えます。

10_arn

Step Functionsの作成

ステートマシンの作成を開始します。

今回は、とりあえずStep FunctionsからLambdaが実行できたらゴールとします。

ので、設計図の「失敗のRetry」をベースに作成します。

ちなみに、設計図を選択すると名前も勝手に変更されてしまうので、ステップ2で設計図を選んでから名前を付けます。

11_step

下の方にスクロールしてワークフローを編集します。

今回は「失敗のRetry」をベースにしていますが、この中のStates(1つの実行単位)には「HelloWorld」というStateが定義されています。

Statesには何種類かのTypeがありますが、これは標準的な「Task」というもので、Resourceで指定した要素を実行します。

他にも必要なTypeがありますが、興味があればこちらで確認して下さい。後続のブログでも幾つか解説します。

今回はResourceを先ほど作成したLambdaに変更します。

直接書き換えてもいいですが、どうやらこの画面で編集すると下記のように補完してくれました。

ダブルクリックで入力できました。

12_resource

Resourceのみ変更したら、「ステートマシンの作成」から作成します。

IAMロールを選択する画面になりますが、Step Functionsがデフォルトで作成したロールが選択されているので、「OK」を選んでこれをそのまま利用します。

13_role

作成が完了したので、そのまま実行してみます。

14_exe

入力値は関係ないのでそのまま「実行の開始」をします。実行IDは自動的に入力されます。

15_exe

しばらくすると「実行ステータス」が「成功」になります。

グラフ上でも「HelloWorld」が緑色となり成功していることが読み取れます。

16_result_2

出力タブでも作成したLambdaからのレスポンスが確認できました。

17_output

とりあえず問題なくStep FunctionsからLambdaを実行できました。

次はエラーを取得したい

Step Functionsをほとんど知らなくても、とりあえずLambdaを実行できました。

次回は、エラーが発生した際の処理をStep Functions上で実装してみたいと思います。

ワークフローでのTask以外のStatesについても調べて解説します。

AWS Cloud Roadshow 2017 福岡