3scaleの基本的な使い方
はじめに
今回は、3scaleの基本的な使い方を解説します。図1のように、実際にAPIバックエンドに存在する(APIプロバイダが提供する)Hello APIを、3scaleを使って公開するというユースケース(Step 1~Step 3)に沿って解説します。
Hello APIは、”user_key”クエリに指定した値と、リクエストヘッダの値をJSON形式で返却する簡単なAPIです。
$ curl "http://api_backend.oss.example.co.jp:18080/myapp/api/hello?user_key=api_key" { "your_user_key": "api_key", "your_request_headers": { "User-Agent": [ "curl/7.29.0" ], "Accept": [ "*/*" ], "Host": [ "api_backend.oss.example.co.jp:18080" ] } }
ここでは、既にこのような簡単なAPIが存在することを前提に解説を進めていきます。
Step 1. APIを公開してみよう
それでは、早速APIバックエンドに存在するHello APIを3scaleで公開してみましょう。以下の3つを設定します。
- プロキシ設定
- APIゲートウェイのURL(クライアントアプリケーション(APIコンシューマ)がコールするURL)と、APIバックエンドのURLとをマッピングする
- 認証用設定
- Hello APIを利用するクライアントアプリケーションを定義する
- 分析用設定
- Hello APIのコール数をカウントできるようにする
まず、管理ポータルのダッシュボードから[NEW API]を選択します(図2)。
3scaleでは、手動でAPIを追加する方法と、サービスディスカバリ機能(OpenShift上にデプロイされたAPIサービスをシームレスに3scaleに取り込む機能)を用いてAPIを追加する方法があります。ここでは、手動でAPIを追加してみましょう(図3)。
これでサービス(3scaleでは“API”と“サービス”は同義)の定義ができあがりました(図4)。以降、具体的な設定をしていきます。
プロキシ設定
まず、プロキシを設定します。Hello APIの概要画面から[Configuration]→[add the base URL of your API and save the configuration]を選択すると、Hello APIのインテグレーション画面が表示されます(図5)。プロキシの設定や認証用の設定など、APIの構成に関わる設定は、基本的にこのインテグレーション画面を用いて設定します。
[Private Base URL]にAPIバックエンドのURL、[Staging Public Base URL]および[Production Public Base URL]にAPIゲートウェイのURLを定義することで、APIゲートウェイのURLとAPIバックエンドのURLとをマッピングします。
APIゲートウェイのURLが2つありますが、これらは名前の通り、それぞれステージング環境用と本番環境用のAPIゲートウェイです。
前述したように、3scaleにはOpenShiftのサービスとしてステージング環境用と本番環境用のAPIゲートウェイが存在します。新しくAPIを追加した場合は、そのゲートウェイに設定したURLとOpenShiftのサービスとをマッピングする必要があります。そのマッピングは、OpenShiftのルートを2つ(ステージング環境用と本番環境用)作成することで実現できます(図6)。
認証用設定
次に認証用の設定をします。Hello APIを利用するクライアントアプリケーションを作成するには、そのクライアントアプリケーションの開発者のアカウントを作成する必要があります。
管理ポータルのダッシュボードから[Audience]→[Create]を選択し、開発者アカウントを作成します(図7)。
開発者アカウントを作成すると、デフォルトでクライアントアプリケーションが1つ作成されます(図8)。このデフォルトクライアントアプリケーションは、デフォルトサービスである”API”を利用するように設定されています。ここではサービスとしてHello APIを用いるため、このデフォルトクライアントアプリケーションは利用できません。
新規クライアントアプリケーションを作成する前に、まずクライアントアプリケーションとサービスとをマッピングするためのアプリケーションプランを作成します。アプリケーションプランとは、流量制御やマネタイズ等のルールをクライアントアプリケーション単位で設定するための枠組みです。
Hello APIの概要画面から[Create Application Plan]を選択すると、アプリケーションプラン作成画面が表示されます(図9)。アプリケーションプランを作成後、作成したアプリケーションプランを[Publish]します。
次に、新規クライアントアプリケーションを作成します(図10)。ここでは、”test application”というアプリケーションを作成します。[Application Plan]には、先ほど作成したHello APIの”Basic”アプリケーションプランを設定します。
分析用設定
最後に分析用の設定を行います。まずはメソッドを設定しましょう。3scaleでは、APIのパスをメソッドと呼びます(図11)。
次にHello APIの概要画面から[Methods]を選択し、新規メソッドとしてHello methodを作成しましょう(図12)。
続けて、作成したメソッドとAPIのパスとをマッピングします。Hello APIのインテグレーション画面で[Add Mapping Rule]を選択し、マッピングルールを追加します(図13)。
以上で設定は完了です。最後にHello APIのインテグレーション画面で[Update & test in Staging Environment]ボタンを押下し、インテグレーションテスト(ステージング環境用のAPIゲートウェイからAPIバックエンドまでの疎通テスト)に成功することを確認しましょう(図14)。
ステージング環境用のAPIゲートウェイを用いて、Hello APIをコールしてみます。”user_key”クエリには、作成したクライアントアプリケーションのAPIキーを付与します。APIキーは、クライアントアプリケーションの概要画面で確認できます。
$ curl "https://hello-3scale-apicast-staging.192.168.99.113.nip.io:443/myapp/api/hello?user_key=cf6e6569d04dc087541b2f49b486a2f1" { "your_user_key": "cf6e6569d04dc087541b2f49b486a2f1", "your_request_headers": { "Accept": [ "*/*" ], "User-Agent": [ "curl/7.29.0" ], "X-Forwarded-Host": [ "hello-3scale-apicast-staging.192.168.99.113.nip.io" ], "X-Forwarded-Proto": [ "https" ], "Forwarded": [ "for=192.168.99.113;host=hello-3scale-apicast-staging.192.168.99.113.nip.io;proto=https;proto-version=" ], "X-Forwarded-For": [ "192.168.99.113" ], "Host": [ "api_backend.oss.example.co.jp:18080" ], "X-Real-IP": [ "172.17.0.1" ], "X-3scale-proxy-secret-token": [ "Shared_secret_sent_from_proxy_to_API_backend_9b581ebf1068c969" ], "X-Forwarded-Port": [ "443" ] } }
ステージング環境用のAPIゲートウェイを用いて、Hello APIをコールすることに成功しました。
続いて、本番環境用のAPIゲートウェイを用いてHello APIをコールしてみます。本番環境用のAPIゲートウェイにHello APIをデプロイするためには、コンフィギュレーション画面で[Promote]ボタンを押下します(図15)。
本番環境用のAPIゲートウェイを用いて、Hello APIをコールします。
$ curl "https://hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello?user_key=cf6e6569d04dc087541b2f49b486a2f1" { "your_user_key": "cf6e6569d04dc087541b2f49b486a2f1", "your_request_headers": { "Accept": [ "*/*" ], "User-Agent": [ "curl/7.29.0" ], "X-Forwarded-Host": [ "hello-3scale-apicast-production.192.168.99.113.nip.io" ], "X-Forwarded-Proto": [ "https" ], "Forwarded": [ "for=192.168.99.113;host=hello-3scale-apicast-production.192.168.99.113.nip.io;proto=https;proto-version=" ], "X-Forwarded-For": [ "192.168.99.113" ], "Host": [ "api_backend.oss.example.co.jp:18080" ], "X-Real-IP": [ "172.17.0.1" ], "X-3scale-proxy-secret-token": [ "Shared_secret_sent_from_proxy_to_API_backend_9b581ebf1068c969" ], "X-Forwarded-Port": [ "443" ] } }
本番環境用のAPIゲートウェイを用いて、Hello APIをコールすることに成功しました。Hello APIの概要画面から[Analytics]を選択するとHello APIの分析画面が表示され、Hello APIの使用量等を確認できます(図16)。
Step 2. APIのセキュリティを高めよう
デフォルトではAPIキーによるクライアントアプリケーションの認証が有効になっていますが、APIキーは簡単に漏えいするリスクがあり、セキュリティレベルが低いです。エンタープライズ領域で利用できるようなAPIのセキュリティを担保するためには、別の手段を考える必要があります。
ここでは、公開するAPIのセキュリティを高める方法として、以下の2つの方法を紹介します。
- OpenID Connectインテグレーション
- サードパーティのアイデンティティプロバイダと連携し、OpenID Connectの仕様に基づいたAPIリクエストの認証を行う
- OpenID ConnectはOAuth 2.0を拡張した仕様で、API認証フローを定めた仕様のデファクトスタンダード。そのフローの中で認証を司るアイデンティティプロバイダがアクセストークンやリフレッシュトークン、IDトークンを発行する
- シークレットトークン
- 3scaleを通るAPIリクエストに秘密のトークンを付与することで、APIリクエストが3scaleを通ったかをAPIバックエンドが判別できるようにする
OpenID Connectインテグレーション
OpenID Connectインテグレーションを試してみましょう。ここではサードパーティのアイデンティティプロバイダとして、Keycloakのバージョン3.4.3を利用します(Keycloakの構築に関しては、OpenStandiaで提供されている公式ドキュメントの日本語版を参照)。
まず、Keycloakを設定します。ここでは3scaleという名前のレルムを準備します。3scaleレルムに、3scale用のクライアントを設定します(図17)。
ここで設定する項目を表に示します。
設定項目 | 値 |
---|---|
クライアントID | ※ここでは3scale |
クライアントプロトコル | openid-connect |
アクセスタイプ | confidential |
Standard Flowの有効 | オフ |
Implicit Flowの有効 | オフ |
ダイレクトアクセスグラントの有効 | オフ |
サービスアカウントの有効 | オン |
付与するサービスアカウントロール | realm-managementクライアントのmanage-clientsロール |
[Credentials]タブで、作成したクライアントのクライアントシークレットを確認しておきましょう。
続いて、Keycloakとのデータ同期に使用する3scaleのコンポーネントであるZyncを設定します。Zync~ Keycloak間はSSL通信が必要なため、KeycloakのCA証明書をZyncにインポートします(下記リストのpublic_keyの項目は、実際には1行です)。
$ keytool -export -alias server -keystore /opt/keycloak-3.4.3.Final/standalone/configuration/application.keystore -file customCA.crt $ openssl x509 -in customCA.crt -inform der -out customCA.pem -outform PEM $ curl https://keycloak-server.oss.example.co.jp:8443/auth/realms/master --cacert customCA.pem { "realm": "master", "public_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm64KWQJHSK7JwmfVmXt VZ2V2KCA2hl2y9aRSTdazBnBVAfBoBcVvsNIDIuSTzgfKqh/RDgAPun39/BA7FXIn7rnoRHlq9MXWY q3zWzRtDet2nqUux8zBDQeBkvylQB59SC758605wKpTN0YHvt50i8lOTpQBkAeZ8mOKNLMO+GMK9nF lBQdt+FO+pWXYKfwqcr61Yoz5dHWE2BntmNOdyLcfK9UmXB/z3jvoowfRnx6M1EousUscLr4ErfUyZ OWjWxt+X8buo3KDeOFbWXYCYoC7tPuGUcCbMv03D610NH1y9gX76h0bzh/UAzqdIGNtS+LoXZZdyxa rp32CxIRvwwIDAQAB", "token-service": "https://keycloak-server.oss.example.co.jp:8443/auth/realms/master/protocol/openid-connect", "account-service": "https://keycloak-server.oss.example.co.jp:8443/auth/realms/master/account", "tokens-not-before": 0 } $ oc exec zync-1-gfq2z cat /etc/pki/tls/cert.pem > zync.pem $ cat customCA.pem >> zync.pem $ oc create configmap zync-ca-bundle --from-file=./zync.pem $ oc set volume dc/zync --add --name=zync-ca-bundle --mount-path /etc/pki/tls/zync/zync.pem --sub-path zync.pem --source='{"configMap":{"name":"zync-ca-bundle","items":[{"key":"zync.pem","path":"zync.pem"}]}}' $ oc patch dc/zync --type=json -p '[{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/0/subPath", "value":"zync.pem"}]' $ oc exec zync-2-zkpmp cat /etc/pki/tls/zync/zync.pem ~~省略:KeycloakのCA証明書が追加されていることを確認します~~ $ oc set env dc/zync SSL_CERT_FILE=/etc/pki/tls/zync/zync.pem
最後に、管理ポータルでOpenID Connectを有効にしましょう。Hello APIのコンフィギュレーション画面から[edit integration settings]を選択し、認証方法をOpenID Connectに変更します(図18)。
Hello APIのインテグレーション画面で、[AUTHENTICATION SETTINGS]→[OpenID Connect Issuer]の欄に3scale用クライアントのクライアントクレデンシャルとKeycloakのURLを設定します(図19)。図中では、[OpenID Connect Issuer]の欄に“https://3scale:xxx@keycloak-server.oss.example.co.jp:8443/auth/realms/3scale”と指定していますが、”xxx”の部分には、3scale用クライアントのクライアントシークレットを指定します。
認証方法をOpenID Connectに変更すると、Hello APIのクライアントアプリケーションであるtest applicationのAPIクレデンシャルとして、APIキーの代わりにクライアントIDとクライアントシークレットが表示されます(図20)。[Add Random key]を押下し、クライアントシークレットを生成しましょう。
クライアントシークレットを生成すると、3scaleはKeycloakの”OpenID Connect動的クライアント登録機能”により、動的にKeycloakのクライアントを登録します。Keycloakのクライアント一覧画面でtest application用のクライアントが作成されていることを確認しましょう(図21)。
以上で設定は完了です。3scaleがサポートする4つのOAuth 2.0フロー(Authorization Code Grant、Resource Owner Password Credentials Grant、Implicit Grant、Client Credentials Grant)のいずれかを用いてアクセストークンを発行し、Hello APIをコールしてみましょう。ここではResource Owner Password Credentials Grantを使います。
$ export token=$(curl -X POST https://keycloak-server.oss.example.co.jp:8443/auth/realms/3scale/protocol/openid-connect/token -d "client_id=17df53c0&client_secret=***&username=tabata&password=***&grant_type=password&scope=openid" | jq -r '.access_token') $ curl "https://hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token" { "your_user_key": null, "your_request_headers": { "Authorization": [ "Bearer" ], "Accept": [ "*/*" ], "User-Agent": [ "curl/7.64.1" ], "X-Forwarded-Host": [ "hello-3scale-apicast-production.192.168.99.113.nip.io" ], "X-Forwarded-Proto": [ "https" ], "Forwarded": [ "for=192.168.99.1;host=hello-3scale-apicast-production.192.168.99.113.nip.io;proto=https;proto-version=" ], "X-Forwarded-For": [ "192.168.99.1" ], "Host": [ "api_backend.oss.example.co.jp:18080" ], "X-Real-IP": [ "172.17.0.1" ], "X-3scale-proxy-secret-token": [ "Shared_secret_sent_from_proxy_to_API_backend_9b581ebf1068c969" ], "X-Forwarded-Port": [ "443" ] } }
Hello APIをコールすることに成功しました。ちなみにアクセストークンを付与しなかったり、無効なアクセストークンを付与したりすると、以下のように403エラーが返ってきます。
$ curl -v "https://hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer invalid_token" < HTTP/1.1 403 Forbidden Authentication parameters missing
シークレットトークン
次に、シークレットトークンを試してみます。実はシークレットトークンはデフォルトで有効になっており、前述した確認結果にも、以下のように表示されていました(6~8行目)。
$ curl "https://hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token" { "your_user_key": null, "your_request_headers": { ~~省略~~ "X-3scale-proxy-secret-token": [ "Shared_secret_sent_from_proxy_to_API_backend_9b581ebf1068c969" ], ~~省略~~ } }
デフォルトでは、”X-3scale-proxy-secret-token”というヘッダに、” Shared_secret_sent_from_proxy_to_API_backend_”という値が入ります。APIバックエンドで、この値をチェックする処理を作り込むことで、APIバックエンドが直接コールされるといったAPIの意図しない使われ方を防ぐことができます。
シークレットトークンに設定する値は、Hello APIのインテグレーション画面の[AUTHENTICATION SETTINGS]→[Secret Token]から変更できます(図22)。
Step 3. 開発者ポータルを使ってみよう
ここまでの説明で、APIを公開し、APIのセキュリティを高めることまではできました。しかし、実際にAPIがどのような仕様なのか、どのように使えばよいのかが分からなければ、開発者はAPIを使ってくれません。ここでは、開発者がAPIを使ってくれるように、開発者向けのポータルを作成しましょう。
3scaleには、開発者ポータルのテンプレートが準備されています。“https://3scale.$(minishift-ip).nip.io”にアクセスしてみましょう(図23)。
トップ画面に加えて、開発者のクライアントアプリケーションのクレデンシャルを確認したり(図24)、
使用量を分析したり(図25)、
仕様を確認したりできます(図26)。
ここでは、トップ画面およびドキュメンテーションをHello API仕様に変更してみましょう。
API仕様の準備
開発者ポータルのドキュメンテーションにHello APIの仕様を表示するため、まずはHello APIの仕様を作成します。フォーマットにはSwagger 2.2.10を用います。
Hello APIの概要画面から[ActiveDocs]→[Create your first spec]を選択し、新規API仕様を作成しましょう(図27)。
Hello APIの仕様は、次のようになります。
{ "swagger": "2.0", "info": { "version": "1.0.0", "title": "Hello API", "description": "This API returns the \"user_key\" query and the request headers." }, "host": "hello-3scale-apicast-production.192.168.99.113.nip.io", "basePath": "/", "schemes": [ "https" ], "consumes": [ "application/json" ], "produces": [ "application/json" ], "paths": { "/myapp/api/hello": { "get": { "description": "Hello API", "operationId": "hello", "produces": [ "application/json", "application/xml", "text/xml", "text/html" ], "parameters": [ { "name": "user_key", "in": "query", "description": "Your API access key", "required": false, "x-data-threescale-name": "user_keys", "type": "string" }, { "name": "access_token", "in": "query", "description": "Your access token", "type": "string", "required": true } ], "responses": { "200": { "description": "response", "schema": { "$ref": "#/definitions/ResponseModel" } } } } } }, "definitions": { "ResponseModel": { "type": "object", "properties": { "your_user_key": { "type": "string" }, "your_request_headers": { "type": "object" } } } } }
Hello APIをコールするためには、アクセストークンが必要になります。アクセストークンを取得するためのAPIの仕様も、Hello APIの仕様と同様の手順で作成します。
{ "swagger": "2.0", "info": { "version": "v1", "title": "OAuth for Hello API", "description": "OAuth2.0 Client Credentails Flow for authentication of our Hello API." }, "host": "keycloak-server.oss.example.co.jp:8443", "basePath": "/auth/realms/3scale/protocol/openid-connect", "schemes": [ "https" ], "consumes": [ "application/x-www-form-urlencoded" ], "paths": { "/token": { "post": { "description": "This operation returns the access token for the API. You must call this before calling any other endpoints.", "operationId": "oauth", "parameters": [ { "name": "client_id", "description": "Your client id", "type": "string", "in": "formData", "required": true, "default": "9d1a338f" }, { "name": "client_secret", "description": "Your client secret", "type": "string", "in": "formData", "required": true, "default": "xxx" }, { "name": "grant_type", "description": "OAuth2 Grant Type", "type": "string", "required": true, "default": "client_credentials", "in": "formData" }, { "name": "scope", "description": "Scopes", "type": "string", "required": true, "default": "openid", "in": "formData" } ], "responses": { "200": { "description": "response" } } } } } }
ポータル画面の変更
次に、開発者ポータル画面を変更していきます。まずは、トップ画面のタイトルを”Echo API”から”Hello API”に変更し、ついでに画面の背景も青色から緑色に変更しましょう。
開発者ポータル画面を変更するには、管理ポータルのダッシュボードから[Audience]→[Developer Portal]→[Content]を選択します。[Homepage]にて、トップ画面のタイトルを変更します(図28)。
[default.css]で、画面の背景を変更します(図29)。
変更を[Save]し、[Publish]すると、開発者ポータルに反映されます(図30)。
続けて、開発者ポータルのドキュメンテーションを変更します。ドキュメンテーションは[Documentation]で変更します。ここでは、アクセストークンを取得するためのAPIの仕様とHello APIの仕様を並べて表示するために、新しく”another-swagger-ui-container”というDOMを設けています(図31)。
変更を[Save]し、[Publish]すると、開発者ポータルに反映されます(図32)。
ここで、実際に開発者ポータルを用いてAPIを試し打ちしてみましょう。各APIをクリックすると、リクエストに必要なパラメータを入力できる欄が表示されます(図33)。クライアントIDとクライアントシークレットの欄には、開発者が持つクライアントアプリケーションのクライアントIDとクライアントシークレットを入力させても良いのですが、API仕様は広く一般に公開することも考えられるので、テスト用のクライアントアプリケーションを作成し、そのクライアントIDとクライアントシークレットをデフォルト値として入れておくのが親切でしょう。
[Try it out!]を押下すると、リクエストおよびレスポンスが表示されます(図34)。
続いて、Hello APIです。Oauth for Hello APIのレスポンスから取得したアクセストークンをパラメータに指定して、試し打ちしてみましょう(図35)。
[Try it out!]を押下すると、無事にHello APIからレスポンスが返ってきました(図36)。
以上で、Hello APIの仕様を開発者ポータルで公開することができました。
おわりに
次回は、APIcast(3scaleのAPIゲートウェイ)の機能を柔軟に拡張可能なポリシーという機能について紹介します。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 3scaleのAPIゲートウェイの機能を拡張してみよう!
- 3scaleをインストールしてみよう!
- APIファーストの設計ツール「Apicurio」「Microcks」を使ってみよう!
- Keycloakを用いたハードニングの実装方法
- Keycloakのインストールと構築例
- FAPI 1.0に準拠したクライアントアプリケーションと リソースサーバの作り方
- クライアントポリシーを利用したKeycloakの設定方法と、FAPIリファレンス実装の紹介
- NGINX Ingress Controllerの柔軟なアプリケーション制御、具体的なユースケースと設定方法を理解する
- コンテナ上のマイクロサービスの認証強化 ~StrimziとKeycloak~
- クラウドネイティブな環境でKeycloakによるシングルサインオンを実現