Apache APISIX 認証ポリシー:APIを保護する

Qi Guo

Qi Guo

April 21, 2023

Technology

はじめに

現在、APIはデータや機能の面でさまざまなシステムやアプリケーションを接続する橋渡し役となっています。APIの利便性を享受する一方で、データの安全性を確保し、データ漏洩などのセキュリティ問題を回避することがユーザーの主な関心事となっています。この点において、アクセス制御は重要な役割を果たします。APIに対して適切なアクセス制御ポリシーを策定することで、APIを膨大なサイバー攻撃から保護し、データの安全性を確保するだけでなく、企業がコンプライアンス要件を満たし、顧客の信頼を高めるのにも役立ちます。

Apache APISIXは、動的でリアルタイム、高性能なクラウドネイティブAPIゲートウェイであり、ロードバランシング、動的アップストリーム、カナリアリリース、サービスサーキットブレーカー、認証、可観測性など、豊富なトラフィック管理機能を提供します。本記事では、Apache APISIXのアクセス制御ポリシーを紹介し、APIのセキュリティを保護し、システムの安定した運用を確保するためにどのような一般的な戦略が利用できるかについて説明します。

アクセス制御ポリシーとは?

アクセス制御ポリシーは、コンピュータシステム、ネットワーク、またはアプリケーション内の機密データやリソースを保護するためのセキュリティメカニズムであり、許可されたユーザーやアプリケーションのみがそれらにアクセスできるようにします。これにより、データ漏洩やセキュリティ脆弱性のリスクを低減することができます。APIゲートウェイにおいて、アクセス制御ポリシーは不可欠な要素です。すべてのトラフィックのエントリーポイントとして、APIゲートウェイはすべてのAPIリクエストを受信し、転送する責任を負っています。したがって、APIゲートウェイのアクセス制御ポリシーは、アップストリームサービスの安全性と安定性を直接決定します。

Apache APISIXにおける一般的なアクセス制御ポリシー

Apache APISIXは、豊富なアクセス制御ポリシーを提供し、OAuth 2.0認証プロトコルをサポートし、Keycloak、Ory Hydra、Okta、Auth0などの外部認証サービスと統合しています。外部認証サービスをサポートするだけでなく、APISIXは強力な内部認証方法も提供します。APISIXのConsumerオブジェクトと組み合わせることで、認証、認可、レートリミット、IPブラックリスト、ホワイトリストプラグインを自由に組み合わせてAPIを保護し、悪意のあるリクエストがAPIサービスに損害を与えるのを効果的に防ぐことができます。

schematic

1. IPベースのアクセス制御

IPベースのアクセス制御は、最もシンプルで直接的な方法であり、特定のアドレスからのリクエストのみがAPIにアクセスできるように制限することができます。

APISIXのip-restrictionプラグインを使用してこの機能を有効にすることができます。このプラグインは、許可または拒否するIPアドレスのリスト、IPアドレスの範囲、リクエストを拒否した際に返されるエラーメッセージなど、さまざまな設定オプションを提供します。これらのオプションを必要に応じて設定することで、より細かい粒度のアクセス制御を実現できます。ただし、IPベースのアクセス制御にはいくつかの制限があることに注意が必要です。IPアドレスは偽装されたり共有されたりする可能性があるため、ip-restrictionプラグインを使用する際は、他のアクセス制御プラグインと組み合わせて使用することで、システムのセキュリティと柔軟性を向上させることが推奨されます。

2. APIキーベースのアクセス制御

このアクセス制御は、非常に一般的なAPIアクセス制御戦略です。その基本原理は、事前に生成されたAPIキーを使用してリクエストを認証および認可することで、APIに迅速に認証メカニズムを追加することができます。ただし、APIキーを保護し、漏洩や悪意のある攻撃を受けないようにすることが重要です。

APISIXのkey-authプラグインを使用すると、APIに簡単に認証メカニズムを追加できます。リクエストを送信する際に、クエリ文字列やヘッダーにキーを追加して認証を行います。APISIXバージョン3.1以降では、暗号化されたストレージフィールド data_encryption設定を使用して、APIキーをetcdに暗号化して保存することもサポートしており、APIのセキュリティをさらに強化できます。

3. トークンベースのアクセス制御

この方法は、リクエストヘッダーにトークンを含む認証フィールドを追加することで実装されます。トークンは、通常、文字列または数字で、APIリクエストの送信者がAPIにアクセスする権限を持っているかどうかを検証するために使用されます。一般的に、トークンにはユーザーの身元と権限が含まれており、ユーザーがAPIリクエストを開始した際に、サーバーがユーザーにアクセス権限があるかどうかを判断し、適切な認可または拒否の決定を行うことができます。

APISIXは、jwt-authプラグインを提供しており、このアクセス制御戦略を使用できます。トークンの保存場所、トークンの有効期間、JWT署名アルゴリズム、キーなどの設定オプションをサポートしています。これらのオプションを必要に応じて設定することで、さまざまな認証要件を満たすことができます。

4. リクエストパスベースのアクセス制御

リクエストパスベースのアクセス制御は、リクエストパスをフィルタリングしてマッチングすることで、特定のAPI、サービス、またはリソースへのアクセスを制御します。この戦略は、リソースに対する細かい粒度のアクセス制御が必要なシナリオでよく使用されます。例えば、機密データを保護したり、システム内の特定のリソースへの特定のユーザーのアクセスを制御する場合などです。

