Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove AWS key and secret from configuration #49

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 9 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ parse-server adapter for AWS S3

`npm install --save parse-server-s3-adapter`

# aws credentials
# AWS Credentials

Although it is not recommended, AWS credentials can be explicitly configured through an options
object, constructor string arguments or environment variables ([see below](#using-a-config-file)).
This option is provided for backward compatibility.
This adapter uses the AWS SDK to access S3. The SDK must have access to appropriate credentials. To properly configure the AWS SDK see [the docs](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#config-settings-and-precedence). For more information on AWS best practices, see [IAM Best Practices User Guide](http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html).

The preferred method is to use the default AWS credentials pattern. If no AWS credentials are explicitly configured, the AWS SDK will look for credentials in the standard locations used by all AWS SDKs and the AWS CLI. More info can be found in [the docs](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#config-settings-and-precedence). For more information on AWS best practices, see [IAM Best Practices User Guide](http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html).
In short, for development purposes, you can configure your credentials using the aws cli with the following command:

``` aws configure```

For production on an AWS ec2 instance, the instance role should have appropriate permissions and this adapter will pick them up through the AWS SDK.

# usage with parse-server

Expand All @@ -32,8 +34,6 @@ The preferred method is to use the default AWS credentials pattern. If no AWS c
"options": {
"bucket": "my_bucket",
// optional:
"accessKey": "accessKey",
"secretKey": "secretKey",
"region": 'us-east-1', // default value
"bucketPrefix": '', // default value
"directAccess": false, // default value
Expand All @@ -55,11 +55,9 @@ Set your environment variables:
S3_BUCKET=bucketName
```

the following optional configurations can be set by environment variables too:
the following optional configuration can be set by environment variable too:

```
S3_ACCESS_KEY=accessKey
S3_SECRET_KEY=secretKey
S3_SIGNATURE_VERSION=v4
```

Expand All @@ -79,8 +77,7 @@ And update your config / options
```
var S3Adapter = require('parse-server-s3-adapter');

var s3Adapter = new S3Adapter('accessKey',
'secretKey', bucket, {
var s3Adapter = new S3Adapter(bucket, {
region: 'us-east-1'
bucketPrefix: '',
directAccess: false,
Expand All @@ -100,8 +97,6 @@ var api = new ParseServer({
```
S3Adapter("bucket")
S3Adapter("bucket", options)
S3Adapter("key", "secret", "bucket")
S3Adapter("key", "secret", "bucket", options)
S3Adapter(options) // where options must contain bucket.
S3Adapter(options, s3overrides)
```
Expand All @@ -117,8 +112,6 @@ var S3Adapter = require('parse-server-s3-adapter');
var s3Options = {
"bucket": "my_bucket",
// optional:
"accessKey": null, // default value
"secretKey": null, // default value
"region": 'us-east-1', // default value
"bucketPrefix": '', // default value
"directAccess": false, // default value
Expand Down
7 changes: 1 addition & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var AWS = require('aws-sdk');
var optionsFromArguments = require('./lib/optionsFromArguments');

// Creates an S3 session.
// Providing AWS access, secret keys and bucket are mandatory
// Providing AWS bucket is mandatory
// Region will use sane defaults if omitted
function S3Adapter() {
var options = optionsFromArguments(arguments);
Expand All @@ -28,11 +28,6 @@ function S3Adapter() {
globalCacheControl: this._globalCacheControl
};

if (options.accessKey && options.secretKey) {
s3Options.accessKeyId = options.accessKey;
s3Options.secretAccessKey = options.secretKey;
}

Object.assign(s3Options, options.s3overrides);

this._s3Client = new AWS.S3(s3Options);
Expand Down
4 changes: 0 additions & 4 deletions lib/optionsFromArguments.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ const optionsFromArguments = function optionsFromArguments(args) {
if (typeof args[1] != 'string' || typeof args[2] != 'string') {
throw new Error('Failed to configure S3Adapter. Arguments don\'t make sense');
}
options.accessKey = args[0];
options.secretKey = args[1];
options.bucket = args[2];
otherOptions = args[3];
}
Expand Down Expand Up @@ -65,8 +63,6 @@ const optionsFromArguments = function optionsFromArguments(args) {
}

options = requiredOrFromEnvironment(options, 'bucket', 'S3_BUCKET');
options = fromEnvironmentOrDefault(options, 'accessKey', 'S3_ACCESS_KEY', null);
options = fromEnvironmentOrDefault(options, 'secretKey', 'S3_SECRET_KEY', null);
options = fromEnvironmentOrDefault(options, 'bucketPrefix', 'S3_BUCKET_PREFIX', '');
options = fromEnvironmentOrDefault(options, 'region', 'S3_REGION', DEFAULT_S3_REGION);
options = fromEnvironmentOrDefault(options, 'directAccess', 'S3_DIRECT_ACCESS', false);
Expand Down
5 changes: 1 addition & 4 deletions spec/config/test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
module.exports = {
accessKey: 'accessKey',
secretKey: 'secretKey',
insufficientOptions: {
accessKey: 'accessKey',
secretKey: 'secretKey',
random: 'key',
},
bucket: 'bucket',
objectWithBucket: {
Expand Down
55 changes: 12 additions & 43 deletions spec/test.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@ describe('S3Adapter tests', () => {
expect(() => {
new S3Adapter();
}).toThrow("S3Adapter requires option 'bucket' or env. variable S3_BUCKET");

expect(() => {
new S3Adapter('accessKey', 'secretKey', {});
}).toThrow(new Error('Failed to configure S3Adapter. Arguments don\'t make sense'));

expect(() => {
new S3Adapter({ accessKey: 'accessKey' , secretKey: 'secretKey'});
}).toThrow("S3Adapter requires option 'bucket' or env. variable S3_BUCKET")
})

it('should not throw when initialized properly', () => {
Expand All @@ -48,12 +40,6 @@ describe('S3Adapter tests', () => {

describe('configured with immutable values', () => {
describe('not initialized properly', () => {
it('should fail with two string arguments', () => {
expect(() => {
new S3Adapter(config.get('accessKey'), config.get('secretKey'), {});
}).toThrow(new Error('Failed to configure S3Adapter. Arguments don\'t make sense'));
});

it('should fail when passed an object without a bucket', () => {
expect(() => {
new S3Adapter(config.get('insufficientOptions'));
Expand Down Expand Up @@ -105,41 +91,27 @@ describe('S3Adapter tests', () => {
expect(options.bucketPrefix).toEqual('test/');
});

it('should accept key, secret, and bucket as args', () => {
var args = ['key', 'secret', 'bucket'];
var options = optionsFromArguments(args);
expect(options.accessKey).toEqual('key');
expect(options.secretKey).toEqual('secret');
expect(options.bucket).toEqual('bucket');
});

it('should accept key, secret, bucket, and options object as args', () => {
it('should accept bucket, and options object as args', () => {
var confObj = { bucketPrefix: 'test/' };
var args = ['key', 'secret', 'bucket', confObj];
var args = ['bucket', confObj];
var options = optionsFromArguments(args);
expect(options.accessKey).toEqual('key');
expect(options.secretKey).toEqual('secret');
expect(options.bucket).toEqual('bucket');
expect(options.bucketPrefix).toEqual('test/');
});

it('should accept options and overrides as args', () => {
var confObj = { bucketPrefix: 'test/', bucket: 'bucket-1', secretKey: 'secret-1', accessKey: 'key-1' };
var overridesObj = { secretAccessKey: 'secret-2', accessKeyId: 'key-2', params: { Bucket: 'bucket-2' }};
var confObj = { bucketPrefix: 'test/', bucket: 'bucket-1' };
var overridesObj = { params: { Bucket: 'bucket-2' }};
var s3 = new S3Adapter(confObj, overridesObj);
expect(s3._s3Client.config.accessKeyId).toEqual('key-2');
expect(s3._s3Client.config.secretAccessKey).toEqual('secret-2');
expect(s3._s3Client.config.params.Bucket).toEqual('bucket-2');
expect(s3._bucketPrefix).toEqual('test/');
});

it('should accept overrides without params', () => {
var confObj = { bucketPrefix: 'test/', bucket: 'bucket-1', secretKey: 'secret-1', accessKey: 'key-1' };
var overridesObj = { secretAccessKey: 'secret-2'};
var confObj = { bucketPrefix: 'test/', bucket: 'bucket-1' };
var overridesObj = { signatureVersion: 'v2' };
var s3 = new S3Adapter(confObj, overridesObj);
expect(s3._s3Client.config.accessKeyId).toEqual('key-1');
expect(s3._s3Client.config.secretAccessKey).toEqual('secret-2');
expect(s3._s3Client.config.params.Bucket).toEqual('bucket-1');
expect(s3._s3Client.config.signatureVersion).toEqual('v2');
expect(s3._bucketPrefix).toEqual('test/');
});
});
Expand All @@ -160,35 +132,32 @@ describe('S3Adapter tests', () => {
});

it('should get using the baseUrl', () => {
var s3 = new S3Adapter('accessKey', 'secretKey', 'myBucket', options);
var s3 = new S3Adapter('myBucket', options);
expect(s3.getFileLocation(config, 'test.png')).toEqual('http://example.com/files/foo/bar/test.png');
});

it('should get direct to baseUrl', ()=> {
options.baseUrlDirect = true;
var s3 = new S3Adapter('accessKey', 'secretKey', 'myBucket', options);
var s3 = new S3Adapter('myBucket', options);
expect(s3.getFileLocation(config, 'test.png')).toEqual('http://example.com/files/test.png');
});

it('should get without directAccess', () => {
options.directAccess = false;
var s3 = new S3Adapter('accessKey', 'secretKey', 'myBucket', options);
var s3 = new S3Adapter('myBucket', options);
expect(s3.getFileLocation(config, 'test.png')).toEqual('http://my.server.com/parse/files/xxxx/test.png');
});

it('should go directly to amazon', () => {
delete options.baseUrl;
var s3 = new S3Adapter('accessKey', 'secretKey', 'myBucket', options);
var s3 = new S3Adapter('myBucket', options);
expect(s3.getFileLocation(config, 'test.png')).toEqual('https://myBucket.s3.amazonaws.com/foo/bar/test.png');
});
});


if (process.env.TEST_S3_ACCESS_KEY && process.env.TEST_S3_SECRET_KEY && process.env.TEST_S3_BUCKET) {
if (process.env.TEST_S3_BUCKET) {
// Should be initialized from the env
let s3 = new S3Adapter({
accessKey: process.env.TEST_S3_ACCESS_KEY,
secretKey: process.env.TEST_S3_SECRET_KEY,
bucket: process.env.TEST_S3_BUCKET
});
filesAdapterTests.testAdapter("S3Adapter", s3);
Expand Down