1. 程式人生 > >API閘道器Kong(四):功能梳理和外掛使用-認證外掛使用

API閘道器Kong(四):功能梳理和外掛使用-認證外掛使用

作者: 李佶澳   轉載請保留:原文地址   釋出時間:2018/10/18 11:14:00

 

說明

這是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 FrameworkOAuth 認證流程詳解中的介紹不同地方在於,第三方的redirect_uri是註冊在Kong中的,不是訪問應用的授權頁面時帶過去的。

(不是很確定,需要繼續核實)Kong能夠做到的是允許獲取到Access Token的第三方訪問Route或Service。第三方服務能夠獲取的資料,在應用內進行限制。譬如說,使用者A授權第三方從應用中獲取自己的資訊,第三方就可以訪問應用的相應介面。但Kong並不知道第三方正在查詢的是哪個使用者的資訊,如果第三方試圖查詢使用者B的資訊,這時候需要應用拒絕請求。

上面是標準的授權碼方式,對更簡單的password的方式,kong也支援。

要驗證OAuth 2.0,有開發個簡單的應用,這裡暫時不試驗,先過比較容易試驗的外掛。2018-10-19 18:40:49

參考

  1. Kong的plugins
  2. Kong Plugins Website
  3. API閘道器Kong的功能梳理和外掛使用(一):基本使用過程
  4. google echo service
  5. Kong Plugin: Basic Authentication
  6. Kong Plugin: Key Auth
  7. Kong Plugin: JWT Auth
  8. RFC7519:JSON Web Token (JWT)
  9. JSON Web Tokens
  10. Kong Plugin: OAuth 2.0
  11. RFC 6749: The OAuth 2.0 Authorization Framework
  12. OAuth 認證流程詳解