APISIXのuri-blockerプラグインは、正規表現ルールリストを設定してユーザーリクエストのURIをインターセプトし、rejected_coderejected_msgを設定して、インターセプト成功後に返されるHTTPステータスコードとレスポンスボディを指定することができます。これにより、管理者はユーザーの権限を細かく制御し、APIのセキュリティと制御性を向上させることができます。

5. ACLベースのアクセス制御ポリシー

ACL(アクセス制御リスト)は、リストベースのアクセス制御ポリシーであり、ユーザーまたはユーザーグループのリソースへのアクセス権限を制御するために使用されます。その基本原理は、各リソースに対してACLリストを定義し、そのリソースにアクセスを許可するユーザーまたはユーザーグループをリストアップすることです。ユーザーがリソースへのアクセスをリクエストした際に、対応するACLリストに基づいてアクセスが決定されます。

APISIXでは、consumer-restrictionを使用してこの機能を有効にすることができます。管理者は、特定のリソースにアクセスできるユーザーまたはユーザーグループを簡単に制御し、許可されていないユーザーが機密領域にリクエストを送信するのを防ぎ、機密データの漏洩を回避できます。

シナリオ紹介: より細かい粒度のアクセス制御

実際のアプリケーションシナリオでは、機密データを含むリソースに対してより細かい粒度のアクセス制御を実装することがよくあります。例えば、現在、ユーザーAとユーザーBの2人のユーザーがおり、同じ内部認証方法(key-authやbasic-authなど)を使用しています。また、ユーザーBに対して、特定のAPIにアクセスできないようにするためのより細かい粒度のアクセス制御を適用したいと考えています。

schematic_2

APISIXのconsumer-restrictionプラグインを使用して、より細かい制御を行うことができます。このプラグインでは、Route、Service、またはConsumerに基づいてアクセス制限を設定することができ、4つのtype属性値を設定できます:

  • consumer_name: Consumerのusernameをホワイトリストまたはブラックリストに登録して、RouteまたはServiceへのアクセスを制限します。
  • consumer_group_id: Consumer Groupのidをホワイトリストまたはブラックリストに登録して、RouteまたはServiceへのアクセスを制限します。
  • service_id: Serviceのidをホワイトリストまたはブラックリストに登録して、ConsumerのServiceへのアクセスを制限します。これは認証プラグインと併用する必要があります。
  • route_id: Routeのidをホワイトリストまたはブラックリストに登録して、ConsumerのRouteへのアクセスを制限します。

このシナリオでは、ユーザーBが特定のAPIリソースにアクセスできないようにするために、2つの設定方法を使用できます。

Routeでのアクセス制御ポリシーの設定

  1. まず、APISIX上に2つのConsumerオブジェクトを作成し、basic-authプラグインを有効にします。名前はuserAとuserBとします。
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
  "username": "userA",
  "plugins": {
    "basic-auth": {
      "username":"userA",
      "password": "123456"
    }
  }
}'
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
  "username": "userB",
  "plugins": {
    "basic-auth": {
      "username":"userB",
      "password": "123456"
    }
  }
}'
  1. 次に、制限を適用するRouteでconsumer-restrictionwhitelistプロパティを有効にして設定し、先に作成したConsumer userAのusernameを追加します。これにより、このRouteはuserAからのリクエストのみを受け付けるようになります。
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -d '
{
  "uri": "/get",
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "httpbin.org:80": 1
    }
  },
  "plugins": {
    "basic-auth": {},
    "consumer-restriction": {
      "whitelist": [
        "userA"
      ]
    }
  }
}'
  1. userAとuserBを使用して、それぞれアクセスリクエストを送信します。
curl -u userA:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 200 OK
curl -u userB:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 403 Forbidden
...
{"message":"The consumer_name is forbidden."}

結果から、userBがAPIリソースへのアクセスを制限されていることが確認できます。

Consumerでの権限制御ポリシーの設定

  1. まず、IDがforbidden-userBというRouteを設定し、basic-authプラグインを有効にします。
curl http://127.0.0.1:9180/apisix/admin/routes -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -d '
{
  "id": "forbidden-userB",
  "uri": "/get",
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "httpbin.org:80": 1
    }
  },
  "plugins": {
    "basic-auth": {}
  }
}'
  1. 2つのConsumerオブジェクトを作成し、basic-authプラグインを有効にします。ただし、userBに対しては、consumer-restrictionプラグインを設定して、権限制御ポリシーを細かく設定する必要があります。
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
  "username": "userA",
  "plugins": {
    "basic-auth": {
      "username":"userA",
      "password": "123456"
    }
  }
}'
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
  "username": "userB",
  "plugins": {
    "basic-auth": {
      "username":"userB",
      "password": "123456"
    },
    "consumer-restriction": {
      "type": "route_id",
      "blacklist": [
        "forbidden-userB"
      ],
      "rejected_code": 403
    }
  }
}'
  1. userAとuserBを使用して、それぞれリクエストを送信します。
curl -u userA:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 200 OK
curl -u userB:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 403 Forbidden
...
{"message":"The route_id is forbidden."}

テスト結果を確認することで、userBのリクエストが効果的に制限されていることを確認できます。

結論

本記事では、APISIXでよく使用される権限制御ポリシーを紹介し、クラシックなシナリオを使用してAPISIXでそれらを有効化および設定する方法を説明しました。権限制御はAPIゲートウェイにおいて一般的な戦略です。APISIXは、認証のためのすぐに使用できるプラグインを提供するだけでなく、セキュリティ、トラフィック管理、可観測性などの分野でも広範なサポートを提供しています。権限制御ポリシールールを選択して設定することで、APIのセキュリティを簡単に強化することができます。

Tags: