Service Mesh架構下的認證與授權

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"認證與授權幾乎是所有系統必不可少要處理的問題。在傳統架構下,我們習慣了在程序中寫一些代碼或引一些類庫來處理其相關的邏輯,但如果在Service Mesh架構下,會有什麼不同?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Service Mesh的核心是將一切非業務功能交給基礎設施層,討論Service Mesh架構下的認證與授權,實質上是討論能否將認證與授權的處理邏輯委託給基礎設施層,從而讓應用層更加專注於業務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了能讓我們的討論更加形象化,我們可以藉助一個案例。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"某組織要舉辦一次籃球相關的活動,要求參與者以團體的方式報名。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"參賽人員通過微信賬號登錄系統並驗證手機號後,填寫個人信息及團隊其它成員的手機號與信息並報名活動,其它成員通過微信賬號登錄並驗證手機號後,可以看到與自己關聯的活動申請。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"組織方工作人員同樣通過微信登錄並驗證手機號,之後可以獲取其所負責區域的活動申請並做審覈操作。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"系統結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們需要一個用戶池來管理用戶,但我們不想在用戶的賬號密碼等邏輯上花費太多精力,因此決定使用微信作爲我們的用戶池,用戶進入我們的系統時,使用微信登錄即可,這樣就可以將“創建新用戶”,“修改密碼”,“找回密碼”和“短信驗證碼”等邏輯委託給微信,同時也免去了用戶進入系統時的“註冊”過程,一舉兩得。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來,我們需要一個維護活動申請的服務,但因爲活動申請需要的信息較多,用戶可能無法一口氣完成,所以還需要一個能幫助用戶分步驟創建活動申請的服務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後,活動組織方需要審覈活動申請,但活動組織方的管理人員也是用微信登錄系統,那麼我們的系統就得有能力知道當前用戶是不是工作人員,因此我們需要一個領域專屬用戶信息服務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以下是一幅簡單的系統邏輯結構圖:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/6a\/6a1436ee23254d273bbd6db30b900341.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"備註1:此圖隱去了其它相關部分,以免結構圖變得複雜,導致討論範圍擴散。"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"User Pool:用戶池。可以是微信或Google,可以是OKTA或Idaptive,可以用AWS Cognito搭建,也可以完全自己構建,實際上大家的手機號也是一個用戶池。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Applicant Service:幫助用戶分段構建申請信息的服務,通過它我們還可以提供通過社交網站導入成員信息的方式。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Application Service:負責活動申請的服務。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Domain Specific User Information Service:User Pool只能提供有限的信息,此場景中使用的微信用戶池能提供的信息更有限,由於這個系統需要記錄專有的信息,所以需要這樣的服務。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"認證"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個案例中,有兩類具有不同數據訪問權限的用戶,爲了能知道當前訪問系統的用戶歸屬於哪一類,那麼系統必須得先知道當前用戶是誰,這樣才能找出用戶所具有的授權。認證是授權的先決條件,識別出當前用戶是誰,就是“認證”。認證大體上分爲“系統識別用戶”和系統內“微服務識別用戶”,“微服務識別用戶”是我們的重點。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"系統識別用戶"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最終處理用戶請求的是系統中的各個微服務,但我們不能讓每個微服務都和登錄流程打交道,所以需要在系統將請求轉發給微服務前,完成對用戶的識別。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"登錄"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶要使用我們的系統,首先要去登錄界面,登錄界面引導用戶使用微信登錄。微信做爲User Pool幫我們完成對用戶的認證,然後我們的系統會給用戶發一個“外部通行證”,通常情況下,“外部通行證”是一個隨機字符串,放在Cookie中。之後用戶向系統發起請求時,便不再需要提供賬號密碼,只要帶上個這個“外部通行證”即可。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"訪問系統"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶向系統發起請求時,需要在請求中附上“外部通行證”,這樣系統就能知道請求來自於誰。如果請求中沒有“外部通行證”或“外部通行證”不合法,則要求用戶重新登錄。如果“外部通行證”合法,系統則通過“外部通行證”,找到用戶在系統中的記錄及其關聯的授權信息,然後生成一個“內部通行證”。“內部通行證”通常情況下是JWT,包含更加豐富的信息,並對用戶不可見,系統內微服務只關心“內部通行證”。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"微服務識別用戶"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶的請求最終需要訪問系統內的微服務,爲確保到達微服務的請求是由合法的用戶發起的,而不是系統內被劫持的其它子系統捏造的,微服務仍然需要驗證請求者的身份。微服務驗證請求者身份的方式,就是驗證請求中附帶的“內部通行證”是否合法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0e\/0e5802c3be3882791449114fd6d9f04b.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在被請求的微服務處理請求前,需要先驗證“內部通行證”的合法性,也就是驗證請求中附帶的JWT。驗證JWT需要先獲取Key(加密方式決定Key的類型),之後用這個Key計算JWT是否被篡改過。案例使用的JWT,但驗證內部通行證的主流方式都不涉及被請求服務的業務。這個過程與微服務自身承載的業務完全沒有關係,但它又是微服務不可或缺的一部分。傳統方式下,我們會把這部分邏輯放在微服務中,並讓這部分邏輯獨立於微服務的業務模塊,但微服務的職責範圍還是擴大了,導致構建微服務時,開發人員的關注範圍要擴大。如果把這部分邏輯交給Sidecar,我們的微服務可以更加純淨,開發人員在構建微服務時也可以更加聚焦。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"授權"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當請求者的身份被識別後,下一步要做的就是檢查請求者是否被授權訪問其請求的內容。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"用戶到服務"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶需要向Application Service提交活動申請,那麼用戶就得有對Application Service的訪問權限。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/33\/3317511778aaf79bf7feda1fbf3756ce.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶的請求到達後,首先檢查“內部通行證”,確保請求是由合法的用戶發起的。之後檢查發起請求的用戶是否有權限訪問這個服務或這個服務的某一個API,有多種方式可以做,案例中的方式爲檢查“內部通行證”中對這個API訪問權的描述。這個過程與微服務自身承載的業務完全沒有關係,與前面“認證”中“微服務識別用戶”的情況相同。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"服務到服務"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶發起的請求,可能系統內一個微服務就可以完全處理,也有可能需要多個微服務協同處理。所以對於微服務,請求者可以是用戶,也可以是其它微服務。在我們這個系統中,微服務之間會有交互,但它們之間的訪問性不是無限制的。Application Service在接到用戶提交的活動申請時,需要訪問Domain Specific User Information Service獲取一些數據,用來構建活動申請。對於Domain Specific User Information Service,來自Application Service的請求,應予以處理,但如果請求來自其它服務,則要拒絕。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ae\/aeba05b73bb2c02d8250730301b5501b.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務間的訪問性配置需由另外的服務提供,做這步檢查時需要先獲取服務間的訪問性配置,然後依據配置拒絕或放行請求。這個過程與微服務自身承載的業務完全沒有關係,同樣與前面“認證”中“微服務識別用戶”的情況相同。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"用戶到服務的特定數據"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從參賽人員的角度看“Application Service中的數據”。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個活動申請包含多位參賽人員及他們的手機號與身份證號,當團隊中一位成員代表團隊提交了活動申請,我們需要讓團隊其他成員在完成認證後,也能看到這份活動申請及其狀態。這種情況下,活動申請是否可被訪問的“配置”包含在活動申請自身中,其它服務無法提供。也就是說,只有Application Service自身才能提供活動申請能否被訪問的“配置”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果將授權檢查的邏輯提成Sidecar"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個Sidecar在做數據訪問性檢查時,要請求微服務來獲取數據,用於判斷請求是否被授權。這個提供信息用於做訪問檢查的API是被做“數據訪問性檢查”的Sidecar“驅動”出來的,那麼本質上,微服務參與了權限驗證。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/14\/143947e87d37edfa34e2cab5ea46a10e.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲負責數據授權檢查的Sidecar需要從微服務獲取數據才能完成工作,所以微服務需要對做數據授權檢查的Sidecar提供可獲取授權信息的API,這導致授權檢查的職責沒能被完全委託出去。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果不將授權檢查的邏輯提成Sidecar"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於很多使用關係型數據庫的微服務來說,可能只是SQL中INNER JOIN的過濾,無需額外做任何事情。如果需要過濾從數據庫中拿到的數據,服務內數據通信的便捷性強於服務間數據通信。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/70\/70fc3824c44a58534e70cf82f5391d08.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"剛纔我們提到,只有Application Service自身才能提供活動申請能否被訪問的“配置”,這其實已經說明了對於這種場景,維護這份“配置”,就是Application Service的業務。因此,這種場景讓微服務自己做,能讓邏輯更加內聚,也能減少不必要的工作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從“活動申請”審覈人員的角度看“Application Service中的數據”"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於活動在10個城市中舉辦,現有5個活動管理員,平均每人管理兩個城市的活動申請,不同管理員之間不共享數據。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們有城市1 - 10,其中1和2歸屬管理員1,當管理員1要獲取他所負責的所有活動申請時,需要用到類似下面的接口。GET \/applications?cities=1,2"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"他可能也只想查看城市1最近幾天收到的申請。GET\/applications?cities=1&submittedAfter=xxxx-xx-xx"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但他不能查看城市1或2以外任何城市的申請,下面的請求應該被直接拒絕。GET \/applications?cities=3,6"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將授權檢查的邏輯提成Sidecar"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲數據的訪問性配置是由其它服務提供的,微服務不需要也沒有能力向這個Sidecar提供支持,也不需要知道有這個Sidecar。但負責數據授權檢查的Sidecar需要學習微服務的業務,並且這部分內容無法複用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/a6\/a6255c2868deaae5609420d797abc92c.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然這個Sidecar要學習微服務的業務,成爲這個服務專有的Sidecar,但是從微服務的角度看,數據授權檢查的邏輯被完全委託出去了,微服務可以更加純淨,開發人員在構建微服務時也可以更加聚焦。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在微服務處理請求前,對請求者身份的驗證也就是對認證信息的檢查,應委託給基礎設施層。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"授權配置在微服務之外時,如果是“服務到服務”和“用戶到服務”的場景,應委託給基礎設施層,如果是“用戶到服務的特定數據”,類似按城市分配管理員審覈活動申請的場景,可優先考慮委託給基礎設施層。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"授權配置在微服務之內時,如果是“用戶到服務的特定數據”,類似參賽人員與活動申請的關係,屬於微服務本身需要維護的業務邏輯,應優先考慮服務內實現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文轉載自:ThoughtWorks洞見(ID:TW-Insights)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/gVQlxEFz-d0zhTA_nf_3ig","title":"xxx","type":null},"content":[{"type":"text","text":"Service Mesh架構下的認證與授權"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章