Skip to content

Commit fd1aed3

Browse files
thiyaguk09iennae
andauthored
feat(storage): add samples and system tests for bucket encryption enforcement (GoogleCloudPlatform#4272)
* feat(storage): add samples and system tests for bucket encryption enforcement Adds comprehensive code samples and system tests to verify Google-managed, Customer-managed, and Customer-supplied encryption enforcement logic. - Add setBucketEncryptionEnforcementConfig.js sample - Add getBucketEncryptionEnforcementConfig.js sample - Add updateBucketEncryptionEnforcementConfig.js sample - Add system tests to verify CLI output and backend metadata state - Ensure server-side effectiveTime is correctly captured and displayed * code refactor * test(storage): refactor encryption tests to assert state over strings * test: skip bucket encryption enforcement tests if defaultKmsKeyName is missing --------- Co-authored-by: Jennifer Davis <sigje@google.com>
1 parent 7777583 commit fd1aed3

4 files changed

Lines changed: 386 additions & 0 deletions

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// sample-metadata:
18+
// title: Get Bucket Encryption Enforcement
19+
// description: Retrieves the current encryption enforcement configurations for a bucket.
20+
// usage: node getBucketEncryptionEnforcementConfig.js <BUCKET_NAME>
21+
22+
function main(bucketName = 'my-bucket') {
23+
// [START storage_get_encryption_enforcement_config]
24+
/**
25+
* TODO(developer): Uncomment the following lines before running the sample.
26+
*/
27+
// The ID of your GCS bucket
28+
// const bucketName = 'your-unique-bucket-name';
29+
30+
// Imports the Google Cloud client library
31+
const {Storage} = require('@google-cloud/storage');
32+
33+
// Creates a client
34+
const storage = new Storage();
35+
36+
async function getBucketEncryptionEnforcementConfig() {
37+
const [metadata] = await storage.bucket(bucketName).getMetadata();
38+
39+
console.log(
40+
`Encryption enforcement configuration for bucket ${bucketName}.`
41+
);
42+
const enc = metadata.encryption;
43+
if (!enc) {
44+
console.log(
45+
'No encryption configuration found (Default GMEK is active).'
46+
);
47+
return;
48+
}
49+
console.log(`Default KMS Key: ${enc.defaultKmsKeyName || 'None'}`);
50+
51+
const printConfig = (label, config) => {
52+
if (config) {
53+
console.log(`${label}:`);
54+
console.log(` Mode: ${config.restrictionMode}`);
55+
console.log(` Effective: ${config.effectiveTime}`);
56+
}
57+
};
58+
59+
printConfig(
60+
'Google Managed (GMEK) Enforcement',
61+
enc.googleManagedEncryptionEnforcementConfig
62+
);
63+
printConfig(
64+
'Customer Managed (CMEK) Enforcement',
65+
enc.customerManagedEncryptionEnforcementConfig
66+
);
67+
printConfig(
68+
'Customer Supplied (CSEK) Enforcement',
69+
enc.customerSuppliedEncryptionEnforcementConfig
70+
);
71+
}
72+
73+
getBucketEncryptionEnforcementConfig().catch(console.error);
74+
// [END storage_get_encryption_enforcement_config]
75+
}
76+
main(...process.argv.slice(2));
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// sample-metadata:
18+
// title: Set Bucket Encryption Enforcement
19+
// description: Configures a bucket to enforce specific encryption types (e.g., CMEK-only).
20+
// usage: node setBucketEncryptionEnforcementConfig.js <BUCKET_NAME> <KMS_KEY_NAME>
21+
22+
function main(
23+
bucketName = 'my-bucket',
24+
defaultKmsKeyName = process.env.GOOGLE_CLOUD_KMS_KEY_ASIA
25+
) {
26+
// [START storage_set_encryption_enforcement_config]
27+
/**
28+
* TODO(developer): Uncomment the following lines before running the sample.
29+
*/
30+
// The ID of your GCS bucket
31+
// const bucketName = 'your-unique-bucket-name';
32+
33+
// The name of the KMS key to be used as the default
34+
// const defaultKmsKeyName = 'my-key';
35+
36+
// Imports the Google Cloud client library
37+
const {Storage} = require('@google-cloud/storage');
38+
39+
// Creates a client
40+
const storage = new Storage();
41+
42+
async function setBucketEncryptionEnforcementConfig() {
43+
const options = {
44+
encryption: {
45+
defaultKmsKeyName,
46+
googleManagedEncryptionEnforcementConfig: {
47+
restrictionMode: 'FullyRestricted',
48+
},
49+
customerSuppliedEncryptionEnforcementConfig: {
50+
restrictionMode: 'FullyRestricted',
51+
},
52+
customerManagedEncryptionEnforcementConfig: {
53+
restrictionMode: 'NotRestricted',
54+
},
55+
},
56+
};
57+
58+
const [metadata] = await storage.bucket(bucketName).setMetadata(options);
59+
60+
console.log(
61+
`Encryption enforcement configuration updated for bucket ${bucketName}.`
62+
);
63+
const enc = metadata.encryption;
64+
if (enc) {
65+
console.log(`Default KMS Key: ${enc.defaultKmsKeyName}`);
66+
67+
const logEnforcement = (label, config) => {
68+
if (config) {
69+
console.log(`${label}:`);
70+
console.log(` Mode: ${config.restrictionMode}`);
71+
console.log(` Effective: ${config.effectiveTime}`);
72+
}
73+
};
74+
75+
logEnforcement(
76+
'Google Managed (GMEK) Enforcement',
77+
enc.googleManagedEncryptionEnforcementConfig
78+
);
79+
logEnforcement(
80+
'Customer Managed (CMEK) Enforcement',
81+
enc.customerManagedEncryptionEnforcementConfig
82+
);
83+
logEnforcement(
84+
'Customer Supplied (CSEK) Enforcement',
85+
enc.customerSuppliedEncryptionEnforcementConfig
86+
);
87+
}
88+
}
89+
90+
setBucketEncryptionEnforcementConfig().catch(console.error);
91+
// [END storage_set_encryption_enforcement_config]
92+
}
93+
main(...process.argv.slice(2));
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
const {Storage} = require('@google-cloud/storage');
18+
const {assert} = require('chai');
19+
const {before, after, afterEach, it} = require('mocha');
20+
const cp = require('child_process');
21+
const uuid = require('uuid');
22+
23+
const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
24+
25+
const storage = new Storage();
26+
const samplesTestBucketPrefix = `nodejs-storage-samples-${uuid.v4()}`;
27+
const bucketName = `${samplesTestBucketPrefix}-a`;
28+
const defaultKmsKeyName = process.env.GOOGLE_CLOUD_KMS_KEY_ASIA;
29+
const bucket = storage.bucket(bucketName);
30+
31+
before(async () => {
32+
await storage.createBucket(bucketName);
33+
});
34+
35+
async function deleteAllBucketsAsync() {
36+
const [buckets] = await storage.getBuckets({prefix: samplesTestBucketPrefix});
37+
38+
for (const bucket of buckets) {
39+
await bucket.deleteFiles({force: true});
40+
await bucket.delete({ignoreNotFound: true});
41+
}
42+
}
43+
44+
after(deleteAllBucketsAsync);
45+
afterEach(async () => {
46+
await new Promise(res => setTimeout(res, 1000));
47+
});
48+
49+
it('should set bucket encryption enforcement configuration', async function () {
50+
if (!defaultKmsKeyName) {
51+
this.skip();
52+
}
53+
const output = execSync(
54+
`node setBucketEncryptionEnforcementConfig.js ${bucketName} ${defaultKmsKeyName}`
55+
);
56+
57+
assert.include(
58+
output,
59+
`Encryption enforcement configuration updated for bucket ${bucketName}.`
60+
);
61+
62+
assert.include(output, `Default KMS Key: ${defaultKmsKeyName}`);
63+
64+
assert.include(output, 'Google Managed (GMEK) Enforcement:');
65+
assert.include(output, 'Mode: FullyRestricted');
66+
67+
assert.include(output, 'Customer Managed (CMEK) Enforcement:');
68+
assert.include(output, 'Mode: NotRestricted');
69+
70+
assert.include(output, 'Customer Supplied (CSEK) Enforcement:');
71+
assert.include(output, 'Mode: FullyRestricted');
72+
73+
assert.match(output, new RegExp('Effective:'));
74+
75+
const [metadata] = await bucket.getMetadata();
76+
const encryption = metadata.encryption || {};
77+
assert.strictEqual(
78+
encryption.googleManagedEncryptionEnforcementConfig?.restrictionMode,
79+
'FullyRestricted'
80+
);
81+
assert.strictEqual(
82+
encryption.customerManagedEncryptionEnforcementConfig?.restrictionMode,
83+
'NotRestricted'
84+
);
85+
assert.strictEqual(
86+
encryption.customerSuppliedEncryptionEnforcementConfig?.restrictionMode,
87+
'FullyRestricted'
88+
);
89+
});
90+
91+
it('should get bucket encryption enforcement configuration', async function () {
92+
if (!defaultKmsKeyName) {
93+
this.skip();
94+
}
95+
const output = execSync(
96+
`node getBucketEncryptionEnforcementConfig.js ${bucketName}`
97+
);
98+
99+
assert.include(
100+
output,
101+
`Encryption enforcement configuration for bucket ${bucketName}.`
102+
);
103+
assert.include(output, `Default KMS Key: ${defaultKmsKeyName}`);
104+
105+
assert.include(output, 'Google Managed (GMEK) Enforcement:');
106+
assert.include(output, 'Mode: FullyRestricted');
107+
assert.match(output, /Effective:/);
108+
109+
const [metadata] = await bucket.getMetadata();
110+
const encryption = metadata.encryption || {};
111+
112+
assert.strictEqual(encryption.defaultKmsKeyName, defaultKmsKeyName);
113+
assert.strictEqual(
114+
encryption.googleManagedEncryptionEnforcementConfig?.restrictionMode,
115+
'FullyRestricted'
116+
);
117+
assert.strictEqual(
118+
encryption.customerManagedEncryptionEnforcementConfig?.restrictionMode,
119+
'NotRestricted'
120+
);
121+
assert.strictEqual(
122+
encryption.customerSuppliedEncryptionEnforcementConfig?.restrictionMode,
123+
'FullyRestricted'
124+
);
125+
});
126+
127+
it('should update and then remove bucket encryption enforcement configuration', async () => {
128+
const output = execSync(
129+
`node updateBucketEncryptionEnforcementConfig.js ${bucketName}`
130+
);
131+
132+
assert.include(
133+
output,
134+
`Google-managed encryption enforcement set to FullyRestricted for ${bucketName}.`
135+
);
136+
assert.include(
137+
output,
138+
`All encryption enforcement configurations removed from bucket ${bucketName}.`
139+
);
140+
141+
const [metadata] = await bucket.getMetadata();
142+
assert.ok(!metadata.encryption);
143+
});
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// sample-metadata:
18+
// title: Update Bucket Encryption Enforcement Config
19+
// description: Updates and then removes encryption enforcement configurations from a bucket.
20+
// usage: node updateBucketEncryptionEnforcementConfig.js <BUCKET_NAME>
21+
22+
function main(bucketName = 'my-bucket') {
23+
// [START storage_update_bucket_encryption_enforcement_config]
24+
/**
25+
* TODO(developer): Uncomment the following lines before running the sample.
26+
*/
27+
// The ID of your GCS bucket
28+
// const bucketName = 'your-unique-bucket-name';
29+
30+
// Imports the Google Cloud client library
31+
const {Storage} = require('@google-cloud/storage');
32+
33+
// Creates a client
34+
const storage = new Storage();
35+
36+
async function updateBucketEncryptionEnforcementConfig() {
37+
const bucket = storage.bucket(bucketName);
38+
39+
// Update a specific encryption type's restriction mode
40+
// This partial update preserves other existing encryption settings.
41+
const updateOptions = {
42+
encryption: {
43+
googleManagedEncryptionEnforcementConfig: {
44+
restrictionMode: 'FullyRestricted',
45+
},
46+
},
47+
};
48+
49+
await bucket.setMetadata(updateOptions);
50+
console.log(
51+
`Google-managed encryption enforcement set to FullyRestricted for ${bucketName}.`
52+
);
53+
54+
// Remove all encryption enforcement configurations altogether
55+
// Setting these values to null removes the policies from the bucket metadata.
56+
const clearOptions = {
57+
encryption: {
58+
defaultKmsKeyName: null,
59+
googleManagedEncryptionEnforcementConfig: null,
60+
customerSuppliedEncryptionEnforcementConfig: null,
61+
customerManagedEncryptionEnforcementConfig: null,
62+
},
63+
};
64+
65+
await bucket.setMetadata(clearOptions);
66+
console.log(
67+
`All encryption enforcement configurations removed from bucket ${bucketName}.`
68+
);
69+
}
70+
71+
updateBucketEncryptionEnforcementConfig().catch(console.error);
72+
// [END storage_update_bucket_encryption_enforcement_config]
73+
}
74+
main(...process.argv.slice(2));

0 commit comments

Comments
 (0)