我正在尝试创建一个非常轻量级的PHP端点,将数据推送到SQS队列以进行离线处理。如果我能提供帮助,我不想利用整个AWS SDK。
IAM Side
SQS Side
好的,所以我认为它必须是签名。我下载AWSv4 Test Suite并将其抛在调试开关后面。我收到了有效的回复。但是,当我关闭调试时 - 返回错误信息。
我已经尝试过base64编码有效负载,以防这是一个奇怪的转义问题,但仍然没有(当我允许访问所有人时,我能够推送数据)。
无论如何,这是我的代码。它必须是IAM许可问题,不是吗?我似乎无法摆动圆圈:
<?php
define( 'DEBUG', false );
define( 'AMZN_ALGO', 'AWS4-HMAC-SHA256' );
define( 'HASH_ALGO', 'SHA256' );
function getSignatureKey( $key, $date, $region, $service ) {
$kDate = hash_hmac( HASH_ALGO, $date, 'AWS4' . $key, true );
$kRegion = hash_hmac( HASH_ALGO, $region, $kDate, true );
$kService = hash_hmac( HASH_ALGO, $service, $kRegion, true );
$kSigning = hash_hmac( HASH_ALGO, 'aws4_request', $kService, true );
return $kSigning;
}
// these values are the hashes provided in the test suite to validate your approach
function compareTestSig( $type, $val ) {
$testSigs = [
'sts'=>'2e1cf7ed91881a30569e46552437e4156c823447bf1781b921b5d486c568dd1c',
'creq'=>'9095672bbd1f56dfc5b65f3e153adc8731a4a654192329106275f4c7b24d0b6e',
'authz'=>'1a72ec8f64bd914b0e42e42607c7fbce7fb2c7465f63e3092b3b0d39fa77a6fe'
];
if( $testSigs[$type] === $val ) {
return true;
}
return false;
}
$headers = getallheaders();
/**
* Config
* DEBUG = true are all the values from the AWS 4 Test Suite
*/
if( DEBUG === true ) {
define( 'ACCESS_KEY', 'AKIDEXAMPLE' );
define( 'SECRET_ACCESS_KEY', 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY' );
define( 'ENDPOINT', 'https://example.amazonaws.com/' );
$amznDate = '20150830T123600Z';
$nrmlDate = '20150830';
$service = 'service';
$version = '2012-11-05';
$payload = 'Param1=value1';
} else {
define( 'ACCESS_KEY', 'MY_ACCESS_KEY_I_KNOW_IS_CORRECT' );
define( 'SECRET_ACCESS_KEY', 'MY_SECRET_ACCESS_KEY_I_CHECKED_100_TIMES' );
define( 'ENDPOINT', 'https://sqs.us-east-1.amazonaws.com/[ENDPOINT_ID]/[QUEUE_NAME]' );
$amznDate = gmdate( "Ymd\THis\Z" );
$nrmlDate = gmdate( 'Ymd' );
$service = 'sqs';
$version = '2012-11-05';
// create the payload
$pBody = [];
$pBody['Action'] = 'SendMessage';
$pBody['MessageBody'] = json_encode( $headers );
$pBody['Version'] = $version;
$payload = http_build_query( $pBody);
}
$host = parse_url( ENDPOINT, PHP_URL_HOST );
$path = parse_url( ENDPOINT, PHP_URL_PATH );
$region = 'us-east-1';
$contentType = 'application/x-www-form-urlencoded; charset=utf8';
$scope = sprintf( '%s/%s/%s/%s', $nrmlDate, $region, $service, 'aws4_request' );
$payloadHash = hash( HASH_ALGO, $payload );
if( DEBUG ) {
if( compareTestSig( 'creq', $payloadHash ) ) {
var_dump( 'CREQ sig PASS' );
} else {
var_dump( 'CREQ sig NO PASS' );
exit;
}
}
/**
* Sign, seal, deliver.
* First, create the header string
*/
$aggregate = [
'content-type' => $contentType,
'host' => $host,
'x-amz-date' => $amznDate
];
ksort( $aggregate );
$canonHeaders = [];
foreach( $aggregate as $k=>$v ) {
$canonHeaders[] = sprintf( "%s:%s", $k, $v );
}
$signedHeadersString = implode( ';', array_keys( $aggregate ) );
/**
* next, create the canonical request and hash it
*/
$canon = sprintf( "%s\n%s\n%s\n%s\n\n%s\n%s",
'POST',
$path,
'',
implode( "\n", $canonHeaders ),
$signedHeadersString,
$payloadHash
);
$canonHash = hash( HASH_ALGO, $canon );
if( DEBUG ) {
if( compareTestSig( 'sts', $canonHash ) ) {
var_dump( 'STS sig PASS' );
} else {
var_dump( 'STS sig NO PASS' );
exit;
}
}
$toSign = sprintf( "%s\n%s\n%s\n%s", AMZN_ALGO, $amznDate, $scope, $canonHash );
// signingKey will be bin, signature will be in hex
$signingKey = getSignatureKey( SECRET_ACCESS_KEY, $nrmlDate, $region, $service );
$signature = hash_hmac( HASH_ALGO, $toSign, $signingKey );
if( DEBUG ) {
if( compareTestSig( 'authz', $signature ) ) {
var_dump( 'AUTHZ sig PASS' );
} else {
var_dump( 'AUTHZ sig NOPASS' );
exit;
}
}
/**
* set up the post headers
**/
$postHeaders = [];
$postHeaders['Content-Type'] = $contentType;
$postHeaders['Host'] = $host;
$postHeaders['X-Amz-Date'] = $amznDate;
$postHeaders['Authorization'] = sprintf( "%s Credential=%s, SignedHeaders=%s, Signature=%s",
AMZN_ALGO,
ACCESS_KEY . '/' . $scope,
$signedHeadersString,
$signature
);
//do it
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, ENDPOINT );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $postHeaders );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$output = curl_exec( $ch );
curl_close( $ch );
$xml = simplexml_load_string( $output );
if( empty( $xml ) ) {
var_dump( $output );
die( 'UnknownOperationException' );
}
if(! empty( $xml->Error ) ) {
printf( "ERROR %s : %s", $xml->Error->Code, $xml->Error->Message );
exit;
}
echo 'OK=1;';
exit;
?>