Comparing version
@@ -31,2 +31,5 @@ var aws2 = exports | ||
RequestSigner.prototype.isSingleRegion = function() { | ||
// Special case for SimpleDB in us-east-1 | ||
if (this.service === 'sdb' && this.region === 'us-east-1') return true | ||
return ['cloudfront', 'ls', 'route53', 'iam', 'importexport', 'sts'] | ||
@@ -33,0 +36,0 @@ .indexOf(this.service) >= 0 |
var http = require('http') | ||
, https = require('https') | ||
, aws4 = require('aws4') | ||
, aws2 = require('aws2') | ||
// given an options object you could pass to http.request | ||
var opts = { host: 'sqs.us-east-1.amazonaws.com', path: '/?Action=ListQueues' } | ||
var opts = { host: 'sns.us-east-1.amazonaws.com', path: '/?Action=ListTopics' } | ||
aws4.sign(opts) // assumes AWS credentials are available in process.env | ||
aws2.sign(opts) // assumes AWS credentials are available in process.env | ||
@@ -13,9 +13,5 @@ console.log(opts) | ||
{ | ||
host: 'sqs.us-east-1.amazonaws.com', | ||
path: '/?Action=ListQueues', | ||
headers: { | ||
Host: 'sqs.us-east-1.amazonaws.com', | ||
'X-Amz-Date': '20121226T061030Z', | ||
Authorization: 'AWS4-HMAC-SHA256 Credential=ABCDEF/20121226/us-east-1/sqs/aws4_request, SignedHeaders=host;x-amz-date, Signature=d847efb54cd60f0a256174848f26e43af4b5168dbec3118dc9fd84e942285791' | ||
} | ||
host: 'sns.us-east-1.amazonaws.com', | ||
path: '/?Action=ListTopics&Timestamp=2013-01-12T01%3A25%3A55.553Z&SignatureVersion=2&SignatureMethod=HmacSHA256&AWSAccessKeyId=AKIAIHHJHZVAHCEWLG7A&Signature=LyWO%2B%2B%2BZ6x2i7LvQKcbX5HdiFs995kkyqmyTI5y6LCg%3D', | ||
headers: { Host: 'sns.us-east-1.amazonaws.com' } | ||
} | ||
@@ -28,3 +24,3 @@ */ | ||
<?xml version="1.0"?> | ||
<ListQueuesResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/"> | ||
<ListTopicsResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/"> | ||
... | ||
@@ -34,6 +30,6 @@ */ | ||
// you can pass AWS credentials in explicitly | ||
aws4.sign(opts, { accessKeyId: '', secretAccessKey: '' }) | ||
aws2.sign(opts, { accessKeyId: '', secretAccessKey: '' }) | ||
// aws4 can infer the host from a service and region | ||
opts = aws4.sign({ service: 'sqs', region: 'us-east-1', path: '/?Action=ListQueues' }) | ||
// aws2 can infer the host from a service and region | ||
opts = aws2.sign({ service: 'sns', region: 'us-east-1', path: '/?Action=ListTopics' }) | ||
@@ -43,7 +39,7 @@ // create a utility function to pipe to stdout (with https this time) | ||
// aws4 can infer the HTTP method if a body is passed in | ||
// method will be POST and Content-Type: 'application/x-www-form-urlencoded' | ||
request(aws4.sign({ service: 'iam', body: 'Action=ListGroups&Version=2010-05-08' })) | ||
// aws2 can infer the HTTP method if a body is passed in | ||
// method will be POST and Content-Type: 'application/x-www-form-urlencoded; charset=utf-8' | ||
request(aws2.sign({ service: 'monitoring', body: 'Action=ListMetrics&Version=2010-08-01' })) | ||
/* | ||
<ListGroupsResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/"> | ||
<ListMetricsResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/"> | ||
... | ||
@@ -53,4 +49,4 @@ */ | ||
// can specify any custom option or header as per usual | ||
request(aws4.sign({ | ||
service: 'dynamodb', | ||
request(aws2.sign({ | ||
service: 'rds', | ||
region: 'ap-southeast-2', | ||
@@ -60,32 +56,69 @@ method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/x-amz-json-1.0', | ||
'X-Amz-Target': 'DynamoDB_20111205.ListTables' | ||
'Content-Type': 'application/x-www-form-urlencoded' | ||
}, | ||
body: '{}' | ||
body: 'Action=DescribeDBInstances&Version=2012-09-17' | ||
})) | ||
/* | ||
{"TableNames":[]} | ||
<DescribeDBInstancesResponse xmlns="http://rds.amazonaws.com/doc/2012-09-17/"> | ||
... | ||
*/ | ||
// works with all other services that support Signature Version 4 | ||
// works with all other services that support Signature Version 2 | ||
request(aws4.sign({ service: 'sts', path: '/?Action=GetSessionToken&Version=2011-06-15' })) | ||
request(aws2.sign({ service: 'autoscaling', path: '/?Action=DescribeAutoScalingInstances&Version=2011-01-01' })) | ||
/* | ||
<GetSessionTokenResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/"> | ||
<DescribeAutoScalingInstancesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/"> | ||
... | ||
*/ | ||
request(aws4.sign({ service: 'glacier', path: '/-/vaults', headers: { 'X-Amz-Glacier-Version': '2012-06-01' } })) | ||
request(aws2.sign({ service: 'elasticloadbalancing', path: '/?Action=DescribeLoadBalancers&Version=2012-06-01' })) | ||
/* | ||
{"Marker":null,"VaultList":[]} | ||
<DescribeLoadBalancersResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/"> | ||
... | ||
*/ | ||
request(aws4.sign({ service: 'cloudsearch', path: '/?Action=DescribeDomains' })) | ||
request(aws2.sign({ service: 'cloudformation', path: '/?Action=ListStacks&Version=2010-05-15' })) | ||
/* | ||
<DescribeDomainsResponse xmlns="http://cloudsearch.amazonaws.com/doc/2011-02-01"> | ||
<ListStacksResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'ec2', path: '/?Action=DescribeRegions&Version=2012-12-01' })) | ||
/* | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<DescribeRegionsResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'elasticache', path: '/?Action=DescribeCacheClusters&Version=2012-11-15' })) | ||
/* | ||
<DescribeCacheClustersResponse xmlns="http://elasticache.amazonaws.com/doc/2012-11-15/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'elasticbeanstalk', path: '/?Action=ListAvailableSolutionStacks&Version=2010-12-01' })) | ||
/* | ||
<ListAvailableSolutionStacksResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'elasticmapreduce', path: '/?Action=DescribeJobFlows&Version=2009-03-31' })) | ||
/* | ||
<DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'importexport', path: '/?Action=ListJobs&Version=2010-06-01' })) | ||
/* | ||
<ListJobsResponse xmlns="http://importexport.amazonaws.com/doc/2010-06-01/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'sdb', path: '/?Action=ListDomains&Version=2009-04-15' })) | ||
/* | ||
<?xml version="1.0"?> | ||
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/"> | ||
... | ||
*/ | ||
{ | ||
"name": "aws2", | ||
"version": "0.0.2", | ||
"version": "0.1.0", | ||
"description": "Signs and prepares requests using AWS Signature Version 2", | ||
@@ -5,0 +5,0 @@ "author": "Michael Hart <michael.hart.au@gmail.com> (http://github.com/mhart)", |
132
README.md
@@ -1,8 +0,8 @@ | ||
aws4 | ||
aws2 | ||
---- | ||
[](http://travis-ci.org/mhart/aws4) | ||
[](http://travis-ci.org/mhart/aws2) | ||
A small utility to sign vanilla node.js http(s) request options using Amazon's | ||
[AWS Signature Version 4](http://docs.amazonwebservices.com/general/latest/gr/signature-version-4.html). | ||
[AWS Signature Version 2](http://docs.amazonwebservices.com/general/latest/gr/signature-version-2.html). | ||
@@ -13,2 +13,6 @@ It also provides defaults for a number of core AWS headers and | ||
*NB: It is preferrable to use the more secure | ||
[aws4](https://github.com/mhart/aws4) over this library for AWS services | ||
that support AWS Signature Version 4.* | ||
Example | ||
@@ -20,8 +24,8 @@ ------- | ||
, https = require('https') | ||
, aws4 = require('aws4') | ||
, aws2 = require('aws2') | ||
// given an options object you could pass to http.request | ||
var opts = { host: 'sqs.us-east-1.amazonaws.com', path: '/?Action=ListQueues' } | ||
var opts = { host: 'sns.us-east-1.amazonaws.com', path: '/?Action=ListTopics' } | ||
aws4.sign(opts) // assumes AWS credentials are available in process.env | ||
aws2.sign(opts) // assumes AWS credentials are available in process.env | ||
@@ -31,9 +35,5 @@ console.log(opts) | ||
{ | ||
host: 'sqs.us-east-1.amazonaws.com', | ||
path: '/?Action=ListQueues', | ||
headers: { | ||
Host: 'sqs.us-east-1.amazonaws.com', | ||
'X-Amz-Date': '20121226T061030Z', | ||
Authorization: 'AWS4-HMAC-SHA256 Credential=ABCDEF/20121226/us-east-1/sqs/aws4_request, SignedHeaders=host;x-amz-date, Signature=d847efb54cd60f0a256174848f26e43af4b5168dbec3118dc9fd84e942285791' | ||
} | ||
host: 'sns.us-east-1.amazonaws.com', | ||
path: '/?Action=ListTopics&Timestamp=2013-01-12T01%3A25%3A55.553Z&SignatureVersion=2&SignatureMethod=HmacSHA256&AWSAccessKeyId=AKIAIHHJHZVAHCEWLG7A&Signature=LyWO%2B%2B%2BZ6x2i7LvQKcbX5HdiFs995kkyqmyTI5y6LCg%3D', | ||
headers: { Host: 'sns.us-east-1.amazonaws.com' } | ||
} | ||
@@ -46,3 +46,3 @@ */ | ||
<?xml version="1.0"?> | ||
<ListQueuesResponse xmlns="http://queue.amazonaws.com/doc/2012-11-05/"> | ||
<ListTopicsResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/"> | ||
... | ||
@@ -57,6 +57,6 @@ */ | ||
// you can pass AWS credentials in explicitly | ||
aws4.sign(opts, { accessKeyId: '', secretAccessKey: '' }) | ||
aws2.sign(opts, { accessKeyId: '', secretAccessKey: '' }) | ||
// aws4 can infer the host from a service and region | ||
opts = aws4.sign({ service: 'sqs', region: 'us-east-1', path: '/?Action=ListQueues' }) | ||
// aws2 can infer the host from a service and region | ||
opts = aws2.sign({ service: 'sns', region: 'us-east-1', path: '/?Action=ListTopics' }) | ||
@@ -66,7 +66,7 @@ // create a utility function to pipe to stdout (with https this time) | ||
// aws4 can infer the HTTP method if a body is passed in | ||
// method will be POST and Content-Type: 'application/x-www-form-urlencoded' | ||
request(aws4.sign({ service: 'iam', body: 'Action=ListGroups&Version=2010-05-08' })) | ||
// aws2 can infer the HTTP method if a body is passed in | ||
// method will be POST and Content-Type: 'application/x-www-form-urlencoded; charset=utf-8' | ||
request(aws2.sign({ service: 'monitoring', body: 'Action=ListMetrics&Version=2010-08-01' })) | ||
/* | ||
<ListGroupsResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/"> | ||
<ListMetricsResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/"> | ||
... | ||
@@ -76,4 +76,4 @@ */ | ||
// can specify any custom option or header as per usual | ||
request(aws4.sign({ | ||
service: 'dynamodb', | ||
request(aws2.sign({ | ||
service: 'rds', | ||
region: 'ap-southeast-2', | ||
@@ -83,31 +83,68 @@ method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/x-amz-json-1.0', | ||
'X-Amz-Target': 'DynamoDB_20111205.ListTables' | ||
'Content-Type': 'application/x-www-form-urlencoded' | ||
}, | ||
body: '{}' | ||
body: 'Action=DescribeDBInstances&Version=2012-09-17' | ||
})) | ||
/* | ||
{"TableNames":[]} | ||
<DescribeDBInstancesResponse xmlns="http://rds.amazonaws.com/doc/2012-09-17/"> | ||
... | ||
*/ | ||
// works with all other services that support Signature Version 4 | ||
// works with all other services that support Signature Version 2 | ||
request(aws4.sign({ service: 'sts', path: '/?Action=GetSessionToken&Version=2011-06-15' })) | ||
request(aws2.sign({ service: 'autoscaling', path: '/?Action=DescribeAutoScalingInstances&Version=2011-01-01' })) | ||
/* | ||
<GetSessionTokenResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/"> | ||
<DescribeAutoScalingInstancesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/"> | ||
... | ||
*/ | ||
request(aws4.sign({ service: 'glacier', path: '/-/vaults', headers: { 'X-Amz-Glacier-Version': '2012-06-01' } })) | ||
request(aws2.sign({ service: 'elasticloadbalancing', path: '/?Action=DescribeLoadBalancers&Version=2012-06-01' })) | ||
/* | ||
{"Marker":null,"VaultList":[]} | ||
<DescribeLoadBalancersResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/"> | ||
... | ||
*/ | ||
request(aws4.sign({ service: 'cloudsearch', path: '/?Action=DescribeDomains' })) | ||
request(aws2.sign({ service: 'cloudformation', path: '/?Action=ListStacks&Version=2010-05-15' })) | ||
/* | ||
<DescribeDomainsResponse xmlns="http://cloudsearch.amazonaws.com/doc/2011-02-01"> | ||
<ListStacksResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'ec2', path: '/?Action=DescribeRegions&Version=2012-12-01' })) | ||
/* | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<DescribeRegionsResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'elasticache', path: '/?Action=DescribeCacheClusters&Version=2012-11-15' })) | ||
/* | ||
<DescribeCacheClustersResponse xmlns="http://elasticache.amazonaws.com/doc/2012-11-15/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'elasticbeanstalk', path: '/?Action=ListAvailableSolutionStacks&Version=2010-12-01' })) | ||
/* | ||
<ListAvailableSolutionStacksResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'elasticmapreduce', path: '/?Action=DescribeJobFlows&Version=2009-03-31' })) | ||
/* | ||
<DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'importexport', path: '/?Action=ListJobs&Version=2010-06-01' })) | ||
/* | ||
<ListJobsResponse xmlns="http://importexport.amazonaws.com/doc/2010-06-01/"> | ||
... | ||
*/ | ||
request(aws2.sign({ service: 'sdb', path: '/?Action=ListDomains&Version=2009-04-15' })) | ||
/* | ||
<?xml version="1.0"?> | ||
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/"> | ||
... | ||
*/ | ||
``` | ||
@@ -118,7 +155,8 @@ | ||
### aws4.sign(requestOptions, [credentials]) | ||
### aws2.sign(requestOptions, [credentials]) | ||
This calculates and populates the `Authorization` header of | ||
`requestOptions`, and any other necessary AWS headers and/or request | ||
options. Returns `requestOptions` as a convenience for chaining. | ||
This calculates and populates the `Signature` param of either | ||
`requestOptions.path` or requestOptions.body` depending on whether it is | ||
a `GET` or `POST` request. Returns `requestOptions` as a convenience for | ||
chaining. | ||
@@ -139,3 +177,4 @@ `requestOptions` is an object holding the same options that the node.js | ||
- `headers['Host']` (will use `hostname` or `host` or be calculated if not given) | ||
- `headers['Content-Type']` (will use `'application/x-www-form-urlencoded'` if not given and there is a `body`) | ||
- `headers['Content-Type']` (will use `'application/x-www-form-urlencoded; charset=utf-8'` | ||
if not given and there is a `body`) | ||
- `headers['Date']` (used to calculate the signature date if given, otherwise `new Date` is used) | ||
@@ -150,3 +189,3 @@ | ||
```javascript | ||
aws4.sign(requestOptions, { | ||
aws2.sign(requestOptions, { | ||
secretAccessKey: "<your-secret-access-key>", | ||
@@ -172,15 +211,4 @@ accessKeyId: "<your-access-key-id>" | ||
``` | ||
npm install aws4 | ||
npm install aws2 | ||
``` | ||
Thanks | ||
------ | ||
Thanks to [@jed](https://github.com/jed) for his | ||
[dynamo-client](https://github.com/jed/dynamo-client) lib where I first | ||
committed and subsequently extracted this code. | ||
Also thanks to the | ||
[official node.js AWS SDK](https://github.com/aws/aws-sdk-js) for giving | ||
me a start on implementing the v4 signature. | ||
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
19670
16.26%288
11.2%203
16%7
-30%