在前幾章中,有透過OpenID Connect保護K8S環境內的服務;也有透過Key-Auth和Basic-Auth識別不同的Consumer。那有沒有辦法結合OIDC和Comsuer呢?有的,就是jwt-auth
。
OIDC通常已協議Token的格式為JWT(JSON Web Token),主要分成兩個部分:HEADER和PAYLOAD,並且可以加上一段可選的Signature Verification驗證部分。每個部分都是JSON物件,並在經過BASE64編碼以後,以點字符(.
)連接起來。
關於OpenID-Connect和OAuth的學習,可以參考「用Keycloak學習身份驗證與授權」
這次會將「新竹百貨公司」、「OpenID-Connect」和jwt-auth
插件結合。會利用OIDC做為第一層保護,將用jwt-auth
設定Consumer做為第二層保護:
------ ---------
| OIDC | -> | JWT-AUTH |
------ ---------
在「新竹百貨公司」的路由前面加上一個「OIDC」的路由,將openid-connect
插件移到該路由,且給與較高的優先序。這個路由最主要作用是提供一個入口,並嘗試OIDC的登入驗證。如果驗證成功了,就轉發到自身其他路由。因此該路由的目標也是APISIX本身服務 http://localhost:9080 。
是有想嘗試將
openid-connect
和jwt-auth
設定在同個路由上,但遇到一些問題Orz。
所以原本「新竹百貨公司」的路由,現在是一個內部路由。可以將匹配的host設定成localhost
。並且簡單的將jwt-auth
插件設定成啓用。
接下來才是重頭戲。為了讓APISIX和SSO服務(Keycloak)都認識各自產生的Token,需要提供一致私鑰。透過openssl genrsa -out private.key 1024
工具建立一把:
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAM4m3oG/8TdkwCV5
bCZWU0hrjcHskqjjhkKXCxLwc3528al6LDTXdI4pEnBax71ZtpZTLHFUeVwKPxrS
vVRUPHCRAsRrzV92+3JSv4URr+JBbfbAws3f8098xARVTFlCXyQGJxtjnBgZ1Hic
DGI98UZDqoI9B00Y8qXJqf9AKNpNAgMBAAECgYAOLvRuHuOcuQzTRzhept/SArxd
FEa+4fCR0kyLwAliMRLNYz95Xz2Armi7XDOT3oFGdHCBV5uF7pqK4Obvz1/dCyfk
ILKr94gf/LJxu+OjhbH86Krp/aNFdP/2c1dOUmu9IfpG4000DUSiSnh3PUlh8Uho
FSrdsL6qQTAEoXra7QJBAPCawDV5uKiFFr8lwIiMQzanYwtRbHoZbV5rScuLHekw
TxkhSLFJAMzCFueT1+3p8s5ZZPVofB6yw76GdMz5KO8CQQDbV8M6T/rvnSmf1vJy
sRUAlX0huTh9ACT8B8xZK0AiDPZTbBVC3pFl5oT03i9CT3l1wFEGuqTxJTLX2u97
VZiDAkBC+aDVgeuQJXP+g4DDwd+X4CJm7SR4HIngRZdGLJSH6+WoxiYZC4xIcyKz
Fel+laf8HtBGq+4ZEYQBjiYHRLhLAkB0wiT0N3r2bgyoPz1T/BuX8ftoJjaBo8AM
QQJwPOuotImzIoe2zs9LFQiVaGhzveaD3dnD4TrH+uszqCFu38ONAkBYHXV2XWMz
YDfhGxFkqI6QEck0nsldGv5Xo1tArnGD02IIbB0ESlKLA2FlONgIjafleNi+pGQv
rkavaO+XrnC3
-----END PRIVATE KEY-----
透過私鑰導出公鑰openssl rsa -in private.key -pubout -out public.key
:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJt6Bv/E3ZMAleWwmVlNIa43B
7JKo44ZClwsS8HN+dvGpeiw013SOKRJwWse9WbaWUyxxVHlcCj8a0r1UVDxwkQLE
a81fdvtyUr+FEa/iQW32wMLN3/NPfMQEVUxZQl8kBicbY5wYGdR4nAxiPfFGQ6qC
PQdNGPKlyan/QCjaTQIDAQAB
-----END PUBLIC KEY-----
另外設定Keycloak還需要多提供一個憑證格式openssl req -new -x509 -key private.key -out publickey.cer -days 365
:
-----BEGIN CERTIFICATE-----
MIICZjCCAc+gAwIBAgIULRVBYS4UnrKGHelWw5aNGu3+E28wDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTEwMDUwOTE5MjdaFw0yNjEw
MDUwOTE5MjdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEB
BQADgY0AMIGJAoGBAM4m3oG/8TdkwCV5bCZWU0hrjcHskqjjhkKXCxLwc3528al6
LDTXdI4pEnBax71ZtpZTLHFUeVwKPxrSvVRUPHCRAsRrzV92+3JSv4URr+JBbfbA
ws3f8098xARVTFlCXyQGJxtjnBgZ1HicDGI98UZDqoI9B00Y8qXJqf9AKNpNAgMB
AAGjUzBRMB0GA1UdDgQWBBTg0EP6vzIrrNPVuTVhxVNqRDcaWzAfBgNVHSMEGDAW
gBTg0EP6vzIrrNPVuTVhxVNqRDcaWzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4GBABpiD1/sRLdtsMxfGWqWvvNWJuh1A3H04frHdUbhnCk2vunKOEt7
Sg/PCJBK6Jh0kMGBvOs3uWfAd6d4xdMZgg9cHOE7nBG3B/A3LQwphAmYeQdiqZFY
P4aN+/o9E8nN7jO8c9VLRYxZOWgKYb7ZDvGB+JP/6K3vi9QlhcMP+v/h
-----END CERTIFICATE----
啓用Consumer bob
的jwt-auth
插件。提供公私鑰,指定algorithm: RS256
,並且key是bob
。
algorithm: RS256
key: bob
private_key: |-
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAM4m3oG/8TdkwCV5
bCZWU0hrjcHskqjjhkKXCxLwc3528al6LDTXdI4pEnBax71ZtpZTLHFUeVwKPxrS
vVRUPHCRAsRrzV92+3JSv4URr+JBbfbAws3f8098xARVTFlCXyQGJxtjnBgZ1Hic
DGI98UZDqoI9B00Y8qXJqf9AKNpNAgMBAAECgYAOLvRuHuOcuQzTRzhept/SArxd
FEa+4fCR0kyLwAliMRLNYz95Xz2Armi7XDOT3oFGdHCBV5uF7pqK4Obvz1/dCyfk
ILKr94gf/LJxu+OjhbH86Krp/aNFdP/2c1dOUmu9IfpG4000DUSiSnh3PUlh8Uho
FSrdsL6qQTAEoXra7QJBAPCawDV5uKiFFr8lwIiMQzanYwtRbHoZbV5rScuLHekw
TxkhSLFJAMzCFueT1+3p8s5ZZPVofB6yw76GdMz5KO8CQQDbV8M6T/rvnSmf1vJy
sRUAlX0huTh9ACT8B8xZK0AiDPZTbBVC3pFl5oT03i9CT3l1wFEGuqTxJTLX2u97
VZiDAkBC+aDVgeuQJXP+g4DDwd+X4CJm7SR4HIngRZdGLJSH6+WoxiYZC4xIcyKz
Fel+laf8HtBGq+4ZEYQBjiYHRLhLAkB0wiT0N3r2bgyoPz1T/BuX8ftoJjaBo8AM
QQJwPOuotImzIoe2zs9LFQiVaGhzveaD3dnD4TrH+uszqCFu38ONAkBYHXV2XWMz
YDfhGxFkqI6QEck0nsldGv5Xo1tArnGD02IIbB0ESlKLA2FlONgIjafleNi+pGQv
rkavaO+XrnC3
-----END PRIVATE KEY-----
public_key: |-
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJt6Bv/E3ZMAleWwmVlNIa43B
7JKo44ZClwsS8HN+dvGpeiw013SOKRJwWse9WbaWUyxxVHlcCj8a0r1UVDxwkQLE
a81fdvtyUr+FEa/iQW32wMLN3/NPfMQEVUxZQl8kBicbY5wYGdR4nAxiPfFGQ6qC
PQdNGPKlyan/QCjaTQIDAQAB
-----END PUBLIC KEY-----
如此一來APISIX部分就算是設定好了。接著換Keycloak部分。在 Realm settings/Keys/Provider
建立新的提供者,選擇類型是rsa
,提供私鑰和憑證。
注意同樣使用RS256
演算法。
將建立的提供者優先序往前拉。
找到提供給APISIX openid-connect
插件的Client ID,需要調整生成的Token。增加一個映射:使得帳號會出現在Token的key
claim。
如果正確設定,Bob帳號的Access Token Payload中,應該會出現"key": "bob"
APISIX
3.13
版本可以指定Claim名字,就不一定要調整Token的內容,可以直接指定成preferred_username
或sub
。
OK,以上設定差不多了,該來驗證結果了。瀏覽 http://新竹百貨公司.com:9080/ ,應該會因爲openid-connect
插件導向登入頁面。在使用bob登入以後,可以正常拜訪「新竹百貨公司」;但bob以外的帳號就會被拒於門外(jwt-auth
)。