@@ -18,6 +18,13 @@ const { azureAccountNameRegex, base64Regex,
1818const { utapiVersion } = require ( 'utapi' ) ;
1919const { versioning } = require ( 'arsenal' ) ;
2020const constants = require ( '../constants' ) ;
21+ const {
22+ KmsType,
23+ KmsProtocol,
24+ isValidProvider,
25+ isValidType,
26+ isValidProtocol,
27+ } = require ( 'arsenal/build/lib/network/KMSInterface' ) ;
2128
2229const versionIdUtils = versioning . VersionID ;
2330
@@ -449,8 +456,9 @@ class Config extends EventEmitter {
449456
450457 // Read config automatically
451458 this . _getLocationConfig ( ) ;
452- this . _getConfig ( ) ;
459+ const config = this . _getConfig ( ) ;
453460 this . _configureBackends ( ) ;
461+ this . _sseMigration ( config ) ;
454462 }
455463
456464 _parseKmsAWS ( config ) {
@@ -459,13 +467,19 @@ class Config extends EventEmitter {
459467 }
460468 let kmsAWS = { } ;
461469
462- const { region, endpoint, ak, sk, tls } = config . kmsAWS ;
470+ const { providerName , region, endpoint, ak, sk, tls, noAwsArn } = config . kmsAWS ;
463471
472+ assert ( providerName , 'Configuration Error: providerName must be defined in kmsAWS' ) ;
473+ assert ( isValidProvider ( providerName ) ,
474+ 'Configuration Error: kmsAWS.providerNamer must be lowercase alphanumeric only' ) ;
464475 assert ( endpoint , 'Configuration Error: endpoint must be defined in kmsAWS' ) ;
465476 assert ( ak , 'Configuration Error: ak must be defined in kmsAWS' ) ;
466477 assert ( sk , 'Configuration Error: sk must be defined in kmsAWS' ) ;
478+ assert ( [ 'undefined' , 'boolean' ] . some ( type => type === typeof noAwsArn ) ,
479+ 'Configuration Error:: kmsAWS.noAwsArn must be a boolean or not set' ) ;
467480
468481 kmsAWS = {
482+ providerName,
469483 endpoint,
470484 ak,
471485 sk,
@@ -475,6 +489,10 @@ class Config extends EventEmitter {
475489 kmsAWS . region = region ;
476490 }
477491
492+ if ( noAwsArn ) {
493+ kmsAWS . noAwsArn = noAwsArn ;
494+ }
495+
478496 if ( tls ) {
479497 kmsAWS . tls = { } ;
480498 if ( tls . rejectUnauthorized !== undefined ) {
@@ -589,6 +607,10 @@ class Config extends EventEmitter {
589607 transport : this . _parseKmipTransport ( { } ) ,
590608 } ;
591609 if ( config . kmip ) {
610+ assert ( config . kmip . providerName , 'config.kmip.providerName must be defined' ) ;
611+ assert ( isValidProvider ( config . kmip . providerName ) ,
612+ 'config.kmip.providerName must be lowercase alphanumeric only' ) ;
613+ this . kmip . providerName = config . kmip . providerName ;
592614 if ( config . kmip . client ) {
593615 if ( config . kmip . client . compoundCreateActivate ) {
594616 assert ( typeof config . kmip . client . compoundCreateActivate ===
@@ -1145,8 +1167,12 @@ class Config extends EventEmitter {
11451167
11461168 this . kms = { } ;
11471169 if ( config . kms ) {
1170+ assert ( config . kms . providerName , 'config.kms.providerName must be provided' ) ;
1171+ assert ( isValidProvider ( config . kms . providerName ) ,
1172+ 'config.kms.providerName must be lowercase alphanumeric only' ) ;
11481173 assert ( typeof config . kms . userName === 'string' ) ;
11491174 assert ( typeof config . kms . password === 'string' ) ;
1175+ this . kms . providerName = config . kms . providerName ;
11501176 this . kms . userName = config . kms . userName ;
11511177 this . kms . password = config . kms . password ;
11521178 if ( config . kms . helperProgram !== undefined ) {
@@ -1176,6 +1202,11 @@ class Config extends EventEmitter {
11761202 assert ( typeof this . defaultEncryptionKeyPerAccount === 'boolean' ,
11771203 'config.defaultEncryptionKeyPerAccount must be a boolean' ) ;
11781204
1205+ this . kmsHideScalityArn = Object . hasOwnProperty . call ( config , 'kmsHideScalityArn' )
1206+ ? config . kmsHideScalityArn
1207+ : true ; // By default hide scality arn to keep backward compatibility and simplicity
1208+ assert . strictEqual ( typeof this . kmsHideScalityArn , 'boolean' ) ;
1209+
11791210 this . healthChecks = defaultHealthChecks ;
11801211 if ( config . healthChecks && config . healthChecks . allowFrom ) {
11811212 assert ( config . healthChecks . allowFrom instanceof Array ,
@@ -1380,6 +1411,7 @@ class Config extends EventEmitter {
13801411 'bad config: maxScannedLifecycleListingEntries must be greater than 2' ) ;
13811412 this . maxScannedLifecycleListingEntries = config . maxScannedLifecycleListingEntries ;
13821413 }
1414+ return config ;
13831415 }
13841416
13851417 _configureBackends ( ) {
@@ -1455,6 +1487,61 @@ class Config extends EventEmitter {
14551487 } ;
14561488 }
14571489
1490+ _sseMigration ( config ) {
1491+ if ( config . sseMigration ) {
1492+ /**
1493+ * For data that was encrypted internally by default and a new external provider is setup.
1494+ * This config helps detect the existing encryption key to decrypt with the good provider.
1495+ * The key format will be migrated automatically on GET/HEADs to include provider details.
1496+ */
1497+ this . sseMigration = { } ;
1498+ const { previousKeyType, previousKeyProtocol, previousKeyProvider } = config . sseMigration ;
1499+ if ( ! previousKeyType ) {
1500+ assert . fail (
1501+ 'NotImplemented: No dynamic KMS key migration. Set sseMigration.previousKeyType' ) ;
1502+ }
1503+
1504+ // If previousKeyType is provided it's used as static value to migrate the format of the key
1505+ // without additional dynamic evaluation if the key provider is unknown.
1506+ assert ( isValidType ( previousKeyType ) ,
1507+ 'ssenMigration.previousKeyType must be "internal" or "external"' ) ;
1508+ this . sseMigration . previousKeyType = previousKeyType ;
1509+
1510+ let expectedProtocol ;
1511+ if ( previousKeyType === KmsType . internal ) {
1512+ // For internal key type default protocol is file and provider is scality
1513+ this . sseMigration . previousKeyProtocol = previousKeyProtocol || KmsProtocol . file ;
1514+ this . sseMigration . previousKeyProvider = previousKeyProvider || 'scality' ;
1515+ expectedProtocol = [ KmsProtocol . scality , KmsProtocol . mem , KmsProtocol . file ] ;
1516+ } else if ( previousKeyType === KmsType . external ) {
1517+ // No defaults allowed for external provider
1518+ assert ( previousKeyProtocol ,
1519+ 'sseMigration.previousKeyProtocol must be defined for external provider' ) ;
1520+ this . sseMigration . previousKeyProtocol = previousKeyProtocol ;
1521+ assert ( previousKeyProvider ,
1522+ 'sseMigration.previousKeyProvider must be defined for external provider' ) ;
1523+ this . sseMigration . previousKeyProvider = previousKeyProvider ;
1524+ expectedProtocol = [ KmsProtocol . kmip , KmsProtocol . aws_kms ] ;
1525+ }
1526+
1527+ assert ( isValidProtocol ( previousKeyType , this . sseMigration . previousKeyProtocol ) ,
1528+ `sseMigration.previousKeyProtocol must be one of ${ expectedProtocol } ` ) ;
1529+ assert ( isValidProvider ( previousKeyProvider ) ,
1530+ 'sseMigration.previousKeyProvider must be lowercase alphanumeric only' ) ;
1531+
1532+ if ( this . sseMigration . previousKeyType === KmsType . external ) {
1533+ if ( [ KmsProtocol . file , KmsProtocol . mem ] . includes ( this . backends . kms ) ) {
1534+ assert . fail (
1535+ `sseMigration.previousKeyType "external" can't migrate to "internal" KMS provider ${
1536+ this . backends . kms } `
1537+ ) ;
1538+ }
1539+ // We'd have to compare protocol & providerName
1540+ assert . fail ( 'sseMigration.previousKeyType "external" is not yet available' ) ;
1541+ }
1542+ }
1543+ }
1544+
14581545 setAuthDataAccounts ( accounts ) {
14591546 this . authData . accounts = accounts ;
14601547 this . emit ( 'authdata-update' ) ;
0 commit comments