使用 GetSecretValue AWS 机密管理器时出现 InvalidSignatureException API

InvalidSignatureException in using GetSecretValue AWS secrets manager API

我在尝试使用 AWS 机密管理器 REST 检索机密值时收到带有以下错误消息的无效请求 API GetSecretValue

我按照此处给出的步骤 (https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html#sig-v4-examples-post) 使用 sigv4 对请求进行了签名。

我的代码如下所示:

    def sign(self, key, msg):
        return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

    def get_signature_key(self, key, dateStamp, regionName, serviceName):
        kDate = self.sign(('AWS4' + key).encode('utf-8'), dateStamp)
        kRegion = self.sign(kDate, regionName)
        kService = self.sign(kRegion, serviceName)
        kSigning = self.sign(kService, 'aws4_request')
        return kSigning

    def get_request_url(self, region, access_key, secret_key, token, secret_name):
        method = 'POST'
        service = 'secretsmanager'
        host = 'secretsmanager.' + region + '.amazonaws.com'
        endpoint = 'https://secretsmanager.' + region + '.amazonaws.com'
        content_type = 'application/x-amz-json-1.0'
        amz_target = 'secretsmanager.GetSecretValue'
        request_parameters = '{'
        request_parameters += '"SecretId":"%s"' %(secret_name)
        request_parameters += '}'

        t = datetime.datetime.utcnow()
        amz_date = t.strftime('%Y%m%dT%H%M%SZ')
        date_stamp = t.strftime('%Y%m%d')

        canonical_uri = '/'
        canonical_querystring = ''
        canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + '\n' + 'x-amz-date:' + amz_date + '\n' + 'x-amz-target:' + amz_target + '\n' + 'x-amz-security-token:' + token + '\n'

        signed_headers = 'content-type;host;x-amz-date;x-amz-target;x-amz-security-token'
        payload_hash = hashlib.sha256(request_parameters.encode('utf-8')).hexdigest().strip()

        canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash

        algorithm = 'AWS4-HMAC-SHA256'
        credential_scope = date_stamp + '/' + region + '/' + service + '/' + 'aws4_request'
        string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()

        signing_key = self.get_signature_key(secret_key, date_stamp, region, service)
        signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()

        authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' +  'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature


        headers = { 'Content-Type':content_type, 'Host':host, 'X-Amz-Date':amz_date, 'X-Amz-Target':amz_target, 'X-Amz-Content-Sha256':payload_hash, 'X-Amz-Security-Token':token.encode('ascii'), 'Authorization':authorization_header.encode('ascii')}


        # ************* SEND THE REQUEST *************
        print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
        print('Request URL = ' + endpoint)

        r = requests.post(endpoint, headers=headers, data=request_parameters)

        print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
        print('Response code: %d\n' % r.status_code)
        print(r.text)

订单事项

canonical_headerssigned_headers 都应该排序。来自 your link:

Create the canonical headers. Header names must be trimmed and lowercase, and sorted in code point order from low to high.

Create the list of signed headers. This lists the headers in the canonical_headers list, delimited with ";" and in alpha order.


这意味着 x-amz-security-token 必须在 之前 x-amz-target:

    canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + '\n' + 'x-amz-date:' + amz_date + '\n' + 'x-amz-security-token:' + token + '\n' + 'x-amz-target:' + amz_target + '\n'

    signed_headers = 'content-type;host;x-amz-date;x-amz-security-token;x-amz-target'

此外,我认为您需要将 Content-Type 更新为 application/x-amz-json-1.1

使用此 lightly modified version of your code 进行测试。