Skip to content

Commit

Permalink
Add Cloud Storage encryption samples and tests. (#165)
Browse files Browse the repository at this point in the history
* Add Cloud Storage encryption samples and tests.

* Address comments

* Fix typo.
  • Loading branch information
jmdobry authored Aug 11, 2016
1 parent a32f71c commit 09081e7
Show file tree
Hide file tree
Showing 9 changed files with 620 additions and 42 deletions.
3 changes: 2 additions & 1 deletion pubsub/system-test/subscriptions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ describe('pubsub:subscriptions', function () {
assert.ifError(err);
assert.equal(subscription.name, name);
assert(console.log.calledWith('Created subscription %s to topic %s', subscriptionName, topicName));
done();
// The next test sometimes fails, so, slow this test down
setTimeout(done, 2000);
});
});
});
Expand Down
72 changes: 59 additions & 13 deletions storage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,19 @@ View the [documentation][buckets_docs] or the [source code][buckets_code].
__Usage:__ `node buckets --help`

```
Usage: node buckets [COMMAND] [ARGS...]
Usage: node buckets COMMAND [ARGS...]
Commands:
create [BUCKET_NAME]
create BUCKET_NAME
list
delete [BUCKET_NAME]
delete BUCKET_NAME
Examples:
node buckets create my-bucket
node buckets list
node buckets delete my-bucket
```

[buckets_docs]: https://cloud.google.com/storage/docs
Expand All @@ -52,20 +58,60 @@ View the [documentation][files_docs] or the [source code][files_code].
__Usage:__ `node files --help`

```
Usage: node files [COMMAND] [ARGS...]
Usage: node files COMMAND [ARGS...]
Commands:
list [BUCKET_NAME]
listByPrefix [BUCKET_NAME] [PREFIX] [DELIMITER]
upload [BUCKET_NAME] [FILE_NAME]
download [BUCKET_NAME] [SRC_FILE_NAME] [DEST_FILE_NAME]
delete [BUCKET_NAME] [FILE_NAME]
getMetadata [BUCKET_NAME] [FILE_NAME]
makePublic [BUCKET_NAME] [FILE_NAME]
move [BUCKET_NAME] [SRC_FILE_NAME] [DEST_FILE_NAME]
copy [BUCKET_NAME] [SRC_FILE_NAME] [DEST_BUCKET_NAME] [DEST_FILE_NAME]
list BUCKET_NAME
listByPrefix BUCKET_NAME PREFIX [DELIMITER]
upload BUCKET_NAME FILE_NAME
download BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME
delete BUCKET_NAME FILE_NAME
getMetadata BUCKET_NAME FILE_NAME
makePublic BUCKET_NAME FILE_NAME
move BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME
copy BUCKET_NAME SRC_FILE_NAME DEST_BUCKET_NAME DEST_FILE_NAME
Examples:
list my-bucket
listByPrefix my-bucket /some-folder
listByPrefix my-bucket /some-folder -
upload my-bucket ./file.txt
download my-bucket file.txt ./file.txt
delete my-bucket file.txt
getMetadata my-bucket file.txt
makePublic my-bucket file.txt
move my-bucket file.txt file2.txt
copy my-bucket file.txt my-other-bucket file.txt
```

[files_docs]: https://cloud.google.com/storage/docs
[files_code]: files.js

### Encryption

View the [documentation][encryption_docs] or the [source code][encryption_code].

__Usage:__ `node encryption --help`

```
Usage: node encryption COMMAND [ARGS...]
Commands:
generate-encryption-key
upload BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME KEY
download BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME KEY
rotate BUCKET_NAME FILE_NAME OLD_KEY NEW_KEY
Examples:
node encryption generate-encryption-key
node encryption upload my-bucket resources/test.txt file_encrypted.txt QxhqaZEqBGVTW55HhQw9Q=
node encryption download my-bucket file_encrypted.txt ./file.txt QxhqaZEqBGVTW55HhQw9Q=
node encryption rotate my-bucket file_encrypted.txt QxhqaZEqBGVTW55HhQw9Q= SxafpsdfSDFS89sds9Q=
```

[encryption_docs]: https://cloud.google.com/storage/docs
[encryption_code]: encryption.js
12 changes: 8 additions & 4 deletions storage/buckets.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// https://googlecloudplatform.github.io/gcloud-node/#/docs/guides/authentication
var gcloud = require('gcloud');

// Get a reference to the storage component
// Instantiate a storage client
var storage = gcloud.storage();
// [END setup]

