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

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

マスター キー トークン

マスター キー トークンは、ユーザーが特定のアカウント内の Cosmos DB リソースを完全に制御できるようにするすべてのアクセス キー トークンです。 マスター キーは、アカウントの作成時に作成されます。 マスター キーには、プライマリ キーとセカンダリ キーの 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} は、トークンの種類を示します。 masterresource、または aad ( Azure Cosmos DB RBAC を使用している場合)。

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

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

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

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

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

  1. Verb は、要求の 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. 文字列の Date 部分は、メッセージが送信された UTC 日時 ( RFC 7231 日付/時刻形式で定義されている "HTTP 日付" 形式) です (例: "Tue, 01 Nov 1994 08:12:31 GMT" など)。

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

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

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

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

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

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

有効な 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");

有効な Authorization シグネチャを生成する [C#] メソッドの例:

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

  
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 2017 年 4 月 27 日(木) 00:51:12 GMT
キー 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) を使用して新しい時間制限付きトークンが生成され、クライアントに返されます。

参照