Skip to content

Commit 7e551c5

Browse files
CLDSRV-657: Functional tests for sse KMS Migration
Test is run in 3 steps: - seed before migration - run migration - run kms kms tests on fresh buckets and objects
1 parent 315cefc commit 7e551c5

12 files changed

Lines changed: 1979 additions & 0 deletions

File tree

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@
7777
"ft_test": "npm-run-all -s ft_awssdk ft_s3cmd ft_s3curl ft_node ft_healthchecks ft_management ft_backbeat",
7878
"ft_search": "cd tests/functional/aws-node-sdk && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 40000 test/mdSearch",
7979
"ft_kmip": "cd tests/functional/kmip && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 40000 *.js",
80+
"ft_sse_cleanup": "cd tests/functional/sse-kms-migration && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 10000 cleanup.js",
81+
"ft_sse_before_migration": "cd tests/functional/sse-kms-migration && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 10000 cleanup.js beforeMigration.js",
82+
"ft_sse_migration": "cd tests/functional/sse-kms-migration && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 10000 migration.js",
83+
"ft_sse_arn": "cd tests/functional/sse-kms-migration && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 10000 cleanup.js arnPrefix.js",
8084
"install_ft_deps": "yarn install aws-sdk@2.28.0 bluebird@3.3.1 mocha@2.3.4 mocha-junit-reporter@1.23.1 tv4@1.2.7",
8185
"lint": "eslint $(git ls-files '*.js')",
8286
"lint_md": "mdlint $(git ls-files '*.md')",

tests/functional/aws-node-sdk/lib/json/mem_credentials.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@
66
"lisa": {
77
"accessKey": "accessKey2",
88
"secretKey": "verySecretKey2"
9+
},
10+
"vault": {
11+
"accessKey": "TESTAK00000000000000",
12+
"secretKey": "TESTSK0000000000000000000000000000000000"
913
}
1014
}

tests/functional/sse-kms-migration/arnPrefix.js

Lines changed: 507 additions & 0 deletions
Large diffs are not rendered by default.

tests/functional/sse-kms-migration/beforeMigration.js

