【編者按】千里之堤毀于蟻穴。服務(wù)安全有點類似于機(jī)場安檢。工作人員會檢查每一個人,禁止他們帶某些東西上飛機(jī)等等,盡管99.9999%的人都不會劫持飛機(jī)。而機(jī)場采取的所有措施針對的都是0.0001%的情況。因為后果影響非常大。

作者 | Madalin Ilie

譯者 | 彎月

出品 | CSDN(ID:CSDNnews)

軟件的安全問題既困難又復(fù)雜。許多人認(rèn)為安全屬于正常開發(fā)流程之外的東西。通常被視為某些安全人員的責(zé)任,他們只需要關(guān)注安全,不需要理解我們在復(fù)雜的微服務(wù)、事件驅(qū)動、API優(yōu)先戰(zhàn)略以及云生態(tài)系統(tǒng)中快速交付的業(yè)務(wù)價值。我認(rèn)為正是由于這種思想,我們很難在早期階段思考安全問題,找出任何有可能破壞系統(tǒng)的人或事。安全導(dǎo)致復(fù)雜的壞境又多了一層復(fù)雜。安全不僅僅體現(xiàn)了現(xiàn)代架構(gòu)的技術(shù)復(fù)雜性,而且還有很多其他方面的問題,比如快速走向市場、嚴(yán)格的期限、團(tuán)隊內(nèi)部問題、性能問題、流程太多、會議太多等等。雖然安全非常復(fù)雜,但是它并不會在某一天里突然破壞你的系統(tǒng)??赡茉诮?jīng)過數(shù)月/數(shù)年后,才會有人發(fā)現(xiàn)漏洞。那么,為什么我們要從第一天起就關(guān)注安全呢?話雖沒錯,第一天就出現(xiàn)安全問題的可能性非常小。我們都希望集中精力完成具有直接價值的功能,而不是預(yù)防未來可能出現(xiàn)的問題。然而,關(guān)鍵在于,安全問題可能會導(dǎo)致整個系統(tǒng)癱瘓。這對于你和你的用戶都非常不利。

那么,如何在不過度設(shè)計安全性和偏執(zhí)于一切之間取得平衡,同時仍然還能專注于業(yè)務(wù)價值呢?這其實是一種思維模式,而不是一個單獨的關(guān)注點。我并不是說每個人都需要成為安全專家以及無所不知。我是說人們應(yīng)該開發(fā)安全軟件,就像他們開發(fā)軟件一樣。通過一種方式將引入漏洞的可能性降到最低。

灌輸這種思維模式的最佳方式是采用一套標(biāo)準(zhǔn)和實踐來培養(yǎng)習(xí)慣。繼續(xù)拿機(jī)場安檢做類比,你不能讓安檢人員自行做決定:

  • “這個人看上去是好人,他的手提行李可以攜帶剪刀和刀。”

  • “這位先生看上去嚴(yán)重脫水,他可以攜帶一大瓶液體上飛機(jī)!”

你需要創(chuàng)建一套平等且適用于每個人的規(guī)則和程序(即標(biāo)準(zhǔn))。此外,你還需要制定一套關(guān)于如何處理特定情況的指導(dǎo)方針(即實踐):如果你發(fā)現(xiàn)手提行李中有可疑物品,則可以單獨檢查。

接下來,我將詳細(xì)介紹涵蓋整個系統(tǒng)發(fā)展生命周期的標(biāo)準(zhǔn)和實踐。雖然這個列表無法做到詳盡(對于有些小節(jié)的內(nèi)容,你可能有更多良好的實踐),但我希望能夠幫助你思考一些不太常見的情況。

安全的重點

我簡單地將安全問題分為了兩個主要領(lǐng)域:

  • 基礎(chǔ)設(shè)施安全:與應(yīng)用程序在生產(chǎn)中的部署和運行相關(guān)的安全問題。

  • 應(yīng)用程序安全性:與應(yīng)用程序的實現(xiàn)以及業(yè)務(wù)背景細(xì)節(jié)相關(guān)的安全問題。

關(guān)于如何解決這兩個問題,有很多資源:

  • PCI 安全要求():側(cè)重于財務(wù)軟件,但也可作為其他系統(tǒng)的最佳實踐。

  • 安全代碼():有關(guān)開發(fā)、測試、架構(gòu)以及開發(fā)運維的通用實踐。

  • 有關(guān)安全編程的十大最佳實踐():側(cè)重于某些編程語言的安全編程最佳實踐,也有一些通用的實踐。

  • OWASP 備忘單系列():覆蓋了大多數(shù)軟件開發(fā)領(lǐng)域的備忘單。

上述資源非常全面,包括許多解決系統(tǒng)發(fā)展生命周期內(nèi)有關(guān)安全問題的細(xì)節(jié)和實踐。每位開發(fā)人員都應(yīng)該定期做檢查,并掌握最新信息。但在實踐中,我們很難做到。下面,我將設(shè)法總結(jié)出我們需要思考的一些重要問題(注意:這些實踐與業(yè)務(wù)領(lǐng)域無關(guān))。雖然這不是一份詳盡的清單,也不是靈丹妙藥,但它可以幫助你建立堅實的基礎(chǔ),將發(fā)生安全問題的可能性降到最低。

解決安全問題

基礎(chǔ)設(shè)施的安全比較容易解決,因為很多人都會使用產(chǎn)品或云服務(wù)。這些產(chǎn)品和服務(wù)已經(jīng)包含了非常好的安全功能,如果你使用Web應(yīng)用程序防火墻,則可以相信該產(chǎn)品能夠保障安全,不需要由你來實現(xiàn)安全。我并不是說這樣做會更容易,而是說你有更多控制。

應(yīng)用程序的安全則更加難以預(yù)測。你需要依靠開發(fā)人員的技術(shù)來實現(xiàn)安全。你需要確保他們不會做愚蠢的事情,比如在源文件中存儲明文密碼。

以下是我認(rèn)為能夠幫助你建立安全思維方式的實踐列表,主要面向常規(guī)開發(fā)人員。這里的“常規(guī)”指的是實際實現(xiàn)代碼的人,而不是其他專注于設(shè)計、規(guī)劃或管理的人。這些規(guī)則關(guān)注的都是構(gòu)建 (REST) API 時的應(yīng)用程序安全。雖然表面看起來它們與安全并沒有直接的聯(lián)系,但最終它們都可以減少引入安全問題的可能性。

注意:本文的大多數(shù)示例都使用了Java。

標(biāo)準(zhǔn)

如上所述,標(biāo)準(zhǔn)的使用是建立思維方式的主要機(jī)制。所有項目都應(yīng)該采用同一套標(biāo)準(zhǔn)。并非所有人都喜歡標(biāo)準(zhǔn),有些人可能會認(rèn)為標(biāo)準(zhǔn)限制了人們的選擇和創(chuàng)造力。但我認(rèn)為,這是一種簡單的獲得統(tǒng)一性的方法,尤其是當(dāng)多個團(tuán)隊在同一平臺上工作時。建立標(biāo)準(zhǔn)之后,新成員可以更輕松地加入項目,而且還能降低引入bug、不一致或在某些愚蠢的事情(比如空格還是制表符)上發(fā)生爭執(zhí)的可能性。我們可以將這些時間節(jié)省出來討論更有意義的問題。標(biāo)準(zhǔn)不一定要涉及很多細(xì)節(jié),大多數(shù)標(biāo)準(zhǔn)應(yīng)該說明建立在現(xiàn)有實踐之上的原則和選擇。

文檔

需要考慮的關(guān)鍵事項:

  • 將代碼的接口以及API合同寫在文檔中;

  • 定義文檔策略:

  • 整體的文檔策略是什么?

  • 項目的 README.md 文件中包含什么?

  • 是否需要更新更廣泛的文檔?

  • 采用哪些畫圖工具?

  • 是否使用輕量級架構(gòu)決策記錄?

  • 文檔應(yīng)當(dāng)存儲在Git代碼庫中?還是采用單獨的工具?

  • 如果存儲在項目中,推薦的文件夾結(jié)構(gòu)是什么?

