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 があります。
    • 操作が特定のリソースに対して実行される場合、値はそのリソースへのリンクです。 例:

      • Get Database の場合は、次の値を使用します。 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-date" 形式)。たとえば、"火、 01 Nov 1994 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 ヘッダーを構築するときに署名として使用されます。

有効な 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
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) を使用して新しい制限付きトークンが生成され、クライアントに返されます。

参照