API 閘道器策略二三事

Apache_APISIX發表於2023-01-30
作者暴淵,API7.ai 技術工程師,Apache APISIX Committer。

近些年隨著雲原生和微服務架構的日趨發展,API 閘道器以流量入口的角色在技術架構中扮演著越來越重要的作用。API 閘道器主要負責接收所有請求的流量並進行處理轉發至上游服務,API 閘道器的策略決定了 API 閘道器處理這些流量的邏輯與規則,直接決定了實際的業務流量行為。

什麼是 API 閘道器策略?

API 閘道器一般位於所有的上游服務之前,當使用者向服務傳送請求後請求會先到 API 閘道器,API 閘道器接收到請求之後一般會判斷幾件事情:

  1. 請求是否合法,比如是否來自被禁止訪問的使用者列表中;
  2. 這個請求是否透過認證,訪問的內容是否是經過授權的;
  3. 請求是否觸發了某些限制規則,比如限流限速等;
  4. 請求應該轉發給哪個上游服務。

經過這一系列步驟,這個請求要麼不符合預設的規則被拒絕,要麼經過了層層處理正確到達指定的上游服務中。我們將這些處理規則稱之為 API 閘道器的策略。這些規則由閘道器的管理員在閘道器執行時不斷新增至閘道器中,閘道器接受這些規則並根據這些規則作出正確的流量處理行為。

以 API 閘道器 Apache APISIX 為例,APISIX 的配置資訊有兩種:閘道器啟動用的配置檔案,比如 config.yaml,這個檔案決定了閘道器正常啟動所必須的一些配置。另外在執行時管理員可以透過 Admin API 動態建立各種規則與配置,比如 Route、Consumer、Plugin 等等。API 閘道器的策略就是管理員透過 Admin API 動態建立的各種規則與配置。

本文不再額外描述基本常用場景,而是針對認證授權、安全、流量處理與可觀測性這四類 API 閘道器中重要的場景進行闡述,介紹每種場景下包含的一些 API 閘道器策略的作用以及使用方法。

認證和授權策略

認證可以確認 API 呼叫者的身份,授權主要限制呼叫者僅能訪問許可權內的資源。

授權呼叫

比如說一位乘客前往車站出行,進入車站之前會使用身份證進行“認證”確認身份,在進入車站後出示車票,經工作人員確認後被“授權”進入某班列車。

認證授權類策略主要目的是保證閘道器轉發到上游服務的所有請求都是經過認證和授權的,不會出現非法請求。並且訪問的都是許可權範圍內的資源。比較常用的策略有下面幾種:

Basic Auth

基本訪問認證策略,這是一種最簡單的訪問控制技術。一般由使用者的 HTTP 代理在發出請求時攜帶用於認證的請求頭,一般為:Authorization: Basic <credentials>,credentials 中即包含了使用者認證需要的使用者 ID 和密碼,使用 : 隔離。這種方式不需要登陸頁面、cookie 等繁雜的設定,僅僅基於請求頭中的簡單憑據資訊進行認證,一般為使用者名稱和密碼,配置使用起來較為簡單。

攜帶基本認證的 cURL 請求的示例如下,使用者名稱為 username,密碼為 password

curl -i -u 'username:password' http://127.0.0.1:8080/hello

需要注意的是 credentials 中的資訊在傳輸過程中並不會被加密,僅僅做 Base64 編碼,所以通常需要和 HTTPS 一起使用來保證密碼的安全性。

在閘道器中實施這一策略後,未攜帶憑據的請求將無法正常透過閘道器轉發,除非在請求中攜帶了正確的認證資訊,實現了最小成本下為 API 新增了訪問驗證。

Key Auth

Key Auth 策略透過在 API 中新增 Key 來限制 API 呼叫,並識別請求攜帶的 Key 來進行訪問資源的控制。只有攜帶了正確的 Key 之後的請求才能正常訪問,可以在請求頭中或 Query 中攜帶。通常還可以透過這個 Key 來區分不同的 API 呼叫方,從而可以針對不同的呼叫方實施不同的其他策略或資源控制。同樣的 Key 在 HTTP 中是明文傳輸的,確保請求使用了 HTTPS 以保證安全。

