Shared Access Signature を使用して IoT Hub へのアクセスを制御する

この記事では、Azure IoT Hub をセキュリティで保護するためのオプションについて説明します。 IoT Hub では、"アクセス許可" を使用して、IoT Hub の各エンドポイントへのアクセス権を付与します。 次のアクセス許可により、機能に応じて IoT Hub へのアクセスを制限します。

この記事では、次の内容について説明します。

  • IoT Hub へアクセスするためにクライアントに付与できるアクセス許可の種類。
  • アクセス許可を確認するために IoT Hub トークンが使用されます。
  • 資格情報のスコープを指定して特定のリソースへのアクセスを制限する方法。
  • 既存のデバイス ID のレジストリまたは認証スキームを使用した、カスタムのデバイス認証メカニズム。

Note

この記事で言及されている一部の機能 (cloud-to-device メッセージング、デバイス ツイン、デバイス管理など) は、IoT Hub の Standard レベルだけで使用することができます。 Basic および Standard または Free レベルの IoT Hub の詳細については、ソリューションに適した IoT Hub のレベルの選択に関するページを参照してください。

IoT Hub のエンドポイントにアクセスするには、適切なアクセス許可が必要です。 たとえば、デバイスは IoT Hub に送信するすべてのメッセージにセキュリティ資格情報含めたトークンを付けなければいけません。 ただし、デバイスの対称キーと同様に、署名キーはネットワーク経由で送信されることはありません。

アクセス制御とアクセス許可

IoT ハブ レベルのアクセスには共有アクセス ポリシーを使用し、個々のデバイスの資格情報を使用して、そのデバイスへのアクセスのみをスコープにします。

IoT ハブ レベルの共有アクセス ポリシー

共有アクセス ポリシーにより、アクセス許可を自由に組み合わせて付与できます。 ポリシーは、Azure portal で定義したり、IoT Hub Resource REST APIaz iot hub policy CLI を使ってプログラムで定義できます。 新しく作成された IoT Hub には、次の既定のポリシーがあります。

共有アクセス ポリシー アクセス許可
iothubowner すべてのアクセス許可
サービス (service) ServiceConnect アクセス許可
device DeviceConnect アクセス許可
registryRead RegistryRead アクセス許可
registryReadWrite RegistryRead および RegistryWrite アクセス許可

次の表は、IoT hub へのアクセス制御に使用できるアクセス許可の一覧です。

権限 Notes
ServiceConnect クラウド サービス向けの通信エンドポイントと監視エンドポイントへのアクセスを許可します。
デバイスからクラウドへのメッセージの受信、クラウドからデバイスへのメッセージの送信、対応する配信確認メッセージの取得のアクセス許可を付与します。
ファイル アップロードの配信確認メッセージの取得のアクセス許可を付与します。
タグおよび必要なプロパティを更新するためのツインへのアクセス、報告されるプロパティの取得、クエリの実行のアクセス許可を付与します。
このアクセス許可はバックエンドのクラウド サービスによって使用されます。
DeviceConnect デバイス向けのエンドポイントへのアクセスを許可します。
デバイスからクラウドへのメッセージの送信、クラウドからデバイスへのメッセージの受信のアクセス許可を付与します。
デバイスからのファイル アップロードの実行のアクセス許可を付与します。
デバイス ツインの必要なプロパティ通知の受信と、デバイス ツインの報告されるプロパティの更新のアクセス許可を付与します。
ファイル アップロードの実行のアクセス許可を付与します。
このアクセス許可はデバイスによって使用されます。
RegistryRead ID レジストリへの読み取りアクセスを許可します。 詳細については、「Identity registry」(ID レジストリ) を参照してください。
このアクセス許可はバックエンドのクラウド サービスによって使用されます。
RegistryReadWrite ID レジストリへの読み取りと書き込みアクセスを許可します。 詳細については、「Identity registry」(ID レジストリ) を参照してください。
このアクセス許可はバックエンドのクラウド サービスによって使用されます。

デバイスごとのセキュリティ資格情報

各 IoT Hub には ID レジストリが含まれます。この ID レジストリ内の各デバイスでは、対応するデバイスのエンドポイントを対象として DeviceConnect アクセス許可を付与する、セキュリティ資格情報を構成できます。

SAS トークン

IoT Hub では Shared Access Signature (SAS) トークンを使用してデバイスとサービスを認証し、ネットワーク上でのキーの送信を回避しています。 SAS トークンには、有効期間とスコープの制限があります。 Azure IoT SDK を使用すると、特別な構成を行うことなく自動でトークンを生成できます。 一部のシナリオでは、SAS トークンを自分で生成して直接使用する必要があります。 これらのシナリオは、次のとおりです。

  • 直接、MQTT、AMQP、または HTTPS を使用する。

  • トークンのサービス パターンを実装する (「カスタム デバイスの認証」で説明)。

SAS トークンは、IoT Hub の特定の機能へのアクセスを期限付きでデバイスとサービスに許可するために使用します。 IoT Hub に接続する承認を取得するには、デバイスとサービスが共有アクセス キーまたは対称キーのいずれかで署名された SAS トークンを送信する必要があります。 対称キーが、ID レジストリにデバイス ID と共に格納されます。

SAS トークン構造

共有アクセス キーで署名されたトークンでは、その共有アクセス ポリシーのアクセス許可に関連付けられたすべての機能へのアクセスが許可されます。 デバイス ID の対称キーで署名されたトークンは、関連付けられたデバイス ID の DeviceConnect アクセス許可のみを付与します。

SAS トークンには次の形式があります。

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

考えられる値を次に示します。

説明
{signature} HMAC-SHA256 署名文字列 (形式: {URL-encoded-resourceURI} + "\n" + expiry)。 重要:キーは base64 からデコードされ、HMAC-SHA256 計算を実行するためのキーとして使用されます。
{resourceURI} IoT Hub のホスト名 (プロトコルなし) で始まる、このトークンを使用してアクセスできるエンドポイントの (セグメント単位の) URI プレフィックス。 バックエンド サービスに付与される SAS トークンのスコープは IoT ハブ レベル (たとえば myHub.azure-devices.net) です。 デバイスに付与される SAS トークンのスコープは、個々のデバイス (たとえば myHub.azure-devices.net/devices/device1) でなければなりません。
{expiry} 1970 年 1 月 1 日の 00 時 00 分 00 秒 UTC からのエポック秒で表される UTF8 文字列。
{URL-encoded-resourceURI} 小文字のリソース URI の小文字の URL エンコード
{policyName} このトークンの参照先となる共有アクセス ポリシーの名前。 トークンがデバイス レジストリ資格情報を参照する場合は存在しません。

URI プレフィックスは、文字単位ではなくセグメント単位で計算されます。 たとえば、/a/b/a/b/c のプレフィックスであり、/a/bc のプレフィックスではありません。

次のコードでは、リソース URI、署名キー、ポリシー名、有効期限を使用して SAS トークンを生成します。 以降のセクションでは、さまざまなトークンの使用例の各種入力を初期化する方法について詳しく説明します。

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', Buffer.from(signingKey, 'base64'));
    hmac.update(toSign);
    var base64UriEncoded = encodeURIComponent(hmac.digest('base64'));

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

プロトコルの詳細

MQTT、AMQP、および HTTPS など、サポートされているプロトコルごとに、さまざまな方法でトークンが転送されます。

MQTT を使用する場合、CONNECT パケットには、ClientId として deviceId が指定され、ユーザー名フィールドには {iothubhostname}/{deviceId}、パスワード フィールドには SAS トークンが指定されます。 {iothubhostname} は IoT Hub の完全な CName とする必要があります (contoso.azure-devices.net など)。

AMQP を使用する場合、IoT Hub では SASL PLAINAMQP Claims-Based-Security がサポートされます。

AMQP Claims-Based-Security の場合、標準でこれらのトークンの送信方法が指定されます。

SASL PLAIN では、 ユーザー名 を以下のように指定できます。

  • {policyName}@sas.root.{iothubName} (IoT Hub レベルのトークンを使用する場合)。
  • {deviceId}@sas.{iothubname} (デバイスを対象とするトークンを使用する場合)。

どちらの場合も、IoT Hub SAS トークンに関するセクションで説明されているように、パスワード フィールドにトークンが含まれています。

HTTPS では、 Authorization 要求ヘッダーに有効なトークンを含めることによって認証を実装します。

たとえば、Username (DeviceId は大文字と小文字を区別する): iothubname.azure-devices.net/DeviceId

パスワード (CLI 拡張コマンド az iot hub generate-sas-token または Visual Studio Code 用 Azure IoT Tools を使用して SAS トークンを生成できます):

SharedAccessSignature sr=iothubname.azure-devices.net%2fdevices%2fDeviceId&sig=kPszxZZZZZZZZZZZZZZZZZAhLT%2bV7o%3d&se=1487709501

Note

Azure IoT SDK を使用すると、サービスに接続した時点で自動的にトークンが生成されます。 場合によっては、Azure IoT SDK でサポートされないプロトコルや認証方法もあります。

SASL PLAIN に関する特別な考慮事項

SASL PLAIN を AMQP で使用する場合、IoT Hub に接続するクライアントは、TCP 接続ごとにトークンを 1 つ使用できます。 トークンの有効期限が切れると、サービスから TCP 接続が切断され、再接続がトリガーされます。 この動作は、バックエンド アプリの場合は問題ありませんが、デバイス アプリの場合は、次の理由から有害である可能性があります。

  • ゲートウェイは、通常多くのデバイスの代理として接続しています。 SASL PLAIN を使用する場合、IoT Hub に接続するデバイスごとに、個別の TCP 接続を作成する必要があります。 このシナリオにより、電源とネットワーク リソースの消費量が大幅に増大し、各デバイスの接続の待機時間が増加します。

  • 各トークンの有効期限が切れた後に、再接続に使用するリソースの量が増加すると、リソースが限られたデバイスには悪影響が出ます。

サービスからの SAS トークンを使用する

サービスは、前述の「アクセス制御とアクセス許可」で説明したように、適切なアクセス許可を定義する共有アクセス ポリシーを使用して SAS トークンを生成できます。

たとえば、 registryRead という事前作成済みの共有アクセス ポリシーを使用するサービスの場合、次のパラメーターを持つトークンが作成されます。

  • リソース URI: {IoT hub name}.azure-devices.net
  • 署名キー: registryRead ポリシーのいずれかのキー
  • ポリシー名: registryRead
  • 任意の有効期間
var endpoint = "myhub.azure-devices.net";
var policyName = 'registryRead';
var policyKey = '...';

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

結果は次のようになります (すべてのデバイス ID の読み取りアクセスが許可されます)。

SharedAccessSignature sr=myhub.azure-devices.net&sig=JdyscqTpXdEJs49elIUCcohw2DlFDR3zfH5KqGJo4r4%3D&se=1456973447&skn=registryRead

サービスの場合、SAS トークンでアクセス許可が付与されるのは IoT Hub レベルだけです。 つまり、サービス ポリシーに基づいてトークンを使用して認証するサービスは、ServiceConnect アクセス許可によって付与されるすべての操作を実行できるようになります。 これらの操作には、デバイスからクラウドへのメッセージの受信、クラウドからデバイスへのメッセージの送信などが含まれます。 よりきめ細かいサービスへのアクセス権を付与したい場合 (たとえばあるサービスをクラウドからデバイスへのメッセージ送信だけに制限するなど)、Azure Active Directory を使用することができます。 詳細については、「Azure AD による IoT Hub へのアクセスの制御」を参照してください。

デバイスを IoT Hub に認証

サポートされている X.509 証明書

証明書拇印や証明書機関 (CA) を Azure IoT Hub にアップロードすることで、IoT Hub のデバイスを X.509 証明書で認証できます。 詳細については、「X.509 CA 証明書を使用したデバイス認証」をご覧ください。 IoT ハブで証明機関から証明書をアップロードし、検証する方法については、「Azure IoT Hub での X.509 セキュリティの設定」を参照してください。

X.509 認証の適用

セキュリティを強化するために、デバイスとモジュールの SAS 認証を許可しないように IoT ハブを構成し、X.509 を許可されている唯一の認証オプションとして残します。 現在のところ、この機能は Azure portal では使用できません。 構成するには、IoT Hub リソース プロパティの disableDeviceSASdisableModuleSAStrue に設定します。

az resource update -n <iothubName> -g <resourceGroupName> --resource-type Microsoft.Devices/IotHubs --set properties.disableDeviceSAS=true properties.disableModuleSAS=true

デバイスとして SAS トークンを使用する

SAS トークンを使用して IoT Hub で DeviceConnect アクセス許可を取得するには、ID レジストリの対称デバイス キーを使用する方法と、共有アクセス キーを使用する方法の 2 通りがあります。

デバイスからアクセスできるすべての機能は、仕様により、/devices/{deviceId}というプレフィックスを持つエンドポイントで公開されることにご注意ください。

デバイス向けのエンドポイントを次に示します (プロトコルは関係ありません)。

エンドポイント 機能
{iot hub host name}/devices/{deviceId}/messages/events デバイスからクラウドへのメッセージを送信します。
{iot hub host name}/devices/{deviceId}/messages/devicebound クラウドからデバイスへのメッセージを受信します。

ID レジストリの対称キーを使用する

デバイス ID の対称キーを使用してトークンを生成すると、トークンの policyName (skn) 要素は省略されます。

たとえば、すべてのデバイス機能にアクセスするために作成されるトークンには、次のパラメーターが必要です。

  • リソース URI: {IoT hub name}.azure-devices.net/devices/{device id}
  • 署名キー: {device id} ID の任意の対称キー
  • ポリシー名なし
  • 任意の有効期間

上の Node.js 関数を使用した例を次に示します。

var endpoint ="myhub.azure-devices.net/devices/device1";
var deviceKey ="...";

var token = generateSasToken(endpoint, deviceKey, null, 60);

結果は、次のように、device1 のすべての機能に対するアクセスが許可されます。

SharedAccessSignature sr=myhub.azure-devices.net%2fdevices%2fdevice1&sig=13y8ejUk2z7PLmvtwR5RqlGBOVwiq7rQR3WZ5xZX3N4%3D&se=1456971697

Note

CLI 拡張コマンド az iot hub generate-sas-token または Visual Studio Code 用 Azure IoT Tools を使用して SAS トークンを生成できます。

デバイスの代わりに共有アクセス ポリシーを使用してアクセスする

共有アクセス ポリシーからトークンを作成するときは、skn フィールドをポリシーの名前に設定します。 このポリシーは DeviceConnect アクセス許可を付与する必要があります。

共有アクセス ポリシーを使用してデバイスの機能にアクセスするための 2 つの主なシナリオは次のとおりです。

共有アクセス ポリシーは任意のデバイスとして接続するためのアクセス権を付与する可能性があるため、SAS トークンの作成時に適切なリソース URI を使用することが重要です。 この設定は、トークン サービスに特に重要です。このサービスでは、リソース URI を使用して、トークンのスコープを特定のデバイスに限定する必要があります。 これは、プロトコル ゲートウェイにはあまり関連がありません。このようなゲートウェイは、すべてのデバイスのトラフィックを既に仲介しているためです。

たとえば、 device という事前作成済みの共有アクセス ポリシーを使用するトークン サービスの場合、次のパラメーターを持つトークンが作成されます。

  • リソース URI: {IoT hub name}.azure-devices.net/devices/{device id}
  • 署名キー: device ポリシーのいずれかのキー
  • ポリシー名: device
  • 任意の有効期間

上の Node.js 関数を使用した例を次に示します。

var endpoint ="myhub.azure-devices.net/devices/device1";
var policyName = 'device';
var policyKey = '...';

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

結果は、次のように、device1 のすべての機能に対するアクセスが許可されます。

SharedAccessSignature sr=myhub.azure-devices.net%2fdevices%2fdevice1&sig=13y8ejUk2z7PLmvtwR5RqlGBOVwiq7rQR3WZ5xZX3N4%3D&se=1456971697&skn=device

リソース URI を myhub.azure-devices.net/devicesに設定するだけで、プロトコル ゲートウェイはすべてのデバイスに同じトークンを使用できます。

既存のデバイスを統合するためにトークン サービスを作成する

IoT Hub の ID レジストリを使用して、デバイス/モジュールごとのセキュリティ資格情報とアクセス制御をトークンにより構成できます。 IoT ソリューションにすでにカスタム ID レジストリや認証スキームがある場合、トークン サービスを作成してこのインフラストラクチャを IoT Hub と統合することを検討してください。 この方法により、ソリューションで他の IoT 機能を使用できます。

トークン サービスはカスタム クラウド サービスの 1 つです。 これにより、DeviceConnect アクセス許可が指定された IoT Hub の "共有アクセス ポリシー" を使用して、"デバイス スコープ" または "モジュール スコープ" のトークンが作成されます。 これらのトークンにより、デバイスとモジュールは IoT Hub に接続できるようになります。

Steps of the token service pattern

トークン サービス パターンの主な手順を次に示します。

  1. IoT Hub に対する DeviceConnect アクセス許可を指定して、IoT Hub の共有アクセス ポリシーが作成されます。 このポリシーは、Azure portal またはプログラムで作成できます。 トークン サービスは、このポリシーを使用して、作成されるトークンに署名します。

  2. IoT Hub にアクセスする必要があるデバイス/モジュールは、トークン サービスに署名付きトークンを要求します。 デバイスは、カスタム ID レジストリ/認証スキームで認証し、トークン サービスがトークンの作成に使用するデバイス/モジュール ID を特定できます。

  3. トークン サービスは、トークンを返します。 トークンは、/devices/{deviceId} または /devices/{deviceId}/modules/{moduleId}resourceURI として使用して作成され、deviceId は認証対象のデバイスになり、moduleId は認証対象のモジュールになります。 トークン サービスは、共有アクセス ポリシーを使用してトークンを作成します。

  4. デバイス/モジュールは、IoT Hub で直接トークンを使用します。

Note

.NET クラス SharedAccessSignatureBuilder または Java クラス IotHubServiceSasToken を使用して、トークン サービスでトークンを作成できます。

トークン サービスは、必要に応じて、トークンの有効期限を設定できます。 トークンの期限が切れた時点で、IoT Hub はデバイス/モジュールの接続を切断します。 その後、デバイス/モジュールは新しいトークンをトークン サービスに要求する必要があります。 有効期限までの期間が短いと、デバイス/モジュールとトークン サービスの両方で負荷が増加します。

デバイス/モジュールをハブに接続するには、デバイス/モジュールが接続にキーではなくトークンを使用している場合でも、引き続き IoT Hub の ID レジストリにデバイス/モジュールを追加する必要があります。 そのため、ID レジストリでデバイス/モジュール ID を有効または無効にすることで、引き続きデバイスごと/モジュールごとのアクセス制御を行うことができます。 この方法は、有効期限までの期間が長い場合にトークンを使用するリスクを軽減します。

カスタム ゲートウェイとの比較

IoT Hub でカスタム ID レジストリ/認証スキームを実装する場合は、トークン サービス パターンをお勧めします。 このパターンにより、IoT Hub がほとんどのソリューション トラフィックを処理できるためです。 ただし、カスタム認証スキームがプロトコルとそのように組み合わさっている場合、すべてのトラフィックを処理するにはカスタム ゲートウェイが必要になる場合があります。 このようなシナリオの例として、トランスポート層セキュリティ (TLS) と事前共有キー (PSK) の使用があります。 詳細は、「IoT Edge デバイスをゲートウェイとして使用する方法」を参照してください。

参考資料

IoT Hub 開発者ガイド内の他の参照トピックは次のとおりです。

次のステップ

IoT Hub へのアクセス制御の方法を理解できたら、次の IoT Hub 開発者ガイドのトピックもご覧ください。

この記事で説明した概念を試す場合は、次の IoT Hub のチュートリアルをご覧ください。