* createCipherBundle * @param {object} serverSideEncryptionInfo - info for encryption * @param {number} serverSideEncryptionInfo.cryptoScheme - * cryptoScheme used * @param {string} serverSideEncryptionInfo.algorithm - * algorithm to use * @param {string} serverSi
(serverSideEncryptionInfo,
log, cb, opts)
| 330 | * @callback called with (err, cipherBundle) |
| 331 | */ |
| 332 | static createCipherBundle(serverSideEncryptionInfo, |
| 333 | log, cb, opts) { |
| 334 | const { algorithm, configuredMasterKeyId, masterKeyId: bucketMasterKeyId } = serverSideEncryptionInfo; |
| 335 | |
| 336 | let masterKeyId = bucketMasterKeyId; |
| 337 | if (configuredMasterKeyId) { |
| 338 | log.debug('using user configured kms master key id'); |
| 339 | masterKeyId = configuredMasterKeyId; |
| 340 | } |
| 341 | // shadowing global client for key |
| 342 | // but should not happen to cipher for another client as Puts should use current KMS |
| 343 | // still extract KeyId and validate arn |
| 344 | const { error, client, implName, clientIdentifier, key } = getClientForKey(masterKeyId, log); |
| 345 | if (error) { |
| 346 | return cb(error); |
| 347 | } |
| 348 | if (previousIdentifier |
| 349 | && clientIdentifier === previousIdentifier |
| 350 | && clientIdentifier !== currentIdentifier |
| 351 | && (opts && !opts.previousOk) |
| 352 | ) { |
| 353 | return cb(errors.InvalidArgument |
| 354 | .customizeDescription( |
| 355 | 'KMS cannot use previous provider to encrypt new objects if a new provider is configured')); |
| 356 | } |
| 357 | |
| 358 | const cipherBundle = { |
| 359 | algorithm, |
| 360 | masterKeyId, // keep arnPrefix in cipherBundle as it is returned to callback |
| 361 | cryptoScheme: 1, |
| 362 | cipheredDataKey: null, |
| 363 | cipher: null, |
| 364 | }; |
| 365 | |
| 366 | return async.waterfall([ |
| 367 | function generateDataKey(next) { |
| 368 | /* There are 2 ways of generating a datakey : |
| 369 | - using the generateDataKey of the KMS backend if it exists |
| 370 | (currently only implemented for the AWS KMS backend). This is |
| 371 | the preferred solution since a dedicated KMS should offer a better |
| 372 | entropy for generating random content. |
| 373 | - using local random number generation, and then use the KMS to |
| 374 | encrypt the datakey. This method is used when the KMS backend doesn't |
| 375 | provide the generateDataKey method. |
| 376 | */ |
| 377 | let res; |
| 378 | if (client.generateDataKey) { |
| 379 | log.debug('creating a data key using the KMS'); |
| 380 | res = client.generateDataKey(cipherBundle.cryptoScheme, |
| 381 | key, |
| 382 | log, (err, plainTextDataKey, cipheredDataKey) => { |
| 383 | if (err) { |
| 384 | log.debug('error generating a new data key from KMS', |
| 385 | { implName, error: err }); |
| 386 | return next(err); |
| 387 | } |
| 388 | log.trace('data key generated by the kms'); |
| 389 | return next(null, plainTextDataKey, cipheredDataKey); |
no test coverage detected