Skip to content

Commit ea8ffe5

Browse files
committed
Add support for bucket policies
1 parent 7e21bdd commit ea8ffe5

30 files changed

+348
-14
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Genbox.ProviderTests.Misc;
2+
using Genbox.SimpleS3.Core.Abstracts;
3+
using Genbox.SimpleS3.Core.Network.Responses.Buckets;
4+
using Genbox.SimpleS3.Utility.Shared;
5+
6+
namespace Genbox.ProviderTests.Buckets;
7+
8+
public class BucketPolicyTests : TestBase
9+
{
10+
[Theory]
11+
[MultipleProviders(S3Provider.AmazonS3)] //Not supported on other cloud providers
12+
public async Task PutBucketPolicyRequest(S3Provider provider, string _, ISimpleClient client)
13+
{
14+
await CreateTempBucketAsync(provider, client, async tempBucket =>
15+
{
16+
string policy = $$"""
17+
{
18+
"Version": "2012-10-17",
19+
"Id": "Policy1740044169364",
20+
"Statement": [
21+
{
22+
"Sid": "Stmt1740044164489",
23+
"Effect": "Allow",
24+
"Principal": "*",
25+
"Action": "s3:*",
26+
"Resource": "arn:aws:s3:::{{tempBucket}}/*"
27+
}
28+
]
29+
}
30+
""";
31+
32+
PutBucketPolicyResponse getResp = await client.PutBucketPolicyAsync(tempBucket, policy);
33+
Assert.Equal(204, getResp.StatusCode);
34+
35+
GetBucketPolicyResponse putResp = await client.GetBucketPolicyAsync(tempBucket);
36+
Assert.Equal(200, putResp.StatusCode);
37+
Assert.NotEmpty(putResp.Policy);
38+
39+
DeleteBucketPolicyResponse getResp2 = await client.DeleteBucketPolicyAsync(tempBucket);
40+
Assert.Equal(204, getResp2.StatusCode);
41+
42+
GetBucketPolicyResponse putResp2 = await client.GetBucketPolicyAsync(tempBucket);
43+
Assert.Equal(404, putResp2.StatusCode);
44+
});
45+
}
46+
}

