Skip to content
64 changes: 64 additions & 0 deletions storage/deleteBucketIpFilterRules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// 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.

'use strict';

function main(bucketName = 'my-bucket') {
// [START storage_delete_ip_filtering_rules]
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

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

// Creates a client
const storage = new Storage();

async function deleteBucketIpFilterRules() {
// Note: To delete specific rules, you fetch the existing config, filter out the rules, and update.
const [metadata] = await storage.bucket(bucketName).getMetadata();

if (!metadata.ipFilter) {
console.log(`No IP Filter configuration found for bucket ${bucketName}.`);
return;
}

const updatedIpRanges = (
metadata.ipFilter.publicNetworkSource?.allowedIpCidrRanges || []
).filter(range => range !== '8.8.8.8/32');

const updatedIpFilter = {
...metadata.ipFilter,
publicNetworkSource: {
...metadata.ipFilter.publicNetworkSource,
allowedIpCidrRanges: updatedIpRanges,
},
};

const [updatedMetadata] = await storage.bucket(bucketName).setMetadata({
ipFilter: updatedIpFilter,
});

console.log(`Specific IP Filter rules deleted for bucket ${bucketName}.`);
console.log(JSON.stringify(updatedMetadata.ipFilter, null, 2));
}

deleteBucketIpFilterRules().catch(console.error);
// [END storage_delete_ip_filtering_rules]
}

main(...process.argv.slice(2));
48 changes: 48 additions & 0 deletions storage/disableBucketIpFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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.

'use strict';

function main(bucketName = 'my-bucket') {
// [START storage_disable_ip_filtering]
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

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

// Creates a client
const storage = new Storage();

async function disableBucketIpFilter() {
const ipFilter = {
mode: 'Disabled',
};

const [updatedMetadata] = await storage.bucket(bucketName).setMetadata({
ipFilter,
});

console.log(`IP Filter disabled for bucket ${bucketName}.`);
console.log(JSON.stringify(updatedMetadata.ipFilter, null, 2));
}

disableBucketIpFilter().catch(console.error);
// [END storage_disable_ip_filtering]
}

main(...process.argv.slice(2));
71 changes: 71 additions & 0 deletions storage/enableBucketIpFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// 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.

'use strict';

function main(bucketName = 'my-bucket', filterMode = 'Enabled') {
// [START storage_enable_ip_filtering]
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

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

// Creates a client
const storage = new Storage();

async function enableBucketIpFilter() {
// Note: IP Filter configurations cannot be partially updated.
// We must fetch the existing configuration and modify it, or set a completely new one.
const [metadata] = await storage.bucket(bucketName).getMetadata();
const existingIpFilter = metadata.ipFilter || {
mode: filterMode,
publicNetworkSource: {allowedIpCidrRanges: ['0.0.0.0/0']},
allowCrossOrgVpcs: false,
allowAllServiceAgentAccess: false,
};

// Add a new IP range to publicNetworkSource
const updatedIpRanges = [
...(existingIpFilter.publicNetworkSource?.allowedIpCidrRanges || []),
];
if (!updatedIpRanges.includes('8.8.8.8/32')) {
updatedIpRanges.push('8.8.8.8/32');
}

const updatedIpFilter = {
...existingIpFilter,
mode: filterMode,
publicNetworkSource: {
...existingIpFilter.publicNetworkSource,
allowedIpCidrRanges: updatedIpRanges,
},
};

const [updatedMetadata] = await storage.bucket(bucketName).setMetadata({
ipFilter: updatedIpFilter,
});

console.log(`IP Filter mode set to ${updatedMetadata.ipFilter.mode} for bucket ${bucketName}.`);
console.log(JSON.stringify(updatedMetadata.ipFilter, null, 2));
}

enableBucketIpFilter().catch(console.error);
// [END storage_enable_ip_filtering]
}

main(...process.argv.slice(2));
47 changes: 47 additions & 0 deletions storage/getBucketIpFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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.

