使用共用存取簽章和安全性權杖來控制對Azure IoT 中樞裝置布建服務 (DPS) 的存取

本文說明保護您Azure IoT 中樞裝置布建服務 (DPS) 的可用選項。 布建服務會使用 驗證 許可權 來授與每個端點的存取權。 許可權可讓驗證程式根據功能限制對服務實例的存取。

本文討論:

  • 驗證程式和布建服務用來驗證服務與裝置 REST API 的許可權

  • 您可以授與後端應用程式以存取服務 API 的不同許可權。

驗證

裝置 API 支援金鑰型和 X.509 憑證型裝置驗證。

服務 API 支援後端應用程式的金鑰型驗證。

使用金鑰型驗證時,裝置布建服務會使用安全性權杖來驗證服務,以避免在網路傳送金鑰。 此外,安全性權杖在時間有效性和範圍內受到限制。 Azure IoT 裝置布建 SDK 會自動產生權杖,而不需要任何特殊設定。

在某些情況下,您可能需要直接使用 HTTP 裝置布建服務 REST API,而不需使用 SDK。 下列各節說明如何直接針對 REST API 進行驗證。

裝置 API 驗證

裝置會使用裝置 API 來證明裝置布建服務,並接收IoT 中樞連線。

注意

若要接收已驗證的連線,必須先透過註冊在裝置布建服務中註冊裝置。 使用服務 API 透過註冊以程式設計方式註冊裝置。

裝置必須在布建程式中向裝置 API 進行驗證。 當您設定註冊群組或個別註冊時,會定義裝置用來驗證的方法。 無論驗證方法為何,裝置都必須向下列 URL 發出 HTTPS PUT,才能布建本身。

    https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01

如果使用金鑰型驗證,安全性權杖會以下列格式傳遞 HTTP 授權 要求標頭:

    SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI} 

金鑰型驗證的安全性權杖結構

安全性權杖會以下列格式傳遞 HTTP 授權 要求標頭:

    SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI} 

預期的值為:

Description
{signature} 格式為 HMAC-SHA256 簽章字串: {URL-encoded-resourceURI} + "\n" + expiry 。 重要 事項:金鑰會從 base64 解碼,並做為執行 HMAC-SHA256 計算的金鑰。
{expiry} UTF8 字串自 1970 年 1 月 1 日 00:00:00 UTC 以來的秒數。
{URL-encoded-resourceURI} 小寫 URL 編碼的 {ID_Scope}/registrations/{registration_id}
{policyName} 針對裝置 API,此原則一律為「註冊」。

下列 Python 程式碼片段顯示名為 generate_sas_tokenuri 函式,會針對使用對稱金鑰驗證類型的個別註冊,從輸入 、 keypolicy_nameexpiry 計算權杖。


from base64 import b64encode, b64decode, encode 
from hashlib import sha256 
from time import time 
from urllib.parse import quote_plus, urlencode 
from hmac import HMAC 

 def generate_sas_token(uri, key, policy_name, expiry=3600): 
    ttl = time() + expiry 
    sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl)) 
    signature = b64encode(HMAC(b64decode(key), sign_key.encode('utf-8'), sha256).digest()) 

    rawtoken = { 
        'sr' :  uri, 
        'sig': signature, 
        'se' : str(int(ttl)), 
        'skn' : policy_name 
    } 

    return 'SharedAccessSignature ' + urlencode(rawtoken) 

print(generate_sas_token("myIdScope/registrations/mydeviceregistrationid", "00mysymmetrickey", "registration"))

結果應該類似下列輸出:


SharedAccessSignature sr=myIdScope%2Fregistrations%2Fmydeviceregistrationid&sig=SDpdbUNk%2F1DSjEpeb29BLVe6gRDZI7T41Y4BPsHHoUg%3D&se=1630175722&skn=registration 

下列範例示範如何使用共用存取簽章向裝置 API 進行驗證。


curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [token]' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01 

如果使用對稱金鑰型註冊群組,您必須先使用註冊群組金鑰來產生 device symmetric 金鑰。 使用註冊群組主要或次要金鑰來計算裝置註冊識別碼的 HMAC-SHA256。 然後,結果會轉換成 Base64 格式,以取得衍生的裝置金鑰。 若要檢視程式碼範例,請參閱 如何使用對稱金鑰註冊群組 布建裝置。 一旦衍生裝置對稱金鑰,您就可以使用先前的範例來註冊裝置。

