iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0

認證(AuthN)與授權(AuthZ) - 續

昨天說到了之前從未特別談過的kong授權的問題,因為如果僅有做認證,那就沒有辦法一次將多個API服務納管到kong上進行一致的管理了。這顯然不符合一個合格的API Gateway的產品。

在前面Day 6的時候有介紹到,kong的協助轉換的核心是建立在serviceroute以及service上,大多數其他附加的功能都是建立在plugin之上。認證授權其實也是一樣,就例如之前所有認證的範例,都是使用apikey的方式來進行consumer身份辨識,而授權則是使用ACL這個plugin來進行。就讓我們一起進入SamAries的討論,共同理解這個套件的使用方式。

ACL 的使用方式與場景

https://ithelp.ithome.com.tw/upload/images/20250929/20162800vt918GVeai.png
圖19-1 ACL

故事

Aries: Sam,我大概理解怎樣使用了,其實滿直觀的,當然也是有一些雷坑需要注意,還有要如何規劃也是需要思考的。

Sam: 你說說看研究到的內容,我很期待。

Aries: 我是模仿之前的設定,將需要apikey的認證的route後面,直接設定了ACL plugin。而且同樣的在consumer的位置,新增了ACL的設定。不過這裡就是我說雷的地方,因為原廠文件其實沒有把這件事情的declaretive yaml 寫得非常詳細,所以我試錯了滿多次的。

Sam: 很不錯,踩過的雷都是自己的,那你最後是怎麼試出來的?

Aries: 我去翻找了內部曾經建立過workspace,接著把Kong Control Plane Setting使用deck匯出後,才發現箇中奧秘的。

Sam: 這真的是一個好方法,那就一起來看看設定要如何進行吧~

說明:

這次為了示範,前一天有說明建立了兩個route,今天就基於昨天的kong.yml來繼續說明,要如何在route上面將acl plugin建立起來。

請參考 ironman2025\case_ELK_JPG_AuthZN\1.Kong_declarative\declarative\kong.yml

services:
- name: case_ELK_JPG_AuthZN
  url: http://case_ELK_JPG_AuthZN:8080
  routes:
  - name: case_ELK_JPG_AuthZN
    paths:
    - /case_ELK_JPG_AuthZN/
    plugins:

    ...中間省略...

    - name: acl
      config:
        allow:
        - VIP
        - trial
        deny: null
        hide_groups_header: false
      enabled: true
      protocols:
      - grpc
      - grpcs
      - http
      - https
      tags:
      - VIP
      - trial
- name: case_ELK_JPG_AuthZN_weather
  url: http://case_ELK_JPG_AuthZN_weather:8080
  routes:
  - name: case_ELK_JPG_AuthZN_weather
    paths:
    - /case_ELK_JPG_AuthZN_weather/
    plugins:

    ...中間省略...
    
    - name: acl
      config:
        allow:
        - VIP
        deny: null
        hide_groups_header: false
      enabled: true
      protocols:
      - grpc
      - grpcs
      - http
      - https
      tags:
      - VIP

可以注意到在case_ELK_JPG_AuthZNcase_ELK_JPG_AuthZN_weather這兩個route,都設定了一組 ACL plugin。其實就是各自在不同的route上面,建立了可以被許可授權存取的群組名稱,整理如下:

  • route: case_ELK_JPG_AuthZN
    • acl: vip
    • acl: trail
  • route: case_ELK_JPG_AuthZN_weather
    • acl: vip

當設定好route上面可授權存取的群組後,接著當然是要在consumer的部分,將權限授予不同的來源,當然還是回到kong.yml來說明這件事情。

consumers:
- acls:
  - group: VIP
  username: user1@user.com
  custom_id: user1
  keyauth_credentials:
  - key: user1-api-key
- acls:
  - group: trial
  username: user2@user.com
  custom_id: user2
  keyauth_credentials:
  - key: user2-api-key

可以注意到如果不同的user被授予了不同的group,同樣列點如下:

這邊最雷的就是,原本在yaml僅定義consumer的時候,該元素是對齊yaml的最左邊無空格(第0列)。但是當加上acl的時候,居然是acl這個元素對齊最左邊。
筆者在茫茫網海中找了許久,真的沒有找到範本,大多數的範例都是使用UI進行設定的。最後筆者也是透過UI先設定進去,再用deck dump出來比對,才找到答案。
而更討厭的是,kong的原廠文件關於這一段的說明,則是:

_format_version: "1.1"
...
consumers:
  - username: api-second-user
    acls:
      - group: guest
  - username: api-user
    acls:
     - group: developer