Lines changed: 430 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* eslint-disable */
2+
const helpers = require('./helpers');
3+
const scenarios = require('./scenarios');
4+
5+
// copy part of aws-node-sdk/test/object/encryptionHeaders.js and add more tests
6+
7+
async function cleanup(Bucket) {
8+
try {
9+
void await helpers.cleanup(Bucket);
10+
} catch (e) {
11+
console.log('Ignore error for', Bucket, e.toString());
12+
}
13+
}
14+
15+
describe('SSE KMS Cleanup', () => {
16+
/** Bucket to test CopyObject from and to */
17+
const copyBkt = 'enc-bkt-copy';
18+
const mpuCopyBkt = 'enc-bkt-mpu-copy';
19+
20+
it('Empty and delete buckets for SSE KMS Migration', async () => {
21+
console.log('Run cleanup',
22+
{ profile: helpers.credsProfile, accessKeyId: helpers.s3.config.credentials.accessKeyId });
23+
const allBuckets = (await helpers.s3.listBuckets().promise()).Buckets.map(b => b.Name);
24+
console.log('List buckets:', allBuckets);
25+
26+
void await helpers.MD.setup();
27+
28+
try {
29+
// pre cleanup
30+
void await cleanup(copyBkt);
31+
void await cleanup(mpuCopyBkt);
32+
void await Promise.all(scenarios.testCases.map(async bktConf => {
33+
void await cleanup(`enc-bkt-${bktConf.name}`);
34+
return await cleanup(`versioned-enc-bkt-${bktConf.name}`);
35+
}));
36+
} catch (e) { void e; }
37+
});
38+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
3+
"kmsAWS": {
4+
"noAwsArn": true,
5+
"providerName": "local",
6+
"region": "us-east-1",
7+
"endpoint": "http://0:8080",
8+
"ak": "456",
9+
"sk": "123"
10+
}
11+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
{
2+
"port": 8000,
3+
"listenOn": [],
4+
"metricsPort": 8002,
5+
"metricsListenOn": [],
6+
"replicationGroupId": "RG001",
7+
"restEndpoints": {
8+
"localhost": "us-east-1",
9+
"127.0.0.1": "us-east-1",
10+
"cloudserver-front": "us-east-1",
11+
"s3.docker.test": "us-east-1",
12+
"127.0.0.2": "us-east-1",
13+
"s3.amazonaws.com": "us-east-1"
14+
},
15+
"websiteEndpoints": ["s3-website-us-east-1.amazonaws.com",
16+
"s3-website.us-east-2.amazonaws.com",
17+
"s3-website-us-west-1.amazonaws.com",
18+
"s3-website-us-west-2.amazonaws.com",
19+
"s3-website.ap-south-1.amazonaws.com",
20+
"s3-website.ap-northeast-2.amazonaws.com",
21+
"s3-website-ap-southeast-1.amazonaws.com",
22+
"s3-website-ap-southeast-2.amazonaws.com",
23+
"s3-website-ap-northeast-1.amazonaws.com",
24+
"s3-website.eu-central-1.amazonaws.com",
25+
"s3-website-eu-west-1.amazonaws.com",
26+
"s3-website-sa-east-1.amazonaws.com",
27+
"s3-website.localhost",
28+
"s3-website.scality.test"],
29+
"replicationEndpoints": [{
30+
"site": "zenko",
31+
"servers": ["127.0.0.1:8000"],
32+
"default": true
33+
}, {
34+
"site": "us-east-2",
35+
"type": "aws_s3"
36+
}],
37+
"cdmi": {
38+
"host": "localhost",
39+
"port": 81,
40+
"path": "/dewpoint",
41+
"readonly": true
42+
},
43+
"bucketd": {
44+
"bootstrap": ["localhost:9000"]
45+
},
46+
"vaultd": {
47+
"host": "localhost",
48+
"port": 8500
49+
},
50+
"clusters": 10,
51+
"log": {
52+
"logLevel": "info",
53+
"dumpLevel": "error"
54+
},
55+
"healthChecks": {
56+
"allowFrom": ["127.0.0.1/8", "::1"]
57+
},
58+
"metadataClient": {
59+
"host": "localhost",
60+
"port": 9990
61+
},
62+
"dataClient": {
63+
"host": "localhost",
64+
"port": 9991
65+
},
66+
"metadataDaemon": {
67+
"bindAddress": "localhost",
68+
"port": 9990
69+
},
70+
"dataDaemon": {
71+
"bindAddress": "localhost",
72+
"port": 9991
73+
},
74+
"recordLog": {
75+
"enabled": false,
76+
"recordLogName": "s3-recordlog"
77+
},
78+
"requests": {
79+
"viaProxy": false,
80+
"trustedProxyCIDRs": [],
81+
"extractClientIPFromHeader": ""
82+
},
83+
"bucketNotificationDestinations": [
84+
{
85+
"resource": "target1",
86+
"type": "dummy",
87+
"host": "localhost:6000"
88+
}
89+
],
90+
"defaultEncryptionKeyPerAccount": true
91+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"kmip": {
3+
"providerName": "thales",
4+
"client": {
5+
"compoundCreateActivate": false
6+
},
7+
"transport": {
8+
"pipelineDepth": 8,
9+
"tls": {
10+
"port": 5696,
11+
"host": "pykmip.local",
12+
"key": "/tmp/ssl-kmip/kmip-client-key.pem",
13+
"cert": "/tmp/ssl-kmip/kmip-client-cert.pem",
14+
"ca": "/tmp/ssl-kmip/kmip-ca.pem"
15+
}
16+
}
17+
}
18+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"sseMigration": {
3+
"previousKeyType": "internal",
4+
"previousKeyProtocol": "file",
5+
"previousKeyProvider": "scality"
6+
}
7+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* eslint-disable no-unused-expressions */
2+
const getConfig = require('../aws-node-sdk/test/support/config');
3+
const { S3 } = require('aws-sdk');
4+
const kms = require('../../../lib/kms/wrapper');
5+
const { promisify } = require('util');
6+
const { DummyRequestLogger } = require('../../unit/helpers');
7+
const BucketUtility = require('../aws-node-sdk/lib/utility/bucket-util');
8+
const metadata = require('../../../lib/metadata/wrapper');
9+
const log = new DummyRequestLogger();
10+
const { config } = require('../../../lib/Config');
11+
const { getKeyIdFromArn } = require('arsenal/build/lib/network/KMSInterface');
12+
const { ArsenalError } = require('arsenal/build/lib/errors');
13+
14+
function getKey(key) {
15+
return config.kmsHideScalityArn ? getKeyIdFromArn(key) : key;
16+
}
17+
18+
// for Integration use default profile, in cloudserver use vault profile
19+
const credsProfile = process.env.S3_END_TO_END === 'true' ? 'default' : 'vault';
20+
const s3config = getConfig(credsProfile, { signatureVersion: 'v4' });
21+
const s3 = new S3(s3config);
22+
const bucketUtil = new BucketUtility(credsProfile);
23+
24+
function hydrateSSEConfig({ algo: SSEAlgorithm, masterKeyId: KMSMasterKeyID }) {
25+
// stringify and parse to strip undefined values
26+
return JSON.parse(JSON.stringify({ Rules: [{
27+
ApplyServerSideEncryptionByDefault: {
28+
SSEAlgorithm,
29+
KMSMasterKeyID,
30+
},
31+
}] }));
32+
}
33+
34+
function putObjParams(Bucket, Key, sseConfig, kmsKeyId) {
35+
return {
36+
Bucket,
37+
Key,
38+
...(sseConfig.algo && {
39+
ServerSideEncryption: sseConfig.algo,
40+
...(sseConfig.masterKeyId && {
41+
SSEKMSKeyId: kmsKeyId,
42+
}),
43+
}),
44+
};
45+
}
46+
47+
const MD = {
48+
setup: promisify(metadata.setup.bind(metadata)),
49+
getBucket: promisify(metadata.getBucket.bind(metadata)),
50+
getObject: promisify(metadata.getObjectMD.bind(metadata)),
51+
updateBucket: promisify(metadata.updateBucket.bind(metadata)),
52+
};
53+
54+
async function getBucketSSE(Bucket) {
55+
const sse = await s3.getBucketEncryption({ Bucket }).promise();
56+
return sse
57+
.ServerSideEncryptionConfiguration
58+
.Rules[0]
59+
.ApplyServerSideEncryptionByDefault;
60+
}
61+
62+
async function putEncryptedObject(Bucket, Key, sseConfig, kmsKeyId, Body) {
63+
return s3.putObject({
64+
...putObjParams(Bucket, Key, sseConfig, kmsKeyId),
65+
Body,
66+
}).promise();
67+
}
68+
69+
async function getObjectMDSSE(Bucket, Key) {
70+
const objMD = await MD.getObject(Bucket, Key, {}, log);
71+
72+
const sse = objMD['x-amz-server-side-encryption'];
73+
const key = objMD['x-amz-server-side-encryption-aws-kms-key-id'];
74+
75+
return {
76+
ServerSideEncryption: sse,
77+
SSEKMSKeyId: key,
78+
};
79+
}
80+
81+
async function createKmsKey(log) {
82+
return new Promise((resolve, reject) => {
83+
kms.client.createBucketKey('testFakeBucketName', log, (err, masterKeyId, masterKeyArn) => {
84+
if (err) {
85+
if (err instanceof ArsenalError) {
86+
// Help see error detail in logs
87+
// eslint-disable-next-line no-param-reassign
88+
err.message += ` ${err.description}`;
89+
}
90+
return reject(err);
91+
}
92+
return resolve({ masterKeyId, masterKeyArn });
93+
});
94+
});
95+
}
96+
97+
async function cleanup(Bucket) {
98+
await bucketUtil.empty(Bucket);
99+
await s3.deleteBucket({ Bucket }).promise();
100+
}
101+
102+
module.exports = {
103+
config,
104+
getKey,
105+
credsProfile,
106+
s3,
107+
bucketUtil,
108+
hydrateSSEConfig,
109+
putObjParams,
110+
MD,
111+
getBucketSSE,
112+
putEncryptedObject,
113+
getObjectMDSSE,
114+
createKmsKey,
115+
cleanup,
116+
};

0 commit comments

Comments
 (0)