Src/SimpleS3.AmazonS3/AmazonS3Client.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public AmazonS3Client(string keyId, string accessKey, AmazonS3Region region, Net
3939
/// <param name="credentials">The credentials to use</param>
4040
/// <param name="region">The region you wish to use</param>
4141
/// <param name="networkConfig">Network configuration</param>
42-
public AmazonS3Client(IAccessKey credentials, AmazonS3Region region, NetworkConfig? networkConfig = null) : this(new AmazonS3Config(credentials, region), networkConfig) {}
42+
public AmazonS3Client(IAccessKey? credentials, AmazonS3Region region, NetworkConfig? networkConfig = null) : this(new AmazonS3Config(credentials, region), networkConfig) {}
4343

4444
/// <summary>Creates a new instance of <see cref="AmazonS3Client" /></summary>
4545
/// <param name="config">The configuration you want to use</param>
@@ -132,4 +132,10 @@ internal AmazonS3Client(IObjectClient objectClient, IBucketClient bucketClient,
132132
public string SignRequest<TReq>(TReq request, TimeSpan expiresIn) where TReq : IRequest => Client.SignRequest(request, expiresIn);
133133

134134
public Task<TResp> SendSignedRequestAsync<TResp>(string url, HttpMethodType httpMethod, Stream? content = null, CancellationToken token = default) where TResp : IResponse, new() => Client.SendSignedRequestAsync<TResp>(url, httpMethod, content, token);
135+
136+
public Task<GetBucketPolicyResponse> GetBucketPolicyAsync(string bucketName, Action<GetBucketPolicyRequest>? config = null, CancellationToken token = default) => Client.GetBucketPolicyAsync(bucketName, config, token);
137+
138+
public Task<DeleteBucketPolicyResponse> DeleteBucketPolicyAsync(string bucketName, Action<DeleteBucketPolicyRequest>? config = null, CancellationToken token = default) => Client.DeleteBucketPolicyAsync(bucketName, config, token);
139+
140+
public Task<PutBucketPolicyResponse> PutBucketPolicyAsync(string bucketName, string policy, Action<PutBucketPolicyRequest>? config = null, CancellationToken token = default) => Client.PutBucketPolicyAsync(bucketName, policy, config, token);
135141
}

Src/SimpleS3.BackBlazeB2/BackBlazeB2Client.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ internal BackBlazeB2Client(IObjectClient objectClient, IBucketClient bucketClien
8282

8383
public Task<PutPublicAccessBlockResponse> PutPublicAccessBlockAsync(string bucketName, Action<PutPublicAccessBlockRequest>? config = null, CancellationToken token = default) => throw new NotSupportedException(ErrorMessages.ProviderNotSupported);
8484

85+
public Task<GetBucketPolicyResponse> GetBucketPolicyAsync(string bucketName, Action<GetBucketPolicyRequest>? config = null, CancellationToken token = default) => throw new NotSupportedException(ErrorMessages.ProviderNotSupported);
86+
87+
public Task<DeleteBucketPolicyResponse> DeleteBucketPolicyAsync(string bucketName, Action<DeleteBucketPolicyRequest>? config = null, CancellationToken token = default) => throw new NotSupportedException(ErrorMessages.ProviderNotSupported);
88+
89+
public Task<PutBucketPolicyResponse> PutBucketPolicyAsync(string bucketName, string policy, Action<PutBucketPolicyRequest>? config = null, CancellationToken token = default) => throw new NotSupportedException(ErrorMessages.ProviderNotSupported);
90+
8591
public Task<DeleteObjectResponse> DeleteObjectAsync(string bucketName, string objectKey, Action<DeleteObjectRequest>? config = null, CancellationToken token = default) => Client.DeleteObjectAsync(bucketName, objectKey, config, token);
8692

8793
public Task<DeleteObjectsResponse> DeleteObjectsAsync(string bucketName, IEnumerable<S3DeleteInfo> objectKeys, Action<DeleteObjectsRequest>? config = null, CancellationToken token = default) => Client.DeleteObjectsAsync(bucketName, objectKeys, config, token);

Src/SimpleS3.Core.Common/Misc/AmzHeaders.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,12 @@ public static class AmzHeaders
9393
public const string XAmzCopySourceVersionId = "x-amz-copy-source-version-id";
9494

9595
#endregion
96+
97+
#region Buckets
98+
99+
public const string XAmzSdkCheckumAlgorithm = "x-amz-sdk-checksum-algorithm";
100+
public const string XAmzConfirmRemoveSelfBucketAccess = "x-amz-confirm-remove-self-bucket-access";
101+
public const string XAmzExpectedBucketOwner = "x-amz-expected-bucket-owner";
102+
103+
#endregion
96104
}

Src/SimpleS3.Core.Common/Misc/AmzParameters.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public static class AmzParameters
3838
public const string Accelerate = "accelerate";
3939
public const string Lifecycle = "lifecycle";
4040
public const string VersionIdMarker = "version-id-marker";
41+
public const string Policy = "policy";
4142

4243
#region Presigning
4344

Src/SimpleS3.Core/Abstracts/Clients/IBucketClient.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,10 @@ public interface IBucketClient
113113
Task<GetBucketLifecycleConfigurationResponse> GetBucketLifecycleConfigurationAsync(string bucketName, Action<GetBucketLifecycleConfigurationRequest>? config = null, CancellationToken token = default);
114114

115115
Task<PutPublicAccessBlockResponse> PutPublicAccessBlockAsync(string bucketName, Action<PutPublicAccessBlockRequest>? config = null, CancellationToken token = default);
116+
117+
Task<GetBucketPolicyResponse> GetBucketPolicyAsync(string bucketName, Action<GetBucketPolicyRequest>? config = null, CancellationToken token = default);
118+
119+
Task<DeleteBucketPolicyResponse> DeleteBucketPolicyAsync(string bucketName, Action<DeleteBucketPolicyRequest>? config = null, CancellationToken token = default);
120+
121+
Task<PutBucketPolicyResponse> PutBucketPolicyAsync(string bucketName, string policy, Action<PutBucketPolicyRequest>? config = null, CancellationToken token = default);
116122
}

Src/SimpleS3.Core/Abstracts/Operations/IBucketOperations.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,10 @@ public interface IBucketOperations
7777
/// Creates or modifies the PublicAccessBlock configuration for an Amazon S3 bucket. To use this operation, you must have the s3:PutBucketPublicAccessBlock permission.
7878
/// </summary>
7979
Task<PutPublicAccessBlockResponse> PutPublicAccessBlockAsync(PutPublicAccessBlockRequest request, CancellationToken token = default);
80+
81+
Task<GetBucketPolicyResponse> GetBucketPolicyAsync(GetBucketPolicyRequest request, CancellationToken token = default);
82+
83+
Task<DeleteBucketPolicyResponse> DeleteBucketPolicyAsync(DeleteBucketPolicyRequest request, CancellationToken token = default);
84+
85+
Task<PutBucketPolicyResponse> PutBucketPolicyAsync(PutBucketPolicyRequest request, CancellationToken token = default);
8086
}

