-
Notifications
You must be signed in to change notification settings - Fork 0
chore: add S3EC .NET v2 and v3 test server #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
rishav-karanjit
merged 37 commits into
fireegg-test-servers
from
rishav/dotnet/testserver
Sep 19, 2025
Merged
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
0d652b9
docs
rishav-karanjit fe1e1ff
init server
rishav-karanjit 833e20a
auto commit
rishav-karanjit 139b88a
Add context for q
rishav-karanjit 7ed605b
auto commit
rishav-karanjit c2826e0
auto commit
rishav-karanjit cecf9aa
auto commit
rishav-karanjit 2263f16
auto commit
rishav-karanjit e7806a4
clean up
rishav-karanjit 4e39960
:rename
rishav-karanjit b106aba
readme
rishav-karanjit bf1d6fd
auto commit
rishav-karanjit 62e9383
remove temp
rishav-karanjit d9924f0
logs
rishav-karanjit 2312865
auto commit
rishav-karanjit a039186
Merge branch 'fireegg-test-servers' of https://github.com/aws/amazon-…
rishav-karanjit a142eab
logs
rishav-karanjit f82b4ab
legacy
rishav-karanjit d01506e
makefile
rishav-karanjit 8b19cdf
auto commit
rishav-karanjit 43514e0
auto commit
rishav-karanjit 24637c5
Merge remote-tracking branch 'origin/fireegg-test-servers' into risha…
rishav-karanjit 86146f5
auto commit
rishav-karanjit b9acf93
auto commit
rishav-karanjit 6255978
Error model
rishav-karanjit 69fdd20
auto commit
rishav-karanjit 4738803
auto commit
rishav-karanjit a3baf9d
auto commit
rishav-karanjit a37a232
remove redundant import
rishav-karanjit 8d07ee4
auto commit
rishav-karanjit a89ce29
validation
rishav-karanjit f9ade30
Update test-server/net-v2-v3-server/Controllers/ObjectController.cs
rishav-karanjit ac556cb
Add not implemented feature
rishav-karanjit 8c95c21
Merge branch 'rishav/dotnet/testserver' of https://github.com/aws/ama…
rishav-karanjit 8ed7ee4
Merge branch 'fireegg-test-servers' into rishav/dotnet/testserver
rishav-karanjit 46ae023
Update test-server/java-tests/src/it/java/software/amazon/encryption/…
rishav-karanjit 0b18711
Update test-server/net-v2-v3-server/Controllers/ClientController.cs
rishav-karanjit File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # Build results | ||
| [Dd]ebug/ | ||
| [Dd]ebugPublic/ | ||
| [Rr]elease/ | ||
| [Rr]eleases/ | ||
| x64/ | ||
| x86/ | ||
| [Ww][Ii][Nn]32/ | ||
| [Aa][Rr][Mm]/ | ||
| [Aa][Rr][Mm]64/ | ||
| bld/ | ||
| [Bb]in/ | ||
| [Oo]bj/ | ||
| [Ll]og/ | ||
| [Ll]ogs/ | ||
|
|
||
| # Visual Studio 2015/2017 cache/options directory | ||
| .vs/ | ||
|
|
||
| # User-specific files | ||
| *.rsuser | ||
| *.suo | ||
| *.user | ||
| *.userosscache | ||
| *.sln.docstates | ||
|
|
||
| # NuGet Packages | ||
| *.nupkg | ||
| *.snupkg | ||
| packages/ | ||
|
|
||
| # JetBrains Rider | ||
| .idea/ | ||
| *.sln.iml | ||
|
|
||
| # VS Code | ||
| .vscode/ | ||
|
|
||
| # macOS | ||
| .DS_Store | ||
|
|
||
| # Temporary files | ||
| *.tmp | ||
| *.temp |
72 changes: 72 additions & 0 deletions
72
test-server/net-v2-v3-server/Controllers/ClientController.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| using System.Text.Json; | ||
| using Amazon.Extensions.S3.Encryption; | ||
| using Amazon.Extensions.S3.Encryption.Primitives; | ||
| using Microsoft.AspNetCore.Mvc; | ||
| using NetV2V3Server.Models; | ||
| using NetV2V3Server.Services; | ||
|
|
||
| namespace NetV2V3Server.Controllers; | ||
|
|
||
| [ApiController] | ||
| [Route("[controller]")] | ||
| public class ClientController(IClientCacheService clientCacheService, ILogger<ClientController> logger) : ControllerBase | ||
| { | ||
| [HttpPost] | ||
| public IActionResult CreateClient([FromBody] ClientRequest request) | ||
| { | ||
| // Return 501 for not implemented features by the server | ||
| if (request.Config.EnableDelayedAuthenticationMode) | ||
| return StatusCode(501, new GenericServerError { Message = "EnableDelayedAuthenticationMode not supported" }); | ||
| if (request.Config.SetBufferSize.HasValue) | ||
| return StatusCode(501, new GenericServerError { Message = "SetBufferSize not supported" }); | ||
| if (request.Config.KeyMaterial.RsaKey != null) | ||
| return StatusCode(501, new GenericServerError { Message = "RsaKey not supported" }); | ||
| if (request.Config.KeyMaterial.AesKey != null) | ||
| return StatusCode(501, new GenericServerError { Message = "AesKey not supported" }); | ||
|
|
||
| var kmsKeyId = request.Config.KeyMaterial.KmsKeyId; | ||
| var enableLegacyUnauthenticatedModes = request.Config.EnableLegacyUnauthenticatedModes; | ||
| var enableLegacyWrappingAlgorithms = request.Config.EnableLegacyWrappingAlgorithms; | ||
|
|
||
| try | ||
| { | ||
| // The POST request does not contain encryption context. | ||
| // However, encryption context is a required field when using KMS. | ||
| // So, we are passing empty dictionary. | ||
| var encryptionContext = new Dictionary<string, string>(); | ||
| var encryptionMaterial = new EncryptionMaterialsV2(kmsKeyId, KmsType.KmsContext, encryptionContext); | ||
| logger.LogInformation( | ||
| "Created EncryptionMaterialsV2: KMS={KmsKeyId}", | ||
| kmsKeyId); | ||
| // SecurityProfile V2AndLegacy can decrypt from legacy S3EC but V2 cannot | ||
| var enableLegacyMode = enableLegacyUnauthenticatedModes || enableLegacyWrappingAlgorithms; | ||
| var securityProfile = enableLegacyMode ? SecurityProfile.V2AndLegacy : SecurityProfile.V2; | ||
|
|
||
| logger.LogInformation("Created securityProfile= {securityProfile}", securityProfile.ToString()); | ||
|
|
||
| var configuration = new AmazonS3CryptoConfigurationV2(securityProfile); | ||
| // Create S3 encryption client | ||
| var encryptionClient = new AmazonS3EncryptionClientV2(configuration, encryptionMaterial); | ||
| // Add to cache and return client ID | ||
| var clientId = clientCacheService.AddClient(encryptionClient); | ||
| var response = new ClientResponse { ClientId = clientId }; | ||
|
|
||
| logger.LogInformation("Created S3EC client with ID: {clientId}", clientId); | ||
|
|
||
| return new ContentResult | ||
| { | ||
| Content = JsonSerializer.Serialize(response), | ||
| ContentType = "application/json", | ||
| StatusCode = 200 | ||
| }; | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.LogError(ex, "Failed to create S3EC client"); | ||
| return StatusCode(500, new S3EncryptionClientError | ||
| { | ||
| Message = $"Failed to create client: {ex.Message}" | ||
| }); | ||
| } | ||
| } | ||
| } |
105 changes: 105 additions & 0 deletions
105
test-server/net-v2-v3-server/Controllers/ObjectController.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| using System.Text.Json; | ||
| using Amazon.S3.Model; | ||
| using Microsoft.AspNetCore.Mvc; | ||
| using NetV2V3Server.Models; | ||
| using NetV2V3Server.Services; | ||
|
|
||
| namespace NetV2V3Server.Controllers; | ||
|
|
||
| [ApiController] | ||
| [Route("[controller]")] | ||
| public class ObjectController(IClientCacheService clientCacheService, ILogger<ObjectController> logger) : ControllerBase | ||
| { | ||
| [HttpPut("{bucket}/{key}")] | ||
| public async Task<IActionResult> PutObject(string bucket, string key) | ||
| { | ||
| logger.LogInformation("Starting PutObject"); | ||
| var clientId = Request.Headers["clientId"].FirstOrDefault(); | ||
| if (string.IsNullOrEmpty(clientId)) | ||
| return BadRequest(new GenericServerError { Message = "ClientID header is required" }); | ||
|
|
||
| var client = clientCacheService.GetClient(clientId); | ||
| if (client == null) | ||
| return NotFound(new GenericServerError { Message = $"No client found for ClientID: {clientId}" }); | ||
|
|
||
| try | ||
| { | ||
| // Read raw body data | ||
| using var memoryStream = new MemoryStream(); | ||
| // Request is the HTTP request this method is currently handling | ||
| await Request.Body.CopyToAsync(memoryStream); | ||
| var bodyBytes = memoryStream.ToArray(); | ||
|
|
||
| // Create put request | ||
| var putRequest = new PutObjectRequest | ||
| { | ||
| BucketName = bucket, | ||
| Key = key, | ||
| InputStream = new MemoryStream(bodyBytes) | ||
| }; | ||
|
|
||
| await client.PutObjectAsync(putRequest); | ||
|
|
||
| var response = new { bucket, key }; | ||
|
|
||
| logger.LogInformation( | ||
| "Put object succeeded for bucket={bucket}, key={key} and clientId = {clientId}", | ||
| bucket, key, clientId); | ||
| return new ContentResult | ||
| { | ||
| Content = JsonSerializer.Serialize(response), | ||
| ContentType = "application/json", | ||
| StatusCode = 200 | ||
| }; | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.LogError(ex, "Failed to put object from S3 for bucket={bucket}, key={key}", bucket, key); | ||
| return StatusCode(500, new S3EncryptionClientError { Message = $"Failed to put object: {ex.Message}" }); | ||
| } | ||
| } | ||
|
|
||
| [HttpGet("{bucket}/{key}")] | ||
| public async Task<IActionResult> GetObject(string bucket, string key) | ||
| { | ||
| logger.LogInformation("Starting GetObject"); | ||
| var clientId = Request.Headers["clientId"].FirstOrDefault(); | ||
| if (string.IsNullOrEmpty(clientId)) | ||
| return BadRequest(new GenericServerError { Message = "ClientID header is required" }); | ||
|
|
||
| var client = clientCacheService.GetClient(clientId); | ||
| if (client == null) | ||
| return NotFound(new GenericServerError { Message = $"No client found for ClientID: {clientId}" }); | ||
|
|
||
| try | ||
| { | ||
| var getRequest = new GetObjectRequest | ||
| { | ||
| BucketName = bucket, | ||
| Key = key | ||
| }; | ||
| var response = await client.GetObjectAsync(getRequest); | ||
| logger.LogInformation("Got object from S3 for bucket={bucket}, key={key}", bucket, key); | ||
| // Read response body | ||
| using var memoryStream = new MemoryStream(); | ||
| await response.ResponseStream.CopyToAsync(memoryStream); | ||
| var bodyBytes = memoryStream.ToArray(); | ||
|
|
||
| // Convert metadata to content-metadata header format | ||
| var metadataList = response.Metadata.Keys | ||
| .Select(metaDataKey => $"{metaDataKey}={response.Metadata[metaDataKey]}") | ||
| .ToList(); | ||
| var metadataStr = string.Join(",", metadataList); | ||
|
|
||
| // Set response headers | ||
| Response.Headers["Content-Metadata"] = metadataStr; | ||
|
|
||
| return File(bodyBytes, "application/octet-stream"); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.LogError(ex, "Failed to get object from S3 for bucket={bucket}, key={key}", bucket, key); | ||
| return StatusCode(500, new S3EncryptionClientError { Message = ex.Message }); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Makefile for S3 Encryption Client .NET Testing | ||
|
|
||
| .PHONY: start-server stop-server wait-for-server | ||
|
|
||
| PID_FILE_NET_V2 := net-v2-server.pid | ||
| PID_FILE_NET_V3 := net-v3-server.pid | ||
| PORT_NET_V2 := 8083 | ||
| PORT_NET_V3 := 8084 | ||
|
|
||
| start-server: | ||
| $(MAKE) start-net-v2-server; \ | ||
| $(MAKE) start-net-v3-server; | ||
|
|
||
| stop-server: | ||
| @if [ -f $(PID_FILE_NET_V2) ]; then \ | ||
| kill $$(cat $(PID_FILE_NET_V2)) 2>/dev/null || true; \ | ||
| rm $(PID_FILE_NET_V2); \ | ||
| fi | ||
| @if [ -f $(PID_FILE_NET_V3) ]; then \ | ||
| kill $$(cat $(PID_FILE_NET_V3)) 2>/dev/null || true; \ | ||
| rm $(PID_FILE_NET_V3); \ | ||
| fi | ||
|
|
||
| # Start .NET V2 server in background | ||
| # This builds first into bin/v2 and runs through dll | ||
| # to avoid simultaneous dotnet run conflict | ||
| start-net-v2-server: | ||
| @echo "Starting .NET V2 server..." | ||
| AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ | ||
| AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ | ||
| AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ | ||
| AWS_REGION="us-west-2" \ | ||
| rm -rf obj/v2 bin/v2 && \ | ||
| dotnet build -p:S3EncryptionVersion=v2 -o bin/v2 -p:BaseIntermediateOutputPath=obj/v2/ && \ | ||
| dotnet bin/v2/NetV2V3Server.dll > net-v2-server.log 2>&1 & echo $$! > net-v2-server.pid | ||
| @echo ".NET V2 server starting..." | ||
|
|
||
|
|
||
| # Start .NET V3 server in background | ||
| # This builds first into bin/v3 and runs through dll | ||
| # to avoid simultaneous dotnet run conflict | ||
| start-net-v3-server: | ||
| @echo "Starting .NET V3 server..." | ||
| AWS_ACCESS_KEY_ID="$$AWS_ACCESS_KEY_ID" \ | ||
| AWS_SECRET_ACCESS_KEY="$$AWS_SECRET_ACCESS_KEY" \ | ||
| AWS_SESSION_TOKEN="$$AWS_SESSION_TOKEN" \ | ||
| AWS_REGION="us-west-2" \ | ||
| rm -rf obj/v3 bin/v3 && \ | ||
| dotnet build -p:S3EncryptionVersion=v3 -o bin/v3 -p:BaseIntermediateOutputPath=obj/v3/ && \ | ||
| dotnet bin/v3/NetV2V3Server.dll > net-v3-server.log 2>&1 & echo $$! > net-v3-server.pid | ||
| @echo ".NET V3 server starting..." | ||
|
|
||
| wait-for-server: | ||
| $(MAKE) -C .. wait-for-port PORT=$(PORT_NET_V2) \ | ||
| $(MAKE) -C .. wait-for-port PORT=$(PORT_NET_V3) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.