通用(微)服務(wù)設(shè)計指南

需要考慮的關(guān)鍵事項:

  • 使用藍(lán)圖/模板/原型作為所有(微)服務(wù)的起點;

  • 將藍(lán)圖與所有公共庫、插件等捆綁在一起,并且必須符合標(biāo)準(zhǔn);

  • 每個(微)服務(wù)必須能夠通過運行一個命令來啟動;

  • (微)服務(wù)只能通過API/事件處理數(shù)據(jù),沒有后門;

  • 每個(微)服務(wù)都是獨立的;

  • 所有(微)服務(wù)都符合應(yīng)用的十二要素,以及其他標(biāo)準(zhǔn)。

代碼格式/風(fēng)格

選擇一種代碼風(fēng)格,并貫徹到底。如果可以,在提交前自動格式化。

命名約定

選擇一種約定,并貫徹到底。

API標(biāo)準(zhǔn)

需要考慮的關(guān)鍵事項:

  • 遵循 REST 命名實踐(名詞、復(fù)數(shù)以及其他常見的標(biāo)準(zhǔn)),網(wǎng)上有很多指南,選擇一種,并貫徹到底;

  • 與命名規(guī)則統(tǒng)一。該標(biāo)準(zhǔn)適用于一切,比如負(fù)載對象命名、屬性等,而不僅限于端點。無論是駝峰式、蛇式還是烤肉串式,選擇一種,并貫徹到底;

  • POST、PUT、PATCH的響應(yīng)包含有意義的主體;

  • 使用有意義的 HTTP 狀態(tài)碼,不要遇到錯誤就返回 400;

  • 所有端點必須返回有意義的錯誤情況;

  • 提供錯誤列表(更多細(xì)節(jié)請參見錯誤處理部分的介紹);

  • 考慮 OpenAPI,以及契約優(yōu)先開發(fā),即剛開始的時候編寫 OpenAPI 契約,與(內(nèi)部)消費者溝通,這樣可以實現(xiàn)更好的并行開發(fā);

  • 使用有意義的描述和示例記錄 OpenAPI 契約;

  • 所有(內(nèi)部)API 必須使用 CorrelationId/TraceId 的標(biāo)頭;

  • 默認(rèn)情況下,所有 API 輸入都必須有非常嚴(yán)格的限制;

  • 所有 API(內(nèi)部或外部)都必須經(jīng)過身份驗證,最好采用實時授權(quán);

  • 所有 API 必須重用相同的公共數(shù)據(jù)結(jié)構(gòu):可以采用通用的地址、人、國家等,也可以定義特定于業(yè)務(wù)的數(shù)據(jù)結(jié)構(gòu);

  • 所有 API(內(nèi)部或外部)只能通過 HTTPS 公開;

  • 考慮在 API 的響應(yīng)中返回安全標(biāo)頭,例如:Cache-Control: no-store,Content-Security-Policy: frame-ancestors 'none',Content-Type, Strict-Transport-Security,X-Content-Type-Options: nosniff,X-Frame-Options: DENY等。

  • 內(nèi)部 API 之間的通信不應(yīng)該通過互聯(lián)網(wǎng)(除非是架構(gòu)有意為之,或有此類要求);

  • 不要通過互聯(lián)網(wǎng)公開管理端點;如果有這種要求,請使用身份驗證;

  • 確保所有 API 都會嚴(yán)格驗證收到的請求:不允許使用未記錄的 JSON 字段、拒絕格式錯誤的 JSON 等;

  • 正確使用數(shù)據(jù)類型,不要將所有內(nèi)容都作為字符串;

  • 盡可能使用枚舉值;

  • 定義字符串的長度限制,定義數(shù)字的最小值/最大值;

  • 定義每個字符串的輸入限制模式;

  • 某些屬性有明確的定義,因此定義正則表達(dá)式很容易,比如國家代碼一律以“[A-Z]+”開頭。但有些屬性很難定義正則表達(dá)式,比如考慮到所有語言中人們的姓氏,這個屬性(lastName)的要求就會非常寬松。建議定義一些能夠防止出現(xiàn)奇怪字符的模式,比如 Unicode 控制字符、分隔符或符號;推薦的正則表達(dá)式對象如下:“^[^\p{C}\p{Z}\p{So}]*[^\p{C}\p{so}]+[^\p{C}\p{Z}\p{So}]*$”,但這并不能確保程序可以免受任何類型的注射,你仍然需要很好地理解數(shù)據(jù)的去向和處理方式,但至少可以確保表情符號不會破壞你的系統(tǒng)。

