3scaleのAPIゲートウェイの機能を拡張してみよう!

2019年8月9日(金)
田畑 義之

はじめに

実際のAPI管理システムでは、より高度なセキュリティ仕様(OAuth 2.0、OpenID Connect、Financial-grade APIなど)に準拠したり、システム独自の要件を実装したりする必要に迫られる場面が多々あります。

今回は、そのような場面にも3scaleを適用できるように、「ポリシー」という機能を使って3scaleのAPIゲートウェイである「APIcast」(図1)に機能を追加する方法を紹介します。

図1:3scaleの構成要素

ポリシーとは

ポリシーとは、任意の機能を実装したプラグインをAPIcastに追加する機能、または任意の機能を実装したプラグインそのものを指します。本機能により、本体のソースコードを変更することなく、任意の機能をAPIcastに追加し、要件に合ったAPIゲートウェイを設計できます。また、スタンダードポリシーとして複数の強力なポリシーが準備されており、管理者ポータルから適当なポリシーを選択するだけで、初心者でも簡単にOAuth 2.0に則った高度なセキュリティを有するAPIゲートウェイを設計できます。

ポリシーを理解するにあたり、「ポリシーチェーン」という概念を説明します。文字通り複数のポリシーを鎖(チェーン)のように順番に定義することで、複数のポリシーを適用可能にし、またポリシーの実行順序を制御可能にする概念です。

例(図2)を用いて、ポリシーの実行順序を説明しましょう。

図2:ポリシーチェーン

この例では、流量制御(Edge Limiting policy)とトークンイントロスペクション(Token Introspection policy)をポリシーチェーンに定義しています(これらのポリシーについては後述)。もう1つ、APIcast policyというポリシーが定義されていますが、これはAPIcastのオリジナル機能です。オリジナル機能もポリシーとして定義することで、オリジナル機能を考慮したポリシーチェーンを設計できます。APIcastはNGINXをベースに作られているため、各ポリシーはポリシーチェーンに加えて、NGINXのフェーズでも実行順序が制御されます。この例で用いられているポリシーではそれぞれ、流量制御はaccessフェーズとlogフェーズ、トークンイントロスペクションはaccessフェーズ、APIcastオリジナルはrewriteフェーズ、accessフェーズ、contentフェーズ、post actionフェーズに処理を持ち、各処理は①~⑦の順序で実行されます。なお、ポリシー開発時やポリシーチェーンの設計時は、各処理の実行順序を意識する必要があります。

ポリシーを設定してみよう

それでは、実際にポリシーを設定してみましょう。ポリシーはAPIのインテグレーション画面から設定できます(図3)。設定したいポリシーを選択し、必要なパラメータを管理ポータル上で入力するだけで、欲しい機能を追加できます。

図3:Hello APIのインテグレーション画面

以降では、代表的なスタンダードポリシーとして、流量制御、トークンイントロスペクション、スコープチェックの3つのポリシーの設定方法と挙動を説明します。

流量制御 (Edge Limiting Policy)

流量制御とは、APIリクエスト数に上限値を設け、上限値以内であればAPIリクエストを許可し、上限値を超えた場合はAPIリクエストを拒否するというアクセス制御です(図4)。

図4:流量制御 (Edge Limiting Policy)

流量制御のアルゴリズムは複数あります。3scaleでは、以下の3つをサポートしています。

  • 固定ウィンドウ方式
    最も一般的なアルゴリズムで、ある期間内に許可するAPIコール数を制御する(10分間で1000回、2時間で50回、など)。
  • リーキーバケット方式
    帯域幅を制御するイメージで、秒間のAPIコール数を制御する(100回/秒、1000回/秒、など)。
  • コネクション数方式
    APIバックエンドに接続するコネクション数を制御する(100コネクションまで、1000コネクションまで、など)。

それでは、管理者ポータルを使って流量制御を設定してみましょう(図5)。ここでは最も一般的な固定ウィンドウ方式を使って、「1分間に5回」という上限値を設定します。このポリシーでは、ある条件に合致したときのみ上限値を設けたり、条件によって上限値を変えたりする設定も可能です。

図5:Hello APIのインテグレーション画面(流量制御の設定)

挙動を確かめてみます。1分間に5回までは通常通りAPIコールに成功しますが、6回目以降は以下のように「429 Too Many Requests」でAPIコールに失敗します。1分後にはまたカウント値がリセットされ、APIコールに成功するようになります。

$ curl -v "hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token"
< HTTP/1.1 429 Too Many Requests
<html>
<head><title>429 Too Many Requests</title></head>
<body bgcolor="white">
<center><h1>429 Too Many Requests</h1></center>
<hr><center>openresty/1.13.6.2</center>
</body>
</html>

トークンイントロスペクション(Token Introspection Policy)

