eip-cloud-services 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +2 -2
  3. package/src/s3.js +53 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.0.21] - 2023-06-21
6
+
7
+ ### Fixed
8
+ - Bug where ACL's were not copied across when moving S3 objects.
9
+
10
+ ## [1.0.2] - 2023-06-21
11
+
12
+ ### Added
13
+ - Initial release of the module.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eip-cloud-services",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Houses a collection of helpers for connecting with Cloud services.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -22,4 +22,4 @@
22
22
  "mysql": "^2.18.1",
23
23
  "redis": "^4.6.7"
24
24
  }
25
- }
25
+ }
package/src/s3.js CHANGED
@@ -41,6 +41,7 @@
41
41
  const { S3Client, HeadObjectCommand, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, CopyObjectCommand, DeleteObjectsCommand } = require ( '@aws-sdk/client-s3' );
42
42
  const config = require ( 'config' );
43
43
  const zlib = require ( 'zlib' );
44
+ const crypto = require ( 'crypto' );
44
45
 
45
46
  const S3 = new S3Client ( { region: 'eu-west-1' } );
46
47
 
@@ -92,6 +93,23 @@ exports.get = async ( key ) => {
92
93
  if ( response.ContentType !== 'application/json' ) {
93
94
  return data.toString ( 'utf8' );
94
95
  }
96
+
97
+ if ( response.ContentType === 'application/json' && response.Metadata[ 'tmg-crypt' ] && response.Metadata[ 'tmg-crypt-vec' ] ) {
98
+ const key = await crypto.subtle.importKey (
99
+ 'raw',
100
+ Buffer.from ( response.Metadata[ 'tmg-crypt' ], 'base64' ),
101
+ { name: 'AES-CBC', length: 256 },
102
+ false,
103
+ [ 'decrypt' ]
104
+ );
105
+ const iv = Buffer.from ( response.Metadata[ 'tmg-crypt-vec' ], 'base64' );
106
+ const decryptedArrayBuffer = await crypto.subtle.decrypt (
107
+ { name: 'AES-CBC', iv },
108
+ key,
109
+ Buffer.from ( data.toString (), 'base64' )
110
+ );
111
+ data = Buffer.from ( decryptedArrayBuffer ).toString ( 'utf8' );
112
+ }
95
113
 
96
114
  return JSON.parse ( data.toString ( 'utf8' ) );
97
115
  }
@@ -114,6 +132,8 @@ exports.get = async ( key ) => {
114
132
  * @param {string} [options.contentType='application/json'] - The content type of the object. Defaults to 'application/json'.
115
133
  * @param {string} [options.acl='public-read'] - The ACL (Access Control List) of the object. Defaults to 'public-read'.
116
134
  * @param {string} [options.cacheControl='max-age=25,s-maxage=30,must-revalidate'] - Sets cache control for the object.
135
+ * @param {boolean} [options.encrypt=false] - When storing JSON parsing this as true will encrypt the data with a random uuid stored in the metadata of the object.
136
+ * @param {object} [options.metadata={}] - Sets metadata for the object.
117
137
  * @returns {Promise} A promise that resolves when the object is successfully set in S3.
118
138
  * @description Sets an object in S3 with the provided key, body, and optional parameters.
119
139
  */
@@ -122,9 +142,34 @@ exports.set = async ( key, body, options = {} ) => {
122
142
  bucket = config.s3.Bucket,
123
143
  contentType = 'application/json',
124
144
  acl = 'public-read',
125
- cacheControl = 'max-age=25,s-maxage=30,must-revalidate'
145
+ cacheControl = 'max-age=25,s-maxage=30,must-revalidate',
146
+ encrypt = false,
147
+ metadata = {}
126
148
  } = options;
127
-
149
+
150
+ if ( encrypt && contentType === 'application/json' ) {
151
+ const encoder = new TextEncoder ();
152
+ const data = encoder.encode ( body );
153
+
154
+ const encryptionKey = await crypto.subtle.generateKey (
155
+ { name: 'AES-CBC', length: 256 },
156
+ true,
157
+ [ 'encrypt', 'decrypt' ]
158
+ );
159
+ const iv = crypto.randomBytes ( 16 );
160
+ const exportedKey = await crypto.subtle.exportKey ( 'raw', encryptionKey );
161
+ const exportedIV = iv.toString ( 'base64' );
162
+ metadata[ 'Tmg-Crypt' ] = Buffer.from ( exportedKey ).toString ( 'base64' );
163
+ metadata[ 'Tmg-Crypt-Vec' ] = exportedIV;
164
+
165
+ const encryptedData = await crypto.subtle.encrypt (
166
+ { name: 'AES-CBC', iv },
167
+ encryptionKey,
168
+ data
169
+ );
170
+ body = Buffer.from ( encryptedData ).toString ( 'base64' );
171
+ }
172
+
128
173
  try {
129
174
  const command = new PutObjectCommand ( {
130
175
  Bucket: bucket,
@@ -132,7 +177,8 @@ exports.set = async ( key, body, options = {} ) => {
132
177
  Body: body,
133
178
  ContentType: contentType,
134
179
  ACL: acl,
135
- CacheControl: cacheControl
180
+ CacheControl: cacheControl,
181
+ Metadata: metadata
136
182
  } );
137
183
 
138
184
  const data = await S3.send ( command );
@@ -140,6 +186,7 @@ exports.set = async ( key, body, options = {} ) => {
140
186
  return data;
141
187
  }
142
188
  catch ( error ) {
189
+ console.log ( error );
143
190
  throw error;
144
191
  }
145
192
  };
@@ -184,7 +231,9 @@ exports.move = async ( sourceKey, destinationKey, sourceBucket = config.s3.Bucke
184
231
  const copyCommand = new CopyObjectCommand ( {
185
232
  CopySource: `/${sourceBucket}/${sourceKey}`,
186
233
  Bucket: destinationBucket,
187
- Key: destinationKey
234
+ Key: destinationKey,
235
+ ACL: 'public-read',
236
+ MetadataDirective: 'COPY',
188
237
  } );
189
238
 
190
239
  await S3.send ( copyCommand );