使用共用存取簽章的服務匯流排存取控制
這篇文章討論共用存取簽章 (SAS)、其運作方式,以及如何搭配 Azure 服務匯流排以平台無關的方式使用共用存取簽章。
SAS 會根據在命名空間或傳訊實體 (佇列或主題)上設定的授權規則,來保護對服務匯流排的存取權限。 授權規則具有名稱、與特定權限相關聯,並且承載了密碼編譯金鑰組。 您可以透過服務匯流排 SDK 使用規則的名稱和金鑰,或用於您自己的程式碼中以產生 SAS 權杖。 接著,用戶端可將權杖傳至服務匯流排,以證明要求之作業的授權。
注意
Azure 服務匯流排支援使用 Microsoft Entra ID 授權對服務匯流排命名空間及其實體的存取。 使用由 Microsoft Entra ID 傳回的 OAuth 2.0 權杖來授權使用者或應用程式,可透過共用存取簽章 (SAS) 提供卓越的安全性與易用性。 SAS 金鑰缺乏精細的訪問控制,難以管理/輪替,而且沒有稽核功能來將其使用與特定使用者或服務主體產生關聯。 基於這些原因,我們建議使用 Microsoft Entra ID。
Microsoft 建議盡可能搭配使用 Microsoft Entra ID 與 Azure 服務匯流排應用程式。 如需詳細資訊,請參閱下列文章:
您可以停用服務匯流排命名空間的本機或 SAS 金鑰驗證,只允許透過 Microsoft Entra 驗證。 如需逐步指示,請參閱停用本機驗證。
SAS 的概觀
共用存取簽章是使用簡易權杖的宣告式授權機制。 使用 SAS 時,金鑰一律不會透過網路傳遞。 金鑰可用來以密碼編譯方式簽署稍後可由服務驗證的資訊。 SAS 的作用可類似於用戶端直接擁有授權規則名稱和相符金鑰的使用者名稱和密碼。 SAS 的作用也可類似於同盟安全性模型;在此模型中,用戶端會收到來自於安全性權杖服務、具有時效性且已簽署的存取權杖,而從未擁有簽署金鑰。
服務匯流排中的 SAS 驗證,會使用具有相關存取權限的具名共用存取授權原則以及主要和次要密碼編譯金鑰組進行設定。 金鑰是採用 Base64 表示法的 256 位元值。 您可以在服務匯流排佇列和主題上,於命名空間層級設定規則。
注意
這些金鑰是使用 Base64 表示法的純文字字串,而且在使用前不得解碼。
共用存取簽章權杖包含所選授權規則的名稱、應存取之資源的 URI、到期時間,以及使用所選授權原則的主要或次要密碼編譯金鑰對這些欄位計算的 HMAC RSA-SHA256 密碼編譯簽章。
共用存取授權原則
每個服務匯流排命名空間和每個服務匯流排實體,都有一個由規則組成的共用存取授權原則。 命名空間層級的原則會套用至命名空間內的所有實體,無論其個別的原則組態為何。
對於每個授權原則規則,您會決定三項資訊:名稱、範圍和權限。 名稱 只是該範圍內的唯一名稱。 範圍也很簡單:它是發生問題之資源的 URI。 針對服務匯流排命名空間,範圍是完整的命名空間,例如 https://<yournamespace>.servicebus.windows.net/
。
原則規則所授與的權限可由下列項目組合而成:
- 傳送 - 授與將訊息傳送至實體的權限
- 接聽 - 授與接收 (佇列、訂用帳戶) 和所有相關訊息處理的權限
- 管理 - 授與管理命名空間拓撲的權限,包括建立和刪除實體
管理權限包含「傳送」和「接聽」權限。
命名空間或實體原則最多可包含 12 個共用存取授權規則,而提供三組規則的空間,每組規則分別涵蓋基本權限以及「傳送」與「接聽」的組合。 此限制是以每個實體為主,這表示命名空間和每個實體最多可以有 12 個共用存取授權規則。 此限制突顯 SAS 原則存放區並非使用者或服務帳戶存放區。 如果您的應用程式需要根據使用者或服務身分識別授與服務匯流排的存取權,則應實作會在驗證和存取檢查後發行 SAS 權杖的安全性權杖服務。
授權規則會被指派「主要金鑰」和「次要金鑰」。 這些是強式密碼編譯的金鑰。 請勿遺失或洩漏金鑰 - 它們永遠都可在 Azure 入口網站取得。 您可以使用其中一個產生的金鑰,以及您可以隨時重新產生它們。 如果您重新產生或變更原則中的金鑰,所有先前根據該金鑰發行的權杖都將立即無效。 不過,根據這類權杖建立的作用中連線會繼續運作,直到權杖到期。
當您建立服務匯流排命名空間時,系統會自動為命名空間建立名為 RootManageSharedAccessKey 的原則規則。 此原則具有整個命名空間的「管理」權限。 建議您將此規則視為系統管理根帳戶,且不要將其用於您的應用程式。 您可以在入口網站中,透過 PowerShell 或 Azure CLI,在命名空間的 [共用存取原則] 索引標籤中建立更多的原則規則。
建議您定期重新產生用於 SharedAccessAuthorizationRule 物件的金鑰。 由於有主要和次要金鑰槽存在,因此您可以逐步輪替金鑰。 如果您的應用程式通常會使用主要金鑰,您可以將主要金鑰複製到次要金鑰槽中,然後再重新產生主要金鑰。 接著,新的主要金鑰值將可設定到可繼續使用次要槽中的舊有主要金鑰進行存取的用戶端應用程式中。 所有的用戶端皆更新後,您即可重新產生次要金鑰,而最終淘汰掉舊的主要金鑰。
如果您確知或懷疑金鑰受到危害而必須撤銷金鑰,您可以重新產生 SharedAccessAuthorizationRule 的 PrimaryKey 和 SecondaryKey,並取代成新的金鑰。 此程序會讓所有以舊金鑰簽章的權杖失效。
使用 SAS 時的最佳做法
當您在應用程式中使用共用存取簽章時,您必須留意兩個潛在風險:
- 如果洩漏 SAS,則任何取得之人皆可使用,有可能危害服務匯流排資源。
- 如果提供給用戶端應用程式的 SAS 過期,且應用程式無法從服務擷取新的 SAS,則可能阻礙應用程式的功能。
下列關於使用共用存取簽章的建議,將可協助您平衡這些風險:
- 必要時讓用戶端自動更新 SAS:用戶端應該在 SAS 到期之前儘早更新 SAS,萬一提供 SAS 的服務無法使用,至少還有時間重試。 如果打算將 SAS 用於少數即時的短暫作業,而這些預計都在到期時間內完成,則不需要此建議,因為預期不會更新 SAS。 不過,如果您有定期透過 SAS 做出要求的用戶端,則到期的可能性便有可能發生。 究竟是需要短期的 SAS (如先前所述),還是需要確保用戶端及早要求更新 (以避免因為 SAS 在成功更新之前過期而導致中斷),主要考量即在這兩者之間尋求平衡。
- 注意 SAS 開始時間:如果您將 SAS 的開始時間設定為現在,由於時鐘誤差 (不同機器的目前時間差距),前幾分鐘可能間歇失敗。 一般而言,請將開始時間設為至少 15 分鐘之前的時間。 或者,完全不設定,在所有情況下立即生效。 到期時間通常也是如此。 請記住,在任何要求上,順逆時鐘誤差可能長達 15 分鐘。
- 特別針對要存取的資源:安全性最佳做法是為使用者提供最低必要權限。 如果使用者只須要針對單一實體的讀取存取權,請為該單一實體授予讀取存取權限,無須為所有實體授予讀取/寫入/刪除權限。 這也有助於減輕 SAS 洩露所造成的損害,因為 SAS 在攻擊者手中權限較低。
- 不一定要使用 SAS:對服務匯流排執行特定作業時,引起的風險有時高過 SAS 的優點。 針對這類作業,請建立中介層服務,在商務規則確認、驗證和稽核之後才寫入服務匯流排。
- 一律使用 HTTPS:一律使用 HTTPS 來建立或發佈 SAS。 如果 SAS 透過 HTTP 傳遞但遭到攔截,則進行中間人攻擊的攻擊者能夠讀取 SAS,然後像預定使用者一樣使用 SAS,可能導致洩露敏感性資料或讓惡意使用者損毀資料。
共用存取簽章驗證的設定
您可以在服務匯流排命名空間、佇列或主題上設定共用授權原則。 目前尚不支援在服務匯流排訂閱中設定,但您可以使用在命名空間或主題上設定的規則來保護訂閱存取。
在此圖中,manageRuleNS、sendRuleNS 和 listenRuleNS 授權規則套用至佇列 Q1 和主題 T1,而 listenRuleQ 和 sendRuleQ 僅套用至佇列 Q1 以及 sendRuleT 僅套用至主題 T1。
產生共用存取簽章權杖
任何有權存取授權規則名稱及其簽署金鑰之一的用戶端,都可以產生 SAS 權杖。 權杖是以下列格式編寫字串而產生的:
SharedAccessSignature sig=<signature-string>&se=<expiry>&skn=<keyName>&sr=<URL-encoded-resourceURI>
se
- 權杖到期時間。 此整數反映自 1970 年 1 月 1 日的 Epoch00:00:00 UTC
(UNIX Epoch) 起到權杖到期時所經過的秒數。skn
- 授權規則個名稱。sr
- URL 編碼的所存取資源 URI。sig
- URL 編碼的 HMACSHA256 簽章。 雜湊計算看起來類似下列虛擬程式碼,會傳回原始二進位輸出值的 base64 碼。urlencode(base64(hmacsha256(urlencode('https://<yournamespace>.servicebus.windows.net/') + "\n" + '<expiry instant>', '<signing key>')))
重要
如需使用不同程式設計語言產生 SAS 權杖的範例,請參閱產生 SAS 權杖。
權杖會包含非雜湊值,因此接收者可以用相同的參數重新計算雜湊,驗證簽發者擁有有效的簽署金鑰。
資源 URI 是宣告其存取權之服務匯流排資源的完整 URI。 例如,http://<namespace>.servicebus.windows.net/<entityPath>
或 sb://<namespace>.servicebus.windows.net/<entityPath>
;也就是 http://contoso.servicebus.windows.net/contosoTopics/T1/Subscriptions/S3
。
URI 必須以百分比編碼。
用於簽署的共用存取授權規則必須設定於此 URI 或其中一個階層式上層所指定的實體。 例如,先前範例中的 http://contoso.servicebus.windows.net/contosoTopics/T1
或 http://contoso.servicebus.windows.net
。
SAS 權杖適用於所有以 signature-string
中所使用的 <resourceURI>
開頭的資源。
重新產生金鑰
建議您定期重新產生用於共用存取授權原則的金鑰。 由於有主要和次要金鑰槽存在,因此您可以逐步輪替金鑰。 如果您的應用程式通常會使用主要金鑰,您可以將主要金鑰複製到次要金鑰槽中,然後再重新產生主要金鑰。 接著,新的主要金鑰值將可設定到可繼續使用次要槽中的舊有主要金鑰進行存取的用戶端應用程式中。 所有的用戶端皆更新後,您即可重新產生次要金鑰,而最終淘汰掉舊的主要金鑰。
如果您確知或懷疑金鑰受到危害而必須撤銷金鑰,您可以重新產生共用存取授權原則的主要金鑰和次要金鑰,並取代成新的金鑰。 此程序會讓所有以舊金鑰簽章的權杖失效。
若要在 Azure 入口網站中重新產生主要和次要金鑰,請遵循下列步驟:
瀏覽至 Azure 入口網站中的 [服務匯流排命名空間]。
選取在左窗格中的 [共用存取原則]。
從清單中選取該原則。 下列範例中已選取了 RootManageSharedAccessKey。
若要重新產生主要金鑰,請在 [SAS 原則:RootManageSharedAccessKey] 頁面上,選取命令列上的 [重新產生主要金鑰]。
若要重新產生次要金鑰,請在 [SAS 原則:RootManageSharedAccessKey] 頁面上,選取命令列上的 [...],然後選取 [重新產生次要金鑰]。
如果您使用的是 Azure PowerShell,請使用 New-AzServiceBusKey
Cmdlet 來重新產生服務匯流排命名空間的主要和次要金鑰。 您也可以使用 -KeyValue
參數,來為所產生的主要和次要索引鍵指定值。
如果您使用的是 Azure CLI,請使用 az servicebus namespace authorization-rule keys renew
命令來重新產生服務匯流排命名空間的主要和次要金鑰。 您也可以使用 --key-value
參數,來為所產生的主要和次要索引鍵指定值。
服務匯流排的共用存取簽章驗證
下方說明的案例包括授權規則的設定、SAS 權杖的產生以及用戶端授權。
如需服務匯流排應用程式的範例,以便了解相關設定及使用 SAS 授權,請參閱共用存取簽章驗證與服務匯流排。
存取實體上的共用存取授權規則
在適用於服務匯流排的管理程式庫的佇列或主題上使用 get/update 作業,藉此存取/更新相對應的共用存取授權原則。 您也可以使用這些程式庫來在建立佇列或主題時新增規則。
使用共用存取簽章授權
在任何正式支援的程式語言 (如 .NET、JAVA、JavaScript 和 Python) 中使用任何服務匯流排 SDK 的應用程式時,都可以透過傳遞至用戶端建構函式的連接字串來使用 SAS 授權。
連接字串可包含規則名稱 (SharedAccessKeyName) 和規則金鑰 (SharedAccessKey) 或先前發行的權杖 (SharedAccessSignature)。 當這些名稱出現在傳至任何建構函式的連接字串中,或是接受連接字串的 Factory 方法中時,系統會自動建立 SAS 權杖提供者並填入。
若要搭配使用 SAS 授權與服務匯流排訂用帳戶,您可以使用在服務匯流排命名空間或主題上設定的 SAS 金鑰。
使用共用存取簽章 (於 HTTP 層級)
既然知道如何為服務匯流排中的任何實體建立共用存取簽章,您可準備執行 HTTP POST:
POST https://<yournamespace>.servicebus.windows.net/<yourentity>/messages
Content-Type: application/json
Authorization: SharedAccessSignature sr=https%3A%2F%2F<yournamespace>.servicebus.windows.net%2F<yourentity>&sig=<yoursignature from code above>&se=1438205742&skn=KeyName
ContentType: application/atom+xml;type=entry;charset=utf-8
請記住,這適用於所有項目。 您可以為佇列、主題或訂用帳戶建立 SAS。
如果您提供寄件者或用戶端 SAS 權杖,他們不會直接有金鑰,並且他們無法回復雜湊來取得它。 因此,您可以控制他們可以存取的項目,以及時間長度。 要記住的重點是,如果您變更原則中的主要金鑰,從該金鑰建立的任何共用存取簽章將會失效。
使用共用存取簽章 (於 AMQP 層級)
在前一節中,說明了如何使用 SAS 權杖搭配 HTTP POST 要求傳送資料到服務匯流排。 如您所了解,您可以使用進階訊息佇列通訊協定 (AMQP) 來存取服務匯流排,此通訊協定在許多案例中,都是基於效能考量而做為慣用的通訊協定。 如需使用 SAS 權杖搭配 AMQP 的用法,請參閱 AMQP 宣告型安全性 1.0 版 文件中的說明,該文件是自 2013 年開始的工作草稿,不過現在 Azure 已能對其提供支援。
開始將資料傳送到服務匯流排之前,發行者必須在 AMQP 訊息內部將 SAS 權杖傳送至正確定義且名為 $cbs 的 AMQP 節點 (您可以將它視為一個由服務所使用的「特別」佇列,用來取得並驗證所有的 SAS 權杖)。 發行者必須在 AMQP 訊息中指定 ReplyTo 欄位;這是服務將以權杖驗證結果 (發行者與服務之間的簡單要求/回覆模式) 回覆發行者的節點所在。 此回覆節點是「動態」建立,如 AMQP 1.0 規格中所述的「動態建立遠端節點」。 檢查 SAS 權杖有效之後,發行者可以繼續並開始將資料傳送至服務。
下列步驟示範如何使用 AMQP.NET Lite 程式庫,搭配 AMQP 通訊協定來傳送 SAS 權杖。 如果您不能使用以 C# 開發的官方服務匯流排 SDK (例如,在 WinRT、.NET Compact Framework、.NET Micro Framework 和 Mono 上),這就非常有用。 此程式庫對於了解宣告型安全性如何在 AMQP 層級運作非常有用,如同您了解其如何在 HTTP 層級運作一樣 (使用 HTTP POST 要求以及在標頭「Authorization」內部傳送的 SAS 權杖)。 如果您不需要對 AMQP 有這類深入的知識,您可以在正式版服務匯流排 SDK 中使用任何支援的語言 (如 .NET、JAVA、JavaScript、Python 和 Go),這麼做也是沒有問題的。
C#
/// <summary>
/// Send claim-based security (CBS) token
/// </summary>
/// <param name="shareAccessSignature">Shared access signature (token) to send</param>
private bool PutCbsToken(Connection connection, string sasToken)
{
bool result = true;
Session session = new Session(connection);
string cbsClientAddress = "cbs-client-reply-to";
var cbsSender = new SenderLink(session, "cbs-sender", "$cbs");
var cbsReceiver = new ReceiverLink(session, cbsClientAddress, "$cbs");
// construct the put-token message
var request = new Message(sasToken);
request.Properties = new Properties();
request.Properties.MessageId = Guid.NewGuid().ToString();
request.Properties.ReplyTo = cbsClientAddress;
request.ApplicationProperties = new ApplicationProperties();
request.ApplicationProperties["operation"] = "put-token";
request.ApplicationProperties["type"] = "servicebus.windows.net:sastoken";
request.ApplicationProperties["name"] = Fx.Format("amqp://{0}/{1}", sbNamespace, entity);
cbsSender.Send(request);
// receive the response
var response = cbsReceiver.Receive();
if (response == null || response.Properties == null || response.ApplicationProperties == null)
{
result = false;
}
else
{
int statusCode = (int)response.ApplicationProperties["status-code"];
if (statusCode != (int)HttpStatusCode.Accepted && statusCode != (int)HttpStatusCode.OK)
{
result = false;
}
}
// the sender/receiver might be kept open for refreshing tokens
cbsSender.Close();
cbsReceiver.Close();
session.Close();
return result;
}
上述 PutCbsToken()
方法會接收代表服務之 TCP 連線的 connection (AMQP .NET Lite 程式庫所提供的 AMQP 連接類別執行個體) 以及要做為 SAS 權杖傳送的 sasToken 參數。
注意
請務必以設為 ANONYMOUS 的 SASL 驗證機制 (而非當您不需要傳送 SAS 權杖時所使用且包含使用者名稱與密碼的預設 PLAIN) 建立連線。
接下來,發行者會建立兩個 AMQP 連結來傳送 SAS 權杖,並接受來自服務的回覆 (權杖驗證結果)。
AMQP 訊息包含眾多屬性,以及比簡單訊息更多的資訊。 SAS 權杖是訊息的內文 (使用其建構函式)。 "ReplyTo" 屬性設定為在接收者連結上接收驗證結果的節點名稱 (您可以視需要變更它的名稱,而服務將會動態建立它)。 最後三個應用程式/自訂屬性是由服務所使用,以指出它必須執行何種類型的作業。 如 CBS 草稿規格所述,它們必須是作業名稱 (像是 "put-token")、權杖類型 (在本案例中為 servicebus.windows.net:sastoken
),以及套用權杖之對象的 "name" (完整實體)。
在發行者於寄件者連結上傳送 SAS 權杖之後,發行者必須在接收者連結上讀取回覆。 回覆是包含名稱為 "status-code" 之應用程式屬性的簡單 AMQP 訊息,可用來包含做為 HTTP 狀態碼的相同值
服務匯流排作業所需的權限
下表顯示服務匯流排資源上各種作業所需的存取權限。
作業 | 所需的宣告 | 宣告範圍 |
---|---|---|
Namespace | ||
在命名空間上設定授權規則 | 管理 | 任何命名空間位址 |
服務登錄 | ||
列舉私人原則 | 管理 | 任何命名空間位址 |
開始在命名空間上接聽 | 接聽 | 任何命名空間位址 |
將訊息傳送至命名空間上的接聽程式 | 傳送 | 任何命名空間位址 |
佇列 | ||
建立佇列 | 管理 | 任何命名空間位址 |
刪除佇列 | 管理 | 任何有效的佇列位址 |
列舉佇列 | 管理 | /$Resources/Queues |
取得佇列描述 | 管理 | 任何有效的佇列位址 |
設定佇列的授權規則 | 管理 | 任何有效的佇列位址 |
傳送到佇列中 | 傳送 | 任何有效的佇列位址 |
從佇列接收訊息 | 接聽 | 任何有效的佇列位址 |
在 peek-lock 模式中接收訊息後放棄或完成訊息 | 接聽 | 任何有效的佇列位址 |
延遲訊息以便稍後擷取 | 接聽 | 任何有效的佇列位址 |
讓訊息寄不出去 | 接聽 | 任何有效的佇列位址 |
取得與訊息佇列工作階段相關聯的狀態 | 接聽 | 任何有效的佇列位址 |
設定與訊息佇列工作階段相關聯的狀態 | 接聽 | 任何有效的佇列位址 |
將一個訊息排程至稍後傳送 | 接聽 | 任何有效的佇列位址 |
主題 | ||
建立主題 | 管理 | 任何命名空間位址 |
刪除主題 | 管理 | 任何有效的主題位址 |
列舉主題 | 管理 | /$Resources/Topics |
取得主題描述 | 管理 | 任何有效的主題位址 |
設定主題的授權規則 | 管理 | 任何有效的主題位址 |
傳送至主題 | 傳送 | 任何有效的主題位址 |
訂用帳戶 | ||
建立訂用帳戶 | 管理 | 任何命名空間位址 |
刪除訂用帳戶 | 管理 | ../myTopic/Subscriptions/mySubscription |
列舉訂用帳戶 | 管理 | ../myTopic/Subscriptions |
取得訂用帳戶描述 | 管理 | ../myTopic/Subscriptions/mySubscription |
在 peek-lock 模式中接收訊息後放棄或完成訊息 | 接聽 | ../myTopic/Subscriptions/mySubscription |
延遲訊息以便稍後擷取 | 接聽 | ../myTopic/Subscriptions/mySubscription |
讓訊息寄不出去 | 接聽 | ../myTopic/Subscriptions/mySubscription |
取得與主題工作階段相關聯的狀態 | 接聽 | ../myTopic/Subscriptions/mySubscription |
設定與主題工作階段相關聯的狀態 | 接聽 | ../myTopic/Subscriptions/mySubscription |
規則 | ||
建立規則 | 接聽 | ../myTopic/Subscriptions/mySubscription |
刪除規則 | 接聽 | ../myTopic/Subscriptions/mySubscription |
列舉規則 | 管理或接聽 | ../myTopic/Subscriptions/mySubscription/Rules |
下一步
若要深入了解服務匯流排訊息,請參閱下列主題。