Red Hatでソリューションアーキテクトをしている杉本 拓です。今回の赤帽ブログではKuadrantについてご紹介します。 Kuadrantは、Kubernetesで動作するアプリケーションを開発するデベロッパーが、そのKubernetesのサービスを安全に公開、利用できるようにするためのクラウドネイティブなAPI管理のオープンソースプロジェクトです。一般的にAPI管理の機能として、APIゲートウェイ、認証認可、流量制御、分析、デベロッパーポータル、課金などの機能が求められますが、Kuadrantではそれらの機能が疎結合なコンポーネントとして独立して動作することを目的として設計されています。まだすべてのコンポーネントが実装されている訳ではありませんが、認証認可についてはAuthorinoというサブプロジェクト、流量制御についてはLimitadorというサブプロジェクトで開発が進められています。このブログでは認証認可のAuthorinoについて、概要を紹介し、サンプルアプリケーションを動かしていきたいと思います。
Authorinoについて
Authorinoを使用することで、アプリケーションのソースコードに手を加えずに、業界標準となっている認証プロトコルや認可のポリシーを自由に組み合わせてAPIをセキュアにすることが可能になります。
AuthorinoはEnvoy ProxyのExternal AuthorizationのgRPCプロトコルを実装しており、KubernetesのCustom Resource DefinitionsとOperatorパターンをベースにしています。
Authorinoを使用した認可のフローは以下のようになっています。
- ユーザーまたはサービスアカウント(以下、コンシューマ)は、Upstreamサービス (APIバックエンド) のリソースにアクセスするためのアクセストークンを取得し、Envoy ingressエンドポイントにリクエストを送信します。
- Envoy ProxyはAuthorinoとのgRPC接続を確立し、Authorino はHTTPリクエストのデータ(コンテキスト情報)を元にAuthConfigカスタムリソースを参照して認証認可を適用します。
- アイデンティティの検証(認証)フェーズ - Authorinoは、IDプロバイダを経由してコンシューマのIDを検証します。
- 外部メタデータフェーズ - Authorinoは、外部のデータソースから認可のための追加のメタデータを取得します(オプション)。
- ポリシー適用(認可)フェーズ - Authorinoは、コンテキスト情報、IDオブジェクト、前フェーズで取得した追加のメタデータから構成されるJSONを入力として受け取り、ユーザー定義の認可ポリシーを適用します。
- レスポンス(メタデータ出力)フェーズ - Authorinoは、ユーザー定義のカスタム・レスポンス(動的JSONオブジェクトやFestival Wristband OIDCトークン)を構成し、クライアントやアップストリーム・サービスにHTTPヘッダやEnvoyの動的メタデータとして提供します(オプション)。
- AuthorinoとEnvoyは、OK/NOK (Not-OK) のいずれかのレスポンスで認可プロトコルを処理します。
- 許可された場合、Envoyは他のHTTPフィルター(もしあれば)をトリガーし、Authorinoから返された動的メタデータをインジェクトし、最終的にリクエストをUpstreamにリダイレクトします。
- Upstreamは要求されたリソースをコンシューマに提供します。
AuthorinoでのAPIキーによる認証
ではAuthorinoでAPIキーを使用した認証がどのように行われるのか、Authorinoのユーザガイドにあるサンプルアプリケーションで確認していきましょう。
AuthorinoはKubernetesで動作しますが、ここではローカルにKubernetesクラスタを簡単に構築できるツールKindを使用します。Kindのセットアップについては、こちらのページ (https://kind.sigs.k8s.io/) をご参照ださい。Authorinoのサンプルアプリケーションを動かすために、以下のKindを使用してKubernetesクラスタ環境を構築しておきます。
kind create cluster --name authorino-trial
1 - Authorinoオペレータのインストール
kubectl apply -f https://raw.githubusercontent.com/Kuadrant/authorino-operator/main/config/deploy/manifests.yaml
2 - ネームスペースの作成
kubectl create namespace authorino
3 - Talker API のデプロイ
Talker APIはAuthorinoに含まれているサンプルのAPI実装で、HTTPのレスポンス情報を返すシンプルなEcho APIとなっており、ここではこのTalker APIをAPIキーを使用して保護します。
kubectl -n authorino apply -f https://raw.githubusercontent.com/kuadrant/authorino-examples/main/talker-api/talker-api-deploy.yaml
4 - Authorinoのデプロイ
kubectl -n authorino apply -f -<<EOF apiVersion: operator.authorino.kuadrant.io/v1beta1 kind: Authorino metadata: name: authorino spec: listener: tls: enabled: false oidcServer: tls: enabled: false EOF
このコマンドにより、AuthorinoはTalker APIのサイドカーやその他のサービスとは別のサービスとして、TLS終端は無効状態でデプロイされます。
5 - Envoyのセットアップ Authorinoに含まれるサンプルアプリケーションでは、以下のコマンドによりEnvoyの設定を行い、Envoy Proxyをデプロイします。これによりEnvoy ProxyがTalker APIのリバースプロキシとなり、AuthorinoでEnvoyのExternal Authorizationが適用されるようになります。
kubectl -n authorino apply -f https://raw.githubusercontent.com/kuadrant/authorino-examples/main/envoy/envoy-notls-deploy.yaml
上記コマンドでは、talker-api-authorino.127.0.0.1.nip.io というホスト名でIngressが作成されますが、Kindコマンドを使用して構築されたローカルのKubernetesクラスタを使用している場合、リクエストがEnvoyサービスに到達できるようにするためには8000ポートへのリクエストをKubernetesクラスタにフォワードする必要があります。
kubectl -n authorino port-forward deployment/envoy 8000:8000 &
6 - AuthConfigの作成
kubectl -n authorino apply -f -<<EOF apiVersion: authorino.kuadrant.io/v1beta1 kind: AuthConfig metadata: name: talker-api-protection spec: hosts: - talker-api-authorino.127.0.0.1.nip.io identity: - name: friends apiKey: labelSelectors: group: friends credentials: in: authorization_header keySelector: APIKEY EOF
7 - APIキーの作成
kubectl -n authorino apply -f -<<EOF apiVersion: v1 kind: Secret metadata: name: api-key-1 labels: authorino.kuadrant.io/managed-by: authorino group: friends stringData: api_key: ndyBzreUzF4zqDQsqSPMHkRhriEOtcRx type: Opaque EOF
8 - APIへのリクエスト 適切なAPIキーをつけてAPIに対してリクエストを行う場合:
curl -H 'Authorization: APIKEY ndyBzreUzF4zqDQsqSPMHkRhriEOtcRx' http://talker-api-authorino.127.0.0.1.nip.io:8000/hello # HTTP/1.1 200 OK
この場合認証が成功し、200のステータスコードでレスポンスが返ってきます。
不適切なAPIキーをつけてAPIに対してリクエストを行う場合:
curl -H 'Authorization: APIKEY invalid' http://talker-api-authorino.127.0.0.1.nip.io:8000/hello -i # HTTP/1.1 401 Unauthorized # www-authenticate: APIKEY realm="friends" # x-ext-auth-reason: the API Key provided is invalid
APIキーが無かったり正しくない場合には認証に失敗し、401のステータスコードでレスポンスが返ってきます。
9 - APIキーの削除(APIへのアクセスの取り消し)
kubectl -n authorino delete secret/api-key-1
以上のように、Authorinoを使用することでAPIの実装に手を加えることなく、APIキーを使用してAPIを保護することができるようになります。
上記のサンプルアプリケーションの環境をクリーンアップするには、以下のコマンドを実行することでKubernetesクラスタを削除することができます。
kind delete cluster --name authorino-trial
ステップ1と2で作成したネームスペースだけを削除したい場合には以下のコマンドを実行します。
kubectl -n authorino namespace authorino kubectl -n authorino namespace authorino-operator
Authorinoのユーザガイドには、他にもOAuth2のトークンイントロスペクション、OIDCのJWT認証、OIDCのRBAC、トークンの正規化、Keycloackとの連携など、さまざまなサンプルアプリケーションが公開されています。
その他のデプロイ方式、AuthorinoのアーキテクチャやCRDの詳細情報については、ドキュメントのGetting Startedページ、Architectureページ、Authorino OperatorリポジトリにあるAuthorino CRDの仕様 を確認してください。