以 APISIX 的 key-auth 外掛為例,外掛需要透過 Admin API 建立一個具有唯一 key 值的 Consumer:

curl http://127.0.0.1:9180/apisix/admin/consumers \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "username": "jack",
    "plugins": {
        "key-auth": {
            "key": "jack-key"
        }
    }
}'

這一請求建立了一個名字為 jack 的 Consumer,它的 key 值為 jack-key。在路由中啟用外掛時需要配置閘道器從請求中讀取 Key 值的位置和欄位名稱。預設的配置位置為 header ,欄位名稱為 apikey, 那麼正確的請求這個路由的示例為:

curl -i http://127.0.0.1:8080/hello -H 'apikey: jack-key'

APISIX 在收到這一請求後會從請求中解析出 Key,然後從配置的所有 Key 中找到和這個請求匹配的 Consumer jack,這樣閘道器就清楚這個請求是 jack 發出的。如果沒有找到匹配的 Key 即可判定為非法請求。

JSON Web Token

JSON Web Token (JWT) 是一個開放的標準,它定義了一種以 json 物件形式在各方之間安全傳遞資訊的方式。JWT 策略可以集認證和授權於一身,在使用者取得授權後會向使用者傳輸一個 JWT Token,在後面的所有請求中呼叫方都會攜帶這個 Token 從而保證請求是被授權的。

在 API 閘道器中可以透過 JWT 策略將 JWT 身份驗證能力新增到閘道器中,從而把這層邏輯從業務中抽離出來,業務實現者可以更加專注實現業務邏輯。以 APISIX 的 jwt-auth 外掛為例,外掛需要在 Consumer 中啟用並配置唯一的 Key、加密用的公私鑰、加密演算法、Token 過期時間等。同時還需要在路由中啟用這一外掛並配置閘道器讀取 Token 的位置和欄位,比如 header、query、cookie 等。該外掛會在 API 閘道器中新增一個 API 用於簽發 Token。在傳送請求之前需要請求籤發 token 的 API 獲得 Token,傳送請求時需要根據配置資訊在指定的位置上攜帶這一 Token。在請求到達閘道器後閘道器會按照配置資訊從請求的指定位置讀取 Token 並驗證 Token 的有效性,驗證透過後該請求才能被轉發至上游服務。

相較於前兩種策略,JWT 策略包含了過期時間選項,簽發的 Token 隨著時間流逝是可以過期的,但是 Basic Auth 和 Key Auth 的有效期是永久的,除非服務端更換了密碼或 Key。除此之外 JWT 策略可以在多個服務之間公用,尤其是針對單點登入場景下很有用。

OpenID Connect

OpenID Connect 是建立在 OAuth2.0 協議之上的身份認證方法,為應用的授權提供了比較完整的方案,API 閘道器中的 OpenID Connect 策略將允許上游服務從身份提供者(IdP)中獲取請求中的使用者資訊,從而保護 API 安全。常見的身份提供者有 Keycloak、Ory Hydra、Okta、Auth0 等等。以 Apache APISIX 為例閘道器中的 OpenID Connect 策略工作流程如下:

工作流程

  1. 客戶端向閘道器發出請求
  2. 閘道器收到請求後向 IdP 發出認證請求
  3. 使用者將被重定向到 IdP 提供的頁面完成登陸認證
  4. IdP 重定向到閘道器並攜帶認證 code
  5. 閘道器透過 code 向 IdP 請求 Access Token 從而獲取使用者資訊
  6. 閘道器向上遊轉發請求時即可攜帶使用者資訊

透過這一流程可以將認證和鑑權從業務中獨立出來放置於閘道器中解決,使架構更加清晰。關於更多 APISIX 的認證授權方法可以參考 API Gateway Authentication

安全策略

API 閘道器安全策略像門衛一樣保證 API 安全訪問,允許正常請求被閘道器轉發並在閘道器上攔截非法請求。根據 OWASP API Security Project,在 API 的呼叫者中存在著大量可能的威脅和攻擊。使用 API 閘道器安全策略可以對所有的 API 請求進行安全驗證,在 API 免於遭受這些安全威脅上起到了重要作用。

