API Gateway custom authorizer

  這一篇不放在這之前的API Gateway節章,而是額外提出在這裡討論,主要的原因是卡一個Cognito的服務,所以才會在談完Cognito這個服務後才來談。

API Gateway custom authorizer 是什麼

  因為API Gateway本身是對外公開的網址,所以會有一種情況是權限控管的需求,而custom authorizer則是讓使用者可以透過這層控制,讓API Gateway具有權限控管的功能。

建立API Gateway custom authorizer

  進到API Gateway的頁面中,選擇我們的API後,即可以看到「Authorizers」的選項。

點選進入後,點選「Create」按鈕後,可以看到有二個選項:

我們分別來述說這二種的處理方式。

Custom Authorizer

流程

  首先Custom Authorized的部份,這個部份是讓使用者客制化自己的API Gateway權限,不過要談論如何處理之前,我們先來看看它的作業流程:

 

上圖截圖至AWS官網,我們根據上圖,來說明一下Custom Authorizer的流程:

  1. 首先是左邊的Clinet,發出Request至API Gateway。

  2. API Gateway收到Request後,會根據Client帶來的Token,先到下方的Cache確認是否有資料,如果沒有資料的話,就轉傳至上方的Lambda Auth function;由此可知,Custom Authorizer只能透過Lamdba來作業。

  3. Lambda Auth function接收到Token資料後,判斷這個Request是誰,並決定該使用者的權限。

  4. Lambda Auth function將Auth資料回傳給API Gateway。這裡的Auth資料是有定義的,待會會再說明。

  5. API Gateway依據收到權限資料,判斷這個Request是否擁有權限,如果沒有權限,則回傳403給使用者,否則就執行原本API Gateway應該執行的事;並且將Auth的資料儲存進Cache中。

設定

瞭解整個流程後,我們來看看API Gateway上的Custom Authorizer要填的資料:

上圖中,關於Lambda的事應該不用再提了,這些選項中,比較重要的部份有二個:

  • Identity token source:這裡的設定是要取Client中的那一個值當成Token,並傳送給Lambda Auth function,以這裡的範例來說,會將header中的Authorization內容,轉給Lambda Auth function去做驗証。

 

  • Result TTL in seconds:這裡設定的數值即是當Lambda Auth function回傳給API Gateway的值,要在Cache中保留多久,以範例上的設定來說,目前是保留3分鐘。

關於TTL的值要多才適合,主要是看自己的需求來決定,如果太短,會變成每次都會需要Lambda Auth function進行處理才能得知權限,但若是保留太久,會有一種情況是:

系統上明明已經給特定的使用者設定權限了,但回應卻還是403(權限不足)。

這是因為API Gateway的Cache所導至,而且目前並沒有一個好的方法可以去刪除API Gateway Cache中的資料,所以只能等它過期;所以數字的多寡,必須由讀者自行去確認自己的需求,才能決定出最適合的數字。

資料格式(API Gateway to Lambda)

瞭解整個流程與設定後,接下來的問題就是這個Lambda Auth function了,剛剛在流程的部份有談到,關於API Gateway與Lambda Auth function中的格式,都是有被定義的,所以我們必須照著這個規範走,首先我們來看由API Gateway至Lambda Auth function的格式,這個格式可以在Lambda中的Configure test event中找到:

從這裡可以看到會有三個值從API Gateway中帶過來,說明如下:

  • authorizationToken:這個就是我們剛剛在API Gateway中看到的「Identity token source」設定,也就是Client Request中的header的Authorization的值。

  • methodArn:這個值代表是由那一個API Gateway中觸發的,通常會從這個值來取得API Gateway中的restApiId與stage的值,再搭配該使用者可使用的Resource,組回後的資料再回傳給API Gateway。

  • type:這個沒什麼好說的,目前它只會固定是「TOKEN」這個值。

有了authorizationToken就可以知道是誰,有了methodArn就可以知道來源的API Gateway,這樣就可以組成這個Request的權限資料了,不過資料格式是?現在才剛要說而已。

資料格式(Lambda to API Gateway)

接下來是要由Lambda Auth function將權限的資料回傳給API Gateway,回應的資料當然是JSON格式的資料,而內容大概如下:

{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Action": "execute-api:Invoke",
     "Effect": "Allow",
     "Resource": [
       "arn:aws:execute-api:[region]:[account_id]:[restApiId]/[stage]/[method]/[resourcePath1]",
       "arn:aws:execute-api:[region]:[account_id]:[restApiId]/[stage]/[method]/[resourcePath2]",
       "arn:aws:execute-api:[region]:[account_id]:[restApiId]/[stage]/[method]/[resourcePath3]"
     ]
   }
 ]
}

不知道讀者對於這種格式有沒有很眼熟,沒錯,這就是IAM的Policy格式,換句話說,我們Lambda Auth function要產生這樣的格式回給API Gateway,而API Gateway會根據Resource內的資料,來判斷這個Request要不要繼續進行。

這邊有一點要特別談的是,這段JSON格式,實際上與IAM的Policy是一樣的,所以*(星號)是可以被使用的,例如:

原本的:

"arn:aws:execute-api:[region]:[account_id]:[restApiId]/[stage]/[method]/[resourcePath2]",

修改為

"arn:aws:execute-api:[region]:[account_id]:[restApiId]/*/*/user/*",

就會變成這個[restApiId]下的所有stage,且是所有method,只要Resource Path是user/*的,都會被允許。

測試

完成上述的Lambda Auth function並設定完API Gateway後,就可以在API Gateway中的Custom Authorizers中進行測試:

在Identity token中貼上給Lambda Auth function的token資料後,按「Test」,就可以得到Lambda執行後的結果,下圖是正常執行的回應。

Cognito User Pool Authorizer

接下來我們來談談另外一種Authorizer,不過基本上也沒什麼好談,因為它是搭配AWS的Cognito的服務,所以只需要設定即可,所有程式的部份都由AWS幫我們處理好了;下圖是API Gateway針對Cognito User Pool Authorizer的設定:

雖說Cognito User Pool Authorizer的設定很簡單,但是它也有它的缺點,那就是它辦法做細微的區隔;Cognito User Pool Authorizer只能幫我們檢查這個使用者是不是有存在Cognito的Uesr Pool裡,有就放行,沒有就擋掉,它不能像是Custom Authorizer一樣,可以針對單一使用者進行細微的權限設定。

至於那一種比較好用,當然是看需求了,不過,大部份的情況,還是Custom Authorizer吧,畢竟一個網站不太可能用一個帳號走完全部需求,通常都會有權限的控管。

Cognito User Pool + Custom Authorizer

假設我們使用了Cognito User pool,並且想要像Custom Authorizer這樣,可以做細微調整的話,能不能辦到呢?答案是可以的,不過在API Gateway的設定上,一樣要走Custom Authorizer的路。

如果我們要達到Cognito User Pool + Custom Authorizer的做法,首先我們必須能夠從Token反解出Cognito中的user,整個Verify token的流程可以在官網中找到,而範例程式在這裡,取得user後,就可以根據使用者組出該使用者的權限。

結論

API Gateway中的Custom Authorizer非常實用,它可以幫我們在API Gateway這一層就完成權限的判斷,而不是放行所有的Request後,再到Lambda上進行權限判斷;再加上搭配的Cache,讓Lambda Auth function的運行負擔可以降到最低,所以讀者勿必熟悉這個部份。

arrow
arrow

    JAVA Programmer 發表在 痞客邦 留言(0) 人氣()