diff --git a/google-cloud-storage/acceptance/storage/bucket_encryption_test.rb b/google-cloud-storage/acceptance/storage/bucket_encryption_test.rb index 7760e2107ed8..c199f378ca8c 100644 --- a/google-cloud-storage/acceptance/storage/bucket_encryption_test.rb +++ b/google-cloud-storage/acceptance/storage/bucket_encryption_test.rb @@ -25,9 +25,23 @@ ENV["GCLOUD_TEST_STORAGE_KMS_KEY_2"] || "projects/#{storage.project_id}/locations/#{bucket_location}/keyRings/ruby-test/cryptoKeys/ruby-test-key-2" } + + let(:customer_managed_config) do + { restriction_mode: "NotRestricted" } + end + + let(:customer_supplied_config) do + { restriction_mode: "FullyRestricted" } + end + + let(:google_managed_config) do + { restriction_mode: "FullyRestricted" } + end + let :bucket do - b = safe_gcs_execute { storage.create_bucket(bucket_name, location: bucket_location) } + b = safe_gcs_execute { storage.bucket(bucket_name) || storage.create_bucket(bucket_name, location: bucket_location) } b.default_kms_key = kms_key + b.customer_managed_encryption_enforcement_config = customer_managed_config b end @@ -71,4 +85,45 @@ _(bucket.default_kms_key).must_be :nil? end end + + describe "Encryption Enforcement Config" do + let(:google_managed_config_complete) do + {google_managed_encryption_enforcement_config: { restriction_mode: "FullyRestricted" } } + end + it "knows its encryption enforcement config" do + _(bucket.customer_managed_encryption_enforcement_config).wont_be :nil? + _(bucket.customer_managed_encryption_enforcement_config.restriction_mode).must_equal "NotRestricted" + bucket.reload! + _(bucket.customer_managed_encryption_enforcement_config).wont_be :nil? + _(bucket.customer_managed_encryption_enforcement_config.restriction_mode).must_equal "NotRestricted" + end + + it "updates encryption enforcement configs" do + _(bucket.customer_supplied_encryption_enforcement_config).must_be :nil? + + bucket.customer_supplied_encryption_enforcement_config = customer_supplied_config + _(bucket.customer_supplied_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + bucket.update do |b| + b.google_managed_encryption_enforcement_config = google_managed_config + end + _(bucket.google_managed_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + + bucket.reload! + _(bucket.customer_supplied_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + _(bucket.google_managed_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + end + + it "deletes all encryption enforcement configs" do + bucket.update do |b| + b.customer_managed_encryption_enforcement_config = nil + b.customer_supplied_encryption_enforcement_config = nil + b.google_managed_encryption_enforcement_config = nil + end + # Removed all encryption enforcement configs without removing default_kms_key + _(bucket.customer_managed_encryption_enforcement_config).must_be :nil? + _(bucket.customer_supplied_encryption_enforcement_config).must_be :nil? + _(bucket.google_managed_encryption_enforcement_config).must_be :nil? + _(bucket.default_kms_key).must_equal kms_key + end + end end diff --git a/google-cloud-storage/acceptance/storage/file_encryption_test.rb b/google-cloud-storage/acceptance/storage/file_encryption_test.rb index 70665da0de1b..f7dbdb2d2c6a 100644 --- a/google-cloud-storage/acceptance/storage/file_encryption_test.rb +++ b/google-cloud-storage/acceptance/storage/file_encryption_test.rb @@ -22,7 +22,7 @@ let(:bucket_location) { "us-central1" } let :bucket do - safe_gcs_execute {storage.create_bucket bucket_name, location: bucket_location } + safe_gcs_execute { storage.bucket(bucket_name) || storage.create_bucket(bucket_name, location: bucket_location) } end let(:file_path) { "acceptance/data/abc.txt" } diff --git a/google-cloud-storage/lib/google/cloud/storage/bucket.rb b/google-cloud-storage/lib/google/cloud/storage/bucket.rb index ca8461354bb7..d9c9ae117724 100644 --- a/google-cloud-storage/lib/google/cloud/storage/bucket.rb +++ b/google-cloud-storage/lib/google/cloud/storage/bucket.rb @@ -716,6 +716,171 @@ def default_kms_key= new_default_kms_key default_kms_key_name: new_default_kms_key patch_gapi! :encryption end + ## + # The bucket's encryption configuration for customer-managed encryption keys. + # This configuration defines the + # default encryption behavior for the bucket and its files, and it can be used to enforce encryption requirements for the bucket. + # For more information, see [Bucket encryption](https://docs.cloud.google.com/storage/docs/encryption/). + # @return [Google::Apis::StorageV1::Bucket::Encryption::CustomerManagedEncryptionEnforcementConfig, nil] The bucket's encryption configuration, or `nil` if no encryption configuration has been set. + # @example + # require "google/cloud/storage" + # # + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # bucket.customer_managed_encryption_enforcement_config + # ==> # + # The value for `restriction_mode` can be either "NotRestricted" or "FullyRestricted" + + def customer_managed_encryption_enforcement_config + @gapi.encryption&.customer_managed_encryption_enforcement_config + end + ## + # Sets the customer-managed encryption enforcement configuration for the bucket. + # + # @param new_customer_managed_encryption_enforcement_config [Hash, nil] + # The configuration hash for encryption enforcement. + # * `:restriction_mode` (String) - Can be "NotRestricted" or "FullyRestricted". + # Pass `nil` to clear the current configuration. + # + # @example Enforcing Customer-Managed Encryption + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # + # # Set restriction mode to FullyRestricted + # restricted_config = { restriction_mode: "FullyRestricted" } + # bucket.customer_managed_encryption_enforcement_config = restricted_config + # + # @example Setting via Request Object (Google API Client) + # require "google/apis/storage_v1" + # + # enforcement_config = { restriction_mode: "FullyRestricted" } + # + # request_obj = Google::Apis::StorageV1::Bucket::Encryption.new( + # customer_managed_encryption_enforcement_config: enforcement_config + # ) + # bucket.customer_managed_encryption_enforcement_config = request_obj + # + # @return [Hash, Google::Apis::StorageV1::Bucket::Encryption] The updated configuration. + # @raise [Google::Cloud::Error] If the update fails due to permissions or invalid arguments. + def customer_managed_encryption_enforcement_config= new_customer_managed_encryption_enforcement_config + @gapi.encryption ||= API::Bucket::Encryption.new + @gapi.encryption.customer_managed_encryption_enforcement_config = + new_customer_managed_encryption_enforcement_config || {} + patch_gapi! :encryption + end + + ## + # The bucket's encryption configuration for customer-supplied encryption keys. + # For more information, see [Bucket encryption](https://docs.cloud.google.com/storage/docs/encryption/). + # @return [Google::Apis::StorageV1::Bucket::Encryption::CustomerSuppliedEncryptionEnforcementConfig, nil] + # The bucket's encryption configuration, or `nil` if no encryption configuration has been set. + # @example + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # + # bucket.customer_supplied_encryption_enforcement_config + # ==> # + # The value for `restriction_mode` can be either "NotRestricted" or "FullyRestricted". + + def customer_supplied_encryption_enforcement_config + @gapi.encryption&.customer_supplied_encryption_enforcement_config + end + + ## + # Sets the bucket's encryption configuration for customer-supplied encryption that will be used to protect files. + # @param new_customer_supplied_encryption_enforcement_config [Hash, nil] + # The configuration hash for encryption enforcement. + # * `:restriction_mode` (String) - Can be "NotRestricted" or "FullyRestricted". + # Pass `nil` to clear the current configuration. + # @example + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # restricted_config = { restriction_mode: "FullyRestricted" } + # bucket.customer_supplied_encryption_enforcement_config = restricted_config + # + # @example Setting via Request Object (Google API Client) + # require "google/apis/storage_v1" + # + # enforcement_config = { restriction_mode: "FullyRestricted" } + # + # request_obj = Google::Apis::StorageV1::Bucket::Encryption.new( + # customer_supplied_encryption_enforcement_config: enforcement_config + # ) + # bucket.customer_supplied_encryption_enforcement_config = request_obj + # + # @return [Hash, Google::Apis::StorageV1::Bucket::Encryption] The updated configuration. + # @raise [Google::Cloud::Error] If the update fails due to permissions or invalid arguments. + + def customer_supplied_encryption_enforcement_config= new_customer_supplied_encryption_enforcement_config + @gapi.encryption ||= API::Bucket::Encryption.new + @gapi.encryption.customer_supplied_encryption_enforcement_config = + new_customer_supplied_encryption_enforcement_config || {} + patch_gapi! :encryption + end + + ## + # The bucket's encryption configuration for google-managed encryption keys. + # This configuration defines the + # default encryption behavior for the bucket and its files, and it can be used to enforce encryption + # requirements for the bucket. + # For more information, see [Bucket encryption](https://docs.cloud.google.com/storage/docs/encryption/). + # @return [Google::Apis::StorageV1::Bucket::Encryption::GoogleManagedEncryptionEnforcementConfig, nil] + # The bucket's encryption configuration, or `nil` if no encryption configuration has been set. + # @example + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # bucket.google_managed_encryption_enforcement_config + # ==> # + # The value for `restriction_mode` can be either "NotRestricted" or "FullyRestricted". + + def google_managed_encryption_enforcement_config + @gapi.encryption&.google_managed_encryption_enforcement_config + end + + ## + # Sets the google-managed encryption enforcement configuration for the bucket. + # + # @param new_google_managed_encryption_enforcement_config [Hash, nil] + # The configuration hash for encryption enforcement. + # * `:restriction_mode` (String) - Can be "NotRestricted" or "FullyRestricted". + # Pass `nil` to clear the current configuration. + # + # @example Enforcing Customer-Managed Encryption + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # bucket = storage.bucket "my-bucket" + # # Set restriction mode to FullyRestricted + # restricted_config = { restriction_mode: "FullyRestricted" } + # bucket.google_managed_encryption_enforcement_config = restricted_config + # + # @example Setting via Request Object (Google API Client) + # require "google/apis/storage_v1" + # + # enforcement_config = { restriction_mode: "FullyRestricted" } + # + # request_obj = Google::Apis::StorageV1::Bucket::Encryption.new( + # google_managed_encryption_enforcement_config: enforcement_config + # ) + # bucket.google_managed_encryption_enforcement_config = request_obj + # + # @return [Hash, Google::Apis::StorageV1::Bucket::Encryption] The updated configuration. + # @raise [Google::Cloud::Error] If the update fails due to permissions or invalid arguments. + + def google_managed_encryption_enforcement_config= new_google_managed_encryption_enforcement_config + @gapi.encryption ||= API::Bucket::Encryption.new + @gapi.encryption.google_managed_encryption_enforcement_config = + new_google_managed_encryption_enforcement_config || {} + patch_gapi! :encryption + end ## # The period of time (in seconds) that files in the bucket must be @@ -1373,6 +1538,7 @@ def update if_metageneration_match: nil, if_metageneration_not_match: nil updater.check_for_changed_labels! updater.check_for_mutable_cors! updater.check_for_mutable_lifecycle! + updater.check_for_encryption_enforcement_config! return if updater.updates.empty? update_gapi! updater.updates, if_metageneration_match: if_metageneration_match, @@ -3386,6 +3552,26 @@ def check_for_mutable_lifecycle! patch_gapi! :lifecycle end + def check_for_encryption_enforcement_config! + return unless @gapi.encryption + + [ + :google_managed_encryption_enforcement_config, + :customer_managed_encryption_enforcement_config, + :customer_supplied_encryption_enforcement_config + ].each do |attr| + config = @gapi.encryption.send(attr) + next unless config + unless config.respond_to?(:to_h) + raise ArgumentError, "Encryption config for #{attr} must be a Hash or valid Config object" + end + clean_config = config.to_h + clean_config.delete :effective_time + clean_config.delete "effective_time" + @gapi.encryption.send "#{attr}=", clean_config + end + end + protected ## diff --git a/google-cloud-storage/samples/Gemfile b/google-cloud-storage/samples/Gemfile index 3b36d79c3373..67a916a8415c 100644 --- a/google-cloud-storage/samples/Gemfile +++ b/google-cloud-storage/samples/Gemfile @@ -36,3 +36,7 @@ group :test do gem "minitest-hooks", "~> 1.5" gem "rake" end +# The following gems have been removed from ruby core and are required for testing. +gem "ostruct" +gem "cgi" +gem "irb" diff --git a/google-cloud-storage/samples/acceptance/buckets_test.rb b/google-cloud-storage/samples/acceptance/buckets_test.rb index bb78ba9bbe44..a8a9326a5e41 100644 --- a/google-cloud-storage/samples/acceptance/buckets_test.rb +++ b/google-cloud-storage/samples/acceptance/buckets_test.rb @@ -37,6 +37,7 @@ require_relative "../storage_get_bucket_class_and_location" require_relative "../storage_get_bucket_metadata" require_relative "../storage_get_default_event_based_hold" +require_relative "../storage_get_bucket_encryption_enforcement_config" require_relative "../storage_get_public_access_prevention" require_relative "../storage_get_requester_pays_status" require_relative "../storage_get_retention_policy" @@ -44,10 +45,12 @@ require_relative "../storage_list_buckets" require_relative "../storage_list_buckets_with_partial_success" require_relative "../storage_lock_retention_policy" +require_relative "../storage_update_bucket_encryption_enforcement_config" require_relative "../storage_remove_bucket_label" require_relative "../storage_remove_cors_configuration" require_relative "../storage_remove_retention_policy" require_relative "../storage_set_bucket_default_kms_key" +require_relative "../storage_set_bucket_encryption_enforcement_config" require_relative "../storage_set_object_retention_policy" require_relative "../storage_set_public_access_prevention_enforced" require_relative "../storage_set_public_access_prevention_inherited" @@ -169,6 +172,44 @@ end end + describe "storage_bucket_encryption_enforcement_config" do + bucket_name = random_bucket_name + + it "gets, sets and updates bucket encryption enforcement config" do + # creates bucket with encryption enforcement config + expected = "Created bucket #{bucket_name} with Encryption Enforcement Config.\n" + + retry_resource_exhaustion do + assert_output expected do + set_bucket_encryption_enforcement_config bucket_name: bucket_name + end + end + + # get encryption enforcement config + expected = "Encryption Enforcement Config for bucket #{bucket_name}:\n" \ + "Customer-managed encryption enforcement config restriction mode: NotRestricted\n" \ + "Customer-supplied encryption enforcement config restriction mode: FullyRestricted\n" \ + "Google-managed encryption enforcement config restriction mode: FullyRestricted\n" + retry_resource_exhaustion do + assert_output expected do + get_bucket_encryption_enforcement_config bucket_name: bucket_name + end + end + + # update encryption enforcement config + expected = "Updated google_managed_config to NotRestricted for bucket #{bucket_name}.\n" + + retry_resource_exhaustion do + assert_output expected do + update_bucket_encryption_enforcement_config bucket_name: bucket_name + end + end + + refute_nil storage_client.bucket bucket_name + end + delete_bucket_helper bucket_name + end + describe "storage_create_bucket_with_object_retention" do it "creates a bucket with object retention enabled." do bucket_name = random_bucket_name diff --git a/google-cloud-storage/samples/storage_get_bucket_encryption_enforcement_config.rb b/google-cloud-storage/samples/storage_get_bucket_encryption_enforcement_config.rb new file mode 100644 index 000000000000..c79911104e2b --- /dev/null +++ b/google-cloud-storage/samples/storage_get_bucket_encryption_enforcement_config.rb @@ -0,0 +1,36 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_get_bucket_encryption_enforcement_config] +def get_bucket_encryption_enforcement_config bucket_name: + # The ID to give your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + puts "Encryption Enforcement Config for bucket #{bucket.name}:" + puts "Customer-managed encryption enforcement config restriction mode: " \ + "#{bucket.customer_managed_encryption_enforcement_config&.restriction_mode}" + puts "Customer-supplied encryption enforcement config restriction mode: " \ + "#{bucket.customer_supplied_encryption_enforcement_config&.restriction_mode}" + puts "Google-managed encryption enforcement config restriction mode: " \ + "#{bucket.google_managed_encryption_enforcement_config&.restriction_mode}" +end +# [END storage_get_bucket_encryption_enforcement_config] + +if $PROGRAM_NAME == __FILE__ + get_bucket_encryption_enforcement_config bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_set_bucket_encryption_enforcement_config.rb b/google-cloud-storage/samples/storage_set_bucket_encryption_enforcement_config.rb new file mode 100644 index 000000000000..92cedc2e6ec6 --- /dev/null +++ b/google-cloud-storage/samples/storage_set_bucket_encryption_enforcement_config.rb @@ -0,0 +1,39 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_set_bucket_encryption_enforcement_config] +def set_bucket_encryption_enforcement_config bucket_name: + # The ID to give your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + + customer_managed_config = { restriction_mode: "NotRestricted" } + customer_supplied_config = { restriction_mode: "FullyRestricted" } + google_managed_config = { restriction_mode: "FullyRestricted" } + + bucket = storage.create_bucket bucket_name do |b| + b.customer_managed_encryption_enforcement_config = customer_managed_config + b.customer_supplied_encryption_enforcement_config = customer_supplied_config + b.google_managed_encryption_enforcement_config = google_managed_config + end + puts "Created bucket #{bucket.name} with Encryption Enforcement Config." +end +# [END storage_set_bucket_encryption_enforcement_config] + +if $PROGRAM_NAME == __FILE__ + set_bucket_encryption_enforcement_config bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_update_bucket_encryption_enforcement_config.rb b/google-cloud-storage/samples/storage_update_bucket_encryption_enforcement_config.rb new file mode 100644 index 000000000000..a1e5bed3ab32 --- /dev/null +++ b/google-cloud-storage/samples/storage_update_bucket_encryption_enforcement_config.rb @@ -0,0 +1,39 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "google/cloud/storage" + +# [START storage_update_bucket_encryption_enforcement_config] + +def update_bucket_encryption_enforcement_config bucket_name: + # The ID to give your GCS bucket + # bucket_name = "your-unique-bucket-name" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + # Update a specific type (e.g., change GMEK to NotRestricted) + new_config = { restriction_mode: "NotRestricted" } + + bucket.update do |b| + b.google_managed_encryption_enforcement_config = new_config + end + puts "Updated google_managed_config to " \ + "#{bucket.google_managed_encryption_enforcement_config.restriction_mode} " \ + "for bucket #{bucket.name}." +end +# [END storage_update_bucket_encryption_enforcement_config] + +if $PROGRAM_NAME == __FILE__ + update_bucket_encryption_enforcement_config bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_encryption_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_encryption_test.rb index ce617da110e6..25eaab02af14 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_encryption_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_encryption_test.rb @@ -20,6 +20,7 @@ let(:bucket_json) { bucket_hash.to_json } let(:bucket_gapi) { Google::Apis::StorageV1::Bucket.from_json bucket_json } let(:bucket) { Google::Cloud::Storage::Bucket.from_gapi bucket_gapi, storage.service } + let(:kms_key) { "path/to/encryption_key_name" } describe "customer-supplied encryption key (CSEK)" do let(:encryption_key) { "y\x03\"\x0E\xB6\xD3\x9B\x0E\xAB*\x19\xFAv\xDEY\xBEI\xF8ftA|[z\x1A\xFBE\xDE\x97&\xBC\xC7" } @@ -70,11 +71,9 @@ end describe "KMS customer-managed encryption key (CMEK)" do - let(:kms_key) { "path/to/encryption_key_name" } - it "gets and sets its encryption config" do mock = Minitest::Mock.new - patch_bucket_gapi = Google::Apis::StorageV1::Bucket.new encryption: encryption_gapi(kms_key) + patch_bucket_gapi = Google::Apis::StorageV1::Bucket.new encryption: encryption_gapi(key_name: kms_key) mock.expect :patch_bucket, patch_bucket_gapi, [bucket_name, patch_bucket_gapi], **patch_bucket_args(options: {retries: 0}) bucket.service.mocked_service = mock @@ -88,9 +87,13 @@ it "sets its encryption config to nil" do bucket_gapi_with_key = bucket_gapi.dup - bucket_gapi_with_key.encryption = encryption_gapi(kms_key) + bucket_gapi_with_key.encryption = encryption_gapi(key_name: kms_key) bucket_with_key = Google::Cloud::Storage::Bucket.from_gapi bucket_gapi_with_key, storage.service - patch_bucket_gapi = Google::Apis::StorageV1::Bucket.new encryption: encryption_gapi(nil) + patch_bucket_gapi = Google::Apis::StorageV1::Bucket.new( + encryption: Google::Apis::StorageV1::Bucket::Encryption.new( + default_kms_key_name: nil + ) + ) mock = Minitest::Mock.new mock.expect :patch_bucket, bucket_gapi, [bucket_name, patch_bucket_gapi], **patch_bucket_args(options: {retries: 0}) @@ -122,6 +125,108 @@ end end + describe "encryption enforcement config" do + let(:bucket_encryption) do + Google::Apis::StorageV1::Bucket::Encryption.new( + customer_managed_encryption_enforcement_config: customer_managed_encryption, + customer_supplied_encryption_enforcement_config: customer_supplied_encryption, + google_managed_encryption_enforcement_config: google_managed_encryption + ) + end + + let(:bucket_gapi) do + b = Google::Apis::StorageV1::Bucket.from_json bucket_json + b.encryption = bucket_encryption + b.encryption.default_kms_key_name = kms_key + b + end + + it "knows its encryption enforcement config" do + _(bucket.customer_managed_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + _(bucket.customer_supplied_encryption_enforcement_config.restriction_mode).must_equal "NotRestricted" + _(bucket.google_managed_encryption_enforcement_config.restriction_mode).must_equal "NotRestricted" + end + + it "updates encryption_enforcement_config using update_bucket_encryption_enforcement_config" do + mock = Minitest::Mock.new + incoming_config = { restriction_mode: "FullyRestricted" } + patch_bucket_gapi = Google::Apis::StorageV1::Bucket.new( + encryption: Google::Apis::StorageV1::Bucket::Encryption.new( + google_managed_encryption_enforcement_config: Google::Apis::StorageV1::Bucket::Encryption::GoogleManagedEncryptionEnforcementConfig.new( + restriction_mode: "FullyRestricted" + ) + ) + ) + + returned_bucket_gapi = bucket_gapi.dup + returned_bucket_gapi.encryption = bucket_gapi.encryption.dup + returned_bucket_gapi.encryption.google_managed_encryption_enforcement_config = patch_bucket_gapi.encryption.google_managed_encryption_enforcement_config + + mock.expect(:update_bucket, returned_bucket_gapi) { |name,**| name == bucket_name} + + bucket.service.mocked_service = mock + _(bucket.customer_managed_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + _(bucket.customer_supplied_encryption_enforcement_config.restriction_mode).must_equal "NotRestricted" + _(bucket.google_managed_encryption_enforcement_config.restriction_mode).must_equal "NotRestricted" + + bucket.update do |b| + b.google_managed_encryption_enforcement_config = incoming_config + end + _(bucket.customer_managed_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + _(bucket.customer_supplied_encryption_enforcement_config.restriction_mode).must_equal "NotRestricted" + _(bucket.google_managed_encryption_enforcement_config.restriction_mode).must_equal "FullyRestricted" + + mock.verify + end + + + it "raises error when a Hash is not provided for encryption enforcement config" do + invalid_config = "test" + + err = assert_raises(ArgumentError) do + bucket.update do |b| + b.google_managed_encryption_enforcement_config = invalid_config + end + end + + # Update the regex to match the error message in your validation method + assert_match(/must be a Hash or valid Config object/, err.message) + end + + it "deletes all encryption enforcement configs together and preserves default_kms_key" do + mock = Minitest::Mock.new + + initial_bucket_gapi = bucket_gapi.dup + initial_bucket_gapi.encryption = bucket_encryption.dup + initial_bucket_gapi.encryption.default_kms_key_name = kms_key + bucket_with_configs_and_key = Google::Cloud::Storage::Bucket.from_gapi initial_bucket_gapi, storage.service + + returned_bucket_gapi = bucket_gapi.dup + returned_bucket_gapi.encryption = Google::Apis::StorageV1::Bucket::Encryption.new default_kms_key_name: kms_key + + mock.expect(:update_bucket, returned_bucket_gapi) { |name, patch_obj, **| name == bucket_name && patch_obj.encryption.default_kms_key_name == kms_key } + + bucket_with_configs_and_key.service.mocked_service = mock + + _(bucket_with_configs_and_key.customer_managed_encryption_enforcement_config).wont_be :nil? + _(bucket_with_configs_and_key.customer_supplied_encryption_enforcement_config).wont_be :nil? + _(bucket_with_configs_and_key.google_managed_encryption_enforcement_config).wont_be :nil? + _(bucket_with_configs_and_key.default_kms_key).must_equal kms_key + + bucket_with_configs_and_key.update do |b| + b.customer_managed_encryption_enforcement_config = nil + b.customer_supplied_encryption_enforcement_config = nil + b.google_managed_encryption_enforcement_config = nil + end + + _(bucket_with_configs_and_key.customer_managed_encryption_enforcement_config).must_be :nil? + _(bucket_with_configs_and_key.customer_supplied_encryption_enforcement_config).must_be :nil? + _(bucket_with_configs_and_key.google_managed_encryption_enforcement_config).must_be :nil? + _(bucket_with_configs_and_key.default_kms_key).must_equal kms_key + + mock.verify + end + end def create_file_gapi bucket=nil, name = nil Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name).to_json diff --git a/google-cloud-storage/test/google/cloud/storage/project_test.rb b/google-cloud-storage/test/google/cloud/storage/project_test.rb index 05724226ca34..c07bff384157 100644 --- a/google-cloud-storage/test/google/cloud/storage/project_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/project_test.rb @@ -389,7 +389,7 @@ def creds.is_a? target it "creates a bucket with block encryption" do mock = Minitest::Mock.new created_bucket = create_bucket_gapi bucket_name - created_bucket.encryption = encryption_gapi(kms_key) + created_bucket.encryption = encryption_gapi(key_name: kms_key) resp_bucket = bucket_with_location created_bucket mock.expect :insert_bucket, resp_bucket, [project, created_bucket], predefined_acl: nil, predefined_default_object_acl: nil, user_project: nil, enable_object_retention: nil, options: {} diff --git a/google-cloud-storage/test/helper.rb b/google-cloud-storage/test/helper.rb index 1a4752e77628..f649951796ba 100644 --- a/google-cloud-storage/test/helper.rb +++ b/google-cloud-storage/test/helper.rb @@ -244,8 +244,30 @@ def download_http_resp gzip: nil OpenStruct.new(header: headers) end - def encryption_gapi key_name - Google::Apis::StorageV1::Bucket::Encryption.new default_kms_key_name: key_name + def customer_managed_encryption + Google::Apis::StorageV1::Bucket::Encryption::CustomerManagedEncryptionEnforcementConfig.new( + restriction_mode: "FullyRestricted" + ) + end + + def customer_supplied_encryption + Google::Apis::StorageV1::Bucket::Encryption::CustomerSuppliedEncryptionEnforcementConfig.new( + restriction_mode: "NotRestricted" + ) + end + + def google_managed_encryption + Google::Apis::StorageV1::Bucket::Encryption::GoogleManagedEncryptionEnforcementConfig.new( + restriction_mode: "NotRestricted" + ) + end + + def encryption_gapi key_name: nil + params = { + default_kms_key_name: key_name + }.compact + + Google::Apis::StorageV1::Bucket::Encryption.new(**params) end def lifecycle_gapi *rules