[API] 初めてのOracle Cloud API Gatewayの作成/Creating Your First API Gateway In The Oracle Cloud

原文はこちら

マイクロサービスとサーバレスは、これまでにも増して人気を得てきており、世界中のチームがこれらのパターンとアーキテクチャに非常に迅速に適応してきています。しかし、大規模にマイクロサービスとサーバレスを活用しようとする際にこうしたチームがまず直面するのが、フロントエンドとモバイルAPIのとても多くの、そして複雑なエンドポイントを管理しなければならないという課題です。そのため、多くのチームではバックエンドをシンプルにし、すべてのクライアントからの「シングルポイント・オブ・エントリー」にするために、API Gatewayを採用しています。API Gatewayはまた、アーキテクチャの中の個々のファンクションではなくゲートウェイのレベルで、レート制限やCORS、認証を簡単に実装できるようにしてくれます。
このブログポストではOracle Cloudの最新サービスのひとつであるAPI Gatewayを概覧していきます。
以下の順で進めていきます:
  • "Hello World"サーバレスファンクションの作成とデプロイ
  • API Gatewayに適したサブネットの作成
  • ダイナミックグループの作成とAPI Gatewayに必要なポリシーの適用
  • Gatewayの作成
  • Gatewayへの仕様のデプロイ
  • Gatewayのテスト

"Hello World"サーバレスファンクションの作成とデプロイ

以前にもOracle Functionsについてのブログを書いています→Oracle Functions:開発者のためのクイックスタートガイドドキュメントはとてもお役立ちですし、他にもOracleのホステッドサーバレスをどのように使うかについてのたくさんの情報がありますので、ここではサーバレスのための環境をどのようにセットアップするかについての詳細には立ち入りません。あなたはOracle Functionsのことを知っているものとして進めていきますので、必要であればこれらのリンクを参照してくださいね。
ではシンプルなサーバレスアプリケーションとファンクションを作成し、そのファンクションをデプロイしてみましょう。このファンクションの内容は今回関係なくて、ただ後にGatewayのテストで使いたいだけです。なので、ファンクションはサンプルの"Hello World"のままにしておきます。ランタイムもここでは関係ないので、Oracle FunctionsとFn Projectでサポートされているものならなんでもよいです。
$ fn create app gw-hello-world-app --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.phx..."]'
Successfully created app:  gw-hello-world-app
$ fn init --runtime node gw-hello-world-fn
Creating function at: /gw-hello-world-fn
Function boilerplate generated.
func.yaml created.
$ cd gw-hello-world-fn
$ fn deploy --app gw-hello-world-app                                                                              
Deploying gw-hello-world-fn to app: gw-hello-world-app
Bumped to version 0.0.3
Building image phx.ocir.io/toddrsharp/faas/gw-hello-world-fn:0.0.3 .........
Parts:  [phx.ocir.io toddrsharp faas gw-hello-world-fn:0.0.3]
Pushing phx.ocir.io/toddrsharp/faas/gw-hello-world-fn:0.0.3 to docker registry...The push refers to repository [phx.ocir.io/toddrsharp/faas/gw-hello-world-fn]
643fe44f12a4: Pushed
b279f8214e6b: Pushed
0adc398bfc34: Pushed
0b3e54ee2e85: Pushed
ad77849d4540: Pushed
5bef08742407: Pushed
0.0.3: digest: sha256:e16e74ce194d85a9658177f7637484aded9764e981e395dfcbcac2d018687cac size: 1571
Updating function gw-hello-world-fn using image phx.ocir.io/toddrsharp/faas/gw-hello-world-fn:0.0.3...
Successfully created function: gw-hello-world-fn with phx.ocir.io/toddrsharp/faas/gw-hello-world-fn:0.0.3
view rawfn-create-sh hosted with ❤ by GitHub
この時点でファンクションを fn CLIで呼び出しできます:
$ fn invoke gw-hello-world-app gw-hello-world-fn
{"message":"Hello World"}
view rawfn-invoke.sh hosted with ❤ by GitHub
しかし、HTTP(S)経由やOCI SDKを利用してファンクションを直接呼び出しするにはリクエストへの署名が必要です。ファンクションをインスペクトして呼び出しエンドポイントを取得してみましょう:
$ fn inspect gw-hello-world-app gw-hello-world-fn
view rawfn-inspect.sh hosted with ❤ by GitHub
注! fn inspect コールから id をコピーしておきましょう。これが後で必要になるファンクションのOCIDです!
呼び出ししようすると 401 Unauthorizedで失敗します:
$ curl -i -X GET https://[redacted].us-phoenix-1.functions.oci.oraclecloud.com/20181201/functions/ocid1.fnfunc.oc1.phx..../actions/invoke
HTTP/1.1 401 Unauthorized
Date: Fri, 22 Nov 2019 14:24:33 GMT
Content-Type: application/json
Content-Length: 57
Connection: keep-alive
Opc-Request-Id: /01DT9R03K21BT1A2RZJ0005QSH/01DT9R03K21BT1A2RZJ0005QSJ
Www-Authenticate: Signature headers="date (request-target) host"
{"code":"NotAuthenticated","message":"Not authenticated"}
view rawcurl-fn.sh hosted with ❤ by GitHub
But once we put our serverless function behind our gateway we can invoke it via HTTPS. Let's move on!
しかし、Gatewayのうしろにサーバレスファンクションを配置することによって、HTTPS経由で呼び出しができるようになります!やってみましょう!

