Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions google-cloud-storage/acceptance/storage/bucket_ip_filter_test.rb
Original file line number Diff line number Diff line change
@@ -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
70 changes: 70 additions & 0 deletions google-cloud-storage/lib/google/cloud/storage/bucket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems these values are not correct

# - :public_network_source - [Hash] The public network source configuration:
# - :allowed_ip_cidr_ranges - [Array<String>] Array of IP CIDR ranges allowed for public access.
# - :vpc_network_sources - [Array<Hash>] 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<String>] 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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check this if you pass empty and using patch API make the API remove the existing IP filter instead of patching, check this logic

end
Comment thread
shubhangi-google marked this conversation as resolved.

##
# Retrieves a list of files matching the criteria.
#
Expand Down
20 changes: 18 additions & 2 deletions google-cloud-storage/lib/google/cloud/storage/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

values only enabled and disabled

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shubhangi-google resolve the conflict as well

# - :public_network_source - [Hash] The public network source configuration:
# - :allowed_ip_cidr_ranges - [Array<String>] Array of IP CIDR ranges allowed for public access.
# - :vpc_network_sources - [Array<Hash>] 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<String>] 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
Expand Down Expand Up @@ -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? }
Comment thread
shubhangi-google marked this conversation as resolved.
new_bucket = Google::Apis::StorageV1::Bucket.new(**params)
storage_class = storage_class_for storage_class
Expand All @@ -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!
Expand Down
67 changes: 67 additions & 0 deletions google-cloud-storage/samples/acceptance/buckets_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
41 changes: 41 additions & 0 deletions google-cloud-storage/samples/storage_delete_bucket_ip_filter.rb
Original file line number Diff line number Diff line change
@@ -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
Loading