Azure Cosmos DB SQL API でのアクセス制御

Azure Cosmos DB は、最新のアプリ開発に対応するフル マネージドの NoSQL データベース サービスです。 この記事では、Azure Cosmos DB 用の SQL API について説明します。 SQL API のリソースへのアクセスは、マスター キー トークンまたはリソース トークンで制御します。 リソースにアクセスするために、選択されたトークンは、承認文字列の一部として REST の Authorization ヘッダーに含められます。

マスター キー トークン

マスター キー トークンは、ユーザーが特定のアカウント内の DB リソースCosmos完全に制御できるようにするすべてのアクセス キー トークンです。 マスター キーは、アカウントの作成時に作成されます。 マスター キーには、プライマリ キーとセカンダリ キーの 2 種類があります。 アカウントの管理者は、セカンダリ キーを使用してキーをローテーションさせることができます。 さらに、必要に応じてキーを再生成することもできます。 キーの再生成とローリングの手順については、「Azure Cosmos DB のデータへのアクセスをセキュリティで保護する」を参照してください。

リソース トークン

リソース トークンは、データベース内のユーザーがリソースに対する正確なアクセス制御 (アクセス許可リソースとも呼ばれます) のアクセス許可を使用して設定されるときに作成されます。 アクセス許可リソースには、ユーザーがアクセスできるリソース パスとアクセスの種類に関する情報を使用して構築されたハッシュ リソース トークンが含まれています。 アクセス許可リソース トークンには期限があり、有効期間はオーバーライドできます。 アクセス許可リソースがアクション (POST、GET、PUT) に基づいて実行されると、新しいリソース トークンが生成されます。 アクセス許可とリソース トークンの詳細については、「Cosmos DB のアクセス許可に対する操作」を参照してください。

Authorization header (Authorization ヘッダー)

マスター キー トークンまたはリソース トークンを使用する場合でも、すべての REST 操作は、リソースと対話するために、承認ヘッダーと承認文字列を含める必要があります。 承認文字列の形式は次のとおりです。

type={typeoftoken}&ver={tokenversion}&sig={hashsignature}  

承認文字列は次の例のようになります。

type=master&ver=1.0&sig=5mDuQBYA0kb70WDJoTUzSBMTG3owkC0/cEN4fqa18/s=  

角かっこで囲まれた部分は、次のとおりです。

  • {typeoftoken} は、トークンの種類 (マスターリソース、または aad) を表します (Azure Cosmos DB RBAC を使用している場合)。

  • {tokenversion} は、トークンのバージョン (現在 は 1.0) を表します

  • {hashsignature} は、Azure Cosmos DB RBAC を使用している場合は、ハッシュトークン署名または oauth トークンを表します。

承認文字列は、無効な文字を含まないようにするために、REST 要求に追加する前にエンコードする必要があります。 MIME RFC2045 を使用して Base64 エンコードされていることを確認します。 また、ハッシュ署名で使用されるマスター キーは、Base64 でエンコードされているため、MIME RFC2045 を使用してデコードする必要があります。 承認に問題がある場合は、承認されていない例外を診断してトラブルシューティングする方法を参照してください。

マスター トークンのハッシュトークン署名の構築

マスター キー トークンのハッシュ署名は、 VerbResourceTypeResourceLinkDate の各パラメーターから作成できます。

  1. 動詞は、要求の HTTP 動詞を表します。 使用可能な値は次のとおりです。get、post、put、patch、delete

注:: 値は小文字にする必要があります。

  1. 文字列の ResourceType 部分は、要求の対象となるリソースの種類を識別します。 設定可能な値は、次のとおりです。
    • データベース操作: dbs
    • コンテナー操作: colls
    • ストアド プロシージャ: sprocs
    • ユーザー定義関数: udfs
    • トリガー: triggers
    • ユーザー: users
    • アクセス 許可: permissions
    • 項目レベルの操作: docs

メモ: 値では大文字と小文字が区別され、小文字である必要があります。

  1. 文字列の ResourceLink 部分は、要求が送信されるリソースの ID プロパティです。 ResourceLink 値は、実行しようとしている操作によって異なります。 各操作には、この規則に従って独自の対応する ResourceLink があります。
    • 操作が特定のリソースに対して実行される場合、値はそのリソースへのリンクです。 次に例を示します。

      • データベースの取得に使用する場合: dbs/{databaseId}
      • ドキュメントの取得の用途: dbs/{databaseId}/colls/{containerId}/docs/{docId}
    • 一連のリソース (リスト、作成、クエリ) に対して操作が実行された場合、値は親リソースのリンクになります。 次に例を示します。

      • ドキュメントの作成で使用する場合: dbs/{databaseId}/colls/{containerId}
      • ストアド プロシージャの作成では、次の操作を行います。 dbs/{databaseId}/colls/{containerId}
      • コンテナーを作成する場合は、次を使用します。 dbs/{databaseId}
      • データベースの作成の場合: "" -> データベースに親リソースがないため、空の文字列

