-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathindex.js
146 lines (125 loc) · 4.99 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
console.log("Version 0.3.0");
// Load up all dependencies
var AWS = require('aws-sdk');
var async = require('async');
// get reference to S3 client
var s3 = new AWS.S3({ apiVersion: '2006-03-01' });
// This is the entry-point to the Lambda function.
exports.handler = function (event, context) {
if (event.Records == null) {
context.fail('Error', "Event has no records.");
return;
}
// Process all records in the event asynchronously.
async.each(event.Records, processRecord, function (err) {
if (err) {
context.fail('Error', "One or more objects could not be encrypted.");
} else {
context.succeed();
}
});
};
// processRecord
//
// Iterator function for async.each (called by the handler above).
//
// 1. Gets the head of the object to determine it's current encryption state.
// 2. Gets the encryption configuration from the bucket's tags.
// 3. Copies the object with the desired encryption.
function processRecord(record, callback) {
if (record.s3 == null) {
callback("Event record is missing s3 structure.");
return;
}
// The bucket and key are part of the event data
var bucket = record.s3.bucket.name;
var key = decodeURIComponent(record.s3.object.key.replace(/\+/g, " "));
console.log('Processing ' + bucket + '/' + key);
// Get the head data to determine if the object is already encrypted.
console.log('Getting object head');
s3.headObject({
Bucket: bucket,
Key: key
}, function (err, data) {
if (err) {
console.log('Error getting object head:');
console.log(err, err.stack); // an error occurred
callback("Error getting object head: " + bucket + '/' + key);
} else if (data.ServerSideEncryption != 'AES256') {
readConfig(bucket, function (err, config) {
if (err) {
console.log('Error reading configuration from tags:');
console.log(err, err.stack); // an error occurred
callback("Error reading configuration from tags: " + err);
} else {
var storageClass = 'STANDARD';
if (config.setReducedRedundancy)
storageClass = 'REDUCED_REDUNDANCY';
// Copy the object adding the encryption
console.log('Updating object');
s3.copyObject({
Bucket: bucket,
Key: key,
CopySource: encodeURIComponent(bucket + '/' + key),
MetadataDirective: 'COPY',
ServerSideEncryption: 'AES256',
StorageClass: storageClass
}, function (err, data) {
if (err) {
console.log('Error updating object:');
console.log(err, err.stack); // an error occurred
callback("Error updating object: " + err);
} else {
console.log(bucket + '/' + key + ' updated.');
callback();
}
});
}
});
} else {
console.log(bucket + '/' + key + " is already encrypted using 'AES256'.");
callback();
}
});
}
// readConfig
//
// Gets the tags for the named bucket, and
// from those tags, sets the configuration.
// Once found, it calls the callback function passing
// the configuration.
function readConfig(bucketName, callback) {
var defaultConfig = {
setReducedRedundancy: false
};
console.log("Getting tags for bucket '" + bucketName + "'");
s3.getBucketTagging({
Bucket: bucketName
}, function (err, data) {
if (err) {
if (err.code == 'NoSuchTagSet') {
// No tags on the bucket, so just send the defaults
callback(null, defaultConfig);
} else {
// Some other error
callback(err, null);
}
} else {
// Set defaults
var config = defaultConfig;
var tags = data.TagSet;
console.log("Processing tags...");
for (var i = 0; i < tags.length; ++i) {
var tag = tags[i];
console.log("Processing tag: " + tag.Key);
if (tag.Key == 'SetReducedRedundancy') {
console.log("Tag 'SetReducedRedundancy' found with value '" + tag.Value + "'");
if (tag.Value != null && tag.Value.toLowerCase() == 'yes') {
config.setReducedRedundancy = true;
}
}
}
callback(null, config);
}
});
}