diff --git a/google-cloud-storage/acceptance/storage/bucket_ip_filter_test.rb b/google-cloud-storage/acceptance/storage/bucket_ip_filter_test.rb new file mode 100644 index 000000000000..ca45ce2538a5 --- /dev/null +++ b/google-cloud-storage/acceptance/storage/bucket_ip_filter_test.rb @@ -0,0 +1,79 @@ +# 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 +# +# https://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 "storage_helper" + +describe Google::Cloud::Storage::Bucket, :storage do + let(:ip_filter_disabled) do + { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: ["0.0.0.0/0", "::/0"] + } + } + end + + let(:ip_filter_disabled_update) do + { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: ["8.8.8.8/32"] + } + } + end + + let(:bucket_name) { "#{$bucket_names[2]}-ip-filter" } + + it "creates, gets, updates, and deletes a bucket with ip_filter" do + # Create a bucket with ip_filter + bucket = storage.bucket(bucket_name) || + safe_gcs_execute {storage.create_bucket bucket_name, ip_filter: ip_filter_disabled} + + # _(bucket.ip_filter).wont_be_nil + _(bucket.ip_filter.mode).must_equal "Disabled" + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_equal ["0.0.0.0/0", "::/0"] + + # Get the bucket and verify ip_filter + bucket = storage.bucket bucket_name + _(bucket.ip_filter).wont_be_nil + _(bucket.ip_filter.mode).must_equal "Disabled" + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_equal ["0.0.0.0/0", "::/0"] + + # Update the ip_filter + safe_gcs_execute do + bucket.update do |b| + b.ip_filter = ip_filter_disabled_update + end + end + + _(bucket.ip_filter.mode).must_equal "Disabled" + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_equal ["8.8.8.8/32"] + + # Disable ip_filter + safe_gcs_execute do + bucket.ip_filter = { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: [] + } + } + end + + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_be_nil + + safe_gcs_execute { bucket.delete } + _(storage.bucket(bucket_name)).must_be :nil? + + end +end diff --git a/google-cloud-storage/lib/google/cloud/storage/bucket.rb b/google-cloud-storage/lib/google/cloud/storage/bucket.rb index ca8461354bb7..f8665b203250 100644 --- a/google-cloud-storage/lib/google/cloud/storage/bucket.rb +++ b/google-cloud-storage/lib/google/cloud/storage/bucket.rb @@ -1410,6 +1410,76 @@ def delete if_metageneration_match: nil, if_metageneration_not_match: nil user_project: user_project end + ## + # The bucket's IP filter configuration. + # This value can be modified by calling {#ip_filter=}. + # + # @return [Google::Apis::StorageV1::Bucket::IpFilter, nil] The bucket's IP filter configuration, + # or `nil` if not configured. + # + # @example + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # + # bucket = storage.bucket "my-bucket" + # ip_filter = bucket.ip_filter + # if ip_filter + # puts "Mode: #{ip_filter.mode}" + # puts "Public CIDR: #{ip_filter.public_network_source&.allowed_ip_cidr_ranges}" + # end + # + def ip_filter + @gapi.ip_filter + end + + ## + # Sets the value for IP filter in the bucket. This value can + # be queried by calling {#ip_filter}. + # + # @param [Google::Apis::StorageV1::Bucket::IpFilter, Hash] new_ip_filter The bucket's new IP filter. + # Acceptable Hash structure: + # - :mode - [String] The mode of the IP filter. Acceptable values are: "Disabled", "Enforced", "Preview" + # - :public_network_source - [Hash] The public network source configuration: + # - :allowed_ip_cidr_ranges - [Array] Array of IP CIDR ranges allowed for public access. + # - :vpc_network_sources - [Array] The VPC network sources configuration: + # - :network - [String] The VPC network resource path, e.g. "projects/PROJECT_ID/global/networks/NETWORK_NAME". + # - :allowed_ip_cidr_ranges - [Array] Array of IP CIDR ranges allowed for VPC access. + # - :allow_cross_org_vpcs - [Boolean] Whether to allow cross-org VPC access. + # - :allow_all_service_agent_access - [Boolean] Whether to allow all service agent access. + # + # @example Enable IP filter with Hash: + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # + # bucket = storage.bucket "my-bucket" + # bucket.ip_filter = { + # mode: "Enabled", + # allow_all_service_agent_access: true, + # public_network_source: { + # allowed_ip_cidr_ranges: ["0.0.0.0/0", "::/0"] + # } + # } + # + # @example Clear/delete IP filter: + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # + # bucket = storage.bucket "my-bucket" + # bucket.ip_filter = { + # mode: "Disabled", + # public_network_source: { + # allowed_ip_cidr_ranges: [] + # } + # } + # + def ip_filter= new_ip_filter + @gapi.ip_filter = new_ip_filter || {} + patch_gapi! :ip_filter + end + ## # Retrieves a list of files matching the criteria. # diff --git a/google-cloud-storage/lib/google/cloud/storage/project.rb b/google-cloud-storage/lib/google/cloud/storage/project.rb index 47e4ffc32da4..c5ef54193d10 100644 --- a/google-cloud-storage/lib/google/cloud/storage/project.rb +++ b/google-cloud-storage/lib/google/cloud/storage/project.rb @@ -424,6 +424,18 @@ def bucket bucket_name, # @param [Boolean] enable_object_retention # When set to true, object retention is enabled for this bucket. # + # @param [Hash] ip_filter The bucket's IP filter configuration. + # Acceptable values are: + # - {Google::Apis::StorageV1::Bucket::IpFilter} object + # - Hash that can be converted to a {Google::Apis::StorageV1::Bucket::IpFilter} object + # - :mode - [String] The mode of the IP filter. Acceptable values are: "Disabled", "Enforced", "Preview" + # - :public_network_source - [Hash] The public network source configuration: + # - :allowed_ip_cidr_ranges - [Array] Array of IP CIDR ranges allowed for public access. + # - :vpc_network_sources - [Array] The VPC network sources configuration: + # - :network - [String] The VPC network resource path, e.g. "projects/PROJECT_ID/global/networks/NETWORK_NAME". + # - :allowed_ip_cidr_ranges - [Array] Array of IP CIDR ranges allowed for VPC access. + # - :allow_cross_org_vpcs - [Boolean] Whether to allow cross-org VPC access. + # - :allow_all_service_agent_access - [Boolean] Whether to allow all service agent access. # @yield [bucket] a block for configuring the bucket before it is # created # @yieldparam [Bucket] bucket the bucket object to be configured @@ -477,12 +489,15 @@ def create_bucket bucket_name, user_project: nil, autoclass_enabled: false, enable_object_retention: nil, - hierarchical_namespace: nil + hierarchical_namespace: nil, + ip_filter: nil + params = { name: bucket_name, location: location, custom_placement_config: custom_placement_config, - hierarchical_namespace: hierarchical_namespace + hierarchical_namespace: hierarchical_namespace, + ip_filter: ip_filter }.delete_if { |_, v| v.nil? } new_bucket = Google::Apis::StorageV1::Bucket.new(**params) storage_class = storage_class_for storage_class @@ -496,6 +511,7 @@ def create_bucket bucket_name, b.versioning = versioning unless versioning.nil? b.requester_pays = requester_pays unless requester_pays.nil? b.hierarchical_namespace = hierarchical_namespace unless hierarchical_namespace.nil? + b.ip_filter = ip_filter unless ip_filter.nil? end yield updater if block_given? updater.check_for_changed_labels! diff --git a/google-cloud-storage/samples/acceptance/buckets_test.rb b/google-cloud-storage/samples/acceptance/buckets_test.rb index bb78ba9bbe44..c2a93c518022 100644 --- a/google-cloud-storage/samples/acceptance/buckets_test.rb +++ b/google-cloud-storage/samples/acceptance/buckets_test.rb @@ -21,6 +21,12 @@ require_relative "../storage_create_bucket_class_location" require_relative "../storage_create_bucket_dual_region" require_relative "../storage_create_bucket_hierarchical_namespace" +require_relative "../storage_create_bucket_with_ip_filter" +require_relative "../storage_get_bucket_ip_filter" +require_relative "../storage_update_bucket_with_ip_filter" +require_relative "../storage_delete_bucket_ip_filter" +require_relative "../storage_enable_bucket_ip_filter" +require_relative "../storage_list_bucket_ip_filters" require_relative "../storage_create_bucket_with_object_retention" require_relative "../storage_define_bucket_website_configuration" require_relative "../storage_delete_bucket" @@ -169,6 +175,67 @@ end end + describe "storage_bucket_ip_filter" do + let(:bucket_name) { random_bucket_name } + + after :all do + delete_bucket_helper bucket_name + end + + it "creates, updates, gets, lists, and removes IP filter config" do + # Creates IP filter enabled bucket + expected = "Created bucket #{bucket_name} with IP filter.\n" + retry_resource_exhaustion do + assert_output expected do + create_bucket_with_ip_filter bucket_name: bucket_name + end + end + + # Updates IP filter of an existing bucket + expected = "Updated bucket #{bucket_name} with IP filter.\n" + retry_resource_exhaustion do + assert_output expected do + update_bucket_with_ip_filter bucket_name: bucket_name + end + end + + # Gets IP filter of an existing bucket + expected = "Bucket #{bucket_name} has IP filter mode: Disabled.\n" \ + "Allowed public network CIDR ranges: 8.8.8.8/32.\n" + retry_resource_exhaustion do + assert_output expected do + get_bucket_ip_filter bucket_name: bucket_name + end + end + + # Lists IP filter allowed ranges + expected = "IP filter mode: Disabled\n" \ + "Allowed range: 8.8.8.8/32\n" + retry_resource_exhaustion do + assert_output expected do + list_bucket_ip_filters bucket_name: bucket_name + end + end + + # Deletes IP filter of an existing bucket + expected = "Deleted IP filter for bucket #{bucket_name}.\n" + retry_resource_exhaustion do + assert_output expected do + delete_bucket_ip_filter bucket_name: bucket_name + end + end + + # Enables IP filter of an existing bucket (SKIPPED) + skip "SKIPPED : If Ip filter is enabled, we cannot access the bucket" + expected = "Enabled IP filter for bucket #{bucket_name}.\n" + retry_resource_exhaustion do + assert_output expected do + enable_bucket_ip_filter bucket_name: bucket_name + end + end + end + 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_create_bucket_with_ip_filter.rb b/google-cloud-storage/samples/storage_create_bucket_with_ip_filter.rb new file mode 100644 index 000000000000..b155ad7fe391 --- /dev/null +++ b/google-cloud-storage/samples/storage_create_bucket_with_ip_filter.rb @@ -0,0 +1,42 @@ +# 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_create_bucket_with_ip_filter] +def create_bucket_with_ip_filter bucket_name: + # The ID to give your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + ip_filter = { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: [ + "0.0.0.0/0", "::/0" + ] + } + } + + bucket = storage.create_bucket bucket_name do |b| + b.ip_filter = ip_filter + b.uniform_bucket_level_access = true + end + puts "Created bucket #{bucket_name} with IP filter." +end +# [END storage_create_bucket_with_ip_filter] + +if $PROGRAM_NAME == __FILE__ + create_bucket_with_ip_filter bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_delete_bucket_ip_filter.rb b/google-cloud-storage/samples/storage_delete_bucket_ip_filter.rb new file mode 100644 index 000000000000..f5366527769b --- /dev/null +++ b/google-cloud-storage/samples/storage_delete_bucket_ip_filter.rb @@ -0,0 +1,41 @@ +# 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_delete_ip_filtering_rules] +def delete_bucket_ip_filter bucket_name: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + + # Clear IP filter configuration by setting it to empty/disabled + bucket.update do |b| + b.ip_filter = { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: [] + } + } + end + + puts "Deleted IP filter for bucket #{bucket_name}." +end +# [END storage_delete_ip_filtering_rules] + +if $PROGRAM_NAME == __FILE__ + delete_bucket_ip_filter bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_enable_bucket_ip_filter.rb b/google-cloud-storage/samples/storage_enable_bucket_ip_filter.rb new file mode 100644 index 000000000000..6e96767479f1 --- /dev/null +++ b/google-cloud-storage/samples/storage_enable_bucket_ip_filter.rb @@ -0,0 +1,44 @@ +# 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_enable_bucket_ip_filter] +def enable_bucket_ip_filter bucket_name: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + + # Enable the IP filter configuration. + ip_filter = { + mode: "Enabled", + allow_all_service_agent_access: true, + public_network_source: { + allowed_ip_cidr_ranges: ["0.0.0.0/0", "::/0"] + } + } + + bucket.update do |b| + b.ip_filter = ip_filter + end + + puts "Enabled IP filter for bucket #{bucket_name}." +end +# [END storage_enable_bucket_ip_filter] + +if $PROGRAM_NAME == __FILE__ + enable_bucket_ip_filter bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_get_bucket_ip_filter.rb b/google-cloud-storage/samples/storage_get_bucket_ip_filter.rb new file mode 100644 index 000000000000..62f872a3fa43 --- /dev/null +++ b/google-cloud-storage/samples/storage_get_bucket_ip_filter.rb @@ -0,0 +1,40 @@ +# 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_ip_filter] +def get_bucket_ip_filter bucket_name: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + + ip_filter = bucket.ip_filter + + if ip_filter + puts "Bucket #{bucket_name} has IP filter mode: #{ip_filter.mode}." + if ip_filter.public_network_source + puts "Allowed public network CIDR ranges: #{ip_filter.public_network_source.allowed_ip_cidr_ranges.join(', ')}." + end + else + puts "Bucket #{bucket_name} does not have an IP filter configuration." + end +end +# [END storage_get_bucket_ip_filter] + +if $PROGRAM_NAME == __FILE__ + get_bucket_ip_filter bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_list_bucket_ip_filters.rb b/google-cloud-storage/samples/storage_list_bucket_ip_filters.rb new file mode 100644 index 000000000000..e0d294cfc436 --- /dev/null +++ b/google-cloud-storage/samples/storage_list_bucket_ip_filters.rb @@ -0,0 +1,41 @@ +# 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_list_bucket_ip_filters] +def list_bucket_ip_filters bucket_name: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + + ip_filter = bucket.ip_filter + if ip_filter + puts "IP filter mode: #{ip_filter.mode}" + if ip_filter.public_network_source + ip_filter.public_network_source.allowed_ip_cidr_ranges.each do |range| + puts "Allowed range: #{range}" + end + end + else + puts "No IP filter configured on bucket #{bucket_name}." + end +end +# [END storage_list_bucket_ip_filters] + +if $PROGRAM_NAME == __FILE__ + list_bucket_ip_filters bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/samples/storage_update_bucket_with_ip_filter.rb b/google-cloud-storage/samples/storage_update_bucket_with_ip_filter.rb new file mode 100644 index 000000000000..dd616d1b1001 --- /dev/null +++ b/google-cloud-storage/samples/storage_update_bucket_with_ip_filter.rb @@ -0,0 +1,44 @@ +# 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_update_bucket_with_ip_filter] +def update_bucket_with_ip_filter bucket_name: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + require "google/cloud/storage" + + storage = Google::Cloud::Storage.new + bucket = storage.bucket bucket_name + + ip_filter = { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: [ + "8.8.8.8/32" + ] + } + } + + bucket.update do |b| + b.ip_filter = ip_filter + end + + puts "Updated bucket #{bucket_name} with IP filter." +end +# [END storage_update_bucket_with_ip_filter] + +if $PROGRAM_NAME == __FILE__ + update_bucket_with_ip_filter bucket_name: ARGV.shift +end diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_ip_filter_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_ip_filter_test.rb new file mode 100644 index 000000000000..9706f05c8b74 --- /dev/null +++ b/google-cloud-storage/test/google/cloud/storage/bucket_ip_filter_test.rb @@ -0,0 +1,151 @@ +# 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 +# +# https://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 "helper" + +describe Google::Cloud::Storage::Bucket, :ip_filter, :mock_storage do + let(:bucket_name) { "new-bucket-#{Time.now.to_i}" } + let(:bucket_hash) { random_bucket_hash name: bucket_name } + let(:bucket_gapi) { Google::Apis::StorageV1::Bucket.from_json bucket_hash.to_json } + let(:bucket) { Google::Cloud::Storage::Bucket.from_gapi bucket_gapi, storage.service } + + let(:ip_filter_hash) do + { + "mode" => "Disabled", + "publicNetworkSource" => { + "allowedIpCidrRanges" => ["0.0.0.0/0", "::/0"] + } + } + end + let(:ip_filter_gapi) { Google::Apis::StorageV1::Bucket::IpFilter.from_json ip_filter_hash.to_json } + + it "knows its ip_filter value" do + _(bucket.ip_filter).must_be_nil + + bucket_gapi.ip_filter = ip_filter_gapi + _(bucket.ip_filter).wont_be_nil + _(bucket.ip_filter.mode).must_equal "Disabled" + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_equal ["0.0.0.0/0", "::/0"] + end + + + it "updates its ip_filter" do + mock = Minitest::Mock.new + mock.expect :update_bucket, resp_bucket_gapi(bucket_hash, ip_filter: ip_filter_gapi), + [bucket_name, patch_bucket_gapi(ip_filter: ip_filter_gapi)], **update_bucket_args(options: {retries: 0}) + + bucket.service.mocked_service = mock + + _(bucket.ip_filter).must_be_nil + + bucket.update do |b| + b.ip_filter = ip_filter_gapi + end + + _(bucket.ip_filter).wont_be_nil + _(bucket.ip_filter.mode).must_equal "Disabled" + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_equal ["0.0.0.0/0", "::/0"] + + mock.verify + end + + it "enables its ip_filter" do + enable_ip_filter_hash = { + "mode" => "Enabled", + "allowAllServiceAgentAccess" => true, + "publicNetworkSource" => { + "allowedIpCidrRanges" => ["0.0.0.0/0", "::/0"] + } + } + enable_ip_filter_gapi = Google::Apis::StorageV1::Bucket::IpFilter.from_json enable_ip_filter_hash.to_json + + mock = Minitest::Mock.new + mock.expect :update_bucket, resp_bucket_gapi(bucket_hash, ip_filter: enable_ip_filter_gapi), + [bucket_name, patch_bucket_gapi(ip_filter: enable_ip_filter_gapi)], **update_bucket_args(options: {retries: 0}) + + bucket.service.mocked_service = mock + + bucket.update do |b| + b.ip_filter = { + mode: "Enabled", + allow_all_service_agent_access: true, + public_network_source: { + allowed_ip_cidr_ranges: ["0.0.0.0/0", "::/0"] + } + } + end + + _(bucket.ip_filter).wont_be_nil + _(bucket.ip_filter.mode).must_equal "Enabled" + _(bucket.ip_filter.allow_all_service_agent_access).must_equal true + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_equal ["0.0.0.0/0", "::/0"] + + mock.verify + end + + it "deletes its ip_filter" do + delete_ip_filter_hash = { + "mode" => "Disabled", + "publicNetworkSource" => { + "allowedIpCidrRanges" => [] + } + } + delete_ip_filter_gapi = Google::Apis::StorageV1::Bucket::IpFilter.from_json delete_ip_filter_hash.to_json + + mock = Minitest::Mock.new + mock.expect :update_bucket, resp_bucket_gapi(bucket_hash, ip_filter: delete_ip_filter_gapi), + [bucket_name, patch_bucket_gapi(ip_filter: delete_ip_filter_gapi)], **update_bucket_args(options: {retries: 0}) + + bucket.service.mocked_service = mock + + bucket.update do |b| + b.ip_filter = { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: [] + } + } + end + + _(bucket.ip_filter).wont_be_nil + _(bucket.ip_filter.mode).must_equal "Disabled" + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_be_empty + + mock.verify + end + + it "clears its ip_filter with nil" do + mock = Minitest::Mock.new + mock.expect :patch_bucket, resp_bucket_gapi(bucket_hash, ip_filter: Google::Apis::StorageV1::Bucket::IpFilter.new), + [bucket_name, patch_bucket_gapi(ip_filter: Google::Apis::StorageV1::Bucket::IpFilter.new)], **patch_bucket_args(options: {retries: 0}) + + bucket.service.mocked_service = mock + + bucket.ip_filter = nil + + mock.verify + end + + def patch_bucket_gapi ip_filter: nil + Google::Apis::StorageV1::Bucket.new( + ip_filter: ip_filter + ) + end + + def resp_bucket_gapi bucket_hash, ip_filter: nil + b = Google::Apis::StorageV1::Bucket.from_json bucket_hash.to_json + b.ip_filter = ip_filter + b + end +end 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..344bd8c88378 100644 --- a/google-cloud-storage/test/google/cloud/storage/project_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/project_test.rb @@ -597,6 +597,38 @@ def creds.is_a? target _(bucket.hierarchical_namespace[:enabled]).must_equal false end + it "creates a bucket with block ip_filter" do + mock = Minitest::Mock.new + created_bucket = create_bucket_gapi bucket_name + ip_filter_hash = { + "mode" => "Disabled", + "publicNetworkSource" => { + "allowedIpCidrRanges" => ["0.0.0.0/0", "::/0"] + } + } + ip_filter_gapi = Google::Apis::StorageV1::Bucket::IpFilter.from_json ip_filter_hash.to_json + created_bucket.ip_filter = ip_filter_gapi + 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: {} + storage.service.mocked_service = mock + + bucket = storage.create_bucket bucket_name do |b| + b.ip_filter = { + mode: "Disabled", + public_network_source: { + allowed_ip_cidr_ranges: ["0.0.0.0/0", "::/0"] + } + } + end + mock.verify + + _(bucket).must_be_kind_of Google::Cloud::Storage::Bucket + _(bucket.ip_filter).wont_be_nil + _(bucket.ip_filter.mode).must_equal "Disabled" + _(bucket.ip_filter.public_network_source.allowed_ip_cidr_ranges).must_equal ["0.0.0.0/0", "::/0"] + end + it "raises when creating a bucket with a blank name" do bucket_name = ""