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

Add Server Side Encryption #67

Merged
merged 5 commits into from
Oct 9, 2016
Merged
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
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ The client specified MUST implement functions called `getObject` and `putObject`

*Default:* the default S3 library is `aws-sdk`

### serverSideEncryption

The Server-side encryption algorithm used when storing this object in S3 (e.g., AES256, aws:kms). Possible values include:
- "AES256"
- "aws:kms"

### How do I activate a revision?

A user can activate a revision by either:
Expand Down Expand Up @@ -239,7 +245,7 @@ You can deploy your Ember application to S3 and still use the history-api for pr
### With Cloudfront
A Cloudfront Custom Error Response can handle catching the 404 error that occurs when a request is made to a pretty URL and can allow that request to be handled by index.html and in turn Ember.

A Custom Error Response can be created for your CloudFront distrubution in the AWS console by navigating to:
A Custom Error Response can be created for your CloudFront distrubution in the AWS console by navigating to:

Cloudfront > `Distribution ID` > Error Pages > Create Custom Error Response.

Expand Down
40 changes: 25 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,17 @@ module.exports = {
requiredConfig: ['bucket', 'region'],

upload: function(/* context */) {
var bucket = this.readConfig('bucket');
var prefix = this.readConfig('prefix');
var acl = this.readConfig('acl');
var cacheControl = this.readConfig('cacheControl');
var revisionKey = this.readConfig('revisionKey');
var distDir = this.readConfig('distDir');
var filePattern = this.readConfig('filePattern');
var gzippedFiles = this.readConfig('gzippedFiles');
var allowOverwrite = this.readConfig('allowOverwrite');
var filePath = joinUriSegments(distDir, filePattern);
var bucket = this.readConfig('bucket');
var prefix = this.readConfig('prefix');
var acl = this.readConfig('acl');
var cacheControl = this.readConfig('cacheControl');
var revisionKey = this.readConfig('revisionKey');
var distDir = this.readConfig('distDir');
var filePattern = this.readConfig('filePattern');
var gzippedFiles = this.readConfig('gzippedFiles');
var allowOverwrite = this.readConfig('allowOverwrite');
var serverSideEncryption = this.readConfig('serverSideEncryption');
var filePath = joinUriSegments(distDir, filePattern);

var options = {
bucket: bucket,
Expand All @@ -59,18 +60,23 @@ module.exports = {
allowOverwrite: allowOverwrite
};

if (serverSideEncryption) {
options.serverSideEncryption = serverSideEncryption;
}

this.log('preparing to upload revision to S3 bucket `' + bucket + '`', { verbose: true });

var s3 = new this.S3({ plugin: this });
return s3.upload(options);
},

activate: function(/* context */) {
var bucket = this.readConfig('bucket');
var prefix = this.readConfig('prefix');
var acl = this.readConfig('acl');
var revisionKey = this.readConfig('revisionKey');
var filePattern = this.readConfig('filePattern');
var bucket = this.readConfig('bucket');
var prefix = this.readConfig('prefix');
var acl = this.readConfig('acl');
var revisionKey = this.readConfig('revisionKey');
var filePattern = this.readConfig('filePattern');
var serverSideEncryption = this.readConfig('serverSideEncryption');

var options = {
bucket: bucket,
Expand All @@ -80,6 +86,10 @@ module.exports = {
revisionKey: revisionKey,
};

if (serverSideEncryption) {
options.serverSideEncryption = serverSideEncryption;
}

this.log('preparing to activate `' + revisionKey + '`', { verbose: true });

var s3 = new this.S3({ plugin: this });
Expand Down
56 changes: 33 additions & 23 deletions lib/s3.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,18 @@ module.exports = CoreObject.extend({
},

upload: function(options) {
var client = this._client;
var plugin = this._plugin;
var bucket = options.bucket;
var acl = options.acl;
var cacheControl = options.cacheControl;
var allowOverwrite = options.allowOverwrite;
var key = options.filePattern + ":" + options.revisionKey;
var revisionKey = joinUriSegments(options.prefix, key);
var putObject = Promise.denodeify(client.putObject.bind(client));
var gzippedFilePaths = options.gzippedFilePaths || [];
var isGzipped = gzippedFilePaths.indexOf(options.filePattern) !== -1;
var client = this._client;
var plugin = this._plugin;
var bucket = options.bucket;
var acl = options.acl;
var cacheControl = options.cacheControl;
var allowOverwrite = options.allowOverwrite;
var key = options.filePattern + ":" + options.revisionKey;
var revisionKey = joinUriSegments(options.prefix, key);
var putObject = Promise.denodeify(client.putObject.bind(client));
var gzippedFilePaths = options.gzippedFilePaths || [];
var isGzipped = gzippedFilePaths.indexOf(options.filePattern) !== -1;
var serverSideEncryption = options.serverSideEncryption;

var params = {
Bucket: bucket,
Expand All @@ -55,6 +56,10 @@ module.exports = CoreObject.extend({
CacheControl: cacheControl
};

if (serverSideEncryption) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we please add a test for this conditional

params.ServerSideEncryption = serverSideEncryption;
}

if (isGzipped) {
params.ContentEncoding = 'gzip';
}
Expand All @@ -77,18 +82,19 @@ module.exports = CoreObject.extend({
},

activate: function(options) {
var plugin = this._plugin;
var client = this._client;
var bucket = options.bucket;
var acl = options.acl;
var prefix = options.prefix;
var filePattern = options.filePattern;
var key = filePattern + ":" + options.revisionKey;

var revisionKey = joinUriSegments(prefix, key);
var indexKey = joinUriSegments(prefix, filePattern);
var copySource = encodeURIComponent([bucket, revisionKey].join('/'));
var copyObject = Promise.denodeify(client.copyObject.bind(client));
var plugin = this._plugin;
var client = this._client;
var bucket = options.bucket;
var acl = options.acl;
var prefix = options.prefix;
var filePattern = options.filePattern;
var key = filePattern + ":" + options.revisionKey;
var serverSideEncryption = options.serverSideEncryption;

var revisionKey = joinUriSegments(prefix, key);
var indexKey = joinUriSegments(prefix, filePattern);
var copySource = encodeURIComponent([bucket, revisionKey].join('/'));
var copyObject = Promise.denodeify(client.copyObject.bind(client));

var params = {
Bucket: bucket,
Expand All @@ -97,6 +103,10 @@ module.exports = CoreObject.extend({
ACL: acl,
};

if (serverSideEncryption) {
params.ServerSideEncryption = serverSideEncryption;
}

return this.fetchRevisions(options).then(function(revisions) {
var found = revisions.map(function(element) { return element.revision; }).indexOf(options.revisionKey);
if (found >= 0) {
Expand Down
38 changes: 38 additions & 0 deletions tests/unit/index-nodetest.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ describe('s3-index plugin', function() {
});
});

it('detects serverSideEncryption when defined', function() {
context.config['s3-index'].serverSideEncryption = 'AES256';
var promise = plugin.upload(context);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(s3Options.serverSideEncryption, 'AES256', 'serverSideEncryption passed correctly');
});
});

it('filters serverSideEncryption when not defined', function() {
var promise = plugin.upload(context);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(s3Options.hasOwnProperty('serverSideEncryption'), false, 'serverSideEncryption filtered correctly');
});
});

it('passes cacheControl options based on the cacheControl option to the s3-abstraction', function() {
var cacheControl = 'max-age=3600';
context.config['s3-index'].cacheControl = cacheControl;
Expand Down Expand Up @@ -192,6 +211,25 @@ describe('s3-index plugin', function() {
assert.deepEqual(s3Options, expected);
});
});

it('detects serverSideEncryption when defined', function() {
context.config['s3-index'].serverSideEncryption = 'AES256';
var promise = plugin.activate(context);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(s3Options.serverSideEncryption, 'AES256', 'serverSideEncryption passed correctly');
});
});

it('filters serverSideEncryption when not defined', function() {
var promise = plugin.activate(context);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(s3Options.hasOwnProperty('serverSideEncryption'), false, 'serverSideEncryption filtered correctly');
});
});
});

describe('#fetchInitialRevisions', function() {
Expand Down
38 changes: 38 additions & 0 deletions tests/unit/lib/s3-nodetest.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ describe('s3', function() {
});
});

it('detects serverSideEncryption when defined', function() {
options.serverSideEncryption = 'AES256';
var promise = subject.upload(options);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(s3Params.ServerSideEncryption, 'AES256', 'serverSideEncryption passed correctly');
});
});

it('filters serverSideEncryption when not defined', function() {
var promise = subject.upload(options);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(s3Params.hasOwnProperty('serverSideEncryption'), false, 'serverSideEncryption filtered correctly');
});
});

it('detects `filePattern` other than `index.html` in order to customize ContentType', function() {
var filePath = 'tests/unit/fixtures/test.tar';

Expand Down Expand Up @@ -346,6 +365,25 @@ describe('s3', function() {
assert.equal(copyParams.ACL, acl);
});
});

it('detects serverSideEncryption when defined', function() {
options.serverSideEncryption = 'AES256';
var promise = subject.activate(options);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(copyParams.ServerSideEncryption, 'AES256', 'serverSideEncryption passed correctly');
});
});

it('filters serverSideEncryption when not defined', function() {
var promise = subject.activate(options);

return assert.isFulfilled(promise)
.then(function() {
assert.equal(copyParams.hasOwnProperty('serverSideEncryption'), false, 'serverSideEncryption filtered correctly');
});
});
});

describe('with an invalid revision key', function() {
Expand Down