警告

若要避免在裝置程式碼中包含群組主要金鑰,應該從裝置上完成衍生裝置金鑰的程式。

憑證型驗證

如果您已設定以 X.509 憑證為基礎的驗證個別註冊或註冊群組,裝置必須使用其發行的 X.509 憑證來證明裝置 API。 請參閱下列文章,以瞭解如何設定註冊並產生裝置憑證。

設定註冊並核發裝置憑證之後,下列範例示範如何使用裝置的 X.509 憑證向裝置 API 進行驗證。


curl -L -i -X PUT –cert ./[device_cert].pem –key ./[device_cert_private_key].pem -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01 

服務 API 驗證

服務 API 可用來擷取註冊狀態並移除裝置註冊。 後端應用程式也會使用此服務,以程式設計方式管理 個別群組 註冊群組 。 服務 API 支援後端應用程式的金鑰型驗證。

您必須具有適當的許可權,才能存取任何服務 API 端點。 例如,後端應用程式必須包含包含安全性認證的權杖,以及傳送至服務的每個訊息。

Azure IoT 中樞裝置布建服務會針對共用存取原則驗證權杖,以授與端點的存取權。 安全性認證,例如對稱金鑰,永遠不會透過網路傳送。

存取控制和許可權

您可以透過下列方式授與 許可權

  • 共用存取授權原則 。 共用存取原則可以授與任何許可權 組合 。 您可以在Azure 入口網站 定義原則,或使用裝置布建服務 REST API 以程式設計方式 定義原則。 新建立的布建服務具有下列預設原則:

  • provisioningserviceowner :具有擁有權限的原則。 如需詳細資訊,請參閱 許可權

注意

裝置布建服務資源提供者會透過您的 Azure 訂用帳戶進行保護,如同 Azure Resource Manager 中的所有 提供者一樣。

如需如何建構和使用安全性權杖的詳細資訊,請參閱下一節。

HTTP 是唯一支援的通訊協定,它會在授權 要求標頭中包含 有效的權杖來實作驗證。

範例

SharedAccessSignature sr = 
   mydps.azure-devices-provisioning.net&sig=kPszxZZZZZZZZZZZZZZZZZAhLT%2bV7o%3d&se=1487709501&skn=provisioningserviceowner`\

注意

Azure IoT 裝置布建服務 SDK 會在 連線到服務時自動產生權杖。

安全性權杖

裝置布建服務會使用安全性權杖來驗證服務,以避免在網路傳送金鑰。 此外,安全性權杖在時間有效性和範圍內受到限制。 Azure IoT 裝置布建服務 SDK 會自動產生權杖,而不需要任何特殊設定。 某些案例會要求您直接產生和使用安全性權杖。 這類案例包括直接使用 HTTP 介面。

安全性權杖結構

您可以使用安全性權杖,將服務的時間限定存取權授與 IoT 裝置布建服務中的特定功能。 若要取得連線到布建服務的授權,服務必須傳送使用共用存取或對稱金鑰簽署的安全性權杖。

使用共用存取金鑰簽署的權杖會授與與共享存取原則許可權相關聯之所有功能的存取權。

安全性權杖的格式如下:

SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}

以下是預期的值

Description
{signature} 格式為 HMAC-SHA256 簽章字串: {URL-encoded-resourceURI} + "\n" + expiry重要 事項:金鑰會從 base64 解碼,並做為執行 HMAC-SHA256 計算的金鑰。
{expiry} UTF8 字串自 1970 年 1 月 1 日 00:00:00 UTC 以來的秒數。
{URL-encoded-resourceURI} 小寫資源 URI 的小寫 URL 編碼。 可以使用此權杖存取之端點的 URI 前置詞(依區段),從 IoT 裝置布建服務的主機名稱開始(沒有通訊協定)。 例如: mydps.azure-devices-provisioning.net
{policyName} 此權杖所參考之共用存取原則的名稱。

注意

URI 前置詞是由區段計算,而不是依字元計算。 例如 /a/b ,是 的 /a/b/c 前置詞,但不是 的 /a/bc 前置詞。

下列 Node.js 程式碼片段顯示名為 generateSasToken 的函 式,其會從輸入 resourceUri, signingKey, policyName, expiresInMins 計算權杖。 下一節將詳細說明如何初始化不同權杖使用案例的不同輸入。

var generateSasToken = function(resourceUri, signingKey, policyName, expiresInMins) {
    resourceUri = encodeURIComponent(resourceUri);

    // Set expiration in seconds
    var expires = (Date.now() / 1000) + expiresInMins * 60;
    expires = Math.ceil(expires);
    var toSign = resourceUri + '\n' + expires;

    // Use crypto
    var hmac = crypto.createHmac('sha256', new Buffer(signingKey, 'base64'));
    hmac.update(toSign);
    var base64UriEncoded = encodeURIComponent(hmac.digest('base64'));

    // Construct authorization string
    var token = "SharedAccessSignature sr=" + resourceUri + "&sig="
    + base64UriEncoded + "&se=" + expires + "&skn="+ policyName;
    return token;
};

相較之下,產生安全性權杖的對等 Python 程式碼為:

from base64 import b64encode, b64decode
from hashlib import sha256
from time import time
from urllib.parse import quote_plus, urlencode
from hmac import HMAC

def generate_sas_token(uri, key, policy_name, expiry=3600):
    ttl = time() + expiry
    sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl))
    print sign_key
    signature = b64encode(HMAC(b64decode(key), sign_key, sha256).digest())

    rawtoken = {
        'sr' :  uri,
        'sig': signature,
        'se' : str(int(ttl)),
        'skn' : policy_name
    }

    return 'SharedAccessSignature ' + urlencode(rawtoken)

注意

由於權杖在 IoT 裝置布建服務機器上驗證權杖的時間有效性,因此產生權杖的機器時鐘漂移必須最小。

使用服務元件的安全性權杖

服務元件只能使用授與適當許可權的共用存取原則來產生安全性權杖,如先前所述。

以下是在端點上公開的服務函式:

端點 功能
{your-service}.azure-devices-provisioning.net/enrollments 使用裝置布建服務提供裝置註冊作業。
{your-service}.azure-devices-provisioning.net/enrollmentGroups 提供管理裝置註冊群組的作業。
{your-service}.azure-devices-provisioning.net/registrations/{id} 提供擷取和管理裝置註冊狀態的作業。

例如,使用預先建立的共用存取原則 enrollmentread 所產生的服務會建立具有下列參數的權杖:

  • 資源 URI: {mydps}.azure-devices-provisioning.net
  • 簽署金鑰:原則的 enrollmentread 其中一個金鑰,
  • 原則名稱: enrollmentread
  • 任何到期時間.backn

Create a shared access policy for your Device Provisioning Service instance in the portal

var endpoint ="mydps.azure-devices-provisioning.net";
var policyName = 'enrollmentread'; 
var policyKey = '...';

var token = generateSasToken(endpoint, policyKey, policyName, 60);

結果會授與讀取所有註冊記錄的存取權,其為:

SharedAccessSignature sr=mydps.azure-devices-provisioning.net&sig=JdyscqTpXdEJs49elIUCcohw2DlFDR3zfH5KqGJo4r4%3D&se=1456973447&skn=enrollmentread

SDK 與範例

參考主題:

下列參考主題提供您控制 IoT 裝置布建服務存取權的詳細資訊。

裝置布建服務許可權

下表列出可用來控制 IoT 裝置布建服務存取權的許可權。

權限 備註
ServiceConfig 授與變更服務組態的存取權。
後端雲端服務會使用此許可權。
EnrollmentRead 授與裝置註冊和註冊群組的讀取權限。
後端雲端服務會使用此許可權。
EnrollmentWrite 授與裝置註冊和註冊群組的寫入權限。
後端雲端服務會使用此許可權。
RegistrationStatusRead 授與裝置註冊狀態的讀取權限。
後端雲端服務會使用此許可權。
RegistrationStatusWrite 授與裝置註冊狀態的刪除存取權。
後端雲端服務會使用此許可權。