0

我想玩 Amazon Selling Partner API。从邮递员那里一切正常。从 Powershell 不是。

我试图从文档https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html和 python 示例中派生出我的 powershell 脚本。

我整天都在尝试,但我找不到解决方案。

我做了什么:

  • 来自 Postman -> Works 的测试功能
  • 阅读有关使用签名版本 4 签署 AWS 请求的信息 -> 确定
  • 使用来自https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html -> Works的测试输入了解签名密钥功能
  • 尝试将 Python 示例翻译为 Powershell:https ://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html ->不起作用
  • 使用 Google 从示例中找到解决方案并发现:http ://www.laurierhodes.info/?q=node/114 ->不起作用- 可能是因为它适用于 aws lambda

无论我做什么,我都会收到错误消息Sender SignatureDoesNotMatch

我附上了 Postman 的截图,它显示了来自这个端点的响应。我知道这是“拒绝访问”,它与亚马逊的示例非常接近。稍后,我需要发出 sts 请求以在每次通话中接收临时凭证,并且我还需要签署对亚马逊销售合作伙伴 API 的每次通话。

也许有人可以帮助我,好吗?我要疯了 :D

这是我的 Python 示例中的 Powershell 代码:https ://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html

我尝试了两种获取变体,

  1. 将 GET 与授权标头一起使用 (Python)
  2. 在查询字符串中使用带有身份验证信息的 GET (Python)

此代码来自 2nd -> Using GET with authentication information in the Query string

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[cultureinfo]::CurrentCulture = 'de-DE'

#powershell variant with example test input from #https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html

<#  
   .Synopsis
     HMACSHA256 signing function used in the construction of a "Signature 4 " request
#>
# translated function from Deriving a signing key using .NET (C#)
function hmacSHA256(
    [string]$data, 
    [byte[]]$key) 
    {
       $hmacsha = New-Object System.Security.Cryptography.HMACSHA256
       $hmacsha.key = $key
       $signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($data))
       
       return $signature
}

<#  
   .Synopsis
    The AWS Signature version 4 creation routine
#>
function getSignatureKey(
    [String]$AWSAccessKey,
    [String]$dateStamp,
    [String]$regionName,
    [String]$serviceName)
{
   [Byte[]]$kSecret    = [System.Text.Encoding]::UTF8.GetBytes("AWS4" + $AWSAccessKey)
   $kDate              = hmacSHA256 -data $dateStamp -key $kSecret
   $kRegion            = hmacSHA256 -data $regionName -key $kDate
   $kService           = hmacSHA256 -data $serviceName -key $kRegion
   $kSigningKey        = hmacSHA256 -data "aws4_request" -key $kService
   
   return $kSigningKey
}

 <#  
   .Synopsis
     Retrieves an SHA hash of a string as required by AWS Signature 4 
#>
function hash($request) {
    $sha256 = new-object -TypeName System.Security.Cryptography.SHA256Managed
    $utf8   = new-object -TypeName System.Text.UTF8Encoding
    $hash   = [System.BitConverter]::ToString($sha256.ComputeHash($utf8.GetBytes($request)))
    return $hash.replace('-','').toLower()
}


# ************* REQUEST VALUES *************

$method = 'GET'
$service = 'iam'
$host1 = 'iam.amazonaws.com'
$region = 'us-east-1'
$endpoint = 'https://iam.amazonaws.com'

$access_key = 'AKIA4KA7FVL7SN2EXAMPLE'
$secret_key = 'EXPL[enter image description here][1]Y59hS5KWKAnfOSnWLjNsiKaK/EXAMPLE'

$now = [DateTime]::UtcNow
$amz_date = $now.ToString('yyyyMMddTHHmmssZ')
$datestamp = $now.ToString('yyyyMMdd')



# ************* TASK 1: CREATE A CANONICAL REQUEST *************
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html

# Step 2: Create canonical URI--the part of the URI from domain to query 
# string (use '/' if no path)
$canonical_uri = '/' 

# Step 3: Create the canonical headers and signed headers. Header names
# must be trimmed and lowercase, and sorted in code point order from
# low to high. Note trailing \n in canonical_headers.
# signed_headers is the list of headers that are being included
# as part of the signing process. For requests that use query strings,
# only "host" is included in the signed headers.
$canonical_headers = "host:" + $host1 + "`n" 

$signed_headers = "host"

# Match the algorithm to the hashing algorithm you use, either SHA-1 or
# SHA-256 (recommended)
$algorithm = 'AWS4-HMAC-SHA256'
$credential_scope = $datestamp + '/' + $region + '/' + $service + '/' + 'aws4_request'


# Step 4: Create the canonical query string. In this example, request
# parameters are in the query string. Query string values must
# be URL-encoded (space=%20). The parameters must be sorted by name.
$canonical_querystring = "Action=CreateUser&UserName=NewUser&Version=2010-05-08"

$canonical_querystring += "&X-Amz-Algorithm=AWS4-HMAC-SHA256 `n"
$canonical_querystring += "&X-Amz-Credential=" + [uri]::EscapeDataString(($access_key + "/" + $credential_scope))
$canonical_querystring += "&X-Amz-Date=" + $amz_date
$canonical_querystring += "&X-Amz-Expires=30"
$canonical_querystring += "&X-Amz-SignedHeaders=" + $signed_headers

# Step 5: Create payload hash. For GET requests, the payload is an
# empty string ("").
$payload_hash = hash ''

# Step 6: Combine elements to create canonical request
$canonical_request = $method + "`n" + 
                     $canonical_uri + "`n" + 
                     $canonical_querystring + "`n" + 
                     $canonical_headers + "`n" + 
                     $signed_headers + "`n" + 
                     $payload_hash

#$canonical_request_hash = hash -request $canonical_request
#write-host $canonical_request_hash 


# *************************************************************#
# ************* TASK 2: CREATE THE STRING TO SIGN *************#
$string_to_sign = $algorithm + "`n" +  
                  $amz_date + "`n" +  
                  $credential_scope + "`n" + 
                  $canonical_request_hash 


# *************************************************************#
# ************* TASK 3: CALCULATE THE SIGNATURE ***************#
# Create the signing key
$signing_key = getSignatureKey($secret_key, $datestamp, $region, $service)

#write-host "signing-key: $($signing_key)"
# Sign the string_to_sign using the signing_key
$signature = HmacSHA256 -data $string_to_sign -key $signing_key
$signature = [System.BitConverter]::ToString($signature).Replace('-','').ToLower()


# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
# The auth information can be either in a query string
# value or in a header named Authorization. This code shows how to put
# everything into a query string.

$canonical_querystring += '&X-Amz-Signature=' + $signature

# ************* SEND THE REQUEST *************
# The 'host' header is added automatically by the Python 'request' lib. But it
# must exist as a header in the request.


### 
#I am not sure how to work with headers, because i used the Get Variant with authentication information in the Query string
####
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("authorization", "AWS4-HMAC-SHA256 Credential=$($AWSAccessID)/$($shortdate)/$($AWSRegion)/$($AWSService)/aws4_request, SignedHeaders=$($SignedHeadersList), Signature=$($signature)")


$request_url = $endpoint + "/?" + $canonical_querystring

Invoke-RestMethod  $request_url -Method 'GET' -Headers $headers


最好的问候,非常感谢帕特里克

邮递员截图

4

0 回答 0