クラウドネイティブなAPI管理を実現するKuadrantとそのサブプロジェクトAuthorino

Red Hatでソリューションアーキテクトをしている杉本 拓です。今回の赤帽ブログではKuadrantについてご紹介します。 Kuadrantは、Kubernetesで動作するアプリケーションを開発するデベロッパーが、そのKubernetesのサービスを安全に公開、利用できるようにするためのクラウドネイティブなAPI管理のオープンソースプロジェクトです。一般的にAPI管理の機能として、APIゲートウェイ、認証認可、流量制御、分析、デベロッパーポータル、課金などの機能が求められますが、Kuadrantではそれらの機能が疎結合なコンポーネントとして独立して動作することを目的として設計されています。まだすべてのコンポーネントが実装されている訳ではありませんが、認証認可についてはAuthorinoというサブプロジェクト、流量制御についてはLimitadorというサブプロジェクトで開発が進められています。このブログでは認証認可のAuthorinoについて、概要を紹介し、サンプルアプリケーションを動かしていきたいと思います。

Authorinoについて

Authorinoを使用することで、アプリケーションのソースコードに手を加えずに、業界標準となっている認証プロトコルや認可のポリシーを自由に組み合わせてAPIをセキュアにすることが可能になります。

AuthorinoはEnvoy ProxyExternal AuthorizationのgRPCプロトコルを実装しており、KubernetesのCustom Resource DefinitionsとOperatorパターンをベースにしています。

Authorinoを使用した認可のフローは以下のようになっています。 f:id:tsugimot:20220325144003p:plain

  1. ユーザーまたはサービスアカウント(以下、コンシューマ)は、Upstreamサービス (APIバックエンド) のリソースにアクセスするためのアクセストークンを取得し、Envoy ingressエンドポイントにリクエストを送信します。
  2. Envoy ProxyはAuthorinoとのgRPC接続を確立し、Authorino はHTTPリクエストのデータ(コンテキスト情報)を元にAuthConfigカスタムリソースを参照して認証認可を適用します。
  3. アイデンティティの検証(認証)フェーズ - Authorinoは、IDプロバイダを経由してコンシューマのIDを検証します。
  4. 外部メタデータフェーズ - Authorinoは、外部のデータソースから認可のための追加のメタデータを取得します(オプション)。
  5. ポリシー適用(認可)フェーズ - Authorinoは、コンテキスト情報、IDオブジェクト、前フェーズで取得した追加のメタデータから構成されるJSONを入力として受け取り、ユーザー定義の認可ポリシーを適用します。
  6. レスポンス(メタデータ出力)フェーズ - Authorinoは、ユーザー定義のカスタム・レスポンス(動的JSONオブジェクトやFestival Wristband OIDCトークン)を構成し、クライアントやアップストリーム・サービスにHTTPヘッダやEnvoyの動的メタデータとして提供します(オプション)。
  7. AuthorinoとEnvoyは、OK/NOK (Not-OK) のいずれかのレスポンスで認可プロトコルを処理します。
  8. 許可された場合、Envoyは他のHTTPフィルター(もしあれば)をトリガーし、Authorinoから返された動的メタデータをインジェクトし、最終的にリクエストをUpstreamにリダイレクトします。
  9. 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の仕様 を確認してください。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。