Skip to content

Commit 1b840a7

Browse files
committed
feat: add createBucketWithIpFilter sample and update IP filtering utility scripts and tests
1 parent fb90ae8 commit 1b840a7

5 files changed

Lines changed: 94 additions & 15 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
function main(bucketName = 'my-bucket', filterMode = 'Enabled') {
18+
// [START storage_create_bucket_ip_filtering]
19+
/**
20+
* TODO(developer): Uncomment the following lines before running the sample.
21+
*/
22+
// The ID of your GCS bucket
23+
// const bucketName = 'your-unique-bucket-name';
24+
25+
// Toggle data filtering (e.g., 'Enabled' | 'Disabled')
26+
// const filterMode = 'Enabled';
27+
28+
// Imports the Google Cloud client library
29+
const {Storage} = require('@google-cloud/storage');
30+
31+
// Creates a client
32+
const storage = new Storage();
33+
34+
async function createBucketWithIpFilter() {
35+
const ipFilter = {
36+
mode: filterMode,
37+
publicNetworkSource: {
38+
allowedIpCidrRanges: ['8.8.8.8/32'],
39+
},
40+
allowCrossOrgVpcs: false,
41+
allowAllServiceAgentAccess: false,
42+
};
43+
44+
const [bucket] = await storage.createBucket(bucketName, {
45+
ipFilter: ipFilter,
46+
});
47+
48+
console.log(
49+
`Bucket ${bucket.name} created with IP filter mode ${bucket.metadata.ipFilter.mode}.`
50+
);
51+
}
52+
53+
createBucketWithIpFilter().catch(console.error);
54+
// [END storage_create_bucket_ip_filtering]
55+
}
56+
57+
main(...process.argv.slice(2));

storage/deleteBucketIpFilterRules.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ function main(bucketName = 'my-bucket', cidrToDelete = '8.8.8.8/32') {
2121
*/
2222
// The ID of your GCS bucket
2323
// const bucketName = 'your-unique-bucket-name';
24+
25+
// Target IP address/CIDR block to remove
2426
// const cidrToDelete = '8.8.8.8/32';
2527

2628
// Imports the Google Cloud client library
@@ -33,14 +35,25 @@ function main(bucketName = 'my-bucket', cidrToDelete = '8.8.8.8/32') {
3335
// Note: To delete specific rules, you fetch the existing config, filter out the rules, and update.
3436
const [metadata] = await storage.bucket(bucketName).getMetadata();
3537

36-
if (!metadata.ipFilter) {
37-
console.log(`No IP Filter configuration found for bucket ${bucketName}.`);
38+
if (!metadata.ipFilter || !metadata.ipFilter.publicNetworkSource) {
39+
console.log(
40+
`No IP Filter public network configuration found for bucket ${bucketName}.`
41+
);
42+
return;
43+
}
44+
45+
const currentIpRanges =
46+
metadata.ipFilter.publicNetworkSource.allowedIpCidrRanges || [];
47+
if (!currentIpRanges.includes(cidrToDelete)) {
48+
console.log(
49+
`CIDR range ${cidrToDelete} not found in bucket ${bucketName}. No changes made.`
50+
);
3851
return;
3952
}
4053

41-
const updatedIpRanges = (
42-
metadata.ipFilter.publicNetworkSource?.allowedIpCidrRanges || []
43-
).filter(range => range !== cidrToDelete);
54+
const updatedIpRanges = currentIpRanges.filter(
55+
range => range !== cidrToDelete
56+
);
4457

4558
const updatedIpFilter = {
4659
...metadata.ipFilter,

storage/enableBucketIpFilter.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ function main(bucketName = 'my-bucket', filterMode = 'Enabled') {
2222
// The ID of your GCS bucket
2323
// const bucketName = 'your-unique-bucket-name';
2424

25+
// Toggle data filtering (e.g., 'Enabled' | 'Disabled')
26+
// const filterMode = 'Enabled';
27+
2528
// Imports the Google Cloud client library
2629
const {Storage} = require('@google-cloud/storage');
2730

@@ -34,7 +37,7 @@ function main(bucketName = 'my-bucket', filterMode = 'Enabled') {
3437
const [metadata] = await storage.bucket(bucketName).getMetadata();
3538
const existingIpFilter = metadata.ipFilter || {
3639
mode: filterMode,
37-
publicNetworkSource: {allowedIpCidrRanges: ['0.0.0.0/0']},
40+
publicNetworkSource: {allowedIpCidrRanges: []},
3841
allowCrossOrgVpcs: false,
3942
allowAllServiceAgentAccess: false,
4043
};

storage/listBucketIpFilters.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,14 @@
1414

1515
'use strict';
1616

17-
function main(projectId = 'my-project-id') {
17+
function main() {
1818
// [START storage_list_buckets_ip_filtering]
19-
/**
20-
* TODO(developer): Uncomment the following lines before running the sample.
21-
*/
22-
// The ID of the project to which the service account belongs
23-
// const projectId = 'my-project-id';
2419

2520
// Imports the Google Cloud client library
2621
const {Storage} = require('@google-cloud/storage');
2722

2823
// Creates a client
29-
const storage = new Storage({projectId});
24+
const storage = new Storage();
3025

3126
async function listBucketsIpFiltering() {
3227
const [buckets] = await storage.getBuckets();

storage/system-test/buckets.test.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,17 @@ it('should update and then remove bucket encryption enforcement configuration',
142142
assert.ok(!metadata.encryption);
143143
});
144144

145+
it('should create a bucket with IP filter', () => {
146+
const newBucketName = `${samplesTestBucketPrefix}-c`;
147+
const output = execSync(
148+
`node createBucketWithIpFilter.js ${newBucketName} Disabled`
149+
);
150+
assert.include(
151+
output,
152+
`Bucket ${newBucketName} created with IP filter mode Disabled.`
153+
);
154+
});
155+
145156
it('should enable the bucket IP filter', () => {
146157
const output = execSync(
147158
`node enableBucketIpFilter.js ${bucketName} Disabled`
@@ -160,8 +171,7 @@ it('should get the bucket IP filter', () => {
160171
});
161172

162173
it('should list the bucket IP filters', () => {
163-
const projectId = process.env.GCLOUD_PROJECT;
164-
const output = execSync(`node listBucketIpFilters.js ${projectId}`);
174+
const output = execSync('node listBucketIpFilters.js');
165175
assert.include(output, `${bucketName}: IP Filter Mode - Disabled`);
166176
assert.include(output, 'Public Network Allowed IP Ranges:');
167177
assert.include(output, '- 8.8.8.8/32');
@@ -173,6 +183,7 @@ it('should delete specific bucket IP filter rules', () => {
173183
output,
174184
`Specific IP Filter rules deleted for bucket ${bucketName}.`
175185
);
186+
assert.notInclude(output, '8.8.8.8/32');
176187
});
177188

178189
it('should disable the bucket IP filter', () => {

0 commit comments

Comments
 (0)