メモ: ResourceLink 値の一部として参照されているリソース名は大文字と小文字が区別され、データベースでの宣言方法の大文字と小文字が一致する必要があります。 その他のコンポーネントは小文字にする必要があります。

  1. 文字列の日付部分は、メッセージが送信された UTC 日時 ( RFC 7231 日付/時刻形式で定義されている "HTTP 日付" 形式) です (たとえば、"1994 年 11 月 01 日(火)08:12:31 GMT")。

    C# では、値に対して "R" 書式指定子を DateTime.UtcNow 使用して取得できます。

    この同じ日付 (同じ形式) も要求のヘッダーとして x-ms-date 渡す必要があります。

メモ: 値では大文字と小文字が区別され、すべて小文字である必要があります。

署名を計算するには、CosmosDB キーをシークレットとして使用する SHA256 ベースのハッシュ ベースのメッセージ認証コード (HMAC) 関数を使用します。

ハッシュ関数のペイロードは、次の形式 "{verb}\n{resourceType}\n{resourceLink}\n{date}\n\n" を使用して上記の 4 つのコンポーネントに基づいています (ペイロードの末尾にある余分な新しい行に注意してください)。

関数の Base64 でエンコードされた結果は、呼び出しの Authorization ヘッダーを構築するときにシグネチャとして使用されます。

有効な承認ヘッダーの [C#] の例:

    httpClient.DefaultRequestHeaders.Clear();
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("authorization", auth); //generated using method below
    httpClient.DefaultRequestHeaders.Add("x-ms-date", requestDateString);
    httpClient.DefaultRequestHeaders.Add("x-ms-version", "2018-12-31");

有効な承認署名を生成する [C#] メソッドの例:

COSMOS DB REST API の完全なサンプルについては、GitHubの DB REST API サンプル リポジトリCosmos参照してください。

  
string GenerateMasterKeyAuthorizationSignature(HttpMethod verb, ResourceType resourceType, string resourceLink, string date, string key)
{
    var keyType = "master";
    var tokenVersion = "1.0";
    var payload = $"{verb.ToString().ToLowerInvariant()}\n{resourceType.ToString().ToLowerInvariant()}\n{resourceLink}\n{date.ToLowerInvariant()}\n\n";

    var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
    var hashPayload = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payload));
    var signature = Convert.ToBase64String(hashPayload);
    var authSet = WebUtility.UrlEncode($"type={keyType}&ver={tokenVersion}&sig={signature}");

    return authSet;
}
  

例 [Node.js]:

  
var crypto = require("crypto");  
  
function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceId, date, masterKey) {  
    var key = new Buffer(masterKey, "base64");  
  
    var text = (verb || "").toLowerCase() + "\n" +   
               (resourceType || "").toLowerCase() + "\n" +   
               (resourceId || "") + "\n" +   
               date.toLowerCase() + "\n" +   
               "" + "\n";  
  
    var body = new Buffer(text, "utf8");  
    var signature = crypto.createHmac("sha256", key).update(body).digest("base64");  
  
    var MasterToken = "master";  
  
    var TokenVersion = "1.0";  
  
    return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);  
}  
  

エンコードの例:

引数
動詞 GET
リソースの種類 "dbs"
リソース リンク "dbs/ToDoList"
Date 木, 27 Apr 2017 00:51:12 GMT
Key dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5Jiwv
W0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==
キーの種類 master
トークンのバージョン 1.0
出力承認文字列 type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJr
gp2uQRkr934kFbTqhByc7TVr3OHyqlu%2bc%2bc%3d

リソース トークンのハッシュ署名の構築

リソース トークンは、中間サーバーによって生成される必要があります。 サーバーはマスター キーガーディアンとして機能し、Web ブラウザーなどの信頼されていないクライアントに対して時間制約付きトークンを生成します。

このサーバーは、次の手順を実行します。

  1. 新しいトークンの受信クライアント要求を処理します。

  2. アプリケーション固有の方法でクライアント ID を検証します。

  3. クライアントが正常に認証されると、Cosmos DB インターフェイス (SDK または REST) を使用して新しい時間制限付きトークンが生成され、クライアントに返されます。

参照