標(biāo)準(zhǔn)日志

需要考慮的關(guān)鍵事項:

  • 日志的格式:使用逗號分隔的鍵值對(key=value)?還是使用JSON對象?選擇適合工具的格式;

  • 日志的每一行都包含 CorrelationId/TraceId,這樣可以方便工具創(chuàng)建儀表板;

  • 日志中記錄方便理解實際情況的信息:哪個實體?業(yè)務(wù)領(lǐng)域?成功了嗎?失敗了?

  • 一些參考做法();

  • 在實際的日志實現(xiàn)之上使用抽象層;例如在 Java中,使用由logback實現(xiàn)的slf4j;

  • 將日志作為橫切關(guān)注點,利用面向切面的程序設(shè)計,僅在異常情況下記錄日志,限制敏感內(nèi)容的記錄;

  • 不能將日志作為記錄一切備用信息的手段,將所有請求和響應(yīng)都完整地記錄下來。應(yīng)當(dāng)謹(jǐn)慎地記錄日志,即使在調(diào)試級別或較低級別中也應(yīng)如此。

  • 更多有關(guān)日志記錄的參考信息()。

數(shù)據(jù)標(biāo)準(zhǔn)

需要考慮的關(guān)鍵事項:

  • 使用現(xiàn)有的 ISO 標(biāo)準(zhǔn)處理廣為人知的對象:貨幣、日期、金額等;

  • 定義可重復(fù)使用的特定于業(yè)務(wù)的對象;

  • API對象、數(shù)據(jù)庫實體和事件也需要采用這些標(biāo)準(zhǔn)。

處理數(shù)據(jù)

需要考慮的關(guān)鍵事項:

  • 在處理數(shù)據(jù)之前清理數(shù)據(jù),下面是一個通用的清理正則表達(dá)式:“^[^\p{C}\p{Z}\p{So}]*[^\p{C}\p{so}]+[^\p{C}\p{Z}\p{So}]*$”,雖然無法杜絕所有的問題,但是可以刪除可能會導(dǎo)致系統(tǒng)崩潰的奇怪字符;

  • 確保不會將輸入數(shù)據(jù)傳輸?shù)絻?nèi)部的訪問操作,如數(shù)據(jù)庫查詢、命令行執(zhí)行等。使用參數(shù)化的數(shù)據(jù)庫查詢,具體指定獲取的內(nèi)容與傳遞的內(nèi)容;

  • 當(dāng)需要針對特定輸入的處理施加限制時,請使用白名單(而不是黑名單);

  • 采用防御性編程實踐;

  • 確保使用不易受到 XXE 或類似攻擊的高效 XML 解析器。最好不要使用 XML 作為輸入,除非上下文有這樣的強(qiáng)制要求。

日志數(shù)據(jù)

需要考慮的關(guān)鍵事項:

  • 不要記錄敏感數(shù)據(jù)。如果出于某種原因仍然需要記錄,請屏蔽敏感數(shù)據(jù)。這里的敏感程度取決于具體的業(yè)務(wù)與法規(guī);

  • 創(chuàng)建/使用一個庫,默認(rèn)屏蔽平臺中最敏感的數(shù)據(jù),例如,如果你正在處理付款,則默認(rèn)屏蔽銀行卡號,不要讓每個開發(fā)者自行決定;

  • 考慮在每次添加新的敏感數(shù)據(jù)時擴(kuò)展該庫,如果需要添加大量數(shù)據(jù),則必須平衡性能;

  • 日志記錄庫必須允許特定的配置,以便每個單獨的服務(wù)可以屏蔽額外的數(shù)據(jù),而無需擴(kuò)展該庫;

  • 日志記錄庫必須提供清理方法(即通過調(diào)用特定的方法),確保所有情況都可以使用同一種清理技術(shù);

  • 日志記錄庫必須在記錄數(shù)據(jù)之前清理數(shù)據(jù)(比如刪除所有與“\p{Z}\p{C}\p{So}”相匹配的字符);

  • 日志記錄庫必須刪除 CR 和 LF 字符,以防止 CRLF 注入;

  • 建立明確的日志歸檔策略。