安全策略

以下是幾種比較重要的 API 閘道器安全策略。

IP 訪問限制

IP 限制策略透過將某些 IP 或 CIDR 設定為白名單或者黑名單來限制某些客戶端對 API 的訪問,確保重要資料不會被隨意訪問。正確配置這一策略很大程度上提高了 API 的安全性,實現了更高的 API 安全治理。

URI 攔截

URI 攔截策略主要透過設定 URI 的一些規則來阻止潛在的危險 API 請求。比如一些安全攻擊透過嗅探 URI 路徑從而發現潛在的安全漏洞進而攻擊。

Apache APISIX 提供了 uri-blocker 外掛來提供這一能力。透過 uri-blocker 外掛可以設定一些正則規則,如果請求命中規則就可以攔截當前使用者的請求,例如設定 root.exeadmin ,這一外掛就可以阻止 */root.exe*/admin 這種類似的請求,進一步保護 API 安全。

CORS

CORS 即瀏覽器針對跨域請求作出的安全策略。一般情況下在瀏覽器中發出 xhr 請求前瀏覽器會驗證請求地址和當前地址是否為同一域,如果在同一域下請求可以直接發出,否則瀏覽器會先出發一個 OPTION 型別的跨域預檢請求,然後在該請求的響應頭中會有 CORS 相關的設定,例如允許跨域請求的方法、允許請求攜帶的憑據等。瀏覽器會根據這些資訊決定是否發出正式的請求,詳細可以參考 CORS

一般情況下包含 CORS 設定的響應是由後端服務設定的,但是如果服務數量很多,在閘道器層面針對不同服務統一處理會更加便捷安全。CORS 策略可以在不同的 API 上設定不同的跨域解決策略,上游服務無需再處理這些邏輯。

CSRF

CSRF 即跨站請求偽造攻擊,通常情況下會使終端使用者在他們已經認證的站點中執行非自願的動作。這種攻擊通常伴隨著社會工程學(透過電子郵件向攻擊者傳送攻擊連結),當使用者點選這一連結後利用攻擊者在網站中已登陸認證的身份執行攻擊操作。在網站看來因為使用者已經登陸,所以所做的任何操作都是正常的。

通常網站的後端服務需要新增額外的中介軟體處理這部分邏輯,防範的方法也都有統一的標準。使用 CSRF 策略可以為閘道器提供防範這一攻擊的能力,在閘道器層統一做 CSRF 安全處理,簡化上游服務邏輯複雜度。

流量處理策略

流量處理策略主要保證 API 閘道器進行流量轉發的上游負載都在健康範圍內,同時在請求轉發前或者返回給呼叫者前對請求進行按需改寫。這一型別的策略主要圍繞限流限速、熔斷、快取、重寫等功能展開。

限流限速

在資源有限的情況下,API 可以提供的服務能力是有一定限度的,如果呼叫超過了這一限制可能會使上游服務崩潰繼而引起一些連鎖反應。限流限速可以防範這種情況的發生,另一方面也可以有效防止 API 遭受 DDOS 攻擊。

在限流限速策略中可以設定一個時間視窗和可允許最大的請求數量,在時間視窗內超過這個數量的請求會被拒絕並返回設定的資訊,直到請求數量低於設定的值或到下一個時間視窗後會允許繼續訪問。

請求計數的憑據可以設定為請求中的變數或著某一個請求頭等,例如根據不同的 IP 設定相應的限速策略。實現更加靈活的控制。

熔斷

API 熔斷策略可以為上游服務提供熔斷能力,使用這一策略時需要設定上游服務健康和不健康的狀態碼,用於閘道器判斷上游服務狀態。另外還需要設定觸發熔斷或者恢復健康的請求次數,連續達到這一次數後即判定為對應的狀態。當上遊服務連續向閘道器返回一定次數的不健康狀態碼後,閘道器就會熔斷該上游服務一段時間,在這段時間內不再向該上游轉發請求而是由閘道器直接返回錯誤。可以防止上游服務因為錯誤後繼續接收請求出現 “雪崩”,保護業務服務。超過這一時間後閘道器會再次嘗試向上遊轉發請求,如果還是返回不健康的狀態碼,閘道器就會繼續熔斷更長的時間(加倍)。直到轉發請求後上遊連續返回了一定次數的健康狀態碼,則閘道器認為上游服務恢復健康,後續會繼續往該上游節點轉發流量。