Src/SimpleS3.Core/Internals/Clients/BucketClient.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,28 @@ public Task<PutPublicAccessBlockResponse> PutPublicAccessBlockAsync(string bucke
135135

136136
return operations.PutPublicAccessBlockAsync(request, token);
137137
}
138+
139+
public Task<GetBucketPolicyResponse> GetBucketPolicyAsync(string bucketName, Action<GetBucketPolicyRequest>? config = null, CancellationToken token = default)
140+
{
141+
GetBucketPolicyRequest request = new GetBucketPolicyRequest(bucketName);
142+
config?.Invoke(request);
143+
144+
return operations.GetBucketPolicyAsync(request, token);
145+
}
146+
147+
public Task<DeleteBucketPolicyResponse> DeleteBucketPolicyAsync(string bucketName, Action<DeleteBucketPolicyRequest>? config = null, CancellationToken token = default)
148+
{
149+
DeleteBucketPolicyRequest request = new DeleteBucketPolicyRequest(bucketName);
150+
config?.Invoke(request);
151+
152+
return operations.DeleteBucketPolicyAsync(request, token);
153+
}
154+
155+
public Task<PutBucketPolicyResponse> PutBucketPolicyAsync(string bucketName, string policy, Action<PutBucketPolicyRequest>? config = null, CancellationToken token = default)
156+
{
157+
PutBucketPolicyRequest request = new PutBucketPolicyRequest(bucketName, policy);
158+
config?.Invoke(request);
159+
160+
return operations.PutBucketPolicyAsync(request, token);
161+
}
138162
}

Src/SimpleS3.Core/Internals/Clients/PooledBucketClient.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,43 @@ void Setup(PutPublicAccessBlockRequest req)
215215

216216
Task<PutPublicAccessBlockResponse> ActionAsync(PutPublicAccessBlockRequest request) => BucketOperations.PutPublicAccessBlockAsync(request, token);
217217
}
218+
219+
public Task<GetBucketPolicyResponse> GetBucketPolicyAsync(string bucketName, Action<GetBucketPolicyRequest>? config = null, CancellationToken token = default)
220+
{
221+
return ObjectPool<GetBucketPolicyRequest>.Shared.RentAndUseAsync(Setup, ActionAsync);
222+
223+
void Setup(GetBucketPolicyRequest req)
224+
{
225+
req.Initialize(bucketName);
226+
config?.Invoke(req);
227+
}
228+
229+
Task<GetBucketPolicyResponse> ActionAsync(GetBucketPolicyRequest request) => BucketOperations.GetBucketPolicyAsync(request, token);
230+
}
231+
232+
public Task<DeleteBucketPolicyResponse> DeleteBucketPolicyAsync(string bucketName, Action<DeleteBucketPolicyRequest>? config = null, CancellationToken token = default)
233+
{
234+
return ObjectPool<DeleteBucketPolicyRequest>.Shared.RentAndUseAsync(Setup, ActionAsync);
235+
236+
void Setup(DeleteBucketPolicyRequest req)
237+
{
238+
req.Initialize(bucketName);
239+
config?.Invoke(req);
240+
}
241+
242+
Task<DeleteBucketPolicyResponse> ActionAsync(DeleteBucketPolicyRequest request) => BucketOperations.DeleteBucketPolicyAsync(request, token);
243+
}
244+
245+
public Task<PutBucketPolicyResponse> PutBucketPolicyAsync(string bucketName, string policy, Action<PutBucketPolicyRequest>? config = null, CancellationToken token = default)
246+
{
247+
return ObjectPool<PutBucketPolicyRequest>.Shared.RentAndUseAsync(Setup, ActionAsync);
248+
249+
void Setup(PutBucketPolicyRequest req)
250+
{
251+
req.Initialize(bucketName, policy);
252+
config?.Invoke(req);
253+
}
254+
255+
Task<PutBucketPolicyResponse> ActionAsync(PutBucketPolicyRequest request) => BucketOperations.PutBucketPolicyAsync(request, token);
256+
}
218257
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Genbox.SimpleS3.Core.Abstracts;
2+
using Genbox.SimpleS3.Core.Abstracts.Request;
3+
using Genbox.SimpleS3.Core.Common.Misc;
4+
using Genbox.SimpleS3.Core.Network.Requests.Buckets;
5+
6+
namespace Genbox.SimpleS3.Core.Internals.Marshallers.Requests.Buckets;
7+
8+
internal sealed class DeleteBucketPolicyRequestMarshal : IRequestMarshal<DeleteBucketPolicyRequest>
9+
{
10+
public Stream? MarshalRequest(DeleteBucketPolicyRequest request, SimpleS3Config config)
11+
{
12+
request.SetQueryParameter(AmzParameters.Policy, string.Empty);
13+
return null;
14+
}
15+
}

0 commit comments

Comments
 (0)