使用IAM授权(NodeJS)从EC2访问AWS API Gateway [英] Accessing AWS API Gateway from an EC2 using IAM authorization (NodeJS)

查看:393
本文介绍了使用IAM授权(NodeJS)从EC2访问AWS API Gateway的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许我要通向远方,但这里却是我得到的:

Perhaps I'm going a bridge to far here but heres what I got:


  • 设置了AWS_IAM的AWS API网关方法授权。

  • 允许访问该方法的策略。

  • 附加了该策略的EC2角色。

  • 以该角色启动的EC2。

  • An AWS API Gateway Method that has AWS_IAM set for Authorization.
  • A Policy that allows access to that Method.
  • An EC2 Role that has that policy attached to it.
  • An EC2 Launched with that Role.

我想拥有自己的NodeJS程序(或任何与此相关的语言)在EC2上调用该API,而无需在代码中硬编码AccessKey和SecretKey。

I would like to have my NodeJS program (or any language for that matter) on that EC2 to be able to call that API without hardcoding an AccessKey and SecretKey in the code.

我使用这种方法来使用aws-sdk来在S3上放置/获取记录,以及执行其他AWS功能(如我上面提到的所有步骤),但是,调用API网关似乎不在aws-sdk范围内。

I have used this approach to use the aws-sdk to put/get records on S3, and do other AWS functionality (like all the steps I mentioned above), However, invoking an API Gateway seems to be outside the aws-sdk scope.

使用Wreck调用API(我通过我的应用程序中的HTTP调用使用的NPM)并且没有标头会导致:

Calling the API with Wreck (the NPM I use from my HTTP calls in my app) and no headers results in:

{
  "message": "Missing Authentication Token"
}

那儿没什么大不了的。

有什么明显的我想念吗?

Anything obvious I am missing?

推荐答案

因此,您似乎需要访问 http://169.254.169.254/latest/meta-data/iam/security-credentials/Role_Name

So it appears you need to access your EC2 at http://169.254.169.254/latest/meta-data/iam/security-credentials/Role_Name

此处。

这是我的最终代码,包括使用签名版本4签名AWS请求

Here is my final code including Signing AWS Requests with Signature Version 4:

var Moment = require('moment');
var Wreck = require('wreck');
var Crypto = require('crypto');

function getSignatureKey(key, dateStamp, regionName, serviceName) {
    var kDate = Crypto.createHmac('sha256', 'AWS4' + key).update(dateStamp,'utf8').digest();
    var kRegion = Crypto.createHmac('sha256', kDate).update(regionName, 'utf8').digest();
    var kService = Crypto.createHmac('sha256', kRegion).update(serviceName, 'utf8').digest();
    var kSigning = Crypto.createHmac('sha256', kService).update('aws4_request', 'utf8').digest();
    return kSigning;
}

var assumed_role = 'MY_ROLE';
Wreck.get('http://169.254.169.254/latest/meta-data/iam/security-credentials/' + assumed_role, function(err, res, payload) {
    var payload_obj = JSON.parse(payload.toString());
    var access_key = payload_obj.AccessKeyId;
    var secret_key = payload_obj.SecretAccessKey;
    var token = payload_obj.Token;

    var payload = {}
    payload.email = 'devin.stewart@example.com';
    payload.first_name = 'Devin';
    payload.last_name = 'Stewart';
    payload.full_name = 'Devin Stewart';

    var request_parameters = JSON.stringify(payload);

    var method = 'POST';
    var api_id = 'MY_API_ID'
    var service = 'execute-api';
    var region = 'us-east-1';
    var api_path = '/production/people';
    var host = api_id + '.' + service + '.' + region + '.amazonaws.com';
    var endpoint = 'https://' + host + api_path;
    var content_type = 'application/json';

    var t = Moment.utc()
    var amz_date = t.format('YYYYMMDD[T]HHmmss[Z]');
    var date_stamp = t.format('YYYYMMDD'); // Date w/o time, used in credential scope

    var canonical_querystring = '';
    var canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + '\n' + 'x-amz-date:' + amz_date + '\n' + 'x-amz-security-token:' + token + '\n';
    var signed_headers = 'content-type;host;x-amz-date;x-amz-security-token';
    var payload_hash = Crypto.createHash('sha256').update(request_parameters).digest('hex');
    var canonical_request = method + '\n' + api_path + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash;

    var algorithm = 'AWS4-HMAC-SHA256';
    var credential_scope = date_stamp + '/' + region + '/' + service + '/' + 'aws4_request';
    var string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  Crypto.createHash('sha256').update(canonical_request).digest('hex');

    var signing_key = getSignatureKey(secret_key, date_stamp, region, service);
    var signature = Crypto.createHmac('sha256', signing_key).update(string_to_sign, 'utf8').digest('hex');

    authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' +  'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature;
    var headers = { 
        'Content-Type':content_type,
        'X-Amz-Date':amz_date,
        'X-Amz-Security-Token':token,
        'Authorization':authorization_header
    };

    var options = {headers: headers, payload: request_parameters};
    Wreck.post(endpoint, options, function (err, res, payload) {
        if (err) {
            console.log(err.data.payload.toString());
        } else {
            console.log(payload.toString());
        }
    });
});

这篇关于使用IAM授权(NodeJS)从EC2访问AWS API Gateway的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