存儲數(shù)據(jù)

需要考慮的關(guān)鍵事項:

只能存儲與當(dāng)前上下文或可預(yù)見的將來相關(guān)的數(shù)據(jù),數(shù)據(jù)存儲不能作為以備不時之需的手段;

  • 數(shù)據(jù)的存儲必須遵守相關(guān)規(guī)定,你必須知道這一點;

  • 某些數(shù)據(jù)不能明文存儲(比如信用卡號),可以使用硬件或軟件加密;

  • 不能在純文本文件的版本控制中存儲隱私數(shù)據(jù)(密碼、加密密鑰、ssh 密鑰、私鑰等),必須使用專用產(chǎn)品或服務(wù),例如 Vault、HSM等;

  • 在執(zhí)行敏感數(shù)據(jù)的加密或散列操作時,必須“加鹽”和/或“加胡椒”,以防止暴力攻擊;

  • 考慮構(gòu)建(或使用)令牌化敏感數(shù)據(jù)的集中式服務(wù);

  • 令牌化所有受某種監(jiān)管的數(shù)據(jù):銀行卡號、PII 數(shù)據(jù)等。所有(微)服務(wù)都應(yīng)該使用令牌(而不是實際的數(shù)據(jù)),并僅在需要時還原令牌,這可以最大限度地減少合規(guī)所需的工作,還可以更好地控制數(shù)據(jù);

  • 加強(qiáng)令牌化解決方案的安全性,不允許從外部訪問其 API。

事件/消息標(biāo)準(zhǔn)

需要考慮的關(guān)鍵事項:

  • 創(chuàng)建一個事件列表,讓每個人都知道每個事件的目的;

  • 使用事件規(guī)范進(jìn)行驗證;

  • 避免使用通用事件來發(fā)送一切消息,避免在不知情的情況下泄露敏感信息;

  • 考慮用交換令牌代替包含敏感信息的實際數(shù)據(jù)。

配置管理

需要考慮的關(guān)鍵事項:

  • 避免在源文件中硬編碼配置;

  • 考慮使用集中式配置管理;

  • 按環(huán)境分隔配置;

  • 不要在源文件或版本控制中存儲隱私數(shù)據(jù)(密碼、api 密鑰、ssh 密鑰、私鑰等),使用適當(dāng)?shù)碾[私數(shù)據(jù)系統(tǒng);

  • 不要保留任何可部署單元(云服務(wù)、產(chǎn)品或自己的(微)服務(wù))的默認(rèn)憑據(jù);

  • 不要將僅用于測試的代碼或配置放入生產(chǎn);

  • 不要只在服務(wù)中構(gòu)建測試后門;

  • 使用版本控制來記錄配置更改;

  • 使用適當(dāng)?shù)呐渲猛暾詸z查機(jī)制。

錯誤處理

需要考慮的關(guān)鍵事項:

將異常和錯誤視為橫切關(guān)注點,利用面向切面的程序設(shè)計,使用 ControllerAdvices 等類似的工具;

將常見的異常/錯誤(驗證問題、未找到資源、格式錯誤消息)處理邏輯放入到共享庫中,這可以減少(微)服務(wù)之間的交互摩擦;

