From 11ace0ffb025adc802bfd2b716a405bb5c0f7a23 Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Thu, 26 Feb 2026 14:09:21 +0000 Subject: [PATCH 1/5] Feat(storage): add bucket encryption enforcement Adds metadata support for the following encryption enforcement fields: - googleManagedEncryptionEnforcementConfig - customerManagedEncryptionEnforcementConfig - customerSuppliedEncryptionEnforcementConfig --- ...t_bucket_encryption_enforcement_config.php | 66 +++++++++++++++++++ ...l_bucket_encryption_enforcement_config.php | 58 ++++++++++++++++ ...t_bucket_encryption_enforcement_config.php | 64 ++++++++++++++++++ storage/test/storageTest.php | 59 +++++++++++++++++ 4 files changed, 247 insertions(+) create mode 100644 storage/src/get_bucket_encryption_enforcement_config.php create mode 100644 storage/src/remove_all_bucket_encryption_enforcement_config.php create mode 100644 storage/src/set_bucket_encryption_enforcement_config.php diff --git a/storage/src/get_bucket_encryption_enforcement_config.php b/storage/src/get_bucket_encryption_enforcement_config.php new file mode 100644 index 000000000..b6cbd2a1f --- /dev/null +++ b/storage/src/get_bucket_encryption_enforcement_config.php @@ -0,0 +1,66 @@ +bucket($bucketName); + $metadata = $bucket->info(); + + printf('Encryption enforcement configuration for bucket %s.' . PHP_EOL, $bucketName); + + if (!isset($metadata['encryption'])) { + print('No encryption configuration found (Default GMEK is active).' . PHP_EOL); + return; + } + + $enc = $metadata['encryption']; + printf('Default KMS Key: %s' . PHP_EOL, $enc['defaultKmsKeyName'] ?? 'None'); + + $printConfig = function ($label, $config) { + if ($config) { + printf('%s:' . PHP_EOL, $label); + printf(' Mode: %s' . PHP_EOL, $config['restrictionMode']); + printf(' Effective: %s' . PHP_EOL, $config['effectiveTime'] ?? 'N/A'); + } + }; + + $printConfig('Google Managed (GMEK) Enforcement', $enc['googleManagedEncryptionEnforcementConfig'] ?? null); + $printConfig('Customer Managed (CMEK) Enforcement', $enc['customerManagedEncryptionEnforcementConfig'] ?? null); + $printConfig('Customer Supplied (CSEK) Enforcement', $enc['customerSuppliedEncryptionEnforcementConfig'] ?? null); +} +# [END storage_get_encryption_enforcement_config] + +// The following 2 lines are only needed to run the samples +require_once __DIR__ . '/../../testing/sample_helpers.php'; +\Google\Cloud\Samples\execute_sample(__FILE__, __NAMESPACE__, $argv); diff --git a/storage/src/remove_all_bucket_encryption_enforcement_config.php b/storage/src/remove_all_bucket_encryption_enforcement_config.php new file mode 100644 index 000000000..a9720216a --- /dev/null +++ b/storage/src/remove_all_bucket_encryption_enforcement_config.php @@ -0,0 +1,58 @@ +bucket($bucketName); + + // Setting these values to null in an update call will remove the + // specific enforcement policies from the bucket metadata. + $options = [ + 'encryption' => [ + 'defaultKmsKeyName' => null, + 'googleManagedEncryptionEnforcementConfig' => null, + 'customerSuppliedEncryptionEnforcementConfig' => null, + 'customerManagedEncryptionEnforcementConfig' => null, + ], + ]; + + $bucket->update($options); + + printf('Encryption enforcement configuration removed from bucket %s.' . PHP_EOL, $bucketName); +} +# [END storage_remove_all_encryption_enforcement_config] + +// The following 2 lines are only needed to run the samples +require_once __DIR__ . '/../../testing/sample_helpers.php'; +\Google\Cloud\Samples\execute_sample(__FILE__, __NAMESPACE__, $argv); diff --git a/storage/src/set_bucket_encryption_enforcement_config.php b/storage/src/set_bucket_encryption_enforcement_config.php new file mode 100644 index 000000000..7f9660458 --- /dev/null +++ b/storage/src/set_bucket_encryption_enforcement_config.php @@ -0,0 +1,64 @@ +bucket($bucketName); + + // This configuration enforces that all objects uploaded to the bucket + // must use Customer Managed Encryption Keys (CMEK). + $options = [ + 'encryption' => [ + 'defaultKmsKeyName' => $kmsKeyName, + 'googleManagedEncryptionEnforcementConfig' => [ + 'restrictionMode' => 'FullyRestricted', + ], + 'customerSuppliedEncryptionEnforcementConfig' => [ + 'restrictionMode' => 'FullyRestricted', + ], + 'customerManagedEncryptionEnforcementConfig' => [ + 'restrictionMode' => 'NotRestricted', + ], + ], + ]; + $bucket->update($options); + + printf('Encryption enforcement configuration updated for bucket %s.' . PHP_EOL, $bucketName); +} +# [END storage_set_encryption_enforcement_config] + +// The following 2 lines are only needed to run the samples +require_once __DIR__ . '/../../testing/sample_helpers.php'; +\Google\Cloud\Samples\execute_sample(__FILE__, __NAMESPACE__, $argv); diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index c71e30e9c..851fa4f07 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -573,6 +573,65 @@ public function testObjectGetKmsKey(string $objectName) ); } + /** @depends testEnableDefaultKmsKey */ + public function testSetBucketEncryptionEnforcementConfig() + { + $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; + + $output = $this->runFunctionSnippet('set_bucket_encryption_enforcement_config', [ + $kmsEncryptedBucketName, + $this->keyName(), + ]); + + $this->assertEquals($output, sprintf( + 'Encryption enforcement configuration updated for bucket %s.' . PHP_EOL, + $kmsEncryptedBucketName + )); + } + + /** @depends testSetBucketEncryptionEnforcementConfig */ + public function testGetBucketEncryptionEnforcementConfig() + { + $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; + sleep(2); + + $output = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ + $kmsEncryptedBucketName + ]); + + $this->assertStringContainsString( + sprintf('Encryption enforcement configuration for bucket %s.', $kmsEncryptedBucketName), + $output + ); + $this->assertStringContainsString(sprintf('Default KMS Key: %s', $this->keyName()), $output); + $this->assertStringContainsString('Google Managed (GMEK) Enforcement:', $output); + $this->assertStringContainsString('Mode: FullyRestricted', $output); + $this->assertStringContainsString('Customer Managed (CMEK) Enforcement:', $output); + $this->assertStringContainsString('Mode: NotRestricted', $output); + } + + /** @depends testGetBucketEncryptionEnforcementConfig */ + public function testRemoveAllBucketEncryptionEnforcementConfig() + { + $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; + + $output = $this->runFunctionSnippet('remove_all_bucket_encryption_enforcement_config', [ + $kmsEncryptedBucketName + ]); + + $this->assertEquals($output, sprintf( + 'Encryption enforcement configuration removed from bucket %s.' . PHP_EOL, + $kmsEncryptedBucketName + )); + + // Final verification: Ensure 'Get' now shows no configuration + sleep(1); + $finalOutput = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ + $kmsEncryptedBucketName + ]); + $this->assertStringContainsString('No encryption configuration found (Default GMEK is active).', $finalOutput); + } + public function testBucketVersioning() { $output = self::runFunctionSnippet('enable_versioning', [ From b9f53cdea09ff2a1af267dd3379b8dae1f437592 Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Thu, 26 Feb 2026 14:18:20 +0000 Subject: [PATCH 2/5] Lint fix --- storage/src/get_bucket_encryption_enforcement_config.php | 2 +- .../src/remove_all_bucket_encryption_enforcement_config.php | 4 ++-- storage/src/set_bucket_encryption_enforcement_config.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/src/get_bucket_encryption_enforcement_config.php b/storage/src/get_bucket_encryption_enforcement_config.php index b6cbd2a1f..460b8fe44 100644 --- a/storage/src/get_bucket_encryption_enforcement_config.php +++ b/storage/src/get_bucket_encryption_enforcement_config.php @@ -28,7 +28,7 @@ /** * Retrieves the current encryption enforcement configurations for a bucket. - * + * * @param string $bucketName The ID of your GCS bucket (e.g. "my-bucket"). */ function get_bucket_encryption_enforcement_config(string $bucketName): void diff --git a/storage/src/remove_all_bucket_encryption_enforcement_config.php b/storage/src/remove_all_bucket_encryption_enforcement_config.php index a9720216a..304ab15b9 100644 --- a/storage/src/remove_all_bucket_encryption_enforcement_config.php +++ b/storage/src/remove_all_bucket_encryption_enforcement_config.php @@ -28,7 +28,7 @@ /** * Removes all encryption enforcement configurations from a bucket. - * + * * @param string $bucketName The ID of your GCS bucket (e.g. "my-bucket"). */ function remove_all_bucket_encryption_enforcement_config(string $bucketName): void @@ -36,7 +36,7 @@ function remove_all_bucket_encryption_enforcement_config(string $bucketName): vo $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); - // Setting these values to null in an update call will remove the + // Setting these values to null in an update call will remove the // specific enforcement policies from the bucket metadata. $options = [ 'encryption' => [ diff --git a/storage/src/set_bucket_encryption_enforcement_config.php b/storage/src/set_bucket_encryption_enforcement_config.php index 7f9660458..0f047510f 100644 --- a/storage/src/set_bucket_encryption_enforcement_config.php +++ b/storage/src/set_bucket_encryption_enforcement_config.php @@ -28,7 +28,7 @@ /** * Configures a bucket to enforce specific encryption types (e.g., CMEK-only). - * + * * @param string $bucketName The ID of your GCS bucket (e.g. "my-bucket"). * @param string $kmsKeyName The name of the KMS key to be used as the default (e.g. "projects/my-project/..."). */ @@ -37,7 +37,7 @@ function set_bucket_encryption_enforcement_config(string $bucketName, string $km $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); - // This configuration enforces that all objects uploaded to the bucket + // This configuration enforces that all objects uploaded to the bucket // must use Customer Managed Encryption Keys (CMEK). $options = [ 'encryption' => [ From f4402643f1ea3bdb86ec0ffac62e51a241e6ffea Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Fri, 27 Feb 2026 07:33:23 +0000 Subject: [PATCH 3/5] Code refactor --- storage/test/storageTest.php | 46 ++++++++++++++---------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index 851fa4f07..7ad5ad6a2 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -32,6 +32,7 @@ class storageTest extends TestCase use TestTrait; private static $bucketName; + private static $kmsEncryptedBucketName; private static $storage; private static $tempBucket; private static $objectRetentionBucketName; @@ -40,6 +41,7 @@ public static function setUpBeforeClass(): void { self::checkProjectEnvVars(); self::$bucketName = self::requireEnv('GOOGLE_STORAGE_BUCKET'); + self::$kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; self::$storage = new StorageClient(); self::$tempBucket = self::$storage->createBucket( sprintf('%s-test-bucket-%s', self::$projectId, time()) @@ -511,16 +513,14 @@ public function testDownloadEncryptedFileFails() public function testEnableDefaultKmsKey() { - $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; - $output = $this->runFunctionSnippet('enable_default_kms_key', [ - $kmsEncryptedBucketName, + self::$kmsEncryptedBucketName, $this->keyName(), ]); $this->assertEquals($output, sprintf( 'Default KMS key for %s was set to %s' . PHP_EOL, - $kmsEncryptedBucketName, + self::$kmsEncryptedBucketName, $this->keyName() )); } @@ -528,14 +528,12 @@ public function testEnableDefaultKmsKey() /** @depends testEnableDefaultKmsKey */ public function testUploadWithKmsKey() { - $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; - $objectName = 'test-object-' . time(); $uploadFrom = tempnam(sys_get_temp_dir(), '/tests'); file_put_contents($uploadFrom, 'foo' . rand()); $output = $this->runFunctionSnippet('upload_with_kms_key', [ - $kmsEncryptedBucketName, + self::$kmsEncryptedBucketName, $objectName, $uploadFrom, $this->keyName(), @@ -544,7 +542,7 @@ public function testUploadWithKmsKey() $this->assertEquals($output, sprintf( 'Uploaded %s to gs://%s/%s using encryption key %s' . PHP_EOL, basename($uploadFrom), - $kmsEncryptedBucketName, + self::$kmsEncryptedBucketName, $objectName, $this->keyName() )); @@ -555,12 +553,11 @@ public function testUploadWithKmsKey() /** @depends testUploadWithKmsKey */ public function testObjectGetKmsKey(string $objectName) { - $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; - $bucket = self::$storage->bucket($kmsEncryptedBucketName); + $bucket = self::$storage->bucket(self::$kmsEncryptedBucketName); $objectInfo = $bucket->object($objectName)->info(); $output = $this->runFunctionSnippet('object_get_kms_key', [ - $kmsEncryptedBucketName, + self::$kmsEncryptedBucketName, $objectName, ]); @@ -576,58 +573,51 @@ public function testObjectGetKmsKey(string $objectName) /** @depends testEnableDefaultKmsKey */ public function testSetBucketEncryptionEnforcementConfig() { - $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; - $output = $this->runFunctionSnippet('set_bucket_encryption_enforcement_config', [ - $kmsEncryptedBucketName, + self::$kmsEncryptedBucketName, $this->keyName(), ]); $this->assertEquals($output, sprintf( 'Encryption enforcement configuration updated for bucket %s.' . PHP_EOL, - $kmsEncryptedBucketName + self::$kmsEncryptedBucketName )); } /** @depends testSetBucketEncryptionEnforcementConfig */ public function testGetBucketEncryptionEnforcementConfig() { - $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; sleep(2); - $output = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ - $kmsEncryptedBucketName + self::$kmsEncryptedBucketName ]); $this->assertStringContainsString( - sprintf('Encryption enforcement configuration for bucket %s.', $kmsEncryptedBucketName), + sprintf('Encryption enforcement configuration for bucket %s.', self::$kmsEncryptedBucketName), $output ); $this->assertStringContainsString(sprintf('Default KMS Key: %s', $this->keyName()), $output); - $this->assertStringContainsString('Google Managed (GMEK) Enforcement:', $output); - $this->assertStringContainsString('Mode: FullyRestricted', $output); - $this->assertStringContainsString('Customer Managed (CMEK) Enforcement:', $output); - $this->assertStringContainsString('Mode: NotRestricted', $output); + $this->assertStringContainsString('Google Managed (GMEK) Enforcement:' . PHP_EOL . ' Mode: FullyRestricted', $output); + $this->assertStringContainsString('Customer Supplied (CSEK) Enforcement:' . PHP_EOL . ' Mode: FullyRestricted', $output); + $this->assertStringContainsString('Customer Managed (CMEK) Enforcement:' . PHP_EOL . ' Mode: NotRestricted', $output); } /** @depends testGetBucketEncryptionEnforcementConfig */ public function testRemoveAllBucketEncryptionEnforcementConfig() { - $kmsEncryptedBucketName = self::$bucketName . '-kms-encrypted'; - $output = $this->runFunctionSnippet('remove_all_bucket_encryption_enforcement_config', [ - $kmsEncryptedBucketName + self::$kmsEncryptedBucketName ]); $this->assertEquals($output, sprintf( 'Encryption enforcement configuration removed from bucket %s.' . PHP_EOL, - $kmsEncryptedBucketName + self::$kmsEncryptedBucketName )); // Final verification: Ensure 'Get' now shows no configuration sleep(1); $finalOutput = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ - $kmsEncryptedBucketName + self::$kmsEncryptedBucketName ]); $this->assertStringContainsString('No encryption configuration found (Default GMEK is active).', $finalOutput); } From 7faba4dc38d6c0495d67c959fe6b7f5b990a291e Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Fri, 13 Mar 2026 09:37:30 +0000 Subject: [PATCH 4/5] Feat(storage): unify encryption enforcement sample Updates the encryption enforcement sample to a single consolidated file under the `storage_update_encryption_enforcement_config` region tag. The updated sample now covers both partial updates (restriction modes) and the full removal of enforcement configurations. --- ..._bucket_encryption_enforcement_config.php} | 31 +++++++++++++------ storage/test/storageTest.php | 20 +++++++----- 2 files changed, 34 insertions(+), 17 deletions(-) rename storage/src/{remove_all_bucket_encryption_enforcement_config.php => update_bucket_encryption_enforcement_config.php} (58%) diff --git a/storage/src/remove_all_bucket_encryption_enforcement_config.php b/storage/src/update_bucket_encryption_enforcement_config.php similarity index 58% rename from storage/src/remove_all_bucket_encryption_enforcement_config.php rename to storage/src/update_bucket_encryption_enforcement_config.php index 304ab15b9..e5d1c4cfb 100644 --- a/storage/src/remove_all_bucket_encryption_enforcement_config.php +++ b/storage/src/update_bucket_encryption_enforcement_config.php @@ -23,22 +23,34 @@ namespace Google\Cloud\Samples\Storage; -# [START storage_remove_all_encryption_enforcement_config] +# [START storage_update_encryption_enforcement_config] use Google\Cloud\Storage\StorageClient; /** - * Removes all encryption enforcement configurations from a bucket. + * Updates or removes encryption enforcement configurations from a bucket. * * @param string $bucketName The ID of your GCS bucket (e.g. "my-bucket"). */ -function remove_all_bucket_encryption_enforcement_config(string $bucketName): void +function update_bucket_encryption_enforcement_config(string $bucketName): void { $storage = new StorageClient(); $bucket = $storage->bucket($bucketName); - // Setting these values to null in an update call will remove the - // specific enforcement policies from the bucket metadata. - $options = [ + // Update a specific encryption type's restriction mode + // This partial update preserves other existing encryption settings. + $updateOptions = [ + 'encryption' => [ + 'googleManagedEncryptionEnforcementConfig' => [ + 'restrictionMode' => 'FullyRestricted' + ] + ] + ]; + $bucket->update($updateOptions); + printf('Google-managed encryption enforcement set to FullyRestricted for %s.' . PHP_EOL, $bucketName); + + // Remove all encryption enforcement configurations altogether + // Setting these values to null removes the policies from the bucket metadata. + $clearOptions = [ 'encryption' => [ 'defaultKmsKeyName' => null, 'googleManagedEncryptionEnforcementConfig' => null, @@ -47,11 +59,10 @@ function remove_all_bucket_encryption_enforcement_config(string $bucketName): vo ], ]; - $bucket->update($options); - - printf('Encryption enforcement configuration removed from bucket %s.' . PHP_EOL, $bucketName); + $bucket->update($clearOptions); + printf('All encryption enforcement configurations removed from bucket %s.' . PHP_EOL, $bucketName); } -# [END storage_remove_all_encryption_enforcement_config] +# [END storage_update_encryption_enforcement_config] // The following 2 lines are only needed to run the samples require_once __DIR__ . '/../../testing/sample_helpers.php'; diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index 7ad5ad6a2..2b9cfaf52 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -603,22 +603,28 @@ public function testGetBucketEncryptionEnforcementConfig() } /** @depends testGetBucketEncryptionEnforcementConfig */ - public function testRemoveAllBucketEncryptionEnforcementConfig() + public function testUpdateBucketEncryptionEnforcementConfig() { - $output = $this->runFunctionSnippet('remove_all_bucket_encryption_enforcement_config', [ + $output = $this->runFunctionSnippet('update_bucket_encryption_enforcement_config', [ self::$kmsEncryptedBucketName ]); - $this->assertEquals($output, sprintf( - 'Encryption enforcement configuration removed from bucket %s.' . PHP_EOL, - self::$kmsEncryptedBucketName - )); + $this->assertStringContainsString( + sprintf('Google-managed encryption enforcement set to FullyRestricted for %s.', self::$kmsEncryptedBucketName), + $output + ); + + $this->assertStringContainsString( + sprintf('All encryption enforcement configurations removed from bucket %s.', self::$kmsEncryptedBucketName), + $output + ); // Final verification: Ensure 'Get' now shows no configuration - sleep(1); + sleep(2); $finalOutput = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ self::$kmsEncryptedBucketName ]); + $this->assertStringContainsString('No encryption configuration found (Default GMEK is active).', $finalOutput); } From 04f0b055cd9c845bdf4832c3caa219125bce93ce Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Fri, 13 Mar 2026 09:40:37 +0000 Subject: [PATCH 5/5] Lint fix --- storage/test/storageTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/test/storageTest.php b/storage/test/storageTest.php index 2b9cfaf52..d396484f8 100644 --- a/storage/test/storageTest.php +++ b/storage/test/storageTest.php @@ -624,7 +624,7 @@ public function testUpdateBucketEncryptionEnforcementConfig() $finalOutput = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ self::$kmsEncryptedBucketName ]); - + $this->assertStringContainsString('No encryption configuration found (Default GMEK is active).', $finalOutput); }