(https://tech.aufomm.com/how-to-use-jwt-plugin/ より翻訳)
Kongにはたくさんの認証プラグインがあります。今回はJWT Pluginの使い方についてお話したいと思います。
使用例#
サービスを作成#
1
2
3
4
| curl -X POST http://localhost:8001/services \
-H "Content-Type: application/json" \
-H "Accept: application/json, */*" \
-d '{"name":"jwt-service","url":"https://httpbin.org/anything"}'
|
Routeを作成#
1
2
3
4
| curl -X POST http://localhost:8001/services/jwt-service/routes \
-H "Content-Type: application/json" \
-H "Accept: application/json, */*" \
-d '{"name":"jwt-route","paths":["/jwt"]}'
|
curl 'http://localhost:8000/jwt' -i
でルートにアクセスすると、HTTP/1.1 200 OK
となるはずです。
JWT Pluginを有効#
:::note
このプラグインは、Service単位またはグローバル全体に有効化することも可能です。
:::
1
2
3
4
| curl --request POST \
--url http://localhost:8001/plugins \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data name=jwt
|
上記のルートをもう一度アクセスすると、HTTP/1.1 401 Unauthorized
となるはずです。
consumerを作成#
JWTの認証情報を持つためのconsumerを作成
1
2
3
4
| curl --request POST \
--url http://localhost:8001/consumers \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data username=jwt-user
|
JWTの認証情報を作成#
JWTプラグインは5つのアルゴリズムに対応しています。主な違いは、Keyの共有方法です。RS256を使用する場合、作成される鍵は非対称である。一方、HS256はトークンに署名するために対称鍵を使用します。以下、HS256とRS256のデモを行います。アルゴリズムの違いについては、Auth0ドキュメントを参照してください。
HS256#
1
| curl -X POST http://localhost:8001/consumers/jwt-user/jwt
|
デフォルトでは、KongはHS256
アルゴリズムを使用して、Key
とSecret
を生成します。
1
2
3
4
5
6
7
8
9
10
11
12
| {
"algorithm": "HS256",
"id": "a5f72a73-daa6-440d-8257-a40c37d34ec8",
"key": "Yb7adJK7ZTcSxEd9r7KKl8VOJ3pY44w1",
"consumer": {
"id": "297e8e1f-1d56-4369-97f9-4765efb853fe"
},
"tags": null,
"secret": "h1Hc2orJlm8aJIefXvIYcdJ3GVfwtcu2",
"created_at": 1607151650,
"rsa_public_key": null
}
|
pwgenでパスワードを二つ生成します。
1
2
| pwgen -sBv 32 2
Mt4RTRWJk9pfWJpgthP4sHhcqR4hFKzK J3NKsJgt79tcLRfLWwVMJvVnTFk7WskW
|
1つ目をkey
、2つ目をSecret
として使用します。同じConsumerで複数のキーペアを作成することができます。
1
2
3
4
5
| curl --request POST \
--url http://localhost:8001/consumers/jwt-user/jwt \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data key=Mt4RTRWJk9pfWJpgthP4sHhcqR4hFKzK \
--data secret=J3NKsJgt79tcLRfLWwVMJvVnTFk7WskW
|
以下が表示されるはずです。
1
2
3
4
5
6
7
8
9
10
11
12
| {
"algorithm": "HS256",
"id": "711c7b54-5551-4803-abc6-cb7ff86b0858",
"key": "Mt4RTRWJk9pfWJpgthP4sHhcqR4hFKzK",
"consumer": {
"id": "297e8e1f-1d56-4369-97f9-4765efb853fe"
},
"tags": null,
"secret": "J3NKsJgt79tcLRfLWwVMJvVnTFk7WskW",
"created_at": 1607152864,
"rsa_public_key": null
}
|
次は、JWT debuggerかJWT CLIを使ってtokenを作成することができます。payloadにiss: ${key}が含まれていることを確認してください。tokenを取得したら、Authentication BearerヘッダとしてJWT tokenを渡すことで、再びAPIにアクセスできるようになるはずです。
1
2
| curl http://localhost:8000/jwt \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJNdDRSVFJXSms5cGZXSnBndGhQNHNIaGNxUjRoRkt6SyJ9.pCV1wm3VixWkZ_Nh24v4RSQjvYhpb5vJp_LeTRZnF2o"
|
RS256#
次は、さっきと同じくJWT debuggerかJWT CLIを使ってtokenを作成することができます。payloadにiss: ${key}が含まれていることを確認してください。tokenを取得したら、Authentication BearerヘッダとしてJWT tokenを渡すことで、再びAPIにアクセスできるようになるはずです。
1
2
3
| curl http://localhost:8000/jwt \
"Accept: application/json, */*" \
-H "Authorization:Bearer eyJhbGciOiJSUzI1NiIsInR5cGUiOiJKV1QifQ.eyJpYXQiOiIxNjA3MTc2NDM4IiwiZXhwIjoiMTYwNzE3Njk3OCIsImlzcyI6InRlc3Qta2V5In0.uLrS8T1j7nrEBYRZgZHYALDH2uhg81emRyv5K0bJi3eOwZj45I0ZXU9Lsz7MqryGwbHtP2dwyAQ9u9WXCuU-KSiwpL0L8fjBBjd339BwinQkevwjcr6QuFvch8hD0grYmS9z09jDJ7its0FrO-P0dIEvKhQ23ihADJiFMgTukgNyk3m76nNPkR22vQdJu-OATKVVp9iGpx7tRqZnPeCZAdlGrUJuiACPuqwxdrfithswnAbFg5AjzwB2K9BXiAl76PVYzo15s5KcPCQWJwJ0JY7MgMIEQ0xyifVBZLq__V3B5GgoWy-HEr9Bkd8Dc7ZkImxmJacpLUveWbuqXZ9JFg"
|
Auth0により認証#
Auth0での認証は、上記のRS256の手順と同様ですが、key
の値はAuth0のurlに設定する必要があり、access_tokenはAuth0が生成します。
1
| curl -o auth0.pem https://{COMPANYNAME}.{REGION-ID}.auth0.com/pem
|
URLに{REGION-ID}を使用する必要がないユーザーもいます。Auth0のベースURLを知っている必要がありますが、もし知らない場合は、Auth0証明書をここからダウンロードできます。
なお、ダウンロードする前に、アカウントにログインする必要があります。
1
| openssl x509 -pubkey -noout -in auth0.pem > auth0-pub.pem
|
これで、現在のフォルダにauth0-pub.pem
があるはずです。
1
2
3
4
| curl -X POST http://localhost:8001/consumers/jwt-user/jwt \
-F [email protected] \
-F algorithm=RS256 \
-F key=https://{COMPANYNAME}.auth0.com/
|
1
2
3
4
5
6
7
| curl --request POST \
--url https://{YOUR_AUTH0_URL}/oauth/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=<APP_CLIENT_ID> \
--data client_secret=<APP_CLIENT_SECRET> \
--data audience=https://{YOUR_AUTH0_URL}/api/v2/
|
以下のようなレスポンスになるはずです。
1
2
3
4
5
6
| {
"access_token": "<YOUR_TOKEN>",
"expires_in": 86400,
"scope": "<SCOPES>",
"token_type": "Bearer"
}
|
Kongにトークンを渡すことで、apiリソースにアクセスできるようになるはずです。
1
2
3
| curl http://localhost:8000/jwt \
"Accept: application/json, */*" \
-H "Authorization: Bearer <YOUR_TOKEN>"
|
その他のデプロイ手法#
DBlessモード#
以下の内容を kong.yaml
に保存し、DBless のデプロイメント構成にロードしてください。以下の例では、jwt-userに対して3種類のJWTクレデンシャルを作成しています。要件に合わせて変更してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| _format_version: "2.1"
_transform: true
services:
- name: jwt-service
url: https://httpbin.org/anything
routes:
- name: jwt-route
paths:
- /jwt
consumers:
- username: jwt-user
jwt_secrets:
- algorithm: RS256
key: test-key
rsa_public_key: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
secret: Qrrg5r3pXyTrEmli67PiUiAheT9S4Fem
- algorithm: HS256
key: <YOUR_HS256_KEY>
secret: <YOUR_HS256_SECRET>
- algorithm: RS256
key: https://{COMPANY}.auth0.com/
rsa_public_key: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
secret: 9VRPEid3GiK5rflY8Cf4wYwJAqyLth7U
plugins:
- name: jwt
route: jwt-route
|
Kubernetes Ingress Controller#
:::note
keyとSecretの値を変更し、ご自分のPublic keyに置き換えてください。
:::
以下の例では、こちらがデプロイされます。
- Echo deployment
- Echo Service
- JWT Plugin
- Consumer jwt-user
- Ingress rule to use jwt plugin
- 3 JWT credentials for HS256, RS256, Auth0.
下記をjwt.yaml
に保存して、kubectl apply -f jwt.yaml
で適用してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
| apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-deployment
spec:
replicas: 1
selector:
matchLabels:
app: echo-pod
template:
metadata:
labels:
app: echo-pod
spec:
containers:
- name: echoheaders
image: k8s.gcr.io/echoserver:1.10
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: echo-service
spec:
selector:
app: echo-pod
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
---
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
name: jwt-user
annotations:
kubernetes.io/ingress.class: "kong"
username: jwt-user
credentials:
- jwt-key-rs256
- jwt-key-auth0
- jwt-key-hs256
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: proxy-to-echo
annotations:
konghq.com/plugins: jwt-auth
konghq.com/strip-path: "true"
spec:
ingressClassName: kong
rules:
- http:
paths:
- backend:
service:
name: echo-service
port:
number: 80
path: /jwt
pathType: Prefix
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: jwt-auth
plugin: jwt
---
apiVersion: v1
kind: Secret
metadata:
name: jwt-key-rs256
type: Opaque
stringData:
kongCredType: jwt
key: test-issuer
algorithm: RS256
rsa_public_key: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
---
apiVersion: v1
kind: Secret
metadata:
name: jwt-key-auth0
type: Opaque
stringData:
kongCredType: jwt
key: https://{COMPANY}.auth0.com/
algorithm: RS256
rsa_public_key: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
---
apiVersion: v1
kind: Secret
metadata:
name: jwt-key-hs256
type: Opaque
stringData:
kongCredType: jwt
algorithm: HS256
key: <YOUR_HS256_KEY>
secret: <YOUR_HS256_SECRET>
|
今日はこれで以上です。読んでくれてありがとう、また次回ね。