どうもこんにちは、SCSKの齋藤です。
みなさんは先日のAWS Summit Japanに参加しましたか?
相変わらずの熱狂ぶりがすごかったですね〜
多くのセッションを通じて学びを得れたのと、社内外多くの知り合いに再会できて、大変刺激的な時間を過ごすことができました。
また、弊社の2024 Japan AWS Jr. Championsも輩出され、一緒に写真を撮ったりして、後輩のジュニチャンができたことを強く実感しました!後輩よ、頑張ってくれ〜
さて話は本題に入りますが、先日のAWS Summit Japanのセッションの中で気になることを学びましたので、早速検証して記事にしてみました。
概要
題名にもある通り、AWS StepFunctionsから直接APIを叩くことができるというものです。
以前からAWS StepFunctionsにはAPI Gatewayの連携はありまして、API Gatewayで作成されたAPIなら直接アクセスすることはできました。しかし、サードパーティAPIについては、Lambda関数を作成してアクセスする必要がありました。
ですが、なんとサードパーティAPIへのアクセスもStepFunctionsから直接叩けるようになってたとのことです。驚きですね!
このアップデート自体は、昨年のre:invent2023で発表されたものなのでまだ半年ちょっとしか経過していません。
ちょうど、私が4月から担当しているプロジェクトでも、サーバーレス開発をしているので、役立つかも知れないと思い検証してみました!
検証内容
今回は下記のようなステートマシンとしております。
ステートマシンのワークフローの中で、APIGatewayに直接叩きに行く処理を先に2回実施し、そのレスポンスをもとに、サードパーティAPIを叩きに行くという流れとなります。
実際のプロジェクトなどで開発する場合では、リソース間の情報を連携してAPIを叩きにいくことは多いかと思いますので、こういった観点で検証してみました。
準備
今回の検証には主に下記3種類のリソースを作成します。
① StepFunctionsステートマシン
② APIGatewayエンドポイント
③ サードパーティAPI(ApiGateway、Lambda)
①、②については、AWS側でテンプレートがあったので、それをそのまま使って構築しました。
③については、サードパーティAPIをAPIGatewayで作成しました。(なんかややこしいですね。)
APIGatewayのデプロイと、APIキーの作成、使用量の作成を行えば、実質サードパーティAPIができたも同然なので、そのAPIを叩きにいくようにしました。さらに、APIの裏側でLambdaを実装し、データの加工を少しだけ行うようにしました。
では、作成方法を解説します。
①StepFunctionsステートマシン、②APIgatewayエンドポイント
StepFunctionsのコンソール画面に行き、「ステートマシンの作成」を押下すると、テンプレート選択画面が出ます。
ここで、自分が実装したいことの類似テンプレートを選択すると、ある程度出来上がったステートマシンを見ることができます。
今回は、「API Gateway への呼び出しを行う」にチェックをつけ、次へ行きます。
テンプレートの活用方法が選択できるので、「デモの実行」を選択します。一旦ステートマシンを作成して、後ほどサードパーティAPIの処理を追加します。
今回のテンプレートは、
① 最初のAPIGatewayでペットストアにペット商品の情報を登録(Post)し、
② 2つ目のAPIGatewayで、ペットストアの情報を取得(Get)する
上記2つの流れのステートマシンとなっております。
次に画面が遷移するので、「デプロイと実行」をクリックし、ステートマシンの実行を行います。
CloudFormationの実行が走るので、少々待ちます。
デプロイが完了すると、実行画面が表示されます。
入力情報を作成し、「実行開始」をクリックします。デフォルトでサンプル値が用意されており、カメの商品情報を追加するデータとなっています。
実行が成功すると、画面上部に成功メッセージが表示され、ステートマシンの通過した処理を緑で表示します。
ちなみに、各アクションをクリックすると、イベント情報の詳細を確認できます。
下記2つののキャプチャは、1番最初に実行されるアクション「Add Pet to Store」の入力と出力です。
そしてさらに下記2つのキャプチャは、「Retrieve Pet Store Data」の入出力データです。入力データが、前の「Add Pet to Store」の出力データと同じになっていることを確認できますね。
出力データも長くて見切れていますが、「ResponseBody」で始まるフェーズと、「ExistingPets」で始まるフェーズがあるのを確認できます。
「ResponseBody」は新規に追加した情報で、「ExistingPets」は従来から存在しているデータのことを指していると思われます。
この後設定するサードパーティAPIは、「Retrieve Pet Store Data」の後に追加する予定のため、この出力データの一部である「ResponseBody」をサードパーティAPIのインプットにする予定です。
一旦、ここまででストップし、サードパーティAPIの作成に移ります。
③ サードパーティAPI
先述した通りAPIGatewayとLambdaを使ってサードパーティAPIもどきを作成します。
Lambda
先にLambda関数を作成します。
サードパーティAPIの裏側で稼動するLambdaとして、今回は受け取ったリクエストをjson形式に変換し、ステータスコードとともに変換するという処理を実施します。
Lambdaのコンソール画面に移動し、「関数の作成」をクリックします。
任意の名前とランタイムで関数を作成します。今回はPythonを使います。
関数が作成されるのを確認します。
デフォルトで作成されたソースコードを少しだけ編集します。
ソースコードのjson.dumpの中身を入力値eventに置き換えます。入力値をjson形式に変換する処理を実施するためです。
下記のように変更いたら、「Deploy」ボタンを押下します。
デプロイの成功後、テストを実施するため、上記画面の「Test」を押下し、テンプレートを作成し、保存します。
その後、再び「Test」ボタンを押下して、テストを実施します。
json形式に変換してステータスコードとともに表示するので、下記のような結果になれば作成成功です!
APIGateway
APIGatewayコンソールに移動し、「APIを作成」をクリックします。
APIの種類を選択する画面で、「REST API」を選択します。
「新しいAPI」を選び、APIエンドポイントタイプを「リージョン」にして、任意のAPI名で作成します。
そうすると、空のAPIが作成されました。
リソースの作成
空のAPIができたので、次はリソースを追加します。
先ほどの空のAPI作成画面の左上に「リソースを作成」というボタンがありますので、そこをクリックします。
リソースパス/の配下に、任意のリソース名を作成します。
作成されると、リソース欄に表示されるのを確認できます。
メソッドの作成
その後、同じ画面の「メソッドを作成」をクリックし、APIが叩かれた後の処理を定義します。
メソッドタイプをPOSTにし、統合タイプを「Lambda関数」に設定します。
Lambda関数は選択式なので、先ほど作成したものを選びます。
後の設定はデフォルトで良いため、画面下の「メソッドの作成」を押下します。
作成が完了すると、メソッド情報が表示されるようになります。
テスト
API動作のテストを行います。
先ほどの画面の「テスト」というボタンを押下すると、テスト作成ができます。
リクエスト本文に{“test”:1}と入力し、テストの作成を行います。
テスト作成後にすぐにテストされるので、結果を確認します。
いいですね!ステータスコード200とjson化された入力値が返されており、先ほど作成したLambda関数と統合されているのがわかります。
APIキーの作成
APIリクエストにはAPIキーによる認証をした方が望ましいので、APIキーを作成します。
まず、作成したAPIの画面の左のバーから、「APIキー」を選択します。
その後の画面から、「APIキーを作成」を押下します。
任意の名前でAPIキーを作成します。
保存後に、APIキーが作成されていることを確認します。
なお、APIキーの四角の部分をクリックすると、APIキーがクリップボードにコピーされます。後ほど必要なので、手元に控えておいてください。
リクエストとAPIキーの結び付け
リクエストにAPIキーを結び付けて、接続の際に認証するようにします。
まず、APIのトップ画面に遷移し、画面左の緑のPOSTをクリックします。そうすると、下記のような画面になるかと思います。
1番最初のリクエストのところでAPIキーが欲しいため、「メソッドリクエストの設定」の編集ボタンをクリックします。
「APIキーは必須です」をクリックし、保存を押下します。
デプロイ
APIそのものは整ったので、公開する準備を行います。
再び、作成したAPIのトップ画面へ遷移します。
その画面の「APIをデプロイ」を選択します。
ステージを作成するため、下記情報を入力します。
今回は開発環境ということでdevというステージ名にしております。
入力後、デプロイを押下します。
使用量プランの設定
API公開前最後の設定を行います。
再び、作成したAPIの画面の左のバーから、「使用量プラン」を選択します。
その後の画面で「使用量プランを作成」をクリックします。
スロットリングやクォータの設定をできますが、今回はどちらもチェックを外して、「使用量プランを作成」をクリックします。
作成後、使用プランのページに遷移するので、ステージとAPIキーを追加していきます。
まずは、「関連づけられたステージ」→「ステージを追加」をクリックします。
APIの部分は作成したリソース名を選択し、ステージの部分は作成したステージを選択し、追加を押下します。
再び使用プランのページに戻り、今度は「関連づけられたAPIキー」にスイッチし、「APIキーを追加」を押下します。
既存のキーから、事前に作成したAPIキーを選択し、追加します。
これにてAPIを公開することができました。
StepFunctionsの編集
作成したサードパーティAPIをStepFunctionsに組み込みます。
事前に作成したStepFunctionsのページを開き、画面右上の編集ボタンを押下します。
編集画面の左側から「Call third-party API」を選択し、2つ目のAPIGatewayの後にドラッグ&ドロップします。
挿入後、API接続の設定画面が表示されるので、設定を諸々入力します。
- APIエンドポイント
作成したサードパーティAPIのURLを入力します。 - メソッド
今回はPOSTするようにサードパーティAPIを作成したので、POSTを選択します。 - Authentication
APIキーの保存先の参照を設定します。これはEventBridgeConnectionというリソースを経由してSecretsManagerに保存されるため、そのリソースを作成します。「新しい接続を作成」をクリックしてください。
接続名は任意の名前を設定し、送信先タイプを「その他」で選択し、認証の部分で「APIキー」を選択します。
ヘッダー名には、x-api-keyと入力してください。
ヘッダー値には、APIキー作成時に控えておいた、APIキーを入力します。
作成後、再びStepFunctionsの画面に戻ります。
Authenticationの選択肢に、先ほど作成したものが追加されるので、選択します。
その後、リクエスト本文を入力します。
今回は、前のAPIGatewayの処理のレスポンスを受け取り、それをサードパーティAPIのリクエストにするため、「実行時に状態入力からリクエスト本文を取得」を選択し、「$.ResponseBody」と入力し、保存を押下します。
これは、先述した「①StepFunctionsステートマシン、②APIgatewayエンドポイント」の最後の方で、「Retrieve Pet Store Data」の出力の一部である「ResponseBody」をサードパーティAPIの入力にすると記載しましたのを反映してます。
先頭に$.をつけると、入力値のjson辞書から該当のKey値(今回でいうとResponseBody)の値を取得する設定を行うことができます。
もちろん、「ExistingPets」を入力としたい場合は、「$.ExistingPets」とすることで正しく渡されるのを確認できます。
保存が完了したら、画面右上から「終了」を押下します。
必要権限の設定
最後に、StepFunctionsに必要な権限を設定します。
ステートマシンの画面からIAMロールARNをクリックし、IAMの画面に遷移します。
最初に作ったStepFunctionsはAPIGatewayを直接叩くのみの権限しかないため、サードパーティAPIを叩くのに必要な権限をインラインポリシーで追加します。
下記のようなポリシーを作成してポリシーをアタッチします。
権限付与に参考にしたブログは下記のとおりです。
ステートマシンの実行
長かったですが、これでサードパーティAPIを叩く準備はできました。
今一度ステートマシンのページに移動し、画面右上の「実行を開始」をクリックします。
入力データを求められるので、最初のStepFunctions作成した時の入力データを参考に新しいペット情報を入力し、「実行を開始」ボタンを押します。
実行された後、ステートマシンのステータスを確認できるので、全て緑になっていれば成功です。
試しに、「Call third-party API」をクリックすると、画面右にデータが表示されます。
出力タブをクリックし、下にスクロールすると、ResponseBodyに1番最初に入力したデータが表示されております。
サードパーティAPIの裏のLambdaで処理された値なので、ResponseBodyの中にステータスコードとjson化された入力データが入っているのを確認できます。
これにより、前の処理で実行された APIGatewayの値をインプットに、サードパーティAPIにアクセスすることができると確認できました。
まとめ
今回はStepFunctionsからサードパーティAPIへの接続を試行してみました。
今回は検証初期段階ですが、私が現時点で気になることとして下記3点が挙げられます。
- 出力の整形はどこまで可能か?
- 前後にLambdaを挟んでも情報を正しくやり取りすることは可能か?
- APIエラー時の扱いもどこまで柔軟に設定が可能か?
上記はこれから検証することとして今回のブログは一旦終わりにしたいと思います。
個人的な所感としては、APIのレスポンス情報を元に複雑なメッセージ整形処理を必要とする場合、Lambdaの方が適しているのかなと考えております。
APIを叩いて、その情報をほとんどそのまま次の処理に渡すなどの場合は、Lambdaではなく、この機能を活用した方が開発生産性が上がるかもしれません。