我尝试使用Jenkinns管道生成AWS身份验证V4签名,用于访问scaleway云中的S3存储桶,这是我的脚本
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;
def SHA256Hash(String input) {
// Create a MessageDigest object for SHA-256 hashing
def digest = MessageDigest.getInstance('SHA-256')
// Convert the input string to bytes and hash it
def hashedBytes = digest.digest(input.getBytes('UTF-8'))
// Convert the hashed bytes to a hexadecimal string
def hexString = new StringBuilder()
hashedBytes.each { b ->
def hex = Integer.toHexString(0xff & b)
if (hex.length() == 1) hexString.append('0')
hexString.append(hex)
}
return hexString.toString()
}
def sign(key, msg) {
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(keySpec);
byte[] signatureBytes = mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
echo "thats from function ${signatureBytes}"
return Hex.encodeHexString(signatureBytes);
}
pipeline {
agent any
environment {
AWS_ACCESS_KEY_ID = credentials('my-bucket-api-access-key')
AWS_SECRET_ACCESS_KEY = credentials('my-bucket-api-secret-key')
AWS_DEFAULT_REGION = 'fr-par'
SERVICE = 's3'
S3_BUCKET_NAME = "NAME_OF_BUCKET"
HOST = "${S3_BUCKET_NAME}.s3.${AWS_DEFAULT_REGION}.scw.cloud"
}
stages {
stage('AWS Version 4 signing') {
steps {
script {
def date_stamp = new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
//generate signing key
def signing_key = "AWS4${AWS_SECRET_ACCESS_KEY}"
signing_key =sign(sign(sign(sign(signing_key, date_stamp), AWS_DEFAULT_REGION), SERVICE), 'aws4_request')
echo " signing_key ${signing_key}"
//generate string to sign
def method = 'GET'
def amz_date = new Date().format("yyyyMMdd'T'HHmmss'Z'", TimeZone.getTimeZone("UTC"))
def canonical_uri = '/'
def canonical_querystring = ''
def Amz_Content_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
def payload_hash = Amz_Content_SHA256
def canonical_headers = "host:${HOST}\nx-amz-content-sha256:${Amz_Content_SHA256}\nx-amz-date:${amz_date}"
def signed_headers = 'host;x-amz-content-sha256;x-amz-date'
def canonical_request = "${method}\n${canonical_uri}\n${canonical_querystring}\n${canonical_headers}\n${signed_headers}\n${payload_hash}"
echo " canonical_request ${canonical_request}"
def algorithm = 'AWS4-HMAC-SHA256'
def credential_scope = "${date_stamp}/${AWS_DEFAULT_REGION}/${SERVICE}/aws4_request"
def canonicalRequestHash = SHA256Hash(canonical_request)
def string_to_sign = "${algorithm}\n${amz_date}\n${credential_scope}\n${canonicalRequestHash}"
echo " string_to_sign ${string_to_sign}"
//create signature
def signature = sign(signing_key, string_to_sign)
echo " signature ${signature}"
//create authorization header
def authorization_header = "${algorithm} Credential=${AWS_ACCESS_KEY_ID}/${credential_scope},SignedHeaders=${signed_headers},Signature=${signature}"
echo " authorization_header ${authorization_header}"
def s3ListObjectsUrl = "http://${S3_BUCKET_NAME}.s3.${AWS_DEFAULT_REGION}.scw.cloud"
def s3Host = "${S3_BUCKET_NAME}.s3.${AWS_DEFAULT_REGION}.scw.cloud"
sh """
curl -X GET "${s3ListObjectsUrl}" \
-H "Host: ${s3Host}" \
-H "X-Amz-Content-Sha256: ${Amz_Content_SHA256}" \
-H "X-Amz-Date: ${amz_date}" \
-H "Authorization: ${authorization_header}"
"""
}
}
}
}
}
我得到的签名不匹配响应jenkins response
为了排除故障,我尝试了:
1-检查我的凭据与 Postman 和它的工作postman 200 response
2-检查我的两个函数**SHA 256 Hash(String input)和sign(key,msg)**的散列值,并使用在线工具比较HmacSHA 256和SHA 256值,我得到了相同的值
3-我遵循scaleway documentation来验证空格和“\n”
但我总是有同样的问题,我哪里做错了?
1条答案
按热度按时间vx6bjr1n1#
解决方案:1-修改canonicalHeaders和signedHeaders这两个日志
因此,X-Amz-Content-Sha 256报头仅停留在请求中而不是在签名的****计算中
2-修改sign函数(HmacSHA 256哈希函数)
我不遵循的文档,并感谢如何张贴这个解决方案script与python在那里我发现了差异