OSSベースのAPI管理製品 3scale 2.2を試してみた

初版: 2018/7/10
著者: 田畑義之, 株式会社日立製作所 (GitHubアカウント: [@y-tabata](https://github.com/y-tabata))
本記事は、あくまで執筆者の見解であり、所属企業及びRed Hatの公式なドキュメントではありません。

昨今API管理の分野が注目を集めています。筆者は、API管理製品の一つ、3scaleに着目し、検証やパッチ投稿を進めていました。最近2.2がリリースされ、大きく機能強化されて面白くなってきたため、紹介します。

# はじめに
2018年5月31日、Red Hat 3scale API Management (以下、3scale)の[バージョン2.2](https://access.redhat.com/documentation/en-us/red_hat_3scale/2.2/html/release_notes/)がリリースされました。2017年10月27日の2.1のリリースから約7か月ぶりの新バージョンです。
本稿では、3scale 2.2の新機能を紹介します。

# 3scaleとは
3scaleとは、Red Hatが開発するAPI管理製品です。
3scaleは、APIの認可認証、分析、流量制御、管理者ポータル、開発者ポータル、Swaggerエディタ、CMS、収益化など、API管理製品に求められる基本的な機能を一通り備えています。
また、Kubernetesのエンタープライズ版であるOpenShift上で動くため、下記の特徴を持ちます。

- 用途に合わせて柔軟にデプロイやスケールができる
- 障害時の影響範囲を局所化できる
- 障害から自動で復旧できる

さらに、認可認証に関しても、昨今注目のOSSであるKeycloakと連携することで、OpenID Connectに対応することができます。

3scaleは、[APIcast](https://github.com/3scale/apicast)、System、[Backend](https://github.com/3scale/apisonator)、[Zync](https://github.com/3scale/zync)の4つのコンポーネントから成り、そのうちSystem以外の3つのコンポーネントはオープンソース化されています。Systemも近いうちにオープンソース化される見込みです。**(2018年9月19日、[System](https://github.com/3scale/porta)もOSS化されました。)**

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/3176b785-c4c6-05aa-4f4c-948fab16134c.png" width="700">

2018年6月25日時点では、完全なOSS化はまだなものの、Red Hat社の[Container Catalog](https://access.redhat.com/containers/)にて3scaleのコンテナイメージが公開されているため、コミュニティ版のOpenShiftであるOpenshift Origin上でも、自己責任・無保証で3scaleを使うことができます。サポートが必要な場合は、Red Hat社よりサブスクリプションの購入が必要です。
また、コミュニティが活発なため、良い機能であると判断されれば、自分のコードを入れ込むことができます。 このように自分のコードが受け入れられるところも3scaleの魅力の一つです。

# 2.2の新機能
2.2の新機能を紹介します。
2.2の新機能の中でも、目玉の機能は下記2つです。

- マルチテナント
- ポリシー

本稿では上記2つの機能を紹介します。
他の新機能の詳細は[リリースノート](https://access.redhat.com/documentation/en-us/red_hat_3scale/2.2/html/release_notes/release-notes)をご参照ください。

## マルチテナント
マルチテナントとは、その名の通り、1つの3scaleを複数のAPI管理者が共同で利用するための機能です。このとき、もちろん1テナントのAPI管理者は、他のテナントのリソースを参照することはできません。 マルチテナントは、下記ユースケースで有効です。

- 複数企業に対し、API管理サービスを提供する<br>
  マルチテナント機能がない場合、企業ごとに3scaleインスタンスを立ててサービスを提供する必要がありますが、マルチテナント機能を用いると、1つの3scaleで複数企業に対してサービスを提供することができます。<br>
  これにより、マシンリソースの削減および管理負荷の軽減を実現できます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/6ba905db-60f8-2f88-a68a-1b6b656ceeb6.png" width="500">

### 2.1までの課題
3scaleには、2.1以前、もともとAdminユーザとMemberユーザの2種類のユーザがいました。

- Adminユーザ: すべてのリソースにアクセスできる
- Memberユーザ: Adminユーザの補佐役という立ち位置で、Adminユーザから割り当てられたリソースにのみアクセスできる

2.1以前も、Memberユーザに対して異なるリソースを割り当てることで、アクセス可能なリソースを制限することはできましたが、開発者ポータルやダッシュボードなど、一部アクセス制限できない機能も存在し、マルチテナント機能としては不完全でした。

### 2.2では
2.2では、新たにMaster Adminユーザというユーザが追加されました。

- Master Adminユーザ: テナントを管理する

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/d81766a3-ab21-47b9-676a-34a2d283d8e4.png" width="500">

Master Adminユーザの追加に伴い、マスター管理者ポータルが追加され、Master Adminユーザは当該ポータルを用いて、テナントを管理します。マスター管理者ポータルの見た目は、管理者ポータルと似ていますが、下図のように、左上に`Master`と表示されます。Adminユーザによる管理者ポータルの見え方は2.1以前と変わりませんが、他テナントのリソースを参照することはできません。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/46cb2199-1d2a-f263-558a-3e9d76f4ab58.png" width="300">

OpenShift上では、マスター管理者ポータル用のコンテナが1つ増えました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/7ddf5943-b82e-3f6d-910f-e1c78660af8d.png" width="800">

マスター管理者ポータルを用いて、テナントを追加してみます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/e5b2f9be-763e-1270-fdc4-e2277cd11dc2.png" width="700">

テナントが追加されました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/c13c6525-ec17-f391-e21a-3ead286bd221.png" width="700">

しかし、このままでは管理者ポータルにはアクセスできません。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/643e915d-c08f-67a3-a09e-ee5daf5c2d40.png" width="700">

OpenShiftで、system-providerサービスのRouteを追加します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/ba0d2242-b10d-9d41-7359-9869bc05f82f.png" width="700">

管理者ポータルにアクセスすることができました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/62fc7617-50ec-3e20-cb89-3c75613ca170.png" width="700">

## ポリシー
ポリシーとは、3scaleのAPI GatewayであるAPIcastに、任意の機能を実装するためのプラグインです。 本機能により、APIcastにポリシーを追加することで機能拡張できるようになり、APIcastの拡張性が格段に向上しただけではなく、強力なポリシーの開発によって、APIcast自体の機能も強化されています。

ポリシーは、ポリシーチェーンという形で順序付けして定義します。
下図の例では、流量制御ポリシー、トークンイントロスペクションポリシー、APIcastポリシーの順番でポリシーチェーンに定義しています。APIのアクセス制御等を行うAPIcast自身の機能もAPIcastポリシーとして定義されています。各ポリシーは、特定のNGINXのフェーズごとに処理を実装しています。例えばAPIcastポリシーは、リライトフェーズ、アクセスフェーズ、ポストアクションフェーズに処理を実装しています。各ポリシーは、NGINXのフェーズごとに、ポリシーチェーンで定義した順番で処理を実行します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/13b9de1d-bc97-161d-f5ea-471f879ccebb.png" width="500">

### 2.1までの課題
実は2.1でも、ポリシー機能はテクノロジプレビュー機能(Red Hat社により正式にサポートされない機能)として存在しました。しかし、下記のような構築・運用上の課題がありました。

- ポリシー定義時およびポリシーのプロパティ変更時は、イメージの作成およびAPIcastの再デプロイが必要なため、APIcastが瞬断される。
- ポリシーを利用する場合、管理者ポータルを用いたサービス(API)の設定変更は反映されなくなる。設定変更を反映する場合は上記同様、イメージの作成およびAPIcastの再デプロイが必要である。

### 2.2では
2.2では、テクノロジプレビューが取れ、正式サポート機能になり、上記のような構築・運用上の課題もなくなりました。さらに、管理者ポータルのIntegrationビューで、ポリシーを設定できるようになりました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/56b4f902-67a1-62c9-801e-309a80ce26cf.png" width="600">

上図のように、現在、下記ポリシーがデフォルトで選択可能です。

- トークンイントロスペクションポリシー (テクノロジプレビュー)<br>
  APIリクエストに付与されたアクセストークンの有効期限をチェックするポリシー。
- アップストリームポリシー<br>
  APIリクエストを正規表現でパースし、マッチした場合、指定したURLをコールするポリシー。一つのサービス(API)による複数バックエンドを実現できる。
- 流量制御ポリシー (テクノロジプレビュー)<br>
  APIリクエストの流量制御を実現するポリシー。
- URL書き換えポリシー<br>
  APIリクエストのパスを正規表現で置換し変更するポリシー。アップストリームポリシーとの違いは、URLのホストを変更できないことと、正規表現を使ってURLを置換すること。
- エコーポリシー<br>
  APIリクエストの内容をそのままボディに出力してレスポンスするポリシー。
- SOAPポリシー<br>
  APIリクエストのSOAPActionまたはContent-Typeヘッダを用いて、独自のマッピングルールを設定するポリシー。
- ヘッダポリシー<br>
  APIリクエストおよびレスポンスのヘッダを変更するポリシー。
- CORSポリシー<br>
  APIcastへのCORSリクエストを可能にするポリシー。
- キャッシュポリシー<br>
  APIリクエストの認可認証結果をキャッシュすることで、スループットの向上およびBackendコンポーネント停止時の縮退運転を実現するポリシー。

また、2.2では独自のポリシーを導入することもできます。独自のポリシーを[Red Hat社公式手順](https://access.redhat.com/solutions/3483041)に沿って導入すると、管理者ポータルのIntegrationビューで独自のポリシーを選択できるようになります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/8bebf79d-f4cb-9a6b-26e4-3cc0b687ee0d.png" width="600">

ポリシーをGUIで設定できるようになったことにより、APIcastを手軽にカスタマイズできるようになりました。

### ポリシー機能の今後
冒頭でも紹介したように、3scaleの魅力の一つは、良い機能であると判断されれば、自分のコードが受け入れられるところです。
OSSで公開されている[apicastリポジトリ](https://github.com/3scale/apicast)にプルリクエストを出すことで、新たなポリシーを提案することが可能です。現在活発に開発が進んでおり、筆者もコミュニティでの開発に参加しています。次のバージョン2.3に向けて、特に注目のポリシーを紹介します。

#### 流量制御(Rate Limit)ポリシー
2.1以前の流量制御機能は、クライアントアプリケーションごとにAPIリクエスト数を制限することが主目的であり、Backendコンポーネントにて行われてきました。
しかし、APIバックエンド(リソースサーバ)を急激な流量増加から保護したい等の目的に適用しようとすると、下記課題がありました。

- 流量制御を非同期で行っているため、厳密な流量制御ができない
- アプリケーション単位の流量制御しかできない

これらの課題に対して、筆者は、APIcast側での流量制御をポリシーとしてパッチ投稿しました。基本的な機能については[PR #648](https://github.com/3scale/apicast/pull/648)で提案し、採用されました。テクノロジプレビューながら3scale 2.2から取り込まれています。

流量制御ポリシーでは、下記が可能です。

- APIcastが流量制御機能を持つことで、既存のアーキテクチャを踏襲しつつ、厳密な流量制御ができる
- サービス(API)単位およびグローバルでの(全サービスにわたる)流量制御ができる

また、本ポリシーでは、単位時間の上限値を制御する流量制御方法以外にも、下記の流量制御方法を新たに選択できます。

- バックエンドへのコネクション数を制御する方法
- 1秒間のリクエスト数を制御する方法(リーキーバケットアルゴリズム)

これらは、急激な流量増加からのAPIバックエンドの保護などに役立てることができます。

以上のように、2.2で導入された流量制御ポリシーは、既存の流量制御機能の課題を解決しつつ、ユースケースの幅を広げるという、非常に強力なものとなっています。

さらに、2.3に向けて下記のような改良パッチを提案し、取り込まれており、次バージョンではさらに使い勝手の良い流量制御ポリシーになっていくと思います。

- [PR #703](https://github.com/3scale/apicast/pull/703): カウント値のキャッシュをRedisに保存した場合、プロパティの変更が適用されないことがあるという問題点([Issue #667](https://github.com/3scale/apicast/issues/667))への対応。
- [PR #719](https://github.com/3scale/apicast/pull/719): Liquidテンプレートをサポート。ngx.var.VARIABLEを用いた、APIリクエストのホストやパス単位の流量制御や、アクセストークン(jwt)を用いた、AudienceやIssuer単位の流量制御が可能となります。

#### トークンイントロスペクション(Token Introspection)ポリシー
3scaleはKeycloakと連携することで、OpenID Connectに対応したAPI認可・認証をサポートすることができます。ここで、OpenID Connectで発行されたアクセストークンが正当であるかのチェックが必要になります(改ざんされていないか、Keycloak側で無効にされていないか)。アクセストークンの正当性については、Keycloakに「トークンイントロスペクション」という形で問い合わせをすると確認できますが、確認ロジックをAPIバックエンドごとに実装するのは煩雑です。そこで、同僚の[茂木さん(@tmogi001)](https://github.com/tmogi001)がAPIcast側でトークンイントロスペクションを行うトークンイントロスペクションポリシー([PR #619](https://github.com/3scale/apicast/pull/619))を提案し、採用されました。テクノロジプレビューながら3scale 2.2から取り込まれています。

このポリシーについても、継続的な改良が加えられています。APIリクエストのたびにKeycloakにトークンイントロスペクションを行うとパフォーマンスに問題が生じるため、問い合わせ結果をキャッシュする機能([PR #655](https://github.com/3scale/apicast/pull/656)) がコアメンバにより開発され、導入されました。 また、筆者も開発に参加し、設定項目の入力を簡単にするユーザビリティ改善([PR #755](https://github.com/3scale/apicast/pull/755))を提案し、採用されました。

#### スコープチェック(Keycloak Role Check)ポリシー
スコープチェックとは、APIリクエストが「リソース」にアクセスするために必要な「ロール」を持っているかどうかチェックする機能です。本機能により、クライアントごとの煩雑なアクセス制御に代わって、「ロール」を用いたダイナミックなアクセス制御ができるようになります。クライアントアプリケーションが要求し、エンドユーザが許可した「ロール」は、OpenID Connectで発行されたアクセストークンに含まれます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/267112/7e5b1792-0d3e-e8a7-0ba2-46fc85a3d340.png" width="700">

スコープチェックの機能を、APIcastで持つのか、APIバックエンドで持つのか、Enterprise Service Busで持つのかに関しては、議論の余地があり、それぞれにメリット・デメリットがあるため、API管理者の好みやシステム要件により、スコープチェックの実装箇所は変わりますが、2.1以前はAPIcastでのスコープチェックは実現できませんでした。

「APIcastでのスコープチェック」という選択肢を実現し、より幅広いユースケースに対応できるように、筆者は[PR #773](https://github.com/3scale/apicast/pull/773)でパッチ提案し、採用されました。

# おわりに

本稿では、3scale 2.2の新機能を紹介しました。
マルチテナント機能とポリシー機能を筆頭に、多くの機能が追加され、3scaleは更なるパワーアップを遂げました。
現在も、コミュニティで活発な議論が交わされており、次バージョンでも更なるパワーアップが期待できます。
現在注目を集めているAPI管理の分野で、3scaleのコミュニティに参画し、自分好みのAPI管理を実現してみてはいかがでしょうか。