API Gatewayに適したサブネットの作成

API Gateway用にHTTPSトラフィックのためのイングレスルールを設定したリージョナルサブネットが必要になります。ここでゃ既存のVCNの中にこのサブネットを作成していきましょう。
選んだセキュリティリストにポート443へのイングレスルールを追加します:
完了です。続いてもセキュリティについて…

ダイナミックグループの作成とAPI Gatewayに必要なポリシーの適用

API Gatewayではテナンシー内でのアクセス制御にダイナミックグループを使用します。なので、新しくダイナミックグループを作成していくつかのポリシーを設定する必要があります。Gatewayを作成するコンパートメントのOCIDが必要になるので、Identity -> Compartmentsから使うコンパートメントのOCIDをコピーしてください。次に、新規ダイナミックグループを以下の定義(コンパートメントOCIDは適切なものに置き換えて)で作成しましょう:
さて、あなたのテナンシーと新しく作成したダイナミックグループに対応するポリシーを作成します。グループ名とコンパートメント名はご自身のものに置き換えてください:
allow dynamic-group [your dynamic group] to use virtual-network-family in compartment [your compartment name]
allow dynamic-group [your dynamic group] to manage public-ips in compartment [your compartment name]
allow dynamic-group [your dynamic group] to use functions-family in compartment [your compartment name]
ご参考まで、わたしのテナンシーでのステートメントは以下のようになりました:
allow dynamic-group api-gw-group to use virtual-network-family in compartment faas-compartment
allow dynamic-group api-gw-group to manage public-ips in compartment faas-compartment
allow dynamic-group api-gw-group to use functions-family in compartment faas-compartment
それではGatewayを作成しましょう!

Gatewayの作成

Gatewayを作成するには、まずサイドバーメニューから'Developer Services'の配下の'API Gateway'を選択します。
'Create Gateway'をクリックしてダイアログを埋めていきます。先程作成したリージョナルサブネットを選択することを忘れないでください。
Gatewayはまず'Creating'のステータスになるでしょう。
数分くらいで、Gatewayは'Active'になります。

Gatewayへの仕様のデプロイ

デプロイメントを作成する前に、エンドポイントを定義するためデプロイメント仕様ファイルをJSONフォーマットで記述する必要があります。前述のファンクションOCIDが手元にあることを確認してください。では、 spec.json というファイルをファンクションのルートに以下の内容で作成しましょう(ファンクションOCIDはご自身のものに置換してください):
{
"routes": [
{
"path": "/hello",
"methods": [
"GET"
],
"backend": {
"type": "ORACLE_FUNCTIONS_BACKEND",
"functionId": "ocid1.fnfunc.oc1.phx..."
}
}
]
}
view rawspec.json hosted with ❤ by GitHub
このブログポストはLimited Availability期間のやり方で説明しているので手で作成したJSONでエンドポイントを定義する必要がありますが、GA後にはコンソールUIからかんたんに定義することができるようになります。
次に、Gateway詳細ページのサイドバーから'Deployments'をクリック。
そして'Deploy API'をクリック。
デプロイメントに名前をつけて、作成した spec.json を選択してパスのプレフィックスを入力します。
'Deploy'をクリックしてちょっと待てばデプロイメントは完了です。

Gatewayのテスト

Gateway詳細のページで、エンドポイントを見てみましょう。
ファンクションをテストするため、このエンドポイントをコピーしたものに spec.json で定義したパスを追加して、実行してみましょう!
$ curl -i -X GET https://[redacted].apigateway.us-phoenix-1.oci.customer-oci.com/v1/hello
HTTP/1.1 200 OK
Date: Fri, 22 Nov 2019 15:04:11 GMT
Content-Type: application/json
Connection: keep-alive
Content-Length: 25
Server: Oracle API Gateway
Strict-Transport-Security: max-age=31536000
X-XSS-Protection: 1; mode=block
X-Frame-Options: sameorigin
X-Content-Type-Options: nosniff
opc-request-id: /429E9723BB6BED8DB8D237876894DDF6/3E4A5D8760D59242A98AB8A91E2B0107
{"message":"Hello World"}
これはAPI Gatewayを使ってできることのほんのさわりです。デプロイメント仕様を拡張して他のファンクションや(Oracle Cloud上や外部の)HTTPエンドポイントをカバーしたり、レート制限や認証などを行うこともできます。