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..460b8fe44 --- /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..304ab15b9 --- /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..0f047510f --- /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..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, ]); @@ -573,6 +570,58 @@ public function testObjectGetKmsKey(string $objectName) ); } + /** @depends testEnableDefaultKmsKey */ + public function testSetBucketEncryptionEnforcementConfig() + { + $output = $this->runFunctionSnippet('set_bucket_encryption_enforcement_config', [ + self::$kmsEncryptedBucketName, + $this->keyName(), + ]); + + $this->assertEquals($output, sprintf( + 'Encryption enforcement configuration updated for bucket %s.' . PHP_EOL, + self::$kmsEncryptedBucketName + )); + } + + /** @depends testSetBucketEncryptionEnforcementConfig */ + public function testGetBucketEncryptionEnforcementConfig() + { + sleep(2); + $output = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ + self::$kmsEncryptedBucketName + ]); + + $this->assertStringContainsString( + 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:' . 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() + { + $output = $this->runFunctionSnippet('remove_all_bucket_encryption_enforcement_config', [ + self::$kmsEncryptedBucketName + ]); + + $this->assertEquals($output, sprintf( + 'Encryption enforcement configuration removed from bucket %s.' . PHP_EOL, + self::$kmsEncryptedBucketName + )); + + // Final verification: Ensure 'Get' now shows no configuration + sleep(1); + $finalOutput = $this->runFunctionSnippet('get_bucket_encryption_enforcement_config', [ + self::$kmsEncryptedBucketName + ]); + $this->assertStringContainsString('No encryption configuration found (Default GMEK is active).', $finalOutput); + } + public function testBucketVersioning() { $output = self::runFunctionSnippet('enable_versioning', [