使用 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_headers
和 signed_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 进行测试。
我在尝试使用 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_headers
和 signed_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 进行测试。