編寫一個錯誤列表;

  • 使用錯誤代碼(例如 MICRO-4221代表結(jié)構(gòu)驗證導(dǎo)致請求出錯,MICRO-4222 代表業(yè)務(wù)驗證導(dǎo)致請求出錯);

  • 不要在響應(yīng)中泄漏內(nèi)部狀態(tài),避免傳遞 e.getMessage,返回的每個錯誤都必須由其根本原因創(chuàng)建,同時不要泄漏內(nèi)部數(shù)據(jù);

  • 使用 catch-all 機(jī)制,以避免因意外異常而泄漏內(nèi)部狀態(tài)。你可以利用全局錯誤處理程序捕獲異常并返回 500;

  • 所有錯誤都應(yīng)該返回同一個對象,以實現(xiàn)統(tǒng)一的體驗;

  • 在API文檔中使用適當(dāng)?shù)?HTTP 狀態(tài)碼記錄所有的錯誤情況。如果使用 OpenAPI,請記錄所有可能的 HTTP 狀態(tài)碼,即使它們返回相同的 OpenAPI 對象。

分支策略與提交

需要考慮的關(guān)鍵事項:

  • 使用簡單的分支策略,基于trunk的方式、GitHub工作流等,隨便選一個;

  • 存儲庫和分支采用有意義的命名;

  • 使用描述性提交,以方便將來追蹤變更;

  • 分多次提交少量的代碼,以更好地分隔變更;

  • 使用智能提交,即提供指向任務(wù)(來自任務(wù)管理系統(tǒng))的鏈接;

  • 考慮使用預(yù)提交鉤子來驗證提交;

  • 提交消息中不要包含敏感信息;

  • 存儲庫啟用遠(yuǎn)程訪問時需要特別小心,特別是托管在云中的存儲庫。

代碼審查

需要考慮的關(guān)鍵事項:

  • 必須執(zhí)行代碼審查(保持善意和自信,提供具體說明,以及其他良好的習(xí)慣);

  • 機(jī)械的檢查交給工具來做,專心審查功能以及是否符合標(biāo)準(zhǔn)和實踐;

  • 如果你反復(fù)遇到同一個問題,請將其添加到標(biāo)準(zhǔn)中;

  • 建立檢查列表,直到所有人都養(yǎng)成關(guān)注同一個問題的習(xí)慣。

工具與第三方庫

需要考慮的關(guān)鍵事項:

  • 制定引入新工具的流程。進(jìn)行權(quán)衡分析,并推廣到更廣泛的群體,得到所有人的接受/同意,并確保覆蓋更廣泛的情況;

  • 選擇開源軟件時注意許可;

  • 創(chuàng)建許可列表,在其中列出所有無需詢問即可使用的許可、需要討論的許可以及不允許使用的許可;

  • 在發(fā)現(xiàn)新工具/庫/產(chǎn)品時,不要著急使用,你需要考慮:是否穩(wěn)定?是否有良好的維護(hù)?是否有成功案例?

  • 考慮使用 OWASP Dependency Check、License Plugin 之類的工具,或其他更復(fù)雜的工具,例如 Black Duck等;

  • 制定一個普遍認(rèn)可的工具/庫創(chuàng)建列表,供所有人挑選;

  • 定期更新依賴項。

代碼分析

  • 需要考慮的關(guān)鍵事項:

  • 使用一種或多種工具來分析代碼;

  • 必須擁有一種(至少)常見的代碼分析工具,以及一種注重安全實踐的工具;

  • 常見的(Java)代碼分析工具:Sonarqube、PMD、SpotBugs;

  • 常見的安全代碼分析工具:Veracode、Checkmarx、Sonarqube;

  • 你不需要遵循這些工具提供的所有標(biāo)準(zhǔn)規(guī)則(盡管通常這些標(biāo)準(zhǔn)都與行業(yè)建議一致),可以根據(jù)實際情況選出適合自己的規(guī)則。

測試

