備忘のためのメモ。
KONGとは?
API GatewayのためのOSSです。
マイクロサービス化された各種APIのフロントに立って、認証やルートの管理、流量制限、などなど各種機能を便利に行ってくれます。
この記事ではKONGの認証管理の機能について少し解説します。
KONGの認証機能
KONGはプラグインの方式を採用しており、必要な機能を必要な経路に対して適用させるといったことができます。
例えば、以下のような3つのサービスのフロントにKONGを立てた場合、Publicサービスには特に認証用プラグインを適用せずに誰でもアクセス可能に、Privateサービスの2つは認証プラグインを適用するといった感じです。
認証関連のプラグイン
KONG Hubというページでどのようなプラグインが利用可能か公開されています。
認証関連だと、以下のようなプラグインがあります。
- JWT認証プラグイン
- Basic認証プラグイン
- Key認証プラグイン
- OAuth認証プラグイン
- LDAP認証プラグイン
各種認証プラグインに対応しているので、場合によっては1つのサービス・ルートに対して複数の認証手法を有効にしたいといった場合もあるのではないでしょうか。
フロントエンドからのアクセスにはJWT認証で、バックエンドのAPI連携にはKey認証でといった具合に。
認証方法が違う場合にはルートのパス自体を変えてしまうというのもありですが、認証毎にパスを変えるというのも手間です。
そこで、以下は1つのルートに複数の認証を有効にする方法です。
1ルートに複数の認証プラグインを有効にする方法
今回は、Basic認証プラグインとKey認証プラグインを有効にする場合の例を紹介します。
単純に1つのルートにBasic認証もKey認証も有効にしてしまうと、両方の条件をクリアしないと認証が通らないようになってしまいます。
実現するためのポイントはAnonymousユーザをうまく活用することです。
最終的な流れは以下のようになります。
このようにAnonymousユーザとRequestTerminationプラグインを使います。
確認するには以下の手順で実施できます。
設定
- サービス登録
- ルート登録
- Consumerを登録(アクセスユーザとAnonymousユーザ)
- ルートに対してBasic認証プラグインを有効化
- ルートに対してKey認証プラグインを有効化
- ルートに対してRequestTerminationプラグインを有効化
- ConsumerにBasic認証の登録
- ConsumerにKey認証のKey発行
アクセス確認
- Basic認証情報を渡してアクセス
- 通過
- Keyを渡してアクセス
- 通過
- Basic認証もKeyも渡さずにアクセス
- 拒否
サービス登録
まず最初に、KONGにサービスを登録します。
$ curl -i -X POST \
--url http://kong-server:8001/services/ \ #8001ポートはKongの管理APIポート
--data 'name=private-service1' \
--data 'url=http://private-server1:3000'
ルートを登録
次に、そのサービスに対して、KONGのどのパスに来たリクエストを流すかのルート情報を登録します。
$ curl -i -X POST \
--url http://kong-server:8001/services/private-service1/routes \
--data 'paths[]=/private1'
この状態で、KONGのサーバに対して/private1で来たリクエストがprivate-server1:3000に転送されます。
Consumerを登録
Consumer(ユーザ)を登録します。
この時、実際にアクセスを行うユーザに紐づくConsumerとAnonymousユーザとなるConsumerの2つを作成します。
Anonymousユーザ
$ curl -XPOST 'http://kong-server:8001/consumers' --data "username=anonymouse-user" | jq
{
"custom_id": null,
"created_at": 1559570799,
"username": "anonymouse-user",
"id": "11df874f-5cb1-4841-a586-acdb9189329d"
}
アクセスを行うユーザ
$ curl -XPOST 'http://kong-server:8001/consumers' --data "username=ike-dai" | jq
{
"custom_id": null,
"created_at": 1559571249,
"username": "ike-dai",
"id": "1b4793c8-1cbb-49da-8a1d-033828559495"
}
ルートに対してBasic認証有効化
作成したルートに対してBasic認証を有効化します。この時、Basic認証プラグインの設定オプションでconfig.anonymousに先程作成したanonymous-userのIDを設定することがポイントです。
$ curl -XPOST 'http://kong-server:8001/routes/9976138f-be9d-4eeb-866e-53f4bc6f8913/plugins' --data "name=basic-auth" --data "config.anonymous=11df874f-5cb1-4841-a586-acdb9189329d" --data "config.hide_credentials=true" | jq
{
"created_at": 1559648627269,
"config": {
"hide_credentials": true,
"anonymous": "11df874f-5cb1-4841-a586-acdb9189329d"
},
"id": "c09b33b9-0fe4-4518-8081-88dec453afb6",
"name": "basic-auth",
"route_id": "9976138f-be9d-4eeb-866e-53f4bc6f8913",
"enabled": true
}
ルートに対してKey認証有効化
同様にKey認証も有効化します。
$ curl -XPOST 'http://kong-server:8001/routes/9976138f-be9d-4eeb-866e-53f4bc6f8913/plugins' --data "name=key-auth" --data "config.anonymous=11df874f-5cb1-4841-a586-acdb9189329d" | jq
{
"created_at":1559561179521,
"config: {
"key_in_body":false,
"run_on_preflight":true,
"anonymous":"11df874f-5cb1-4841-a586-acdb9189329d",
"hide_credentials":false,
"key_names":["apikey"]
},
"id":"c91a9ba2-aba3-496b-b21a-8378e4067cce",
"name":"key-auth",
"route_id":"9976138f-be9d-4eeb-866e-53f4bc6f8913",
"enabled":true
}
ルートに対してRequestTerminationプラグインを有効化
この状態だとAnonymousユーザが両方のプラグインに設定されているので誰でも通過できてしまう状態です。
RequestTerminationでAnonymousユーザのリクエストを遮断します。
$ curl -XPOST 'http://kong-server:8001/plugins' --data 'name=request-termination' --data 'consumer_id=11df874f-5cb1-4841-a586-acdb9189329d' --data 'config.status_code=403' --data 'config.message=required authenticaion' | jq
{
"created_at":1559572720677,
"config": {
"status_code":403,
"message":"required authenticaion"
},
"id":"618a364b-10c3-42a9-a915-afd4b7fafb68",
"name":"request-termination",
"enabled":true,
"consumer_id":"11df874f-5cb1-4841-a586-acdb9189329d"
}
これで基本設定はOKです。
ConsumerにBasic認証の登録
ユーザ認証を行いたいユーザに対して登録します。
$ curl -XPOST 'http://kong-server:8001/consumers/ike-dai/basic-auth' --data 'username=ike-dai' --data 'password=test' | jq
{
"created_at": 1559649081651,
"id": "8f64eeb5-287d-4db6-b54c-bdab346bd912",
"username": "ike-dai",
"password": "27bb533f151c98c3022b4355c979bbd8577f8122",
"consumer_id": "007c5866-abd1-40e0-95f9-723fdef4dbb6"
}
ConsumerにKey認証のKey発行
$ curl -X POST http://kong-server:8001/consumers/ike-dai/key-auth -d '' | jq
{
"id": "2625103a-0b6e-45ca-9185-e1aa17c1f4f0",
"created_at": 1559561684423,
"key": "yg6eZBFt8G5kPu3h6Prab123nfd12W5FLApa",
"consumer_id": "007c5866-abd1-40e0-95f9-723fdef4dbb6"
}
以上で準備完了
Basic認証でアクセス
作成したike-daiユーザを使ってBasic認証アクセスしてみます。
<ユーザID:パスワード>をbase64encodingしてHeaderに渡せばOKです。
$ curl -XGET http://kong-server/private1 -H 'Authorization: Basic aWtlLWRhaTp0ZXN0'
サービスからの応答あり
Key認証でアクセス
作成したike-daiユーザに発行されたキーを使ってアクセスします。
$ curl -XGET http://kong-server/private1 -H ' -H 'apikey: yg6eZBFt8G5kPu3h6Prab123nfd12W5FLApa'
サービスからの応答あり
Basic認証もKeyも渡さずにアクセス
$ curl -XGET http://kong-server/private1
required authenticaion
終わりに
KONGのプラグインはいろいろと組み合わせて使うことができ活用の幅は広そうです。
この辺りを自分で作るのは骨が折れるのでうまくやってくれるツールはありがたいです。