在這個策略中還需要設定當不健康後需要返回的狀態碼和資訊,當上遊服務不健康後請求在閘道器層面直接返回,保護業務服務穩定。

流量拆分

流量拆分策略可以動態控制將流量按比例轉發給不同的上游服務,這在灰度釋出藍綠髮布中非常有用。

灰度釋出又名金絲雀釋出,當服務釋出新功能時可以僅讓一部分請求使用新的服務,另一部分仍然停留在舊的服務中。如果新服務保持穩定,則可以增加比例逐步將所有請求轉移到新的服務中,直至比例完全切換,完成服務升級。

藍綠髮布則是另一種釋出模式,可以做到在使用者使用的高峰期進行釋出,同時不會中斷服務。服務的舊版本和新版本會同時共存。一般會將生產環境(藍色)複製到一個相同但是單獨的容器中(綠色)。在綠色環境中釋出新的更新,之後將綠色和藍色一同釋出至生產環境。之後就可以在綠色環境中進行測試和修復,在這期間使用者訪問的還是藍色系統。之後可以使用某些負載均衡策略將請求重定向到綠色環境中。藍色環境即可保持待機作為災難恢復選項或者用作下一次更新。

APISIX 的 traffic-split 外掛透過流量拆分對上述提到的兩種釋出型別都進行了很好的支援,使得業務部署更加便捷可靠。

請求重寫

在現代微服務架構中,尤其是服務端與服務、服務與服務之間充斥各種不同的協議,或著請求資料格式不統一,這些問題如果單獨在各自服務之間實現轉換處理會產生很多冗餘的邏輯程式碼並且難以管理。一些請求重寫策略可以處理一些協議轉換、請求體改寫等邏輯。

APISIX 提供了 response-rewrite 外掛可以用來修改上游服務返回的 Body 或者 Header 資訊內容,支援新增或者刪除響應頭,設定規則修改響應體等。這在設定 CORS 響應頭實現跨域請求設定或者設定 Location 實現重定向等場景中很有用。

另一方面,對於請求重寫 APISIX 則提供了 proxy-rewrite 外掛也可以處理代理到上游服務的請求內容,可以對請求的 URI、方法、請求頭等重寫,在很多場景下為業務處理提供了便捷。

故障注入

故障注入測試是一種軟體測試方法,透過在系統中故意引入錯誤來確保系統的行為正常。通常在部署之前進行測試以保證在生產環境中沒有潛在的故障。在一些混沌測試場景下,需要對服務注入一些錯誤來驗證服務的可靠性。

軟體的故障注入可以分為編譯時注入和執行時注入。編譯時注入指在編寫軟體的過程中透過改變某些程式碼或邏輯來實現;執行時注入透過向正在執行的軟體環境中設定錯誤來測試軟體的行為。故障注入策略可以在閘道器中以執行時注入的方式,模擬應用網路請求中的故障。透過在策略中設定一個比例,命中這個比例內的請求會執行設定好的故障邏輯,比如延遲時間返回,或直接返回設定的錯誤碼和錯誤資訊給呼叫方。

透過這種方式可以增加軟體的適應性,讓開發人員提前看到可能出現的一些錯誤情況,在釋出之前針對問題做出適應性修改。

協議轉換

協議轉換類的策略可以做一些常見協議之間的轉換。比如常見的 HTTP 請求和 gRPC 之間的轉換。Apache APISIX 提供了 grpc-transcode 外掛可以實現在閘道器接收到 HTTP 請求之後,將請求轉碼並轉發給 gRPC 型別的服務,接收到響應後以 HTTP 的格式返回給客戶端。這樣客戶端無需關注上游 gRPC 的型別,只處理 HTTP 即可。

可觀測性策略

