使用Istio打造微服務(第2部分) - 認證和授權
這篇文章是使用Istio打造微服務的第二部分,如果沒有看第一篇的話,請先看第一部分内容,因為這篇部落格是以第一篇部落格為基礎進行進一步深入的。
在第一篇文章中,我們建立了一個Kubernetes叢集,并且在上面部署了 Istio 和示例微服務應用程式“Sentiment Analysis”,用來展示Istio的功能。
使用Istio後,我們可以把應用層中的重試、逾時、斷路器、跟蹤、監控内容抛棄,以保持我們的服務應用保持在一個簡單專注的微型狀态,(如圖1所示)。此外,我們還啟用了進階測試和部署技術,如A/B測試,鏡像和金絲雀部署。
在本文中,我們将帶領讀者使用Istio來處理身份驗證和授權!
Istio中的認證和授權
我永遠不會相信認證和授權會讓我感到興奮!但是Istio可以讓這個話題變得有趣,這種情況下難道你不感到興奮麼?
答案很簡單: Istio将這些職責從我們的服務下沉到Envoy代理,當請求到達我們的服務時,它們已經經過身份驗證和授權,我們隻需編寫提供業務價值的代碼。
聽起來不錯? 讓我們去瞧瞧吧!
使用Auth0進行身份驗證
作為身份和通路管理伺服器,我們将使用Auth0,它有一個試用選項,直覺易用,我隻是喜歡它! 也就是說,相同的原則可以用于任何 OpenID Connect實作, 如KeyCloak、IdentityServer等等。
要開始使用,請使用您的帳戶導航到Auth0 Portal,在Applications> Default App下建立租戶并選擇Domain,如下圖所示:
更新檔案
resource-manifests/istio/security/auth-policy.yaml
以使用您的域名:
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: auth-policy
spec:
targets:
- name: sa-web-app
- name: sa-feedback
origins:
- jwt:
issuer: "https://{YOUR_DOMAIN}/"
jwksUri: "https://{YOUR_DOMAIN}/.well-known/jwks.json"
principalBinding: USE_ORIGIN
有了這個資源,pilot會配置envoy在将請求轉發給服務
sa-web-app
和
sa-feedback
之前對其進行身份驗證。同時,這個政策不會應用到運作
sa-frontend
服務的envoy上,這使得我們能夠未經認證就通路前端服務。要應用這些政策,請執行以下指令:
$ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml
policy.authentication.istio.io "auth-policy" created
傳回頁面并送出請求,您将看到它将以401 Unauthorized結束,現在讓我們從前端轉發使用者以使用Auth0進行身份驗證。
使用Auth0驗證請求
要驗證最終使用者的請求,我們需要在Auth0中建立一個API,表示經過身份驗證的服務,即:評論,詳細資訊和評級。要建立API,請導航到 Auth0 Portal > API > Create API ,如下圖所示。
這裡的重要資訊是稍後在腳本中使用的辨別符:
- 觀衆: {YOUR_AUDIENCE}
其餘所需的詳細資訊位于Auth0 Portal中的 Applications 下 ,然後選擇自動建立的與API同名的 Test Application。
請記下:
- 域名: {YOUR_DOMAIN}
- 客戶ID: {YOUR_CLIENT_ID}
在Test Application中向下滾動到Allowed Callback URLs文本位置,在此字段中我們指定請求在完成身份驗證後應被轉發到的目的URL。在我們的示例中,它是:
[http://{EXTERNAL_IP}/callback](http://%7BEXTERNAL_IP%7D/callback)
向Allowed Logout URLs添加以下URL:
[http://{EXTERNAL_IP}/logout](http://%7BEXTERNAL_IP%7D/logout)
接下來讓我們開始處理前端。
更新前端
檢出
[istio-mastery]
存儲庫中的auth0 分支。在此分支中,前端包含代碼更改以将使用者轉發到Auth0進行身份驗證,并在對其他服務的請求中使用JWT令牌,如下所示:
analyzeSentence() {
fetch('/sentiment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${auth.getAccessToken()}` // Access Token
},
body: JSON.stringify({ sentence: this.textField.getValue() })
})
.then(response => response.json())
.then(data => this.setState(data));
}
為了更新前端以使用你的租戶的詳細資訊,請導航到該檔案
sa-frontend/src/services/Auth.js
并使用我們之前記下的值替換以下值:
const Config = {
clientID: '{YOUR_CLIENT_ID}',
domain:'{YOUR_DOMAIN}',
audience: '{YOUR_AUDIENCE}',
ingressIP: '{EXTERNAL_IP}' // Used to redirect after authentication
}
應用程式已準備就緒,請在下面的指令中指定docker使用者ID,然後建構并部署:
$ docker build -f sa-frontend/Dockerfile \
-t $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 \
sa-frontend
$ docker push $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0
$ kubectl set image deployment/sa-frontend \
sa-frontend=$DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0
試一試應用吧! 您将被轉發到Auth0,在那裡您必須登入(或注冊),然後跳轉回原頁面,以後就可以發出經過身份驗證的請求了。同時,如果您嘗試使用早期的curl指令,您将獲得401狀态代碼,表明該請求是未授權的。
讓我們進行下一步,授權請求。
使用Auth0授權
身份驗證使我們能夠知道使用者是誰,但我們需要授權才能知道他們可以通路的内容。Istio也為此提供了工具!
作為示例,我們将建立兩組使用者(如圖24所示):
- 使用者 :隻能通路SA-WebApp和SA-Frontend服務。
- 版主 :可以通路所有三項服務。
要建立使用者組,我們将使用Auth0授權擴充,然後使用Istio,我們将為他們提供不同級别的通路權限。
安裝和配置Auth0授權
在Auth0門戶中,導航到Extensions并安裝“Auth0 Authorization”擴充。安裝完成後,導航到授權擴充并通過單擊右上角的租戶并選擇菜單選項“配置”進行配置。啟用組,然後單擊 釋出規則 按鈕。
建立組
在授權擴充中,導航到 Groups 并建立
Moderators
組。同時,我們會将所有經過身份驗證的使用者視為正常使用者,是以無需建立其他組。
選擇Moderators組,然後單擊添加成員,添加您的主帳戶。保留一些沒有任何組的使用者,以驗證是否禁止通路。(您可以在Auth0 Portal>使用者>建立使用者中手動注冊新使用者)
将組聲明添加到通路令牌
使用者将添加到組中,但此資訊不會反映在通路令牌中。為了保持OpenID Connect符合要求并同時傳回組,我們需要向令牌添加自定義命名空間聲明。這可以使用Auth0規則來完成。
要在Auth0 Portal中建立規則,請導航到規則,單擊“建立規則”并 從模闆中 選擇一個 空規則。
粘貼下面的代碼并儲存名為“添加組聲明”的新規則。
function (user, context, callback) {
context.accessToken['https://sa.io/group'] = user.groups[0];
return callback(null, user, context);
}
注意: 此代碼選擇授權擴充中定義的第一個使用者組,并将其作為自定義命名空間聲明添加到通路令牌中。
傳回 規則頁面 ,确認您按此順序擁有兩個角色:
- auth0授權擴充
- 添加組聲明
順序很重要,因為
**auth0-authorization-extension**
規則會異步檢索組字段 ,然後由第二個規則将其添加為命名空間聲明,進而産生以下通路令牌:
{
"https://sa.io/group": "Moderators",
"iss": "https://sentiment-analysis.eu.auth0.com/",
"sub": "google-oauth2|196405271625531691872"
// [shortened for brevity]
}
現在,我們必須通過從
https://sa.io/group
傳回的通路令牌中的聲明中提取組來配置Envoy代理以驗證使用者通路權限。這是下一節的主題,讓我們繼續前進。
在Istio中配置授權
要獲得授權,我們需要為Istio啟用RBAC。為此,請将以下配置應用于Mesh:
apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
name: default
spec:
mode: 'ON_WITH_INCLUSION' # 1
inclusion:
services: # 2
- "sa-frontend.default.svc.cluster.local"
- "sa-web-app.default.svc.cluster.local"
- "sa-feedback.default.svc.cluster.local"
- 僅為“包含”字段中指定的服務和/或命名空間啟用RBAC。
- 包括指定的服務清單。
通過執行以下指令應用配置:
$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml
rbacconfig.rbac.istio.io/default created
現在,所有服務都需要基于角色的通路控制,換句話說,對所有服務的通路都會被拒絕,并響應“RBAC: access denied”。啟用對授權使用者的通路權限将成為下一節的主題。
配置正常使用者通路
所有使用者都應該能夠通路 SA-Frontend 和 SA-WebApp 服務,這是通過以下Istio的資源實作的:
- ServiceRole: 指定使用者擁有的權限
- ServiceRoleBinding: 指定ServiceRole應用于誰。
對于普通使用者,我們将允許通路指定的服務:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: regular-user
namespace: default
spec:
rules:
- services:
- "sa-frontend.default.svc.cluster.local"
- "sa-web-app.default.svc.cluster.local"
paths: ["*"]
methods: ["*"]
使用 正常使用者綁定, 我們将ServiceRole應用于我們頁面的所有通路者:
哦! 所有使用者這意味着未經身份驗證的使用者可以使用SA WebApp嗎? 不,該政策仍将檢查JWT令牌的有效性。?
應用配置:
$ kubectl apply -f resource-manifests/istio/security/user-role.yaml
servicerole.rbac.istio.io/regular-user created
servicerolebinding.rbac.istio.io/regular-user-binding created
配置版主使用者通路權限
對于我們的版主,我們希望啟用對所有服務的通路:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: mod-user
namespace: default
spec:
rules:
- services: ["*"]
paths: ["*"]
methods: ["*"]
但我們隻想将其綁定到Access Token聲明
https://sa.io/group
等于Moderators值的使用者。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: mod-user-binding
namespace: default
spec:
subjects:
- properties:
request.auth.claims[https://sa.io/group]: "Moderators"
roleRef:
kind: ServiceRole
name: "mod-user"
要應用配置,請執行:
$ kubectl apply -f resource-manifests/istio/security/mod-role.yaml
servicerole.rbac.istio.io/mod-user created
servicerolebinding.rbac.istio.io/mod-user-binding created
由于Envoy中的緩存,授權規則可能需要幾分鐘才能生效,但在此之後,您将能夠驗證使用者和版主具有不同的通路級别。
第2部分 - 摘要
您是否真的見過任何更簡單,零工作的可擴充和安全的身份驗證和授權概念?
僅使用三個Istio資源(RbacConfig,ServiceRole和ServiceRoleBinding),我們可以通過細粒度控制對最終使用者通路我們服務進行身份驗證和授權。
此外,我們将這些問題從我們的服務中轉移到我們的Envoy:
- 減少可能出現安全問題和漏洞的樣闆代碼,
- 減少因為忘記标記注解而暴露服務端點的愚蠢狀況。
- 每次添加新角色或權限時,都會消除更新所有服務的連鎖效應。
- 保持簡單,安全和快速地添加新服務。
結論
Istio 使您的團隊能夠再次将資源集中在提供商業價值上,而不需要為服務的周邊任務進行處理,讓微服務回歸“微型”的本質。
本文為您提供了在實際項目中開始使用Istio的知識和實踐。
借此機會,我很感謝你加入我的這次Istio探索之旅,這肯定不容易,你堅持下去就已經很棒了。我十分希望在下面的評論中看到您的想法,你可以随時在 Twitter 或我的首頁 rinormaloku.com 上與我聯系。