我在使用邮递员使用 AAD 令牌作为身份验证时遇到获取容器 ACL 和设置容器 ACL REST API 的问题

I am facing issues for Get Container ACL and Set Container ACL REST API using postman using AAD Token as authentication

我在使用 Postman 对 Get Container ACL 进行 REST API 调用时遇到以下错误:

<?xml version="1.0" encoding="utf-8"?>
<Error>
    <Code>ResourceNotFound</Code>
    <Message>The specified resource does not exist.
RequestId:35678849-101e-005b-0fa8-d4c9bd000000
Time:2021-11-08T13:53:42.8102881Z</Message>
</Error>

使用 Postman 对 Set Container ACL 进行 REST 调用时出现以下错误:

<?xml version="1.0" encoding="utf-8"?>
<Error>
    <Code>ResourceNotFound</Code>
    <Message>The specified resource does not exist.
RequestId:35688854-101e-005b-12a8-d4c9bd000000
Time:2021-11-08T13:58:12.8507122Z</Message>
</Error>

不确定我缺少的是正确的权限还是正确的参数?

Get Container ACL & Set Container ACL暂时只支持SharedKey认证。他们不支持 AAD 身份验证。

我使用 AAD Authorization 方法进行了相同的测试,仅 ACL 操作遇到了同样的问题,而其他操作(如 list blob)却成功了。

@SumanthMarigowda-MSFT 所述,ACL 操作不支持 AAD auth。你必须使用 Shared Key Auth.

步骤:

  1. 创建如下环境变量:

    注意:只提供高亮变量的初始值,其他留空。

  2. 创建请求 https://{{azure_storage_account}}.blob.core.windows.net/yourcontainername?restype=container&comp=acl 根据您的要求 Get/Put 并添加以下内容 headers :

  3. 在 Postman 的 Pre-Request Script 选项卡中添加以下代码:

    const crypto = require("crypto-js");
    
    // Set Date header value for authorization
    // Should be UTC GMT string
    pm.environment.set("header_date", new Date().toUTCString());
    console.log("header date", new Date().toUTCString());
    var substituteEnvVars = function (varStr) {
        let match;
        let replacedVar = varStr;
    
        while ((match = /\{\{([^{}]*?)}}/g.exec(replacedVar)) !== null ) {
            if (!pm.variables.get(match[1])) {
                continue;
            }
            var envVar = new RegExp(RegExp.escape(match[0]), 'g');
            replacedVar = replacedVar.replace(envVar, pm.variables.get(match[1]));
        }
    
        return replacedVar;
    };
    
    // Get hash of all header-name:value
    const headers = pm.request.getHeaders({ ignoreCase: true, enabled: true });
    
    // Construct Signature value for Authorization header
    var signatureParts = [
        pm.request.method.toUpperCase(),
        headers["content-encoding"] || "",
        headers["content-language"] || "",
        pm.request.body.toString().length || "",
        headers["content-md5"] || "",
        headers["content-type"] || "",
        headers["x-ms-date"] ? "" : (pm.variables.get("header_date") || ""),
        headers["if-modified-since"] || "",
        headers["if-match"] || "",
        headers["if-none-match"] || "",
        headers["if-unmodified-since"] || "",
        headers["range"] || ""
    ];
    
    // Construct CanonicalizedHeaders
    const canonicalHeaderNames = [];
    Object.keys(headers).forEach(key => {
        if (key.startsWith("x-ms-")) {
            canonicalHeaderNames.push(key);
            console.log("key: ", canonicalHeaderNames);
        }
    });
    // Sort headers lexographically by name
    canonicalHeaderNames.sort();
    
    const canonicalHeaderParts = [];
    canonicalHeaderNames.forEach(key => {
        let value = pm.request.getHeaders({ ignoreCase: true, enabled: true })[key];
        console.log("value: ",value);
        // Populate variables
        value = substituteEnvVars(value);
        console.log("value: ",value);
        // Replace whitespace in value but not if its within quotes
        if (!value.startsWith("\"")) {
            value = value.replace(/\s+/, " ");
            console.log("value: ",value);
        }
    
        canonicalHeaderParts.push(`${key}:${value}`);
        console.log("canonicalHeaderParts: ",canonicalHeaderParts);
    });
    
    // Add headers to signature
    signatureParts.push.apply(signatureParts, canonicalHeaderParts);
    
    // Construct CanonicalizedResource
    const canonicalResourceParts = [
        `/${pm.environment.get("azure_storage_account")}${pm.request.url.getPath()}`
    ];
    console.log("canonicalResourceParts: ",canonicalResourceParts);
    const canonicalQueryNames = [];
    pm.request.url.query.each(query => {
        canonicalQueryNames.push(query.key.toLowerCase());
        console.log("canonicalQueryNames: ",query.key.toLowerCase());
    });
    canonicalQueryNames.sort();
    canonicalQueryNames.forEach(queryName => {
        const value = pm.request.url.query.get(queryName);
        console.log("canonicalQueryNames: ",value);
        // NOTE: This does not properly explode multiple same query params' values
        // and turn them into comma-separated list
        canonicalResourceParts.push(`${queryName}:${value}`);
        console.log("canonicalResourcePartss: ",canonicalResourceParts);
    });
    // Add resource to signature
    signatureParts.push.apply(signatureParts, canonicalResourceParts);
    
    console.log("Signature Parts", signatureParts);
    
    // Now, construct signature raw string
    const signatureRaw = signatureParts.join("\n");
    
    console.log("Signature String", JSON.stringify(signatureRaw));
    
    // Hash it using HMAC-SHA256 and then encode using base64
    const storageKey = pm.environment.get("azure_storage_key");
    const signatureBytes = crypto.HmacSHA256(signatureRaw, crypto.enc.Base64.parse(storageKey));
    const signatureEncoded = signatureBytes.toString(crypto.enc.Base64);
    
    console.log("Storage Account", pm.environment.get("azure_storage_account"));
    console.log("Storage Key", storageKey);
    
    // Finally, make it available for headers
    pm.variables.set("header_authorization", 
        `SharedKey ${pm.environment.get("azure_storage_account")}:${signatureEncoded}`);
    
  4. 然后保存并发送请求,您将得到如下输出:

预请求脚本参考:

Github