トークンイントロスペクションとは、APIリクエストに付与されたアクセストークンが有効かをアクセストークンの発行元であるKeycloakに確認し、有効であればAPIリクエストを許可し、無効であればAPIリクエストを拒否するというアクセス制御です(図6)。RFC 7662でOAuth 2.0の仕様の1つとして定義されており、Keycloakで無効にされたアクセストークンを用いたAPIリクエストを瞬時に遮断できるようになります。

図6:トークンイントロスペクション(Token Introspection Policy)

管理者ポータルから、トークンイントロスペクションを設定してみましょう(図7)。トークンイントロスペクションを実施するにはKeycloakのクライアントが必要ですが、「auth_type」という項目に「use_3scale_oidc_issuer_endpoint」を設定することで、OpenID Connectインテグレーションで設定した3scale用のクライアントをトークンイントロスペクションに使用できます。このポリシーでは、パフォーマンスを向上するためにトークンイントロスペクションの結果をキャッシュする設定も可能です。

図7:Hello APIのインテグレーション画面(トークンイントロスペクションの設定)

挙動を確かめてみます。アクセストークンが有効であれば通常通りAPIコールに成功しますが、無効の場合は以下のように「403 Forbidden」でAPIコールに失敗します。

$ curl -v "hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token"
< HTTP/1.1 403 Forbidden
Authentication failed

スコープチェック(RH-SSO/Keycloak Role Check Policy)

スコープチェックとは、APIリクエストに付与されたアクセストークンの中に、リクエスト先のAPIをコールするために必要なスコープが指定されているかを確認し、スコープが指定されていればAPIリクエストを許可し、指定されていなければAPIリクエストを拒否するというアクセス制御です(図8)。スコープは、RFC 6749で定義された認可フローにおいて、認可リクエスト時またはトークンリクエスト時に指定することでアクセストークンの中に指定されます。

図8:スコープチェック(RH-SSO/Keycloak Role Check Policy)

管理者ポータルから、スコープチェックを設定してみましょう(図9)。ここでは、「hello_scope」というスコープが指定されたアクセストークンを持つAPIリクエストのみ、「/myapp/api/hello」というAPIをコールできるように設定しています。

図9:Hello APIのインテグレーション画面(スコープチェックの設定)

挙動を確かめてみます。「hello_scope」というスコープが指定されていれば通常通りAPIコールに成功しますが、指定されていなければ以下のように「403 Forbidden」でAPIコールに失敗します。

$ curl -v "hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token"
< HTTP/1.1 403 Forbidden
Authentication failed

独自ポリシーの開発

3scaleでは、スタンダードポリシーのみならず、独自に開発したポリシーもポリシーチェーンに定義できます。ここでは、独自開発ポリシーの設定方法を説明します。

独自ポリシーの開発

ポリシーはLuaという言語で開発します。実際の開発方法は参考文書を紹介するに留めますが、3scaleへのパッチ貢献としては取っかかりやすい分野なので、興味ある方は挑戦してみてはいかがでしょうか。

開発環境は、APIcastリポジトリのREADMEを参考にDocker等を準備します。なお、開発環境自体はREADMEの手順を追うことで構築できますが、これからポリシー開発に参戦する人は、リポジトリに準備されているポリシーポリシー開発に関するマークダウンを一読することをお勧めします。

独自開発ポリシーのインポート

独自ポリシーを3scaleに適用するには、最後に開発したポリシーを3scaleにインポートする必要があります。ポリシーのインポート手順は、コミュニティで参考文献が公開されていないので、ここで簡単に紹介します。

まず、ポリシーデプロイ用のapicast-example-policyというリポジトリをローカルにクローンしましょう。開発したポリシーに合わせて、適宜OpenShiftのテンプレート(openshift.yml)やディレクトリ構造を変更します。

次に、以下のコマンドを実行してapicast-example-policyおよびapicast-custom-policiesをビルドします。その後、apicast-stagingおよびapicast-productionが再デプロイされ、開発したポリシーがAPIcastにインポートされます。

$ oc new-app -f openshift.yml --param AMP_RELEASE=2.4.0
$ oc start-build apicast-example-policy

ポリシーのインポートに成功するとポリシー一覧に表示され(図10)、ポリシーチェーンに定義できるようになります。

図10:Hello APIのインテグレーション画面(独自ポリシー)

おわりに

次回からは、レッドハット株式会社の杉本 拓さんにバトンタッチし、3scaleの他製品とのインテグレーション機能を紹介します。

株式会社 日立製作所
OSSソリューションセンタにて、API管理や認証周りのOSSの開発/サポート/普及活動に従事。3scaleおよびkeycloakコミュニティのコントリビュータであり、多数のコードをコミットしている。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています