Shared Access Signature を使用して IoT Hub へのアクセスを制御する
IoT Hub では Shared Access Signature (SAS) トークンを使用してデバイスとサービスを認証し、ネットワーク上でのキーの送信を回避しています。 SAS トークンは、IoT Hub の特定の機能へのアクセスを期限付きでデバイスとサービスに許可するために使用します。 IoT Hub に接続する承認を取得するには、デバイスとサービスが共有アクセス キーまたは対称キーのいずれかで署名された SAS トークンを送信する必要があります。 対称キーが、ID レジストリにデバイス ID と共に格納されます。
この記事では、次の内容について説明します。
- 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 Hub のエンドポイントにアクセスするには、適切なアクセス許可が必要です。 たとえば、デバイスは IoT Hub に送信するすべてのメッセージにセキュリティ資格情報含めたトークンを付けなければいけません。 ただし、デバイスの対称キーと同様に、署名キーはネットワーク経由で送信されることはありません。
認証と権限承認
"認証" は、ユーザーが身元を証明するプロセスです。 認証は、IoT Hub に対するユーザーまたはデバイスの ID を検証します。 AuthN と短縮される場合があります。 認可は、IoT Hub で認証されたユーザーまたはデバイスのアクセス許可を確定するプロセスです。 これにより、ユーザーがアクセスすることを許可されるリソースとコマンド、およびユーザーがそれらのリソースとコマンドで実行できる操作が指定されます。 承認は AuthZ と短縮される場合があります。
この記事では、Shared Access Signature を使用した認証と認可によって、アクセス許可をグループ化し、アクセス キーと署名されたセキュリティ トークンを使用してそれらをアプリケーションに付与することについて説明します。 IoT Hub でのデバイスの認証には、対称キーまたは共有アクセス キーを使用することもできます。 SAS トークンは、各呼び出しに対称キーを関連付けることによって、デバイスが行う IoT Hub への各呼び出しに認証を提供します。
アクセス制御とアクセス許可
IoT ハブ レベルのアクセスには共有アクセス ポリシーを使用し、個々のデバイスの資格情報を使用して、そのデバイスへのアクセスのみをスコープにします。
IoT ハブ レベルの共有アクセス ポリシー
共有アクセス ポリシーにより、アクセス許可を自由に組み合わせて付与できます。 ポリシーは、Azure portal で定義するか、IoT Hub Resource REST API や Azure CLI az iot hub policy コマンドを使ってプログラムで定義できます。 新しく作成された IoT Hub には、次の既定のポリシーがあります。
共有アクセス ポリシー | アクセス許可 |
---|---|
iothubowner | すべてのアクセス許可 |
サービス (service) | ServiceConnect アクセス許可 |
device | DeviceConnect アクセス許可 |
registryRead | RegistryRead アクセス許可 |
registryReadWrite | RegistryRead および RegistryWrite アクセス許可 |
次のアクセス許可を使用して、IoT ハブへのアクセスを制御できます。
ServiceConnect アクセス許可はバックエンド クラウド サービスによって使用され、以下のアクセスを許可します。
- クラウド サービス向けの通信および監視のエンドポイントへのアクセス。
- デバイスからクラウドへのメッセージの受信、クラウドからデバイスへのメッセージの送信、対応する配信確認メッセージの取得。
- ファイル アップロードの配信確認メッセージの取得。
- タグおよび必要なプロパティを更新するためのツインへのアクセス、報告されたプロパティの取得、クエリの実行。
DeviceConnect アクセス許可はデバイスによって使用され、以下のアクセスを許可します。
- デバイス向けエンドポイントへのアクセス。
- デバイスからクラウドへのメッセージの送信、クラウドからデバイスへのメッセージの受信。
- ファイルのアップロードの実行。
- デバイス ツインの必要なプロパティ通知の受信と、デバイス ツインの報告されるプロパティの更新。
RegistryRead アクセス許可はバックエンド クラウド サービスによって使用され、以下のアクセスを許可します。
- ID レジストリへの読み取りアクセス。 詳細については、「Identity registry」(ID レジストリ) を参照してください。
RegistryReadWrite アクセス許可はバックエンド クラウド サービスによって使用され、以下のアクセスを許可します。
- ID レジストリへの読み取りおよび書き込みアクセス。 詳細については、「Identity registry」(ID レジストリ) を参照してください。
デバイスごとのセキュリティ資格情報
すべての IoT ハブには、それに対する接続が許可されたデバイスおよびモジュールに関する情報を保存する ID レジストリがあります。 デバイスまたはモジュールを接続できるようにするには、そのデバイスまたはモジュールのエントリが IoT ハブの ID レジストリに存在する必要があります。 ID レジストリに保存されている資格情報に基づいて、デバイスまたはモジュールが IoT ハブで認証されます。
SAS トークン認証を使用するようにデバイスを登録すると、そのデバイスは 2 つの対称キーを取得します。 対称キーは、関連付けられたデバイス ID の DeviceConnect アクセス許可を付与します。
サービスからの SAS トークンを使用する
サービスは、前述の「アクセス制御とアクセス許可」セクションで説明したように、適切なアクセス許可を定義する共有アクセス ポリシーを使用して SAS トークンを生成できます。
たとえば、registryRead という事前作成済みの共有アクセス ポリシーを使用するサービスでは、次のパラメーターを持つトークンが作成されます。
- リソース URI:
{IoT hub name}.azure-devices.net
- 署名キー:
registryRead
ポリシーのいずれかのキー - ポリシー名:
registryRead
- 任意の有効期間
例として、次のコードは Node.js で SAS トークンを作成しています。
var endpoint = "myhub.azure-devices.net";
var policyName = 'registryRead';
var policyKey = '...';
var token = generateSasToken(endpoint, policyKey, policyName, 60);
結果は次のようになります (ID レジストリ内のすべてのデバイス ID の読み取りアクセスが許可されます)。
SharedAccessSignature sr=myhub.azure-devices.net&sig=JdyscqTpXdEJs49elIUCcohw2DlFDR3zfH5KqGJo4r4%3D&se=1456973447&skn=registryRead
その他の例については、「SAS トークンを生成する」を参照してください。
サービスの場合、SAS トークンでアクセス許可が付与されるのは IoT Hub レベルだけです。 つまり、service ポリシーに基づくトークンを使用して認証するサービスは、ServiceConnect アクセス許可によって許可されるすべての操作を実行できるようになります。 これらの操作には、デバイスからクラウドへのメッセージの受信、クラウドからデバイスへのメッセージの送信などが含まれます。 サービスに、よりきめ細かいアクセス権を付与したい場合 (たとえばあるサービスをクラウドからデバイスへのメッセージ送信だけに制限するなど)、Microsoft Entra ID を使用することができます。 詳細については、「Microsoft Entra ID を使用した認証」を参照してください。
デバイスからの SAS トークンを使用する
SAS トークンを使用して IoT Hub で DeviceConnect アクセス許可を取得するには、ID レジストリの対称デバイス キーを使用する方法と、共有アクセス キーを使用する方法の 2 通りがあります。
デバイスからアクセスできるすべての機能は、仕様により、/devices/{deviceId}
というプレフィックスを持つエンドポイントで公開されます。
デバイス向けのエンドポイントを次に示します (プロトコルは関係ありません)。
エンドポイント | 機能 |
---|---|
{iot hub name}/devices/{deviceId}/messages/events |
デバイスからクラウドへのメッセージを送信します。 |
{iot hub name}/devices/{deviceId}/messages/devicebound |
クラウドからデバイスへのメッセージを受信します。 |
ID レジストリの対称キーを使用する
デバイス ID の対称キーを使用してトークンを生成すると、トークンの policyName (skn
) 要素は省略されます。
たとえば、すべてのデバイス機能にアクセスするために作成されるトークンには、次のパラメーターが必要です。
- リソース URI:
{IoT hub name}.azure-devices.net/devices/{device id}
- 署名キー:
{device id}
ID の任意の対称キー - ポリシー名なし
- 任意の有効期間
例として、次のコードは Node.js で SAS トークンを作成しています。
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
その他の例については、「SAS トークンを生成する」を参照してください。
デバイスの代わりに共有アクセス ポリシーを使用してアクセスする
共有アクセス ポリシーからトークンを作成するときは、skn
フィールドをポリシーの名前に設定します。 このポリシーは DeviceConnect アクセス許可を付与する必要があります。
共有アクセス ポリシーを使用してデバイスの機能にアクセスするための 2 つの主なシナリオは次のとおりです。
- クラウド プロトコル ゲートウェイ
- トークン サービス (カスタム認証スキームの実装に使用)
共有アクセス ポリシーは任意のデバイスとして接続するためのアクセス権を付与する可能性があるため、SAS トークンの作成時に適切なリソース URI を使用することが重要です。 この設定は、トークン サービスに特に重要です。このサービスでは、リソース URI を使用して、トークンのスコープを特定のデバイスに限定する必要があります。 これは、プロトコル ゲートウェイにはあまり関連がありません。このようなゲートウェイは、すべてのデバイスのトラフィックを既に仲介しているためです。
たとえば、 device という事前作成済みの共有アクセス ポリシーを使用するトークン サービスの場合、次のパラメーターを持つトークンが作成されます。
- リソース URI:
{IoT hub name}.azure-devices.net/devices/{device id}
- 署名キー:
device
ポリシーのいずれかのキー - ポリシー名:
device
- 任意の有効期間
例として、次のコードは Node.js で SAS トークンを作成しています。
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
に設定すると、プロトコル ゲートウェイはすべてのデバイスに同じトークンを使用できるようになります。
その他の例については、「SAS トークンを生成する」を参照してください。
既存のデバイスを統合するためにトークン サービスを作成する
IoT Hub の ID レジストリを使用して、デバイスごとまたはモジュールごとのセキュリティ資格情報とアクセス制御をトークンにより構成できます。 IoT ソリューションにすでにカスタム ID レジストリや認証スキームがある場合、トークン サービスを作成してこのインフラストラクチャを IoT Hub と統合することを検討してください。 この方法により、ソリューションで他の IoT 機能を使用できます。
トークン サービスはカスタム クラウド サービスの 1 つです。 これにより、DeviceConnect アクセス許可が指定された IoT Hub の "共有アクセス ポリシー" を使用して、"デバイス スコープ" または "モジュール スコープ" のトークンが作成されます。 これらのトークンは、デバイスまたはモジュールが IoT Hub に接続することを可能にします。
トークン サービス パターンの主な手順を次に示します。
IoT Hub に対する DeviceConnect アクセス許可を指定して、IoT Hub の共有アクセス ポリシーが作成されます。 このポリシーは、Azure portal またはプログラムで作成できます。 トークン サービスは、このポリシーを使用して、作成されるトークンに署名します。
デバイスまたはモジュールが IoT ハブにアクセスする必要がある場合は、トークン サービスに署名済みトークンを要求します。 デバイスは、カスタム ID レジストリ/認証スキームで認証し、トークン サービスがトークンの作成に使用するデバイス/モジュール ID を特定できます。
トークン サービスは、トークンを返します。 トークンは、
/devices/{deviceId}
または/devices/{deviceId}/modules/{moduleId}
をresourceURI
として使用して作成されます。ここで、deviceId
は認証対象のデバイス、moduleId
は認証対象のモジュールです。 トークン サービスは、共有アクセス ポリシーを使用してトークンを作成します。デバイス/モジュールは、IoT Hub で直接トークンを使用します。
Note
.NET クラス SharedAccessSignatureBuilder または Java クラス IotHubServiceSasToken を使用して、トークン サービスでトークンを作成できます。
トークン サービスは、必要に応じて、トークンの有効期限を設定できます。 トークンの期限が切れた時点で、IoT Hub はデバイス/モジュールの接続を切断します。 その後、デバイス/モジュールは新しいトークンをトークン サービスに要求する必要があります。 有効期限までの期間が短いと、デバイス/モジュールとトークン サービスの両方で負荷が増加します。
デバイス/モジュールをハブに接続するには、接続にキーではなくトークンを使用する場合でも、引き続き IoT Hub の ID レジストリにそれを追加する必要があります。 そのため、ID レジストリでデバイス/モジュール ID を有効または無効にすることで、引き続きデバイスごと/モジュールごとのアクセス制御を行うことができます。 この方法は、有効期限までの期間が長い場合にトークンを使用するリスクを軽減します。
カスタム ゲートウェイとの比較
IoT Hub でカスタム ID レジストリ/認証スキームを実装する場合は、トークン サービス パターンをお勧めします。 このパターンにより、IoT Hub がほとんどのソリューション トラフィックを処理できるためです。 ただし、カスタム認証スキームがプロトコルとそのように組み合わさっている場合、すべてのトラフィックを処理するにはカスタム ゲートウェイが必要になる場合があります。 このようなシナリオの例として、トランスポート層セキュリティ (TLS) と事前共有キー (PSK) の使用があります。 詳細は、「IoT Edge デバイスをゲートウェイとして使用する方法」を参照してください。
SAS トークンを生成する
Azure IoT SDK はトークンを自動的に生成しますが、以下のような一部のシナリオでは、SAS トークンを自分で生成して直接使用する必要があります。
直接、MQTT、AMQP、または HTTPS を使用する。
トークンのサービス パターンを実装する (「トークン サービスを作成する」セクションで説明されているように)。
共有アクセス キーで署名されたトークンでは、その共有アクセス ポリシーのアクセス許可に関連付けられたすべての機能へのアクセスが許可されます。 デバイス ID の対称キーで署名されたトークンは、関連付けられたデバイス ID の DeviceConnect アクセス許可のみを付与します。
このセクションでは、さまざまなコード言語で SAS トークンを生成する例を示します。 CLI 拡張コマンド az iot hub generate-sas-token または Visual Studio Code 用の Azure IoT Hub 拡張機能を使用しても SAS トークンを生成できます。
SAS トークン構造
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 とする必要があります (myhub.azure-devices.net など)。
AMQP を使用する場合、IoT Hub では SASL PLAIN と AMQP Claims-Based-Security がサポートされます。
AMQP Claims-Based-Security の場合、標準でこれらのトークンの送信方法が指定されます。
SASL PLAIN では、 ユーザー名 を以下のように指定できます。
{policyName}@sas.root.{iothubName}
(IoT Hub レベルのトークンを使用する場合)。{deviceId}@sas.{iothubname}
(デバイスを対象とするトークンを使用する場合)。
どちらの場合も、「SAS トークン構造」で説明されているように、パスワード フィールドにトークンが含まれています。
HTTPS では、 Authorization 要求ヘッダーに有効なトークンを含めることによって認証を実装します。
たとえば、Username (DeviceId は大文字と小文字を区別する): iothubname.azure-devices.net/DeviceId
パスワード (CLI 拡張コマンド az iot hub generate-sas-token または Visual Studio Code 用の Azure IoT Hub 拡張機能を使用して 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 接続を作成する必要があります。 このシナリオにより、電源とネットワーク リソースの消費量が大幅に増大し、各デバイスの接続の待機時間が増加します。
各トークンの有効期限が切れた後に、再接続に使用するリソースの量が増加すると、リソースが限られたデバイスには悪影響が出ます。
次のステップ
IoT Hub へのアクセス制御の方法を理解できたら、次の IoT Hub 開発者ガイドのトピックもご覧ください。