はじめに
オープンソースのAPIゲートウェイであるKongを利用し、APIに対するアクセス制御方法を数記事に渡って紹介していきます。
Kongでは、作成したAPIに対して、プラグイン形式で様々な機能(ログ取得、流量制御など)を付与することが可能です。今回紹介するアクセス制御の仕組みもプラグイン形式で提供されており、Pluginsのページに記載の通り、APIに対して様々なアクセス制御を適用することができます(OpenID Connect RPやOAuth2.0 Introspectionなどの一部プラグインは有料版(エンタープライズ版)のみの提供となりますが、、)。
これにより、従来は各リソースにてそれぞれアクセス制御(認証・認可)や流量制御、ロギングなどの機能を実装していたところを、APIゲートウェイであるKongで一元管理できるようになります(個々のリソースにOAuth2や流量制御などの仕組みを実装せずともよくなります)。このあたりの利点はKongの公式サイトでも紹介されていますね。
出典:https://getkong.org/#comparison
Kongにおけるアクセス制御実践のファーストステップとして、Key AuthenticationプラグインとACLプラグインを組み合わせてAPIにアクセス制御を施す方法を本記事では紹介していきます。
本記事で実現する構成
本記事では、Key AuthenticationプラグインとACLプラグインを組み合わせ、**「特定のユーザのみがアクセス可能なAPI」を作成する手順を解説していきます。具体的には、APIにアクセス制御機能を適用することで「ユーザaliceとユーザbobはアクセスできるが、ユーザcharlieはアクセスできないAPI」**を作成していきます。
また、APIをコールした際に呼び出すリソースサーバには、リクエスト情報をそのまま返してくれるhttpbin.org/anythingを利用することにします(Kongからどんなリクエストが投げられてるんだろう~などを確認したい際に結構便利なウェブサイトです)。
Kongのインストール
(※既にKongをインストールされている方はこの節を飛ばしていただいて結構です)
Kongのインストール記事は多数あるので割愛と行きたいところですが、つい先日バージョン0.12.x系がリリースされたばかり(2018/2/19現在)なので、手順を示しておきます。環境はDockerを想定しています。公式ドキュメント(Docker Installation)にもある通り、基本的には以下の3コマンドをコピペ実行でOKです。
① Kongの設定を保存するDBの準備
$ docker run -d --name kong-database \
-p 5432:5432 \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_DB=kong" \
postgres:9.4
② DBとKongの連携(マイグレーション)
$ docker run --rm \
--link kong-database:kong-database \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
kong:latest kong migrations up
③ Kongの起動
$ docker run -d --name kong \
--link kong-database:kong-database \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
-e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
-e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
-e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_ADMIN_LISTEN_SSL=0.0.0.0:8444" \
-p 8000:8000 \
-p 8443:8443 \
-p 8001:8001 \
-p 8444:8444 \
kong:latest
③について、公式ドキュメントではDocker起動時のオプションにアクセスログの出力先や管理者用ポートを指定していますが、他の設定項目を設定したい場合にはConfiguration Referenceを参考にしてください。
Kongの動作確認
①~③の手順を実施し、正常にKongを起動できていれば、以下のcurlを実行した際にKongの基本情報を表すJSONが返ってきます。
$ curl http://localhost:8001/
{"version":"0.12.1","plugins":{"enabled_in_cluster":[], ~以下省略~ }
ちなみに、下表のように、Kongでは8001ポートを利用してAPIの作成・設定やプラグインの適用を行い、8000ポートを利用して作成したAPIをコールします。
ポート | 役割 |
---|---|
8001 | 新規APIの作成、APIへのプラグインの適用、コンシューマの作成など(管理者用ポート) |
8000 | 作成したAPIをクライアントがコールするためのエンドポイント(ユーザ用ポート) |
Kongを利用する準備が整ったので、まずはAPIを作成していきましょう。
プレーンなAPIの作成
APIにアクセス制御機能を付与するにあたり、まずはベースとなるAPIを新規に作成していきます。この段階では、単純にAPIを作成するだけなので、誰でも作成したAPIをコールできる状態となります。
新規APIの作成は、http://[ホスト]:8001/apis
に対してAPI名やAPIのアクセス先URLなどを指定し、POSTすることで行います。具体的には、以下のフォーマットに従ってリクエストを送ります。
$ curl -i -X POST \
--url http://[ホスト]:8001/apis/ \
--data 'name=[API名]' \
--data 'uris=/[APIのURI]' \
--data 'upstream_url=[APIアクセス時に呼び出すサービスのURI]'
上記リクエストのdata部は下表の意味を持ちます。
設定 | 意味 |
---|---|
name | APIの名称。このAPIに対してプラグインを適用するといった設定を行う際にこのnameを指定します。 |
uris | クライアントがこのAPIをコールする際に指定するURI。クライアントはhttp://[ホスト]:8000/[uris] を指定してこのAPIをコールします。 |
upstream_url | このAPIをコールした際に呼び出されるURL。(リソースサーバに相当します) |
早速、APIを作成するリクエストを送信してみましょう。今回はsandbox-api
というAPIを作成してみます。urisはAPI名と同じ/sandbox-api
とします。また、upstream_urlには、http://httpbin.org/anything
を設定します。正常に処理が完了すれば、ステータスコード201と共にAPIを作成した旨のJSONが返されます。
$ curl -i -X POST \
--url http://localhost:8001/apis/ \
--data 'name=sandbox-api' \
--data 'uris=/sandbox-api' \
--data 'upstream_url=http://httpbin.org/anything'
HTTP/1.1 201 Created
Date: Mon, 19 Feb 2018 09:32:32 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.12.1
{"created_at":1519032752107,"strip_uri":true,"id":"287fa349-eb7f-456a-948c-0270b0fc4511","name":"sandbox-api","http_if_terminated":false,"preserve_host":false,"upstream_url":"http:\/\/httpbin.org\/anything","uris":["\/sandbox-api"],"upstream_connect_timeout":60000,"upstream_send_timeout":60000,"upstream_read_timeout":60000,"retries":5,"https_only":false}
正常にAPIを作成できたので、次に作成したAPIをコールして確認してみます。今回はKongと同環境で試すので、以下のようにホストにlocalhostを指定し、ホスト以降にはAPI作成時のurisを指定してコールします。
$ curl -i localhost:8000/sandbox-api
正常にAPIをコールできていれば、以下のように200ステータスと共にupstream_urlに設定したリソースを取得できます。X-Kong-Proxy-Latency以下のJSONがリソースサーバ(httpbin.org/anything)からのレスポンスとなります。(余談となりますが、X-Kong-Upstream-LatencyなどKongがリクエストヘッダに情報を付与していることも確認できますね)
$ curl -i localhost:8000/sandbox-api
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 351
Connection: keep-alive
Server: meinheld/0.6.1
Date: Mon, 19 Feb 2018 09:41:45 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Powered-By: Flask
X-Processed-Time: 0
Via: kong/0.12.1
X-Kong-Upstream-Latency: 30
X-Kong-Proxy-Latency: 0
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "curl/7.55.1",
"X-Forwarded-Host": "localhost"
},
"json": null,
"method": "GET",
"origin": [mask],
"url": "http://localhost/anything"
}
さて、これでAPIの作成&動作確認ができました。
但し、現状はAPIに対して何のアクセス制御も施していないので、下図のように誰でもこのAPIをコールすることができる状態です。
このAPIに対して各種プラグインを適用していくことで、アクセス制御を適用したAPIを実現していきます。
まずは、Key Authenticationプラグインを適用していきましょう。
Key Authenticationプラグインの適用
冒頭で述べた、特定のユーザのみAPIにアクセスできる構成を実現するには、Key AuthenticationプラグインとACLプラグインの両方を適用する必要がありますが、まずはKey Authenticationプラグインを導入していきます。このプラグインを導入することで、APIに対するアクセスをキー所有ユーザに限定することができます。要するに、正しいキーが付与されていないリクエストを拒否するプラグインとなります。
キーを利用した動作イメージは以下のとおりです。図におけるAliceSecretKey
、BobSecretKey
、CharlieSecretKey
がキーに相当します。
Key Authenticationプラグインの導入には、以下の3ステップを実施します。
- ① sandbox-apiにKey Authenticationプラグインを適用する
- ② コンシューマ(ユーザ)を作成する
- ③ コンシューマを識別するキーを設定する
それでは、ステップごとに設定方法を解説します。
① APIにKey Authenticationプラグインを適用する
APIに対してプラグインを適用したい場合には、http://[host]:8001/apis/[API名(name)]/plugins
に対してプラグイン名やプラグインの設定をPOSTします。Key Authenticationプラグインを適用したい場合には、以下をフォーマットに従って設定をPOSTします。
$ curl -X POST localhost:8001/apis/[API名]/plugins \
--data "name=key-auth" \
--data "config.key_names=[キーを指定する際の属性名]"
設定 | 意味 |
---|---|
name | プラグインの名称。Key Authenticationプラグインの場合はkey-auth を指定します。この後設定するACLプラグインではacl を指定します。 |
config.key_names | Key Authenticationプラグインでは、クエリ文字列でユーザを識別します。config.key_namesはクエリ文字列の左側(属性名)を指定します。 |
今回は、先ほど作成したsandbox-apiに対してKey Authenticationプラグインを適用し、config.key_names
にはsandboxApiKeyを設定します。このリクエストをPOSTし、正常に処理が完了すると、プラグインの各設定が記述されたJSONがレスポンスとして返されます。
$ curl -X POST localhost:8001/apis/sandbox-api/plugins \
--data "name=key-auth" \
--data "config.key_names=sandboxApiKey"
{"created_at":1519125441000,"config":{"key_names":["sandboxApiKey"],"key_in_body":false,"anonymous":"","run_on_preflight":true,"hide_credentials":false},"id":"3a342b9e-bf22-4b28-b3f2-ebc0ea54b0aa","name":"key-auth","api_id":"c9c6c0bb-445c-491e-9307-0157fe5d4e74","enabled":true}
これで、sandbox-apiに対してKey Authenticationプラグインを適用できました。この段階で、APIの末尾にクエリ文字列を付与してhttp://localhost:8000/sandbox-api?sandboxApiKey=[ユーザのKey]
をコールできるようになります。
但し、現時点ではクエリ文字列のパラメータにあたる[ユーザのKey]
の設定を行っていません(まだユーザを作成していません)。それでは、②でユーザに相当するものを作成していきましょう。
② コンシューマ(ユーザ)を作成する
ここで新たな概念であるConsumerが登場します。コンシューマについて、公式ドキュメントによると以下の記載があります。
The Consumer object represents a consumer - or a user - of an API.
和訳)Consumerオブジェクトは、APIのコンシューマまたはユーザーを表します。
ドキュメントが指す意味としては、APIの消費者(利用者)といったところでしょうか。ニュアンスとしては、ユーザの集まり(組織)をコンシューマと定義しているように見えます。
※ちなみに、コンシューマはOAuth2プラグイン等でも利用する概念なので、OAuth2プラグインの利用を考えている場合には、是非公式ドキュメントを一読しておきたいところです。
今回はコンシューマをユーザとして捉え、aliceコンシューマ、bobコンシューマ、charlieコンシューマを作成します。作成は下記のフォーマットに従って行います。
$ curl -X POST localhost:8001/consumers/ \
--data "username=<USERNAME>" \
--data "custom_id=<CUSTOM_ID>"
aliceコンシューマを作成したい場合のリクエストは以下になります。
$ curl -X POST localhost:8001/consumers/ \
--data "username=alice" \
--data "custom_id=alice"
{"custom_id":"alice","created_at":1519125666000,"username":"alice","id":"7265a18a-3b2b-4a6a-a51d-18e6e6dea2c7"}
同様にして、bobコンシューマとcharlieコンシューマも作成します。
$ curl -X POST localhost:8001/consumers/ \
--data "username=bob" \
--data "custom_id=bob"
{"custom_id":"bob","created_at":1519127073000,"username":"bob","id":"b4835592-b912-41a8-bfa2-88416db69de5"}
$ curl -X POST localhost:8001/consumers/ \
--data "username=charlie" \
--data "custom_id=charlie"
{"custom_id":"charlie","created_at":1519127112000,"username":"charlie","id":"49509fc9-d6a0-4d6e-887f-73d95a6d83dd"}
③コンシューマを識別するキーを設定する
コンシューマが作成できたら、次に作成したコンシューマに対してキーを設定します。ここで設定するキーが①で設定したクエリ文字列のパラメータ部分([ユーザのKey]
部分)に相当します。
下記フォーマットに従ってコンシューマにキーを設定します。
$ curl -X POST localhost:8001/consumers/[コンシューマ名]/key-auth \
--data "key=[コンシューマのKey]"
今回、aliceコンシューマには、キーとして文字列"AliceSecretKey"を設定します。
$ curl -X POST localhost:8001/consumers/alice/key-auth \
--data "key=AliceSecretKey"
{"id":"fd26bf85-b73e-4eaa-b1bd-8c2b3dfe2d2b","created_at":1519125820000,"key":"AliceSecretKey","consumer_id":"7265a18a-3b2b-4a6a-a51d-18e6e6dea2c7"}
同様にして、bobコンシューマには"BobSecretKey"を、charlieコンシューマには"CharlieSecretKey"を設定します。
$ curl -X POST localhost:8001/consumers/bob/key-auth \
--data "key=BobSecretKey"
{"id":"e504aada-25a3-4e59-a9a5-21e8121a0677","created_at":1519127653000,"key":"BobSecretKey","consumer_id":"b4835592-b912-41a8-bfa2-88416db69de5"}
$ curl -X POST localhost:8001/consumers/charlie/key-auth \
--data "key=CharlieSecretKey"
{"id":"51d48a78-a3e8-489b-9cc5-2108b69ce190","created_at":1519127695000,"key":"CharlieSecretKey","consumer_id":"49509fc9-d6a0-4d6e-887f-73d95a6d83dd"}
ここまでの手順で、プレーンなAPIに対してKey Authenticationプラグインを適用し、Key Authenticationで利用するクエリ文字列のパラメータの設定(Consumerの作成&キー設定)が終わりました。
早速、クエリ文字列にパラメータを付与してAPIにアクセスしてみましょう。コンシューマのキーを正しく付与できていれば、正常にコンテンツを取得できるはずです。
$ curl -i http://localhost:8000/sandbox-api?sandboxApiKey=AliceSecretKey
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 558
Connection: keep-alive
Server: meinheld/0.6.1
Date: Tue, 20 Feb 2018 11:26:50 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Powered-By: Flask
X-Processed-Time: 0
Via: kong/0.12.1
X-Kong-Upstream-Latency: 28
X-Kong-Proxy-Latency: 0
{
"args": {
"sandboxApiKey": "AliceSecretKey"
},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "curl/7.55.1",
"X-Consumer-Custom-Id": "alice",
"X-Consumer-Id": "7265a18a-3b2b-4a6a-a51d-18e6e6dea2c7",
"X-Consumer-Username": "alice",
"X-Forwarded-Host": "localhost"
},
"json": null,
"method": "GET",
"origin": "172.17.0.1, 18.218.119.187",
"url": "http://localhost/anything?sandboxApiKey=AliceSecretKey"
}
正しくないキーを付与したり、そもそもクエリ文字列自体を付与しない場合には以下のようにエラーが返されます。
$ curl -i http://localhost:8000/sandbox-api?sandboxApiKey=MichelSecretKey
HTTP/1.1 403 Forbidden
Date: Tue, 20 Feb 2018 11:29:16 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: kong/0.12.1
{"message":"Invalid authentication credentials"}
$ curl -i http://localhost:8000/sandbox-api
HTTP/1.1 401 Unauthorized
Date: Tue, 20 Feb 2018 11:29:23 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
WWW-Authenticate: Key realm="kong"
Server: kong/0.12.1
{"message":"No API key found in request"}
これで、コンシューマ以外はAPIにアクセスできない設定を適用できました。
しかしながら、これはKongに存在するコンシューマであれば誰でもAPIにアクセスできてしまう状況でもあります。実際は「コンシューマなら誰でもアクセスOK!」なんてことはあまりなく、コンシューマ単位でもアクセスを制御したいケースが多いかと思います。
次に説明するACLプラグインを適用すれば、コンシューマ単位でアクセスを制御できるので、早速設定していきましょう。
ACLプラグインの適用
Key Authenticationプラグインを適用した状態でACLプラグインを適用すれば、コンシューマ単位でAPIへのアクセスを制御することが可能になります。
具体的には、各コンシューマに"ACLグループ"を設定
し、ACLプラグインにてアクセスを許可・拒否するACLグループを指定
することでアクセス制御を実現します。アクセス許可・拒否するACLグループの設定は、ACLプラグインのホワイトリスト・ブラックリスト機能にて行います。
ACLプラグインの導入には、以下の2ステップを実施します。
- ① コンシューマにACLグループを設定する
- ② ACLプラグインを適用し、アクセスを許可・許可しないACLグループを設定する
それでは、ステップごとに設定方法を解説します。
①コンシューマにACLグループを設定する
アクセス制御の単位となるACLグループをコンシューマに設定します。フォーマットは下記のようになります。
$ curl -X POST http://[ホスト]:8001/consumers/[コンシューマ名]/acls \
--data "group=[ACLグループ名]"
今回、各コンシューマに割り振るACLグループ名は下記にしました。aliceとbobは共にアクセスを許可したいので、同じACLグループを割り振っています。
コンシューマ | ACLグループ |
---|---|
alice | allow-group |
bob | allow-group |
charlie | deny-group |
では、各コンシューマにACLグループを設定していきます。
$ curl -X POST http://localhost:8001/consumers/alice/acls \
--data "group=allow-group"
{"group":"allow-group","created_at":1519273998000,"id":"9f04008f-9914-420d-a3a2-edabf32d37ac","consumer_id":"82a61b1a-97b6-43a4-82ed-97040b108707"}
$ curl -X POST http://localhost:8001/consumers/bob/acls \
--data "group=allow-group"
{"group":"allow-group","created_at":1519274058000,"id":"1c048e7a-99ab-4328-a431-a63e43a26aa3","consumer_id":"f6255716-6808-4229-90ce-d8b86c793b8a"}
$ curl -X POST http://localhost:8001/consumers/charlie/acls \
--data "group=deny-group"
{"group":"deny-group","created_at":1519274108000,"id":"0f820d10-9e94-495e-9637-c232bb058a79","consumer_id":"f8158211-be7a-47e9-8cc6-b9d4d1630d61"}
ACLグループのコンシューマへの設定はこれで終わりです。次に、作成したACLグループにアクセスを許可する・拒否する設定を行います。
②ACLプラグインを適用し、アクセスを許可・許可しないACLグループを設定する
sandbox-apiに対してACLプラグインを適用していきますが、適用する際にはconfig.whitelist
、またはconfig.blacklist
を設定する必要があります。
config.whitelist
は文字通り、指定されたACLグループをホワイトリストとして登録する設定となります。ホワイトリストなので、指定されたACLグループのみアクセスを許可し、その他のACLグループのアクセスは拒否する動作となります。config.blacklist
はブラックリストの設定のため、config.whitelist
とは逆の動作となります(指定したACLグループのアクセスを拒否し、その他のACLグループのアクセスを許可する)。
設定のフォーマットは以下の通りです。
$ curl -X POST http://[ホスト]:8001/apis/[API名]/plugins \
--data "name=acl" \
--data "config.whitelist=[ACLグループ]"
今回、aliceコンシューマとbobコンシューマの所属するACLグループ(allow-group)のアクセスを許可し、charlieコンシューマのACLグループ(deny-group)のアクセスを拒否したいので、config.whitelist
にallow-group
を指定します1。
$ curl -X POST http://localhost:8001/apis/sandbox-api/plugins \
--data "name=acl" \
--data "config.whitelist=allow-group"
{"created_at":1519276536000,"config":{"whitelist":["allow-group"]},"id":"79a8ee65-3290-4da8-a6e2-2113928503e1","name":"acl","api_id":"cdab454f-75ff-4761-9eb9-4aee1b33b262","enabled":true}
これで全ての設定が終わりました。動作確認してみましょう。
aliceコンシューマとbobコンシューマでAPIにアクセスします。
$ curl -i http://localhost:8000/sandbox-api?sandboxApiKey=AliceSecretKey
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 558
Connection: keep-alive
Server: meinheld/0.6.1
Date: Thu, 22 Feb 2018 05:11:53 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Powered-By: Flask
X-Processed-Time: 0
Via: kong/0.12.1
X-Kong-Upstream-Latency: 29
X-Kong-Proxy-Latency: 19
{
"args": {
"sandboxApiKey": "AliceSecretKey"
},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "curl/7.55.1",
"X-Consumer-Custom-Id": "alice",
"X-Consumer-Id": "82a61b1a-97b6-43a4-82ed-97040b108707",
"X-Consumer-Username": "alice",
"X-Forwarded-Host": "localhost"
},
"json": null,
"method": "GET",
"origin": "172.17.0.1, 18.218.119.187",
"url": "http://localhost/anything?sandboxApiKey=AliceSecretKey"
}
$ curl -i http://localhost:8000/sandbox-api?sandboxApiKey=BobSecretKey
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 550
Connection: keep-alive
Server: meinheld/0.6.1
Date: Thu, 22 Feb 2018 05:12:48 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Powered-By: Flask
X-Processed-Time: 0
Via: kong/0.12.1
X-Kong-Upstream-Latency: 28
X-Kong-Proxy-Latency: 15
{
"args": {
"sandboxApiKey": "BobSecretKey"
},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "curl/7.55.1",
"X-Consumer-Custom-Id": "bob",
"X-Consumer-Id": "f6255716-6808-4229-90ce-d8b86c793b8a",
"X-Consumer-Username": "bob",
"X-Forwarded-Host": "localhost"
},
"json": null,
"method": "GET",
"origin": "172.17.0.1, 18.218.119.187",
"url": "http://localhost/anything?sandboxApiKey=BobSecretKey"
}
無事APIにアクセスできましたね。では、charlieコンシューマでAPIにアクセスします。
$ curl -i http://localhost:8000/sandbox-api?sandboxApiKey=CharlieSecretKey
HTTP/1.1 403 Forbidden
Date: Thu, 22 Feb 2018 05:16:22 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: kong/0.12.1
{"message":"You cannot consume this service"}
こちらも想定通りアクセスが拒否されました。もちろん、存在しないキーを指定した場合やキーを付与しなかった場合にもアクセスが拒否されます。
$ curl -i http://localhost:8000/sandbox-api?sandboxApiKey=MichelSecretKey
HTTP/1.1 403 Forbidden
Date: Thu, 22 Feb 2018 05:18:52 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: kong/0.12.1
{"message":"Invalid authentication credentials"}
$ curl -i http://localhost:8000/sandbox-api
HTTP/1.1 401 Unauthorized
Date: Thu, 22 Feb 2018 05:20:42 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
WWW-Authenticate: Key realm="kong"
Server: kong/0.12.1
{"message":"No API key found in request"}
これにて、最初想定していた構成を実現できました!
おわりに
今回は、キーとACLを利用し、APIにアクセス制御機能を付与しました。但し、実際の利用シーンでは、ユーザ数が増えれば増えるほどKong単体でコンシューマ作成やキー発行を管理するのは難しくなりますし、ユーザの認証は既に存在するKeycloak2などのIdP(アイデンティティ・プロバイダ)で実施したい要件もあるかと思います。
そのため、またの機会があればユーザの認証部分をKong外に配置し、Kongでは外部の認証情報を元にAPIのアクセス可否を検証するパターンをOAuth2.0 Authenticationプラグインを利用して試してみたいと思います。
また、弊社のOpenStandiaでは、様々なオープンソースの最新情報やサポートを提供しています。興味があれば、是非ご覧ください!
最後までご覧いただき、ありがとうございました。
-
今回はconfig.whitelistにallow-groupを指定することでアクセス制御を実現しましたが、同様のアクセス制御はconfig.blacklistにdeny-groupを指定することでも実現できます。 ↩
-
Keycloakに興味がある方は、Keycloak by OpenStandia Advent Calendar 2017を是非ご覧ください!Keycloakのインストールから応用まで、多岐に渡るコンテンツが掲載されています。 ↩