'use strict';

function main(bucketName = 'my-bucket') {
// [START storage_get_ip_filtering]
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

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

// Creates a client
const storage = new Storage();

async function getBucketIpFilter() {
const [metadata] = await storage.bucket(bucketName).getMetadata();

if (metadata.ipFilter) {
console.log(`IP Filter Mode: ${metadata.ipFilter.mode}`);
console.log('IP Filter Configuration:');
console.log(JSON.stringify(metadata.ipFilter, null, 2));
} else {
console.log(`No IP Filter configuration found for bucket ${bucketName}.`);
}
}

getBucketIpFilter().catch(console.error);
// [END storage_get_ip_filtering]
}

main(...process.argv.slice(2));
74 changes: 74 additions & 0 deletions storage/listBucketIpFilters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// 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.

'use strict';

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

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

// Creates a client
const storage = new Storage({projectId});

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

for (const bucket of buckets) {
if (bucket.metadata?.ipFilter) {
try {
const [metadata] = await storage.bucket(bucket.name).getMetadata();
const ipFilter = metadata.ipFilter;
console.log(`${bucket.name}: IP Filter Mode - ${ipFilter.mode}`);

const publicNetworkSource = ipFilter.publicNetworkSource;
if (publicNetworkSource && publicNetworkSource.allowedIpCidrRanges) {
console.log(' Public Network Allowed IP Ranges:');
publicNetworkSource.allowedIpCidrRanges.forEach(range => {
console.log(` - ${range}`);
});
}

const vpcNetworkSources = ipFilter.vpcNetworkSources;
if (vpcNetworkSources && vpcNetworkSources.length > 0) {
console.log(' VPC Network Sources:');
vpcNetworkSources.forEach(source => {
console.log(` - Network: ${source.network}`);
if (source.allowedIpCidrRanges) {
source.allowedIpCidrRanges.forEach(range => {
console.log(` - ${range}`);
});
}
});
}
} catch (err) {
console.log(
`${bucket.name}: Error fetching IP filter - ${err.message}`
);
}
}
Comment thread
thiyaguk09 marked this conversation as resolved.
}
}

listBucketsIpFiltering().catch(console.error);
// [END storage_list_buckets_ip_filtering]
}

main(...process.argv.slice(2));
36 changes: 36 additions & 0 deletions storage/system-test/buckets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,39 @@ it('should update and then remove bucket encryption enforcement configuration',
const [metadata] = await bucket.getMetadata();
assert.ok(!metadata.encryption);
});

it('should enable the bucket IP filter', () => {
const output = execSync(
`node enableBucketIpFilter.js ${bucketName} Disabled`
);
assert.include(output, `IP Filter mode set to Disabled for bucket ${bucketName}.`);
assert.include(output, '8.8.8.8/32');
});

it('should get the bucket IP filter', () => {
const output = execSync(`node getBucketIpFilter.js ${bucketName}`);
assert.include(output, 'IP Filter Mode: Disabled');
assert.include(output, '8.8.8.8/32');
});

it('should list the bucket IP filters', () => {
const projectId = process.env.GCLOUD_PROJECT;
const output = execSync(`node listBucketIpFilters.js ${projectId}`);
assert.include(output, `${bucketName}: IP Filter Mode - Disabled`);
assert.include(output, 'Public Network Allowed IP Ranges:');
assert.include(output, '- 8.8.8.8/32');
});

it('should delete specific bucket IP filter rules', () => {
const output = execSync(`node deleteBucketIpFilterRules.js ${bucketName}`);
assert.include(
output,
`Specific IP Filter rules deleted for bucket ${bucketName}.`
);
});

it('should disable the bucket IP filter', () => {
const output = execSync(`node disableBucketIpFilter.js ${bucketName}`);
assert.include(output, `IP Filter disabled for bucket ${bucketName}.`);
assert.include(output, '"mode": "Disabled"');
});