API網關Kong(四):功能梳理和插件使用-認證插件使用
作者: 李佶澳 轉載請保留:原文地址 發布時間:2018/10/18 11:14:00
- 說明
- 部署一個echo應用
- Basic Auth
- Key Auth
- JWT Auth
- OAuth 2.0 Auth
- 參考
說明
這是API網關Kong的系列教程中的一篇,使用過程中遇到的問題和解決方法記錄在API網關Kong的使用過程中遇到的問題以及解決方法。
Kong的plugins中列出了Kong的社區版支持的一些插件,這裏嘗試使用一下其中的認證插件:
Basic Auth
HMAC Auth
JWT Auth
Key Auth
LDAP Auth
OAuth 2.0 Auth
完整插件名單和使用方法見:Kong Plugins Website
API網關Kong的功能梳理和插件使用(一):基本使用過程已經介紹了基本使用方法,這裏不再贅述。
Kong-Ingress-Controller的版本是0.2.0,Kong的版本是0.14.1,是用下面的方式部署的:
./kubectl.sh create -f https://raw.githubusercontent.com/introclass/kubernetes-yamls/master/all-in-one/kong-all-in-one.yaml
部署一個echo應用
為了方便後面的測試,這裏部署一個echo應用
./kubectl.sh create -f https://raw.githubusercontent.com/introclass/kubernetes-yamls/master/all-in-one/echo-all-in-one.yaml
創建了一個名為demo-echo的namespace,服務以NodePort的方式暴露出來:
./kubectl.sh -n demo-echo get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo NodePort 172.16.57.150 <none> 80:31512/TCP,22:31608/TCP 1d
echo服務返回接收到的數據:
$ curl 192.168.33.12:31512 Hostname: echo-676ff9c67f-jlr8v Pod Information: -no pod information available- Server values: server_version=nginx: 1.13.3 - lua: 10008 Request Information: client_address=192.168.33.12 method=GET real path=/ query= request_version=1.1 request_uri=http://192.168.33.12:8080/ Request Headers: accept=*/* host=192.168.33.12:31512 user-agent=curl/7.54.0 Request Body: -no body in request-
確保通過Kong的數據平面也可以訪問:
curl 192.168.33.11:31512 -H "host:echo.com"
Hostname: echo-676ff9c67f-jlr8v
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=192.168.33.11
method=GET
real path=/
query=
request_version=1.1
request_uri=http://echo.com:8080/
Request Headers:
accept=*/*
host=echo.com
user-agent=curl/7.54.0
Request Body:
-no body in request-
Basic Auth
Kong Plugin: Basic Authentication可以為Route或者Service添加簡單的用戶名密碼認證,插件類型為basic-auth
。
創建用戶user1,設置user1用戶的basic-auth:
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
name: user1
namespace: demo-echo
username: echo-user1
---
apiVersion: configuration.konghq.com/v1
kind: KongCredential
metadata:
name: user1-basic-auth
namespace: demo-echo
consumerRef: user1
type: basic-auth
config:
username: user1
password: 123456
創建之後可以在Kong-Dashboard中看到新建的Consumer,以及設置的basic-auth信息。
Dashboard中看到的是密碼的哈希,不是密碼原文:
14049af5b1854d7e7e21cd4bef60d8e1d9f9ff0d
創建KongPlugin:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: user1-basic-auth
namespace: kong
disabled: false # optional
plugin: basic-auth
編輯ingress-echo:
./kubectl.sh -n demo-echo edit ingress ingress-echo
在ingress-echo中添加annotations:
metadata:
annotations:
plugins.konghq.com: user1-basic-auth
驗證1,直接訪問提示未授權(如果是用瀏覽器訪問,彈出輸入賬號密碼的對話框):
$ curl 192.168.33.11:30939/ -H "host:echo.com"
{"message":"Unauthorized"}
驗證2,用Basic Auth訪問,需要將用戶名和密碼用base64編碼:
$ KEY=`echo "user1:123456" |base64`
$ curl 192.168.33.11:30939/ -H "host:echo.com" -H "Authorization: Basic $KEY"
Hostname: echo-676ff9c67f-jlr8v
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=172.16.128.17
method=GET
real path=/
query=
request_version=1.1
request_uri=http://172.16.128.16:8080/
Request Headers:
accept=*/*
connection=keep-alive
host=172.16.128.16:8080
user-agent=curl/7.54.0
x-consumer-custom-id=echo-user1
x-consumer-id=e7cd11ac-d1b1-11e8-9da4-525400c042d5
x-consumer-username=echo-user1
x-credential-username=user1
x-forwarded-for=192.168.33.11
x-forwarded-host=echo.com
x-forwarded-port=8000
x-forwarded-proto=http
x-real-ip=192.168.33.11
Request Body:
-no body in request-
Key Auth
Kong Plugin: Key Auth用來為Route和Service設置key,只有帶有正確的key才能訪問服務,插件類型為key-auth
。
在前面的基礎上,為Consumser設置key-auth信息,創建相應的KongPlugin:
apiVersion: configuration.konghq.com/v1
kind: KongCredential
metadata:
name: user1-key-auth
namespace: demo-echo
consumerRef: user1
type: key-auth
config:
key: "123456"
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: user1-key-auth
namespace: demo-echo
disabled: false # optional
plugin: key-auth
config:
hide_credentials: true
將ingress-echo annotation中的plugins修改為新建的KongPlugin:
metadata:
annotations:
plugins.konghq.com: user1-key-auth
驗證,帶有apikey時訪問成功:
$curl 192.168.33.11:30939/ -H "host:echo.com" -H "apikey: 123456"
Hostname: echo-676ff9c67f-jlr8v
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=172.16.128.17
method=GET
real path=/
query=
request_version=1.1
request_uri=http://172.16.128.16:8080/
Request Headers:
accept=*/*
connection=keep-alive
host=172.16.128.16:8080
user-agent=curl/7.54.0
x-consumer-custom-id=echo-user1
x-consumer-id=e7cd11ac-d1b1-11e8-9da4-525400c042d5
x-consumer-username=echo-user1
x-forwarded-for=192.168.33.11
x-forwarded-host=echo.com
x-forwarded-port=8000
x-forwarded-proto=http
x-real-ip=192.168.33.11
Request Body:
-no body in request-
JWT Auth
Kong Plugin: JWT Auth插件為Service或者Route設置Json Web Token
認證,插件類型為jwt
。
RFC7519:JSON Web Token (JWT)規定了JWT的格式和用法。
在前面的基礎上,配置Consumer的jwt信息,並創建KongPlugin:
將Rout到綁定到插件修改為剛創建的KongPlugin:
metadata:
annotations:
plugins.konghq.com: user1-jwt-auth
到網頁jwt.io上,簽署一個Json Web Token:
HEADER:
{
"alg": "HS256", # Consumer的jwt中設置的算法
"typ": "JWT"
}
PAYLOAD:
{
"iss": "a36c3049b36249a3c9f8891cb127243c" # Consumer的jwt中設置的key
}
得到Json Web Token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMzZjMzA0OWIzNjI0OWEzYzlmODg5MWNiMTI3MjQzYyJ9.oqJY4wM3X2DFs8U93w2aeA6MRf4oRwKOv_8wXMtykCU
驗證,直接訪問:
$ curl 192.168.33.11:30939/ -H "host:echo.com"
{"message":"Unauthorized"}
驗證,使用JWT訪問:
$ curl 192.168.33.11:31512/ -H "host:echo.com" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMzZjMzA0OWIzNjI0OWEzYzlmODg5MWNiMTI3MjQzYyJ9.oqJY4wM3X2DFs8U93w2aeA6MRf4oRwKOv_8wXMtykCU"
Hostname: echo-676ff9c67f-jlr8v
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=192.168.33.11
method=GET
real path=/
query=
request_version=1.1
request_uri=http://echo.com:8080/
Request Headers:
accept=*/*
authorization=Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMzZjMzA0OWIzNjI0OWEzYzlmODg5MWNiMTI3MjQzYyJ9.oqJY4wM3X2DFs8U93w2aeA6MRf4oRwKOv_8wXMtykCU
host=echo.com
user-agent=curl/7.54.0
Request Body:
-no body in request-
OAuth 2.0 Auth
Kong Plugin: OAuth 2.0的用來對接OAuth 2.0授權系統,插件類型為oauth2
。
OAuth 2.0認證過程中,一共有三個角色:
用戶
第三方服務
應用
目標是:用戶允許第三方服務直接從應用中查詢自己的數據。
啟用OAuth2.0插件以後,Kong本身成為OAuth 2.0中的認證服務器。
第三方服務將用戶重定向到應用授權頁面。用戶授權之後,應用調用Kong的接口獲得第三方服務的授權碼(Code)、重定向URI。應用將用戶重定向到第三方服務的URI,並且在重定向URI中帶上授權碼。第三方服務從URI匯總獲得授權碼,用授權碼從Kong中獲得Access Token。第三方服務用Access Token直接調用應用的接口,查詢用戶的數據。
要使用Kong的OAuth 2.0,需要做以下幾件事情:
1. 應用開發一個授權頁面,第三方可以訪問
2. 應用將為自己在Kong中的Service或者Route,配置OAuth 2.0,設置scope等
3. 第三方在kong中註冊一個Consumer
4. 第三方為自己的Consumer配置OAuth 2.0,設置client_id、client_secret、redirect_uri
5. 第三方開發申請授權的頁面
授權過程如下:
1. 第三方將用戶重定向到應用的授權頁面,並帶上自己的client_id、request scope等
2. 用戶在應用的授權頁面確認授權,應用將授權信息發送給Kong(允許某個client_id訪問XXX)
3. 應用收到Kong返回的授權碼和第三方在Kong中配置的redirect_uri
4. 應用將用戶重定向到第三方設置的uri,並在重定向uri中帶上了授權碼
5. 第三方從uri中獲得授權碼,用它從Kong中獲取Access Token
6. 第三方使用Access Token訪問應用、查詢數據
這個過程與RFC 6749: The OAuth 2.0 Authorization Framework、OAuth 認證流程詳解中的介紹不同地方在於,第三方的redirect_uri是註冊在Kong中的,不是訪問應用的授權頁面時帶過去的。
(不是很確定,需要繼續核實)Kong能夠做到的是允許獲取到Access Token的第三方訪問Route或Service。第三方服務能夠獲取的數據,在應用內進行限制。譬如說,用戶A授權第三方從應用中獲取自己的信息,第三方就可以訪問應用的相應接口。但Kong並不知道第三方正在查詢的是哪個用戶的信息,如果第三方試圖查詢用戶B的信息,這時候需要應用拒絕請求。
上面是標準的授權碼方式,對更簡單的password的方式,kong也支持。
要驗證OAuth 2.0,有開發個簡單的應用,這裏暫時不試驗,先過比較容易試驗的插件。2018-10-19 18:40:49
參考
- Kong的plugins
- Kong Plugins Website
- API網關Kong的功能梳理和插件使用(一):基本使用過程
- google echo service
- Kong Plugin: Basic Authentication
- Kong Plugin: Key Auth
- Kong Plugin: JWT Auth
- RFC7519:JSON Web Token (JWT)
- JSON Web Tokens
- Kong Plugin: OAuth 2.0
- RFC 6749: The OAuth 2.0 Authorization Framework
- OAuth 認證流程詳解
API網關Kong(四):功能梳理和插件使用-認證插件使用