需要考慮的關(guān)鍵事項:

  • 執(zhí)行各個級別的自動化測試:單元測試、集成測試、組件測試、API測試、端到端測試等;

  • 除了正面測試之外,還需要關(guān)注負(fù)面測試以及邊界測試,CATS 是一款優(yōu)秀的 API 測試工具;

  • 不要忽視失敗的測試,即使是間歇性失敗的測試,其中可能隱藏了嚴(yán)重的潛在問題;

  • 測試必須具有彈性,而且必須充分;

  • 測試必須使用類似且可預(yù)測的方法;

  • 測試不得依賴于復(fù)雜的外部設(shè)置,必須能夠通過模擬依賴項、使用內(nèi)存設(shè)置來完成測試,或采用測試容器,或僅依賴于已部署的(微)服務(wù)。任何其他步驟只會使設(shè)置更加復(fù)雜化;

  • 考慮在管道內(nèi)添加一些安全測試;

  • 考慮突變測試。

CI/CD

需要考慮的關(guān)鍵事項:

  • 在重要的環(huán)節(jié)添加質(zhì)量檢測,并作為檢查點,如果檢測失敗,則構(gòu)建也會失?。?/p>

  • 質(zhì)量檢測必須符合這些標(biāo)準(zhǔn),并自動檢查每個(微)服務(wù);

  • 下面是一個 CI/CD 管道示例:

編譯和構(gòu)建;

檢查格式;

運行測試并檢查覆蓋率;

運行突變測試;

運行代碼分析;

運行安全代碼分析;

檢查第三方庫的漏洞;

檢查第三方庫的許可;

部署;

運行 API 測試;

運行其他類型的測試。

  • 雖然看上去很冗長,但在微服務(wù)上運行這些檢查非??欤?/p>

  • 編寫自己的流水線腳本;

  • 不要將流水線與(微)服務(wù)融合到一起;

  • 使用適合于所有(微)服務(wù)的流水線模板。

認(rèn)證和授權(quán)

需要考慮的關(guān)鍵事項:

  • 不要自行構(gòu)建身份驗證和授權(quán),請使用標(biāo)準(zhǔn)的產(chǎn)品和服務(wù);

  • 所有內(nèi)部與外部API都需要身份認(rèn)證,選擇一些可靠的認(rèn)證服務(wù);

  • 外部和內(nèi)部調(diào)用需要使用單獨的身份驗證和授權(quán)機(jī)制:使用一組憑據(jù)/機(jī)制來驗證外部調(diào)用,再使用另一組單獨的憑據(jù)/機(jī)制來驗證內(nèi)部調(diào)用;

  • 憑據(jù)始終需要加密,無論是否投入了使用;

  • 所有API(無論內(nèi)部還是外部)都需要使用 HTTPS;

  • 不要通過 HTTP GET 接收身份驗證憑據(jù),僅使用 HTTP 頭部或 HTTP POST/PUT;

  • 即使在調(diào)試時也不能記錄憑據(jù),通過日志記錄的catch all來避免記錄憑據(jù);

  • 確保授權(quán)和身份驗證機(jī)制允許細(xì)粒度的控制和管理,即可以限制每個操作的調(diào)用次數(shù)、撤銷訪問、頒發(fā)額外的憑據(jù)等;

  • 考慮使用集中式身份提供程序和公共庫;

  • 對于高度敏感的 API/服務(wù)使用增強(qiáng)的安全控制(API 的雙向 TLS,服務(wù)訪問的 MFA);

  • 使用隨機(jī)數(shù)來防止重放攻擊;

  • 設(shè)計和構(gòu)建采用最低特權(quán)原則。

通用安全實踐

需要考慮的關(guān)鍵事項:

  • 永遠(yuǎn)不要使用自己的加密程序,不要在這個空間內(nèi)重新發(fā)明輪子;

  • 使用行業(yè)推薦算法:AES 256、RSA 2048+、SHA-2 512等;

  • 使用 TLS 1.3+ 來保證傳輸安全;

  • 在執(zhí)行敏感數(shù)據(jù)的加密或散列操作時,必須“加鹽”和/或“加胡椒”,以防止暴力攻擊;

  • 檢查編程語言處理敏感信息的實踐,例如在 Java 中,在處理密碼、銀行卡號、社會保險號時,必須使用 byte,不能使用 String。必須盡量減少數(shù)據(jù)在內(nèi)存中停留的時間并在使用后清除對象。