可觀測性指在一個系統中透過系統的輸出資料來衡量這個系統執行狀態的能力。在一些簡單的系統中,因為系統元件數量相對較少,出現問題時可以透過分析各個元件狀態得到答案。但是在大型分散式系統中,各種微服務元件數量非常大,對元件一一進行排查顯然是不現實的,這個時候就需要系統具備可觀測性。可觀測性提供了對分散式系統的“可見性”,當系統出現問題時它可以提供工程師所需的控制能力,準確定位問題。

輸出資料型別

可觀測性的資料收集可以在應用程式元件內實現,也可以在其他位置實現。API 閘道器作為所有流量的入口,在 API 閘道器中實現系統的可觀測性,可以清晰反映出系統 API 的使用情況。API 閘道器的可觀測性策略可以幫助到公司的每個團隊:

  • 工程師團隊可以監控並解決 API 問題;
  • 產品團隊可以瞭解 API 的使用情況以挖掘背後的商業價值;
  • 銷售和增長團隊可以監控 API 使用情況,觀察商業機會並確保 API 提供正確的資料。

可觀測性策略根據輸出的資料型別一般分為三類:Tracing,Metrics 和 Logging。

Tracing

在大型分散式系統中服務之間的呼叫關係錯綜複雜,Tracing(鏈路追蹤)可以在分散式應用中追蹤完整的呼叫鏈路、應用之間的依賴分析以及請求統計等內容。在系統出現問題時可以幫助工程師確定排查範圍和位置。

Tracing 策略可以在 API 閘道器上整合一些其他的分散式呼叫鏈路追蹤系統,收集資訊並記錄。常見的服務比如 Zipkin、SkyWalking 等。透過 Tracing 策略將這些服務整合到 API 閘道器中,實現在閘道器上資料收集和與這些服務之間的通訊,可以幫助工程師解決諸如這個請求接觸了什麼服務以及引入了多少延遲等問題。Tracing 策略使工程師能夠進一步確認在特定的會話或相關的 API 呼叫中要看哪些日誌,確認排查範圍。

Metrics

Metrics 指在服務執行期間收集到的一個時間間隔內軟體自己的各種觀測資料,這些資料預設是結構化的,可以更好地實現查詢和視覺化。透過對這些資料分析可以掌握系統當下的執行狀態和行為。

Metrics 策略可以在 API 閘道器中整合 Prometheus 或 Datadog 這一類服務,為系統提供監控、報警等能力。這一策略透過 API 閘道器中的各種介面收集閘道器執行過程中的資料,並將資料上報至上述服務中。透過將這些資料視覺化後開發者可以清晰看到閘道器的執行狀態,API 請求的統計資訊等資料統計圖。

Logging

日誌是在某個特定時間系統事件的文字記錄,當系統出現問題時日誌是首要排查的地方。當服務出現一些意外情況時工程師依賴日誌內容檢視系統“發生了什麼”從而找出對應的解決方法。日誌內容一般分為兩類:API 請求日誌和閘道器自身的執行日誌。API 請求日誌記錄了 API 閘道器在執行期間所有的 API 請求記錄,透過這些記錄工程師可以掌握 API 訪問情況,及時發現並排查異常請求。閘道器自身的執行日誌則包含了閘道器在工作期間發生的所有事件的記錄,當 API 閘道器自身出現異常時可以作為排查問題的重要依據。

Logging 策略可以將 API 閘道器中的日誌儲存在伺服器磁碟中或是推送到一些其他的日誌伺服器中,比如 HTTP 日誌伺服器、TCP 日誌伺服器、UDP 日誌伺服器等,或者是其他的日誌系統比如 Apache Kafka、Apache RocketMQ、Clickhouse 等。

總結

這篇文章介紹了什麼是 API 閘道器策略,並針對認證授權、安全、流量處理與可觀測性這四類 API 閘道器中常用的策略進行描述。API 閘道器在所有上游服務之前接收請求的流量,控制一個請求是否要轉發以及如何進行轉發,對不安全的、未授權的請求直接拒絕或進行限制,這些行為都可以由 API 閘道器策略決定。

相關文章