凡是產生鏈接關係,就一定帶來安全問題,人類社會如此,服務網格世界,亦是如此。html
今天,咱們就來談談Istio第二主打功能---保護服務。面試
那麼,便引出3個問題:api
l Istio憑什麼保護服務?瀏覽器
l Istio具體如何保護服務?安全
l 如何告訴Istio發揮保護能力?網絡
將單體應用程序分解爲一個個服務,爲大型軟件系統的開發和維護帶來了諸多好處,好比更好的靈活性、可伸縮性和可複用性。但這也帶來了一些安全問題:架構
l 爲了抵禦中間人攻擊,須要對流量進行加密運維
l 爲了提供靈活的服務訪問控制,須要 mTLS(雙向的安全傳輸層協議)和細粒度的訪問策略工具
l 要審計誰在何時作了什麼,須要審計工具性能
Istio 嘗試提供全面的安全解決方案來解決這3個問題。
如上圖所示,
Istio 安全的三大目標是:
l 默認安全(Security by default):應用程序代碼和基礎結構,無需更改。
l 深度防護(Defense in depth):與現有安全系統集成,提供多層防護。
l 零信任網絡(Zero-trust network):在不受信任的網絡上,構建安全解決方案。
爲了實現這3個目標,Istio 安全功能提供了4大守護系統:
l 強大的身份(Identity)系統
l 健壯的策略(Policy)系統
l 認證,受權和審計(AAA:Authentication,Authorization,Accounting)系統,用於保護服務和數據
l 透明的 TLS 加密(Encryption)系統。
就保護對象而言,Istio 安全系統能夠抵禦來自內部或外部的威脅,這些威脅主要針對服務網格內的端點(Endpoints),通訊(Communication),平臺(Platform)和數據(Data)。
在安全方面,Istio具有3個遠大的目標,配備了4大守護系統,那麼它究竟是經過怎樣的架構實現這個目標的呢,又經過什麼樣的安全基礎設施,和kubernetes配合呢?
如上圖,與Istio的4大守護系統相對應,Istio 中涉及安全的組件有:
l Pilot :將受權策略和安全命名信息分發給代理
l Proxy :實現客戶端和服務端之間的安全通訊
l Citadel :用於密鑰和證書管理
l Mixer :管理受權和審計
因而可知,Pilot不只負責流量規則和策略的分發,還負責安全相關策略的下發,有點像皇上的貼身太監,負責宣讀聖旨;Proxy有點像各州屬的州官,負責奉天承運;Citadel有點像玉璽和虎符,負責鑑真去假;Mixer有點像三省六部,負責受權審計。
身份(Identity)是幾乎全部安全基礎架構的基本概念。在服務和服務的通訊開始前,雙方必須用其身份信息交換憑證,以達到相互認證的目的。在客戶端,根據安全命名(secure naming)信息,檢查服務端的標識,以查看它是不是該服務的受權運行程序;在服務端,服務端能夠根據受權策略(authorization policies)信息,肯定客戶端能夠訪問哪些數據,審計其在什麼時間訪問了什麼,拒絕未受權客戶端的訪問。
在 Istio 身份模型中,Istio 使用一流的服務標識來肯定服務的身份。這爲表示人類用戶,單個服務或一組服務提供了極大的靈活性和粒度。在沒有此類身份的平臺上,Istio 可使用能夠對服務實例進行分組的其餘身份,例如服務名稱。
不一樣平臺上的 Istio 服務標識:
l Kubernetes: Kubernetes 服務賬戶
l GKE/GCE: 可使用 GCP 服務賬戶
l AWS: AWS IAM 用戶/角色 賬戶
l On-premises (non-Kubernetes): 用戶賬戶,自定義服務賬戶,服務名稱,istio 服務賬戶或 GCP 服務賬戶。
作個類比,京東和天貓都有本身的一套很是成熟的服務帳戶系統,淘寶只須要複用天貓的帳戶系統便可,無需從新開發一套,這樣咱們就能夠用天貓的帳號,直接登陸淘寶。而Istio也更傾向於複用業界一流的服務帳戶系統,如Kubernetes和AWS的,但也能夠自定義服務帳戶,並按需複用Kubernetes的帳戶系統。
Istio PKI(Public Key Infrastructure)創建在 Istio Citadel 之上,可爲每一個工做負載提供安全且強大的工做負載標識。Istio 使用 X.509 證書來攜帶 SPIFFE 格式的身份信息。PKI 還能夠大規模自動化地進行密鑰和證書輪換。
Istio 支持在 Kubernetes pod 和本地計算機上運行的服務。目前,Istio爲每一個方案使用不一樣的證書密鑰配置機制,下面試舉例Kubernetes方案的配置過程:
如上一章節所言,Istio基於控制面組件,引入了一流的服務帳戶系統,結合強大的PKI,實現了對服務網格的安全守護。同時,Istio也開放了接口,讓咱們能夠進行精細化的配置,全方位知足咱們對服務的安全需求。
服務安全,老是離不開兩個具體過程:認證(Authentication)和鑑權(Authorization)。Istio經過Policy和MeshPolicy文件,實現對認證相關功能的定義;經過RbacConfig、ServiceRole和ServiceRoleBinding文件,實現對鑑權相關功能的啓用和定義。
讓咱們舉個幾個通俗的例子來區分認證和鑑權:
進火車站須要提供身份證和火車票,身份證能夠證實你就是你,這是認證;火車票能夠證實你有權上那趟火車,這是受權。
又例如,你要訪問本身淘寶的購物車,須要先登陸,這是認證。你要訪問朋友的購物車,就須要他的容許,這是受權。
再例如,有經驗的朋友能發現瀏覽器常常會面對兩個錯誤碼:401和403。一般而言,401就是未登陸的意思,須要認證;403就是禁止訪問的意思,須要受權。
Istio 提供兩種類型的身份認證:
l 傳輸身份認證,也稱爲服務到服務身份認證:對直連客戶端進行驗證。Istio 提供雙向TLS做爲傳輸身份認證的全棧解決方案。咱們能夠輕鬆啓用此功能,而無需更改服務代碼。這個解決方案:
l 爲每一個服務提供強大的身份認定,以實現跨羣集和跨雲的互操做性。
l 保護服務到服務通訊和最終用戶到服務通訊。
l 提供密鑰管理系統,以自動執行密鑰和證書生成,分發和輪換。
l 來源身份認證,也稱爲終端用戶身份認證:對來自終端用戶或設備的原始客戶端請求進行驗證。Istio 經過 JSON Web Token(JWT)、Auth0、Firebase Auth、Google Auth 和自定義身份認證來簡化開發者的工做,使之輕鬆實現請求級別的身份認證。
在這兩種狀況下,Istio 都經過自定義 Kubernetes API 將身份認證策略存儲在 Istio 配置存儲(Istio config store)中。Pilot會在適當的時候進行同步,爲每一個Proxy更新其最新狀態以及密鑰。此外,Istio 支持在許可模式下進行身份認證,以幫助咱們理解策略變動先後,服務的安全狀態是如何變化的。
咱們可使用身份認證策略,爲 Istio 網格中接收請求的服務指定身份認證要求。咱們使用 .yaml 文件來配置策略,策略將保存在 Istio 配置存儲中。在任何策略變動後,Pilot 會將新策略轉換爲適當的配置,下發給Envoy,告知其如何執行所需的身份認證機制。Pilot 能夠獲取公鑰並將其附加到 JWT 進行配置驗證。或者,Pilot 提供 Istio 系統管理的密鑰和證書的路徑,並將它們安裝到負載 Pod 中,以進行雙向 TLS。
本文屢次提到雙向TLS認證,讓咱們理解一下其在Istio裏的實現。Istio 經過客戶端和服務端各自配備的Envoy進行通訊,也就是說,客戶端和服務端的流量,是被各自的Envoy接管了的。對於客戶端調用服務端,遵循的步驟是:
和其餘的 Istio 配置同樣,能夠用 .yaml 文件的形式來編寫認證策略,而後使用 Istioctl 二進制工具進行部署。以下圖的配置,經過配置Policy文件,對reviews服務進行了傳輸身份認證的配置,要求其必須使用雙向TLS作認證。
apiVersion: "authentication.Istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "reviews"
spec:
targets:
- name: reviews
peers:
- mtls: {}
Istio 的受權功能,也稱爲基於角色的訪問控制(RBAC),爲 Istio 服務網格中的服務提供命名空間級別,服務級別和方法級別的訪問控制。它的特色是:
l 基於角色的語義,簡單易用。
l 包含服務到服務和終端用戶到服務兩種受權模式。
l 經過自定義屬性靈活定製受權策略,例如條件,角色和角色綁定。
l 高性能,由於 Istio 受權功能是在 Envoy 裏執行的。
上圖顯示了基本的 Istio 受權架構。和認證的生效過程同樣,運維人員使用.yaml文件指定 Istio 受權策略。部署後,Istio 將策略保存在Istio Config Store中。Pilot 會一直監視 Istio 受權策略的變動,若是發現任何更改,它將獲取更新的受權策略,並將 Istio 受權策略分發給與服務實例位於同一 pod 內的 Envoy 代理。
每一個 Envoy 代理都運行一個受權引擎,該引擎在運行時受權請求。當請求到達代理時,受權引擎根據當前受權策略評估請求上下文,並返回受權結果ALLOW或DENY。
咱們可使用 RbacConfig 啓用受權策略,並使用ServiceRole和ServiceRoleBinding配置受權策略。
RbacConfig是一個網格維度的單例,其固定名稱值爲default,也就是說咱們只能在網格中配置一個RbacConfig實例。與其餘 Istio 配置對象同樣,RbacConfig被定義爲Kubernetes CustomResourceDefinition (CRD)對象。
在RbacConfig中,運算符能夠指定mode值,它能夠是:
l OFF:禁用 Istio 受權。
l ON:爲網格中的全部服務啓用了 Istio 受權。
l ON_WITH_INCLUSION:僅對包含字段中指定的服務和命名空間啓用 Istio 受權。
l ON_WITH_EXCLUSION:除了排除字段中指定的服務和命名空間外,網格中的全部服務都啓用 Istio 受權。
在如下示例中,爲default命名空間啓用了 Istio 受權,。
apiVersion: "rbac.Istio.io/v1alpha1"
kind: RbacConfig
metadata:
name: default
namespace: Istio-system
spec:
mode: 'ON_WITH_INCLUSION'
inclusion:
namespaces: ["default"]
針對服務和命名空間啓用受權後,咱們還須要配置具體的受權策略,這經過配置ServiceRole和ServiceRoleBinding實現。與其餘 Istio 配置對象同樣,它們一樣被定義爲CRD對象。
ServiceRole定義了一組訪問服務的權限。ServiceRoleBinding向特定對象授予 ServiceRole,例如用戶,組或服務。
ServiceRole 和 ServiceRoleBinding 組合規定了: 容許誰在哪些條件下作什麼,具體而言:
l 誰指的是 ServiceRoleBinding 中的 subject 部分。
l 作什麼指的是 ServiceRole 中的 rule 部分。
l 哪些條件指的是咱們能夠在 ServiceRole 或 ServiceRoleBinding 中使用Istio Attributes指定的 condition 部分。
讓咱們再舉一個簡單的例子,以下圖,ServiceRole和 ServiceRoleBinding的配置規定:將全部用戶(user=「*」)綁定爲(products-viewer)角色,這個角色能夠對products這個服務發起GET或HEAD請求,可是其限制條件是請求頭必須包含version,且值爲v1或v2。
apiVersion: "rbac.Istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: products-viewer
namespace: default
spec:
rules:
- services: ["products"]
methods: ["GET", "HEAD"]
constraints:
- key: request.headers[version]
values: ["v1", "v2"]
---
apiVersion: "rbac.Istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: binding-products-allusers
namespace: default
spec:
subjects:
- user: "*"
roleRef:
kind: ServiceRole
name: "products-viewer"
至此,咱們作個簡單的總結:單體應用程序拆分紅成千上百個服務後,帶來了安全問題,Istio嘗試在由服務組成的服務網格里,加入了一套全棧解決方案。這套方案裏,Istio默默處理了大部分安全基礎設施,但也暴露了認證和受權兩個功能讓用戶進行自定義配置。咱們經過Policy、MeshPolicy以及RbacConfig、ServiceRole、ServiceRoleBinding就能夠完成對認證和受權環節全部功能的配置,而不須要侵入地改動任何服務的代碼。