質(zhì)量

如上所述,系統(tǒng)生命周期的標(biāo)準(zhǔn)和實踐并不一定會直接關(guān)系到安全。質(zhì)量方面也有這個問題。當(dāng)前的設(shè)計和方法缺陷可能會導(dǎo)致應(yīng)用程序宕機(jī),即便并不是由真正的安全問題引起的。

關(guān)于性能,需要考慮的關(guān)鍵事項:

  • 對于昂貴的資源,比如數(shù)據(jù)庫、API等,應(yīng)該使用連接池;

  • 使用線程池;

  • 使用緩存;

  • 操作數(shù)據(jù)時使用適當(dāng)?shù)募希?/p>

  • 如果可以,請使用并行編程;

  • 確保你了解對象關(guān)系映射(ORM)如何生成查詢;

  • 避免將大量資源加載到內(nèi)存,請使用數(shù)據(jù)流;

  • 建立每個(微)服務(wù)實例的性能基準(zhǔn),幫助你了解何時需要擴(kuò)展;

  • 定期執(zhí)行負(fù)載測試與性能測試。

關(guān)于彈性,需要考慮的關(guān)鍵事項:

  • 使用斷路器、重試、超時、速率限制;

  • 當(dāng)依賴的 API 不可用時有明確的回退策略;

  • 關(guān)于彈性的資源:

  • 所有 API 都必須具備冪等性;

  • 不要在(微)服務(wù)實例中存儲狀態(tài),可以考慮使用分布式緩存。

關(guān)于可用性和可擴(kuò)展性,需要考慮的關(guān)鍵事項:

  • 設(shè)計不應(yīng)當(dāng)限制(微)服務(wù)的水平擴(kuò)展;

  • 做好故障計劃,建立自動化的機(jī)制,根據(jù)負(fù)載水平自動伸縮;

  • 考慮分片,只讀副本;

  • 使用多區(qū)域部署。

關(guān)于可觀察性和監(jiān)控,需要考慮的關(guān)鍵事項:

  • 所有(微)服務(wù)都必須公開有關(guān)應(yīng)用程序以及底層容器的健康端點;

  • 健康端點必須返回有關(guān)其所有依賴項的信息:數(shù)據(jù)庫、加密服務(wù)、連接的 API、事件總線等。

  • 利用標(biāo)準(zhǔn)化日志創(chuàng)建有意義的操作儀表板。

自動化

一切都應(yīng)盡可能實現(xiàn)自動化。自動化可以確保預(yù)測性和一致性。應(yīng)該利用 CI/CD 流水線自動化所有檢查,這些檢查將從質(zhì)量的角度評估(微)服務(wù)。對于不適合自動化的標(biāo)準(zhǔn),可以考慮 Semgrep 等工具。

總結(jié)

在本文中,我盡可能地列出了方方面面的實踐建議。雖然這不是一份詳盡的攻略,但可以作為建立安全思維模式的起點。在貫徹完成這些實踐后,你可以進(jìn)一步深入的研究。這些實踐不僅可以確保系統(tǒng)安全,而且還具備結(jié)構(gòu)化與統(tǒng)一性。在快速開發(fā)系統(tǒng)(無論是開發(fā)全新的系統(tǒng)還是改造遺留系統(tǒng))時,這些實踐尤為重要。你不需要從第一天開始就貫徹所有實踐,特別是過多的通用標(biāo)準(zhǔn)會限制你的選擇。你可以逐步嘗試,然后看看效果。

原文鏈接:

聲明:本文由CSDN翻譯,轉(zhuǎn)載請注明來源。

1.《提高(微)服務(wù)安全的非完全攻略》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識,僅代表作者本人觀點,與本網(wǎng)站無關(guān),侵刪請聯(lián)系頁腳下方聯(lián)系方式。

2.《提高(微)服務(wù)安全的非完全攻略》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進(jìn)行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。

3.文章轉(zhuǎn)載時請保留本站內(nèi)容來源地址,http://f99ss.com/yule/2185207.html