但這段....試了半天根本就沒有作用,筆者猜測這是給deck讀取並同步用的,但轉譯成declaretive yaml根本不是這回事。
有興趣的讀者請回饋,告訴筆者是哪一步做錯了,讓筆者耗費了一個晚上找答案。參考網址 :How to define ACLs in a declarative config for decK

補充:deck 是kong為了declaretive mode所出的開源專案,這個小工具其實用途也多多,後面會介紹到。

https://ithelp.ithome.com.tw/upload/images/20251002/20162800EINVkbs4D1.png
圖19-2 ACL 圖示說明

請讀者參考圖19-2,可以看到group:VIP有權限存取兩個API,但如果只是group:trial則僅能存取 case_ELK_JPG_AuthZN

可以看到,這種授權策略是將consumer進行分群(類似分等級),並將不同的API授權給不同群體,這種授權策略在API端會有較多種group被貼上。

既然已經授權完成,那當然就要驗證看看。筆者這裡就不一一貼上每一個請求畫面,而是使用Kibana作為查找請求的紀錄。筆者分別用user1@user.comuser2@user.com對兩個API進行了各一次的請求,得到的紀錄如圖19-3:

https://ithelp.ithome.com.tw/upload/images/20250929/20162800J3b3EzRcMZ.png
圖 19-3 Kibana的請求紀錄

可以注意到,user2@user.com這位使用者雖然認證正確(如果認證失敗會是401),但在case_ELK_JPG_AuthZN_weather這個API並未被正確的授權,因此最終得到了一個403(Forbidden)。如果讀者是使用postman進行實驗,則還會在response的body得到更進階的message。

https://ithelp.ithome.com.tw/upload/images/20250929/20162800Ntn7ojwGz9.png
圖19-4 postman 中更進階的未授權資訊

小結

Sam: 不錯,你的確將kong的認證授權大致上說明的很清楚了。

Aries: 其實滿直觀的,不過要如何正確的分類或是給予不同的權限,好像也是可以弄得非常的複雜,這在管理上好像也是值得探討的議題。

Sam: 的確是,另外要是kong的declaretive yaml 要是有更多資訊可以從網路上查到就好了,這對我們這些喜歡透過自動化管道進行IaC管理的研究者會是更大的福音。

Aries: 居然還要再裝一個kong設定完後,再用另外一個deck匯出才可以知道正確答案還真是....

Sam: 好啦,免錢的社群版,很棒棒惹(笑)。

補充:這邊說到的是以consumer分角色來授權,另外一種常見的策略,則是在route中直接貼上例如routename後,一一授權給所有的consumer,可以參考圖19-5。

https://ithelp.ithome.com.tw/upload/images/20250929/20162800ADPQCVk77W.png
圖 19-5 不同的管理策略

這也是常見的管理方式,相較於需要將consumer分群的方式來看,其實也非常的直觀。不過這部分有一個需要注意的地方,請筆者看到 圖19-6。

https://ithelp.ithome.com.tw/upload/images/20250929/20162800ZYrXOPxyIO.png
圖 19-6 往上游附加的資訊

這一個欄位叫做request.header.x-consumer-groups的欄位,這欄位是在認證授權通過的時,kong會將相關請求的認證授權資訊,向上游發送並附加在header中。

筆者就遇過由於設定者過度分權,將每一個API都設定為一個route(每一支喔!不是以一個站為單位喔!),然後將不同的API進行一一的貼標。這導致大量的groups被授權到consumer身上,當認證授權通過後,就會有極大量的request.header.x-consumer-groups被附加在請求header中。

最終header超出了服務器許可的上限大小(IIS 好像是16KB,不同服務器有不同大小),回應了400的錯誤,最終查了半天才知道原因。

筆者其實認為這是一種很直觀的分權管理設定方式,但所有的分權還是要有所限制,過於分權不只造成了管理上設定的繁瑣,更是在未來哪一天可能會埋下不知為何的異常錯誤。

P.S kong其實可以關閉往後送這個資訊,可以參考到kong.yam 中acl plugin 的 hide_groups_header這個參數,如果讀者未來遇到了希望可以短解,這也是一種作法,但最終還是要注意過度分權可能造成的一些極限異常問題。


上一篇
Day 18 : Kong 的認證(AuthN)與授權(AuthZ) - 1
下一篇
Day 20 : 透過 Azure DevOps 實踐 Kong 的 IaC - 1
系列文
解鎖API超能力:我的30天Kong可觀測性與管理實戰之旅23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言