#javascript #node.js #amazon-web-services #graphql #aws-signature
Вопрос:
Я инженер по контролю качества и хочу автоматизировать наши API graphql, которые находятся за пределами шлюзов AWS. Я хочу добиться этого с помощью Javascripts. Проведя исследование, я понял, что нам нужно сгенерировать подпись AWS с помощью ключа доступа AWS и секретного ключа AWS. Я использую aws4
пакет npm для создания подписи AWS и graphql-request
в качестве клиента Javascript для graphql. Я пытаюсь запросить наш API graphql, используя URL-адрес appsync. Написанный ниже код с использованием Javascript mocha
тестовой платформы при выполнении, который возвращает мне сообщение об ошибке Error: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
Я попробовал использовать postman
настольный клиент для запроса graphql API с использованием подписи AWS и отлично работает, получите ожидаемый результат! Если я использую вручную то же authentication headers
самое из запроса почтальона, он завершается ошибкой при программном выполнении!
Оцените любые идеи или решения, которые помогут решить проблему при запросе API grapl с использованием подписи AWS.
var assert = require('assert');
var http = require('https');
var aws4 = require('aws4');
const { GraphQLClient, gql } = require("graphql-request");
var crypto = require('crypto')
describe('Array', function () {
var amzDate = getAmzDate(new Date().toISOString());
// this function converts the generic JS ISO8601 date format to the specific format the AWS API wants
function getAmzDate(dateStr) {
var chars = [":", "-"];
for (var i = 0; i < chars.length; i ) {
while (dateStr.indexOf(chars[i]) != -1) {
dateStr = dateStr.replace(chars[i], "");
}
}
dateStr = dateStr.split(".")[0] "Z";
return dateStr;
}
describe('GetUser status ()', function () {
it('should return the status of the User', async function () {
const query = gql`
{
getUser(userId: "d8a51af2453") {
status
}
}
`
// get the request body hash
const getHash = crypto.createHash('sha256').update(query).digest('hex')
console.log(getHash);
// aws4 will sign an options object as you'd pass to http.request, with an AWS service and region
var opts = { service: 'appsync', region: 'eu-west-1' }
// aws4.sign() will sign and modify these options, ready to pass to http.request
var awsauth = aws4.sign(opts, { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY })
var awsAuthHeaders = awsauth.headers.Authorization;
console.log(awsauth);
const graphQLClient = new GraphQLClient('https://<uniqueId>.appsync-api.eu-west-1.amazonaws.com/graphql', { headers: { authorization: awsAuthHeaders, 'X-Amz-Date': amzDate, 'X-Amz-Content-Sha256': getHash }, });
console.log(graphQLClient);
const data = await graphQLClient.request(query)
console.log(JSON.stringify(data))
});
});
});
GraphQLClient
пример вывода консоли выглядит следующим образом:
GraphQLClient {
url: 'https://<uniqueId>.appsync-api.eu-west-1.amazonaws.com/graphql',
options: {
headers: {
authorization: 'AWS4-HMAC-SHA256 Credential=AKIARASBW/20211005/eu-west-1/appsync/aws4_request, SignedHeaders=host;x-amz-date, Signature=d4a02fe6f6c3be5c5d2f6d6e19e4b32fd88ad0f3a0c',
'X-Amz-Date': '20211005T133243Z',
'X-Amz-Content-Sha256': 'f6b32c10d7968ce5b73783b77564d2c8'
}
}
}
Complete Error Message
Error: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
The Canonical String for this request should have been
'POST
/graphql
host:<uniqueId>.appsync-api.eu-west-1.amazonaws.com
x-amz-date:20211005T133243Z
host;x-amz-date
abbabb07714cac737137d952f0f5eb59807'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20211005T133243Z
20211005/eu-west-1/appsync/aws4_request
3b8858c0ac56f03c47b6ab08b68445'
: {"response":{"errors":[{"errorType":"BadRequestException","message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.nnThe Canonical String for this request should have beenn'POSTn/graphqlnnhost:<uniqueId>.appsync-api.eu-west-1.amazonaws.comnx-amz-date:20211005T133243Znnhost;x-amz-datenabbabb07714cac737137d952f0f5eb5980e559113979727ce4'nnThe String-to-Sign should have beenn'AWS4-HMAC-SHA256n20211005T133243Zn20211005/eu-west-1/appsync/aws4_requestc70829ce6a36f62b673'n"}],"status":400,"headers":{}},"request":{"query":"n {n getUser(userId: "e8213d09-cdfd-94a7-ae07-cd8a51af2453") {n statusn }n }n "}}
at node_modules/graphql-request/dist/index.js:254:31
at step (node_modules/graphql-request/dist/index.js:63:23)
at Object.next (node_modules/graphql-request/dist/index.js:44:53)
at fulfilled (node_modules/graphql-request/dist/index.js:35:58)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
References
- aws4 signature generation reference from examples listed in https://www.npmjs.com/package/aws4
- Graphql Javascript client selection from the list https://graphql.org/code/#javascript
- GraphQLCLient from usage section https://www.npmjs.com/package/graphql-request