none
【Azure REST API】Create Container のREST APIに失敗する RRS feed

  • 質問

  • Azure REST APIについて質問があります。
    Blob Service REST APIの、Create Containerにつきまして
    「AuthenticationFailed」と表示されてしまい、正常に処理を行うことができません。

    処理の作成につきましては、こちらを参考にしました。

    https://docs.microsoft.com/en-us/rest/api/storageservices/create-container
    https://docs.microsoft.com/ja-jp/rest/api/storageservices/authorize-with-shared-key

    また、blobのputやdeleteなどは同様の実装で問題なく処理に成功していましたが
    containerの作成については、同様の方法で失敗してしまい、原因がわからずに頓挫しておりました。

    こちらにつきまして、正しいフォーマットでREST APIを送るためにはどのようにすべきでしょうか。

    下記にサンプルコードを添付いたします。

    処理内容としましては、
    1.必要な情報をhashで定義
    2.各パラメータをSHA256で暗号化、base64で暗号化
    3.curlでリクエスト

    [処理内容概要(ruby)]
    ```
    container_name = "XXXXXXXXXX"
    account_name = "XXXXXXXXXX"
    KEY="XXXXXXXXXX"

    url="https://#{account_name}.blob.core.windows.net/#{container_name}?restype=container"
      datas = {
          #[固定ヘッダ]
          #----------------------------------------------------
          "request_type" => "PUT",
          "Content-Encoding" => "",
          "Content-Language" => "",
          "Content-Length" => "0",
          "Content-MD5" => "",
          "Content-Type" => "application/x-www-form-urlencoded",
          "Date" => "#{Time.now.strftime("%a, %d %b %Y %H:%M:%S")} GMT",
          "If-Modified-Since" => "",
          "If-Match" => "",
          "If-None-Match" => "",
          "If-Unmodified-Since" => "",
          "Range" => "",
          #----------------------------------------------------
          "version" => "x-ms-version:2011-08-18",
          "x-ms-blob-public-access" => "x-ms-blob-public-access:container",
          "endpoint" => "/#{account_name}/#{container_name}",
          "restype" => "restype:container",
      }

      signature = Base64.encode64(OpenSSL::HMAC.digest(
          "sha256",Base64.decode64(KEY),datas.values.join("\n")))

      req=<<STR.gsub("\n"," ")
    curl -v -s "#{url}"
    -X #{datas["request_type"]}
    -H 'Content-Length: #{datas["Content-Length"]}'
    -H 'Content-Type: #{datas["Content-Type"]}'
    -H '#{datas["version"]}'
    -H '#{datas["x-ms-blob-public-access"]}'
    -H 'Authorization:SharedKey #{account_name}:#{signature.strip}'
    -d ''
    STR
    ret = ((res=`#{req}`).length <= 0)
    ```

    [実際のリクエストとレスポンス]
    ```
    "curl -v -s \"https://munarstorage.blob.core.windows.net/cont?restype=container\" -X PUT -H 'Content-Length: 0' -H 'Content-Type: application/x-www-form-urlencoded' -H 'x-ms-version:2011-08-18' -H 'x-ms-blob-public-access:container' -H 'Authorization:SharedKey munarstorage:hlovqEjBPsdnGZUToSxi1EatnDS2CdXqFjc5zGeyFDQ=' -d '' "
    ./create_container.rb:65: warning: Insecure world writable dir /root/d/snippe2/ruby/utils in PATH, mode 040777
    * About to connect() to munarstorage.blob.core.windows.net port 443 (#0)
    *   Trying 52.239.145.36...
    * Connected to munarstorage.blob.core.windows.net (52.239.145.36) port 443 (#0)
    * Initializing NSS with certpath: sql:/etc/pki/nssdb
    *   CAfile: /etc/pki/tls/certs/ca-bundle.crt
      CApath: none
    * SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    * Server certificate:
    *       subject: CN=*.blob.core.windows.net
    *       start date: Dec 03 22:45:16 2019 GMT
    *       expire date: Dec 03 22:45:16 2021 GMT
    *       common name: *.blob.core.windows.net
    *       issuer: CN=Microsoft IT TLS CA 4,OU=Microsoft IT,O=Microsoft Corporation,L=Redmond,ST=Washington,C=US
    > PUT /cont?restype=container HTTP/1.1
    > User-Agent: curl/7.29.0
    > Host: munarstorage.blob.core.windows.net
    > Accept: */*
    > Content-Length: 0
    > Content-Type: application/x-www-form-urlencoded
    > x-ms-version:2011-08-18
    > x-ms-blob-public-access:container
    > Authorization:SharedKey munarstorage:hlovqEjBPsdnGZUToSxi1EatnDS2CdXqFjc5zGeyFDQ=
    >
    < HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
    < Content-Length: 408
    < Content-Type: application/xml
    < Server: Microsoft-HTTPAPI/2.0
    < x-ms-request-id: 44d32759-401e-0054-0e81-eba723000000
    < Date: Tue, 25 Feb 2020 02:12:56 GMT
    * HTTP error before end of send, stop sending
    <
    { [data not shown]
    * Closing connection 0
    <?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
    RequestId:44d32759-401e-0054-0e81-eba723000000
    Time:2020-02-25T02:12:56.3698816Z</Message><AuthenticationErrorDetail>Request date header not specified</AuthenticationErrorDetail></Error>
    ```
    大変恐れ入りますが、諸々ご指摘いただければと思います。
    2020年2月25日 3:23

回答

  • 色々アドバイスいただき、ありがとうございます!

    最終的に、うまく行かない原因がわかりました。

    シグネチャ生成時にcontent-lengthの値を0で指定していたのがまずかったようです。

    ただし、httpヘッダにcontent-lengthの指定がなければ下記のようなエラーが出てしまいました。

    ---

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
    <HTML><HEAD><TITLE>Length Required</TITLE>
    <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
    <BODY><h2>Length Required</h2>
    <hr><p>HTTP Error 411. The request must be chunked or have a content length.</p>
    ---

    そのため、curl等で能動的にcontent-lengthを指定する場合は

    シグネチャの方に値を入れない(\nだけにする)ようにする必要があることがわかりました。

    • 回答としてマーク tachibanana 2020年4月20日 14:38
    2020年4月20日 14:37

すべての返信

  • 公開されているドキュメントを確認する限り、間違っている点は確認できていないのですが、問題の切り分けとして、nx-ms-version のバージョンを変えてみて、正しく動作するかを確認してみてはどうでしょう。
    また、コンテナを作成するAPI側の仕様が変わっている可能性もあるため、マイクロソフトのサポートに確認してみると良いかもしれません。
    2020年2月27日 7:46
  • ご返信ありがとうございます!バージョンの変更を試してみたいと思います。
    また、REST APIのサポートについてはフォーラムに飛ばされてしまい
    AzurePortal上の問い合わせを行うことができませんでした…。
    また進展があり次第共有いたします。
    2020年3月2日 11:23
  • Blob Service REST API は、Microsoft で開発していると思うので、サポート対象になるような感じがしますが。必要に応じて、以下のようにお問い合わせを実施してみても良いかもしれません。

    2020年3月3日 4:57
  • PowerShell 上で Invoke-RestMethod からの実行となりますが、REST API を以下のように実行すると、正常に Azure Storage Blob コンテナーを作成することができました。参考になれば幸いです。

    $StorageAccount = "st****"
    $ContainerName = "con2"
    $Key = "************************"
    $date = [System.DateTime]::UtcNow.ToString("R")
    $stringToSign = "PUT`n`n`n`n`n`n`n`n`n`n`n`nx-ms-date:$date`nx-ms-version:2017-07-29`n/$StorageAccount/$ContainerName`nrestype:container"
    $sharedKey = [System.Convert]::FromBase64String($Key)
    $hasher = New-Object System.Security.Cryptography.HMACSHA256
    $hasher.Key = $sharedKey
    $signedSignature = [System.Convert]::ToBase64String($hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($stringToSign)))
    $authHeader = "SharedKey ${StorageAccount}:$signedSignature"
    $headers = @{'Authorization'=$authHeader
    'x-ms-version'='2017-07-29'
    'x-ms-date'=$date
    }
    $URI = "https://$StorageAccount.blob.core.windows.net/" + $ContainerName + "?restype=container"
    
    Invoke-RestMethod -method PUT -Uri $URI -Headers $headers
    

    2020年3月6日 5:54
  • 色々アドバイスいただき、ありがとうございます!

    最終的に、うまく行かない原因がわかりました。

    シグネチャ生成時にcontent-lengthの値を0で指定していたのがまずかったようです。

    ただし、httpヘッダにcontent-lengthの指定がなければ下記のようなエラーが出てしまいました。

    ---

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
    <HTML><HEAD><TITLE>Length Required</TITLE>
    <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
    <BODY><h2>Length Required</h2>
    <hr><p>HTTP Error 411. The request must be chunked or have a content length.</p>
    ---

    そのため、curl等で能動的にcontent-lengthを指定する場合は

    シグネチャの方に値を入れない(\nだけにする)ようにする必要があることがわかりました。

    • 回答としてマーク tachibanana 2020年4月20日 14:38
    2020年4月20日 14:37