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
45 changes: 45 additions & 0 deletions storage/api/Storage.Samples.Tests/DeleteBucketIpFilterTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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.

using Google.Cloud.Storage.V1;
using System.Linq;
using Xunit;

[Collection(nameof(StorageFixture))]
public class DeleteBucketIpFilterTest
{
private readonly StorageFixture _fixture;

public DeleteBucketIpFilterTest(StorageFixture fixture)
{
_fixture = fixture;
}

[Fact]
public void TestDeleteBucketIpFilter()
{
var deleteSample = new DeleteBucketIpFilterSample();
var storage = StorageClient.Create();
var bucketName = _fixture.GenerateBucketName();
var ipFilteredBucket = _fixture.CreateBucket(bucketName, multiVersion: false, ipFilter: true, registerForDeletion: true);
string targetPublicIp = "0.0.0.0/0";
string targetVpc = $"projects/{_fixture.ProjectId}/global/networks/default";
deleteSample.DeleteBucketIpFilter(bucketName, targetPublicIp, targetVpc);
var updatedBucket = storage.GetBucket(bucketName);
Assert.NotNull(updatedBucket.IpFilter);
Assert.NotNull(updatedBucket.IpFilter.PublicNetworkSource);
Assert.DoesNotContain(targetPublicIp, updatedBucket.IpFilter.PublicNetworkSource.AllowedIpCidrRanges);
Assert.False(updatedBucket.IpFilter?.VpcNetworkSources?.Any(v => v.Network == targetVpc) ?? false);
Comment on lines +39 to +43
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If updatedBucket.IpFilter or updatedBucket.IpFilter.PublicNetworkSource is null, the test will fail with a NullReferenceException instead of a clear assertion failure. Adding explicit Assert.NotNull checks improves test clarity and diagnostic messages.

        var updatedBucket = storage.GetBucket(bucketName);
        Assert.NotNull(updatedBucket.IpFilter);
        Assert.NotNull(updatedBucket.IpFilter.PublicNetworkSource);
        Assert.DoesNotContain(targetPublicIp, updatedBucket.IpFilter.PublicNetworkSource.AllowedIpCidrRanges);
        Assert.False(updatedBucket.IpFilter.VpcNetworkSources?.Any(v => v.Network == targetVpc) ?? false);

}
}
110 changes: 110 additions & 0 deletions storage/api/Storage.Samples.Tests/DisableBucketIpFilterTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// 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.

using Google;
using Google.Apis.Storage.v1.Data;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

[Collection(nameof(StorageFixture))]
public class DisableBucketIpFilterTest
{
private readonly StorageFixture _fixture;

public DisableBucketIpFilterTest(StorageFixture fixture)
{
_fixture = fixture;
}

[Fact]
public async Task TestDisableBucketIpFilter()
{
var disableSample = new DisableBucketIpFilterSample();
var enableSample = new EnableBucketIpFilterSample();
var projectId = _fixture.ProjectId;
var bucketName = _fixture.GenerateBucketName();
_fixture.CreateBucket(bucketName, multiVersion: false, ipFilter: true, registerForDeletion: true);
string dynamicIp = await GetPublicIpAsync();
var newPublicRange = $"{dynamicIp}/32";
var ipFilterEnabledBucket = enableSample.EnableBucketIpFilter(projectId, bucketName, publicRange: newPublicRange);
Bucket unfilteredBucket = null;
int maxRetries = 6;
int delayMilliseconds = 5000;
bool isPropagationBlocked = false;

for (int i = 0; i < maxRetries; i++)
{
try
{
unfilteredBucket = disableSample.DisableBucketIpFilter(ipFilterEnabledBucket.Name);
isPropagationBlocked = false;
break;
}
catch (GoogleApiException ex) when (ex.HttpStatusCode == HttpStatusCode.Forbidden)
{
isPropagationBlocked = true;
if (i < maxRetries - 1)
{
await Task.Delay(delayMilliseconds);
}
}
}
if (isPropagationBlocked)
{
Assert.True(isPropagationBlocked, "Firewall propagation timeout encountered.");
return;
}
Comment on lines +66 to +70
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The assertion Assert.True(isPropagationBlocked, ...) is executed inside the if (isPropagationBlocked) block, meaning isPropagationBlocked is guaranteed to be true. As a result, this assertion will always pass, and the subsequent return; will cause the test to succeed silently even if firewall propagation timed out. If the intention is to fail the test when propagation is blocked, you should use Assert.False(isPropagationBlocked, ...) instead.

        Assert.False(isPropagationBlocked, "Firewall propagation timeout encountered.");


Assert.NotNull(unfilteredBucket.IpFilter);
Assert.Equal("Disabled", unfilteredBucket.IpFilter.Mode);
Assert.NotNull(unfilteredBucket.IpFilter.PublicNetworkSource?.AllowedIpCidrRanges);
Assert.Contains("203.0.113.0/24", unfilteredBucket.IpFilter.PublicNetworkSource.AllowedIpCidrRanges);
}

private async Task<string> GetPublicIpAsync()
{
string[] ipServices = new[]
{
"https://api.ipify.org",
"https://icanhazip.com",
"https://ifconfig.me/ip",
"https://ident.me"
};

using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(3);

foreach (var service in ipServices)
{
try
{
string ip = (await client.GetStringAsync(service)).Trim();
if (IPAddress.TryParse(ip, out _))
{
return ip;
}
}
catch (Exception)
{
// Log or ignore, try the next service
}
}
}
throw new InvalidOperationException("Failed to resolve public IP from all fallback services.");
}
}
50 changes: 50 additions & 0 deletions storage/api/Storage.Samples.Tests/EnableBucketIpFilterTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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.

using System.Linq;
using Xunit;

