零信任是指無論在網路邊界內部還是外部,都沒有任何隱含的信任。阿里雲Service MeshASM是重要的雲原生零信任體系落地載體之一,將身份認證和授權從應用程式代碼整合到ASM,開箱即用、動態可配、更新策略更加容易且立即生效。本文介紹為什麼要使用ASM實現零信任以及如何使用ASM中的零信任體系。
背景資訊
微服務提供了諸多價值,包括延展性、敏捷性、獨立擴充、商務邏輯隔離、獨立生命週期管理和更容易的分布式開發。然而,這些分布眾多的微服務也會增加安全的挑戰,每個微服務都是一個被攻擊的目標。Kubernetes為託管和編排您的微服務提供了一個出色的平台。但是,預設情況下,微服務之間的所有互動都不安全。它們通過純文字HTTP進行通訊,但這不足以滿足安全要求。只依賴網路邊界來保證安全是不夠的,因為一旦內部的某個服務被攻陷,攻擊者能夠以該機器為跳板來攻擊內網。所以,內部的調用也必須安全,這就是零信任安全的價值。零信任是指任何地方都需要顯式認證,並使用最小許可權原則來限制對資源的訪問。
Service Mesh技術的一個重要的價值主張就是它如何有效地保護應用的生產環境,同時又不降低開發人員的生產力。通過Service Mesh技術,為微服務架構採用零信任網路安全方法提供必要的基礎,以此實現所有訪問都經過強身份認證、基於上下文授權、記錄監控等安全目標。使用這些網格功能,您可以為屬於網格的所有應用程式提供安全控制能力,例如所有流量都已加密、到應用程式的所有流量都通過策略執行點(PEP)的驗證等。
在使用Kubernetes Network Policy實現三層網路安全控制之上,ASM提供了包括對等身份和請求身份認證能力、Istio授權策略以及更為精細化管理的基於OPA(Open Policy Agent)的策略控制能力。阿里雲ASM提供的這些零信任安全能力,協助使用者實現上述這些安全目標。
構建ASM能力的理論體系包括了以下幾個方面:
工作負載身份:零信任的基礎,為雲原生工作負載提供了統一的身份。ASM為Service Mesh下的每一個工作負載提供了簡單易用的身份定義,並根據特定情境提供定製機制用於擴充身份構建體系,同時相容社區SPIFFE標準。
安全性憑證:零信任的載體,ASM提供了認證簽發以及認證生命週期管理、輪轉等機制。通過X509 TLS認證建立身份,每個代理都使用該認證,並提供認證和私密金鑰輪換。
策略執行:零信任的引擎,基於策略的信任引擎是構建零信任的核心,ASM除了支援Istio RBAC授權策略之外,還提供了基於OPA提供更加細粒度的授權策略。
可視化與分析:零信任的洞察,ASM提供了可觀測機制用於監視策略執行的日誌和指標,來判斷每一個策略的執行情況。
為什麼要使用ASM實現零信任
與直接在應用程式代碼中構建安全機制的傳統方法相比,ASM體繫結構具有以下多種安全性好處:
Sidecar代理的生命週期與應用程式保持獨立,因此可以更輕鬆地管理這些Sidecar代理。
允許動態配置,更新策略變得更加容易,更新立即生效,而無需重新部署應用程式。
ASM的集中控制架構使企業的安全團隊可以構建、管理和部署適用於整個企業的安全性原則,從而預設情況下就能確保應用開發人員構建的業務應用的安全。他們無需額外的工作即可立即使用這些安全性原則。
ASM提供了對附加到請求的終端使用者憑證進行身份認證的能力,如JWT。
使用ASM體繫結構,可以將身份認證和授權系統作為服務部署在網格中。如同網格中的其他服務一樣,這些安全系統從網格中也可以得到安全保證,包括傳輸中的加密、身份識別、策略執行點、終端使用者憑證的身份認證和授權等。
藉助ASM,可以使用單個控制平面來實施強大的身份和訪問管理、透明的TLS和加密、身份認證和授權以及稽核線索記錄。ASM開箱即用地提供了這些功能,簡單地安裝和管理使開發人員、系統管理員和安全團隊可以保護其微服務應用程式。
如何使用ASM中的零信任體系
ASM能夠減小雲原生環境中的被攻擊面積,並提供零信任應用網路所需的基礎架構。通過ASM管理服務到服務的安全性,可以確保ASM的端到端加密、服務等級身份認證和細粒度授權策略。
在ASM體系下,可以支援:
在服務之間實施雙向TLS認證或者面向Server側的TLS認證,支援認證的自動輪轉等生命週期管理。網格內的通訊都經過身份認證和加密處理。
啟用基於身份的細粒度授權,以及基於其他維度參數的授權。基於角色存取控制 (RBAC) 的基礎,支援“最低許可權”的立場,也就是只有經過授權的服務才能根據ALLOW或DENY規則相互連信。
當前ASM提供了工作負載身份、對等身份認證、請求身份認證、授權策略、OPA策略的零信任安全基本能力。
工作負載身份
當應用程式在ASM環境中運行時,ASM會為每個服務提供一個唯一標識。串連到ASM中啟動並執行其他微服務時,將會使用該標識。服務識別可用於服務的雙向驗證,以此進行驗證是否允許服務間的訪問,同時該服務識別也可用於授權策略中。
當使用ASM管理運行在Kubernetes上的工作負載時,ASM會為每個工作負載提供服務身份。該身份基於工作負載的服務賬戶令牌實現。
ASM中的服務身份符合SPIFFE標準,並具有以下格式:spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>
。
您可以登入ASM控制台,查看基於Kubernetes叢集接入的服務。
登入ASM控制台,在左側導覽列,選擇 。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇 。
在工作負載身份頁面頂部,設定資料面為叢集ID,然後選擇命名空間,查看Kubernetes叢集接入服務網格的工作負載身份。
對等身份認證
ASM提供了兩種身份認證:對等身份認證和請求身份認證。對等身份認證是指當兩個微服務相互互動時,可以啟用雙向TLS進行對等身份認證。
如果請求的用戶端和服務端都注入了Sidecar,預設情況下會啟用ASM的mTLS通訊。
如果只有用戶端注入了Sidecar,用戶端會自行根據服務端的配置,決定是否啟用mTLS通訊。
如果只有服務端注入了Sidecar,預設的mTLS模式是PERMISSIVE,即可以同時接受明文和加密流量。如果您此時給服務端配置了PeerAuthentication,且設定了mTLS模式為STRICT,請求就會失敗。
請求身份認證
ASM提供了兩種身份認證:對等身份認證和請求身份認證。請求身份認證允許終端使用者和系統使用請求身份認證,與微服務進行互動。通常使用JSON Web令牌(JWT)執行該操作。
當請求微服務時,您可以建立請求身分識別驗證策略,對服務的請求執行JWT身分識別驗證。請求身分識別驗證會對帶有JWT Token的請求進行JWT身分識別驗證,只有正確的JWT Token才能訪問服務成功。請求身分識別驗證對不帶有JWT Token的請求不會進行JWT身分識別驗證,不帶有JWT Token的請求不受限制可以正常訪問服務。
您可以使用授權策略和請求身份認證,實現只有正確的JWT Token才能訪問服務,無效的JWT Token或者不帶有JWT Token的請求都將訪問失敗。
部署被請求的bookinfo應用。具體操作,請參見在ASM執行個體關聯的叢集中部署應用。
部署發起請求的sleep應用。
在ACK叢集對應的KubeConfig環境下,建立sleep.yaml。
執行以下命令,部署sleep應用。
kubectl apply -f sleep.yaml -n default
建立請求身份認證策略,對details服務的入站請求強制執行JWT身份認證。
登入ASM控制台,在左側導覽列,選擇 。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇 ,然後單擊建立。
在建立頁面,配置如下資訊,為工作負載details定義JWT規則,然後單擊建立。
部分配置項說明如下:
issuer:JWT的頒發者,本樣本設定為testing@secure.istio.io。
audiences:JWT受眾列表。設定哪些服務可以使用JWT Token訪問目標服務。本樣本設定為空白,表示對訪問的服務不受限制。
jwks:設定JWT請求資訊,本樣本設定的JWT請求資訊如下。更多資訊,請參見jwks.json。
{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}
使用JWT工具將JWT請求資訊編碼成JWT Token。
{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}
預期編碼成以下令牌:
eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
驗證請求身份認證是否生效。
執行以下命令,使用上文編碼的JWT Token訪問details服務。
export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer $TOKEN" -s -w '%{http_code}\n'
返回200,說明訪問成功。
執行以下命令,使用無效的JWT Token訪問details服務。
kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer badtoken" -s -w '%{http_code}\n'
返回403,說明訪問失敗。
執行以下命令,不帶JWT Token訪問details服務。
kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null -s -w '%{http_code}\n'
返回200,說明訪問成功。
根據以上結果,可以看到使用正確的JWT Token訪問服務成功,使用無效的JWT Token訪問服務失敗,不帶有JWT Token的請求訪問成功。說明請求身份認證生效。
授權策略
當請求微服務時,您可以使用授權策略對請求的連接埠、IP、來源等進行限制,只有符合要求的請求才能訪問服務。以下授權策略對請求來源進行限制,限制請求中必須帶有固定簽發者版發的JWT Token才能訪問服務。
部署被請求的bookinfo應用。具體操作,請參見在ASM執行個體關聯的叢集中部署應用。
部署發起請求的sleep應用。
使用以下內容,建立sleep.yaml。
在ACK叢集對應的KubeConfig環境下,執行以下命令,部署sleep應用。
kubectl apply -f sleep.yaml -n default
建立授權策略。
登入ASM控制台,在左側導覽列,選擇 。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇 ,然後單擊使用YAML建立。
在建立頁面,選擇default命名空間,配置如下YAML,然後單擊建立。
關於欄位的說明,請參見Authorization Policy。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: require-jwt namespace: default spec: action: ALLOW rules: - from: - source: requestPrincipals: - testing@secure.istio.io/testing@secure.istio.io selector: matchLabels: app: details
執行以下命令,使用不帶有JWT Token的請求訪問服務。
kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null -s -w '%{http_code}\n'
預期輸出:
403
不使用JWT Token訪問details服務訪問失敗,說明授權策略生效。授權策略限制了所有請求必須帶有
testing@secure.istio.io
頒發的JWT Token才能訪問服務成功。
OPA策略
OPA是一個策略引擎,可為您的應用程式實現細粒度的存取控制。OPA作為通用策略引擎,可以與微服務一起部署為獨立服務。為了保護應用程式,必須先授權對微服務的每個請求,然後才能對其進行處理。為了檢查授權,微服務對OPA進行API調用,以確定請求是否被授權。更多資訊,請參見OPA。
ASM整合了開放策略代理(OPA)外掛程式,通過OPA定義存取控制策略,可以使您的應用實現細粒度的存取控制,並支援動態更新OPA策略。具體操作,請參見在ASM中實現動態更新OPA策略。
總結及參考案例
綜上所述,ASM提供了以下增強安全性的組件:
提供具有完整認證生命週期管理的託管認證基礎設施,解決了憑證發行和CA輪換的複雜性。
託管的控制面API,用於向Envoy代理分發身份認證策略、授權策略和安全命名資訊。
Sidecar代理通過提供策略執行點PEP來協助確保網格的安全。
Envoy代理擴充允許遙測資料收集和審計。
每一個工作負載通過X509 TLS認證建立身份,每個Sidecar代理都使用該認證。ASM會提供並定期輪換認證和私密金鑰。如果某個特定的私密金鑰被盜用,ASM很快就會用新的私密金鑰替換它,從而大大減少了攻擊面。
參考案例
使用授權策略在入口網關上實施基於IP的存取控制或者基於自訂外部授權的存取控制等。
某互聯金融客戶在解決跨叢集多語言應用的存取權限控制方面,使用ASM提供的授權策略隔離外聯地區和應用地區。同時結合出口網關審計網格的流量,配合授權策略,控制應用對第三方服務的存取權限。