Expand Down Expand Up @@ -93,11 +93,15 @@ function deleteBucket (name, callback) {

// [START usage]
function printUsage () {
console.log('Usage: node buckets [COMMAND] [ARGS...]');
console.log('Usage: node buckets COMMAND [ARGS...]');
console.log('\nCommands:\n');
console.log('\tcreate [BUCKET_NAME]');
console.log('\tcreate BUCKET_NAME');
console.log('\tlist');
console.log('\tdelete [BUCKET_NAME]');
console.log('\tdelete BUCKET_NAME');
console.log('\nExamples:\n');
console.log('\tnode buckets create my-bucket');
console.log('\tnode buckets list');
console.log('\tnode buckets delete my-bucket');
}
// [END usage]

Expand Down
193 changes: 193 additions & 0 deletions storage/encryption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Copyright 2015-2016, Google, Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

// [START all]
// [START setup]
// By default, gcloud will authenticate using the service account file specified
// by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use the
// project specified by the GCLOUD_PROJECT environment variable. See
// https://googlecloudplatform.github.io/gcloud-node/#/docs/guides/authentication
var gcloud = require('gcloud');

// Instantiate a storage client
var storage = gcloud.storage();

var crypto = require('crypto');
// [END setup]

// [START generate_encryption_key]
/**
* Generates a 256 bit (32 byte) AES encryption key and prints the base64
* representation.
*
* This is included for demonstration purposes. You should generate your own
* key. Please remember that encryption keys should be handled with a
* comprehensive security policy.
*
* @returns {string} The encryption key.
*/
function generateEncryptionKey () {
var buffer = crypto.randomBytes(32);
var encodedKey = buffer.toString('base64');

console.log('Base 64 encoded encryption key: %s', encodedKey);

return encodedKey;
}
// [END generate_encryption_key]

// [START upload_encrypted_file]
/**
* Uploads a file to a Google Cloud Storage bucket using a custom encryption key.
*
* The file will be encrypted by Google Cloud Storage and only retrievable using
* the provided encryption key.
*
* @param {string} bucketName The bucket where the file will be uploaded.
* @param {string} srcFileName The local file to be uploaded.
* @param {string} destFileName The name of the destination file.
* @param {string} key The encryption key.
* @param {function} callback The callback function.
*/
function uploadEncryptedFile (bucketName, srcFileName, destFileName, key, callback) {
if (!bucketName) {
return callback(new Error('"bucketName" is required!'));
} else if (!srcFileName) {
return callback(new Error('"srcFileName" is required!'));
} else if (!destFileName) {
return callback(new Error('"destFileName" is required!'));
} else if (!key) {
return callback(new Error('"key" is required!'));
}

var bucket = storage.bucket(bucketName);
var options = {
destination: destFileName,
encryptionKey: new Buffer(key, 'base64')
};

bucket.upload(srcFileName, options, function (err, file) {
if (err) {
return callback(err);
}

console.log('Uploaded encrypted file: %s', destFileName);
return callback(null, file);
});
}
// [END upload_encrypted_file]

// [START download_encrypted_file]
/**
* Downloads a previously-encrypted file from Google Cloud Storage.
*
* The encryption key provided must be the same key provided when uploading the
* file.
*
* @param {string} bucketName The bucket from which the file will be downloaded.
* @param {string} srcFileName The name of the file to be downloaded.
* @param {string} destFileName The local path to which to save the file.
* @param {string} key The encryption key.
* @param {function} key The callback function.
*/
function downloadEncryptedFile (bucketName, srcFileName, destFileName, key, callback) {
if (!bucketName) {
return callback(new Error('"bucketName" is required!'));
} else if (!srcFileName) {
return callback(new Error('"srcFileName" is required!'));
} else if (!destFileName) {
return callback(new Error('"destFileName" is required!'));
} else if (!key) {
return callback(new Error('"key" is required!'));
}

var bucket = storage.bucket(bucketName);
var file = bucket.file(srcFileName);
var options = {
destination: destFileName
};

file.setEncryptionKey(new Buffer(key, 'base64'));

file.download(options, function (err) {
if (err) {
return callback(err);
}

console.log('Downloaded encrypted file: %s', destFileName);
return callback(null);
});
}
// [END download_encrypted_file]

// [START rotate_encryption_key]
/**
* Performs a key rotation by re-writing an encrypted blob with a new encryption
* key.
*
* @param {function} key The callback function.
*/
function rotateEncryptionKey (callback) {
callback(new Error('This is currently not available using the Cloud Client Library.'));
}
// [END rotate_encryption_key]

// [START usage]
function printUsage () {
console.log('Usage: node encryption COMMAND [ARGS...]');
console.log('\nCommands:\n');
console.log('\tgenerate-encryption-key');
console.log('\tupload BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME KEY');
console.log('\tdownload BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME KEY');
console.log('\trotate BUCKET_NAME FILE_NAME OLD_KEY NEW_KEY');
console.log('\nExamples:\n');
console.log('\tnode encryption generate-encryption-key');
console.log('\tnode encryption upload my-bucket resources/test.txt file_encrypted.txt QxhqaZEqBGVTW55HhQw9Q=');
console.log('\tnode encryption download my-bucket file_encrypted.txt ./file.txt QxhqaZEqBGVTW55HhQw9Q=');
console.log('\tnode encryption rotate my-bucket file_encrypted.txt QxhqaZEqBGVTW55HhQw9Q= SxafpsdfSDFS89sds9Q=');
}
// [END usage]

// The command-line program
var program = {
generateEncryptionKey: generateEncryptionKey,
uploadEncryptedFile: uploadEncryptedFile,
downloadEncryptedFile: downloadEncryptedFile,
rotateEncryptionKey: rotateEncryptionKey,
printUsage: printUsage,

// Executed when this program is run from the command-line
main: function (args, cb) {
var command = args.shift();
if (command === 'generate-encryption-key') {
this.generateEncryptionKey();
} else if (command === 'upload') {
this.uploadEncryptedFile(args[0], args[1], args[2], args[3], cb);
} else if (command === 'download') {
this.downloadEncryptedFile(args[0], args[1], args[2], args[3], cb);
} else if (command === 'rotate') {
this.rotateEncryptionKey(cb);
} else {
this.printUsage();
}
}
};

if (module === require.main) {
program.main(process.argv.slice(2), console.log);
}
// [END all]

module.exports = program;
33 changes: 22 additions & 11 deletions storage/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// https://googlecloudplatform.github.io/gcloud-node/#/docs/guides/authentication
var gcloud = require('gcloud');

// Get a reference to the storage component
// Instantiate a storage client
var storage = gcloud.storage();
// [END setup]

Expand Down Expand Up @@ -324,17 +324,28 @@ function copyFile (name, srcFileName, destBucketName, destFileName, callback) {

// [START usage]
function printUsage () {
console.log('Usage: node files [COMMAND] [ARGS...]');
console.log('Usage: node files COMMAND [ARGS...]');
console.log('\nCommands:\n');
console.log('\tlist [BUCKET_NAME]');
console.log('\tlistByPrefix [BUCKET_NAME] [PREFIX] [DELIMITER]');
console.log('\tupload [BUCKET_NAME] [FILE_NAME]');
console.log('\tdownload [BUCKET_NAME] [SRC_FILE_NAME] [DEST_FILE_NAME]');
console.log('\tdelete [BUCKET_NAME] [FILE_NAME]');
console.log('\tgetMetadata [BUCKET_NAME] [FILE_NAME]');
console.log('\tmakePublic [BUCKET_NAME] [FILE_NAME]');
console.log('\tmove [BUCKET_NAME] [SRC_FILE_NAME] [DEST_FILE_NAME]');
console.log('\tcopy [BUCKET_NAME] [SRC_FILE_NAME] [DEST_BUCKET_NAME] [DEST_FILE_NAME]');
console.log('\tlist BUCKET_NAME');
console.log('\tlistByPrefix BUCKET_NAME PREFIX [DELIMITER]');
console.log('\tupload BUCKET_NAME FILE_NAME');
console.log('\tdownload BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME');
console.log('\tdelete BUCKET_NAME FILE_NAME');
console.log('\tgetMetadata BUCKET_NAME FILE_NAME');
console.log('\tmakePublic BUCKET_NAME FILE_NAME');
console.log('\tmove BUCKET_NAME SRC_FILE_NAME DEST_FILE_NAME');
console.log('\tcopy BUCKET_NAME SRC_FILE_NAME DEST_BUCKET_NAME DEST_FILE_NAME');
console.log('\nExamples:\n');
console.log('\tlist my-bucket');
console.log('\tlistByPrefix my-bucket /some-folder');
console.log('\tlistByPrefix my-bucket /some-folder -');
console.log('\tupload my-bucket ./file.txt');
console.log('\tdownload my-bucket file.txt ./file.txt');
console.log('\tdelete my-bucket file.txt');
console.log('\tgetMetadata my-bucket file.txt');
console.log('\tmakePublic my-bucket file.txt');
console.log('\tmove my-bucket file.txt file2.txt');
console.log('\tcopy my-bucket file.txt my-other-bucket file.txt');
}
// [END usage]

Expand Down
Loading

0 comments on commit 09081e7

Please sign in to comment.