[Collection(nameof(StorageFixture))]
public class EnableBucketIpFilterTest
{
private readonly StorageFixture _fixture;

public EnableBucketIpFilterTest(StorageFixture fixture)
{
_fixture = fixture;
}

[Fact]
public void TestEnableBucketIpFilter()
{
var updateSample = new EnableBucketIpFilterSample();
var bucketName = _fixture.GenerateBucketName();
var projectId = _fixture.ProjectId;
string newPublicRange = "192.0.2.0/24";
string newVpcRange = "10.0.0.0/24";
_fixture.CreateBucket(bucketName, multiVersion: false, ipFilter: false, registerForDeletion: true);
var updatedBucket = updateSample.EnableBucketIpFilter(projectId, bucketName);
Assert.NotNull(updatedBucket.IpFilter);
Assert.Equal("Enabled", updatedBucket.IpFilter.Mode);
var publicRanges = updatedBucket.IpFilter.PublicNetworkSource?.AllowedIpCidrRanges;
Assert.NotNull(publicRanges);
Assert.Contains(newPublicRange, publicRanges);
var vpcNetwork = updatedBucket.IpFilter.VpcNetworkSources?
.FirstOrDefault(v => v.Network == $"projects/{projectId}/global/networks/default");
Assert.NotNull(vpcNetwork);
var vpcRanges = vpcNetwork.AllowedIpCidrRanges;
Assert.NotNull(vpcRanges);
Assert.Contains(newVpcRange, vpcRanges);
}
}
43 changes: 43 additions & 0 deletions storage/api/Storage.Samples.Tests/GetBucketIpFilterTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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.

using Xunit;

[Collection(nameof(StorageFixture))]
public class GetBucketIpFilterTest
{
private readonly StorageFixture _fixture;

public GetBucketIpFilterTest(StorageFixture fixture)
{
_fixture = fixture;
}

[Fact]
public void TestGetBucketIpFilter()
{
var getIpFilter = new GetBucketIpFilterSample();
var bucketName = _fixture.GenerateBucketName();
_fixture.CreateBucket(bucketName, multiVersion: false, ipFilter: true, registerForDeletion: true);
var bucketIpFilter = getIpFilter.GetBucketIpFilter(bucketName);
Assert.NotNull(bucketIpFilter);
Assert.Equal("Disabled", bucketIpFilter.Mode);
Assert.False(bucketIpFilter.AllowAllServiceAgentAccess);
Assert.False(bucketIpFilter.AllowCrossOrgVpcs);
Assert.NotNull(bucketIpFilter.PublicNetworkSource);
Assert.NotNull(bucketIpFilter.PublicNetworkSource.AllowedIpCidrRanges);
Assert.Contains("203.0.113.0/24", bucketIpFilter.PublicNetworkSource.AllowedIpCidrRanges);
Assert.NotNull(bucketIpFilter.VpcNetworkSources);
}
}
Original file line number Diff line number Diff line change
@@ -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.

using System.Linq;
using Xunit;

[Collection(nameof(StorageFixture))]
public class ListBucketsWithIpFilterStatusTest
{
private readonly StorageFixture _fixture;

public ListBucketsWithIpFilterStatusTest(StorageFixture fixture)
{
_fixture = fixture;
}

[Fact]
public void TestListBucketsWithIpFilterStatus()
{
var listBucketsWithIpFilter = new ListBucketsWithIpFilterStatusSample();
var bucketName = _fixture.GenerateBucketName();
_fixture.CreateBucket(bucketName, multiVersion: false, ipFilter: true, registerForDeletion: true);
var buckets = listBucketsWithIpFilter.ListBucketsWithIpFilterStatus(_fixture.ProjectId);
var targetBucket = buckets.FirstOrDefault(b => b.Name == bucketName);
Assert.NotNull(targetBucket);
Assert.Equal("Disabled", targetBucket.IpFilter?.Mode);
}
}
28 changes: 27 additions & 1 deletion storage/api/Storage.Samples.Tests/StorageFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public void CreateBucket(string bucketName, string location = null, AutoclassDat
TempBucketNames.Add(bucketName);
}

internal Bucket CreateBucket(string name, bool multiVersion, bool softDelete = false, bool registerForDeletion = true)
internal Bucket CreateBucket(string name, bool multiVersion, bool softDelete = false, bool ipFilter = false, bool registerForDeletion = true)
{
var bucket = Client.CreateBucket(ProjectId,
new Bucket
Expand All @@ -227,6 +227,32 @@ internal Bucket CreateBucket(string name, bool multiVersion, bool softDelete = f
Versioning = new Bucket.VersioningData { Enabled = multiVersion },
// The minimum allowed for soft delete is 7 days.
SoftDeletePolicy = softDelete ? new Bucket.SoftDeletePolicyData { RetentionDurationSeconds = (int) TimeSpan.FromDays(7).TotalSeconds } : null,
IpFilter = ipFilter ? new Bucket.IpFilterData
{
Mode = "Disabled",
PublicNetworkSource = new Bucket.IpFilterData.PublicNetworkSourceData
{
AllowedIpCidrRanges = new List<string>
{
"203.0.113.0/24",
"198.51.100.10/32",
"0.0.0.0/0"
}
},
VpcNetworkSources = new List<Bucket.IpFilterData.VpcNetworkSourcesData>
{
new Bucket.IpFilterData.VpcNetworkSourcesData
{
Network = $"projects/{ProjectId}/global/networks/default",
AllowedIpCidrRanges = new List<string>
{
"0.0.0.0/0"
}
}
},
AllowAllServiceAgentAccess = false,
AllowCrossOrgVpcs = false
} : null
});
SleepAfterBucketCreateUpdateDelete();
if (registerForDeletion)
Expand Down
Loading