AWS code-library documentation change
Summary
Updated S3 .NET SDK example from v3 to v4, added interactive scenario mode with dependency injection, improved error handling, added non-interactive mode support, and implemented temporary file cleanup.
Security assessment
The changes focus on code modernization (dependency injection, async/await) and usability improvements (interactive/non-interactive modes). No security vulnerabilities are addressed, and no security-specific features are documented. The temporary file cleanup improves hygiene but doesn't address a specific security vulnerability.
Diff
diff --git a/code-library/latest/ug/s3_example_s3_Scenario_GettingStarted_section.md b/code-library/latest/ug/s3_example_s3_Scenario_GettingStarted_section.md index a77e6b2c7..50a252532 100644 --- a//code-library/latest/ug/s3_example_s3_Scenario_GettingStarted_section.md +++ b//code-library/latest/ug/s3_example_s3_Scenario_GettingStarted_section.md @@ -27 +27 @@ The following code examples show how to: -**SDK for .NET** +**SDK for .NET (v4)** @@ -32 +32,3 @@ The following code examples show how to: -There's more on GitHub. Find the complete example and learn how to set up and run in the [AWS Code Examples Repository](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics#code-examples). +There's more on GitHub. Find the complete example and learn how to set up and run in the [AWS Code Examples Repository](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv4/S3#code-examples). + +Run an interactive scenario demonstrating Amazon S3 features. @@ -37 +39,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - public static async Task Main() + public static bool IsInteractive = true; + public static string BucketName = null!; + public static string TempFilePath = null!; + public static S3Wrapper _s3Wrapper = null!; + public static ILogger<S3_Basics> _logger = null!; + + public static async Task Main(string[] args) @@ -39,8 +47,10 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - // Create an Amazon S3 client object. The constructor uses the - // default user installed on the system. To work with Amazon S3 - // features in a different AWS Region, pass the AWS Region as a - // parameter to the client constructor. - IAmazonS3 client = new AmazonS3Client(); - string bucketName = string.Empty; - string filePath = string.Empty; - string keyName = string.Empty; + // Set up dependency injection for the Amazon service. + using var host = Host.CreateDefaultBuilder(args) + .ConfigureServices((_, services) => + services.AddAWSService<IAmazonS3>() + .AddTransient<S3Wrapper>() + .AddLogging(builder => builder.AddConsole())) + .Build(); + + _logger = LoggerFactory.Create(builder => builder.AddConsole()) + .CreateLogger<S3_Basics>(); @@ -48 +58,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - var sepBar = new string('-', Console.WindowWidth); + _s3Wrapper = host.Services.GetRequiredService<S3Wrapper>(); + + var sepBar = new string('-', 45); @@ -60,0 +73,23 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + await RunScenario(_s3Wrapper, _logger); + + Console.WriteLine(sepBar); + Console.WriteLine("The Amazon S3 scenario has successfully completed."); + Console.WriteLine(sepBar); + } + + /// <summary> + /// Run the S3 Basics scenario with injected dependencies. + /// </summary> + /// <param name="s3Wrapper">The S3 wrapper instance.</param> + /// <param name="scenarioLogger">The logger instance.</param> + /// <returns>A Task object.</returns> + public static async Task RunScenario(S3Wrapper s3Wrapper, ILogger<S3_Basics> scenarioLogger) + { + string bucketName = BucketName; + string filePath = TempFilePath; + string keyName = string.Empty; + + var sepBar = new string('-', 45); + + try + { @@ -65,0 +101,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if (IsInteractive) + { @@ -67,0 +105,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + } + else + { + Console.WriteLine($"Using bucket name: {bucketName}"); + } @@ -69 +111 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - var success = await S3Bucket.CreateBucketAsync(client, bucketName); + var success = await s3Wrapper.CreateBucketAsync(bucketName); @@ -82,0 +125,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if (IsInteractive) + { @@ -95,0 +140,18 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + } + else + { + // Use the public variable if set, otherwise create a temp file + if (!string.IsNullOrEmpty(TempFilePath)) + { + filePath = TempFilePath; + Console.WriteLine($"Using provided test file: {filePath}"); + } + else + { + // Create a temporary test file for non-interactive mode + filePath = Path.GetTempFileName(); + var testContent = "This is a test file for S3 basics scenario.\nGenerated on: " + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss UTC"); + await File.WriteAllTextAsync(filePath, testContent); + Console.WriteLine($"Created temporary test file: {filePath}"); + } + } @@ -100 +162 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - success = await S3Bucket.UploadFileAsync(client, bucketName, keyName, filePath); + success = await s3Wrapper.UploadFileAsync(bucketName, keyName, filePath); @@ -111,3 +173,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - // Set the file path to an empty string to avoid overwriting the - // file we just uploaded to the bucket. - filePath = string.Empty; + // Set up download path + string downloadPath = string.Empty; @@ -114,0 +176,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if (IsInteractive) + { @@ -116 +179 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - while (string.IsNullOrEmpty(filePath)) + while (string.IsNullOrEmpty(downloadPath)) @@ -120 +183 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - filePath = Console.ReadLine(); + downloadPath = Console.ReadLine(); @@ -122,2 +185,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - // Confirm that the file exists on the local computer. - if (File.Exists($"{filePath}\\{keyName}")) + // Confirm that the file doesn't already exist on the local computer. + if (File.Exists($"{downloadPath}\\{keyName}")) @@ -126 +189,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - filePath = string.Empty; + downloadPath = string.Empty; + } @@ -128,0 +193,11 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + else + { + downloadPath = Path.GetTempPath(); + var downloadFile = Path.Combine(downloadPath, keyName); + if (File.Exists(downloadFile)) + { + File.Delete(downloadFile); + } + + Console.WriteLine($"Using download path: {downloadPath}"); + } @@ -131 +206 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - success = await S3Bucket.DownloadObjectFromBucketAsync(client, bucketName, keyName, filePath); + success = await s3Wrapper.DownloadObjectFromBucketAsync(bucketName, keyName, downloadPath); @@ -144,0 +220,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if (IsInteractive) + { @@ -150,2 +227,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - - while (string.IsNullOrEmpty(keyName)) + } + else @@ -153,3 +230,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - // Get the name to give to the object once uploaded. - Console.Write("Enter the name of the object to copy: "); - keyName = Console.ReadLine(); + folderName = "test-folder"; + Console.WriteLine($"Using folder name: {folderName}"); @@ -158 +234 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - await S3Bucket.CopyObjectInBucketAsync(client, bucketName, keyName, folderName); + await s3Wrapper.CopyObjectInBucketAsync(bucketName, keyName, folderName); @@ -161 +237 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - await S3Bucket.ListBucketContentsAsync(client, bucketName); + await s3Wrapper.ListBucketContentsAsync(bucketName); @@ -164 +240,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - await S3Bucket.DeleteBucketContentsAsync(client, bucketName); + if (IsInteractive) + { + Console.WriteLine("Press <Enter> when you are ready to delete the bucket contents."); + _ = Console.ReadLine(); + } @@ -166,2 +246,15 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - // Deleting the bucket too quickly after deleting its contents will - // cause an error that the bucket isn't empty. So... + var deleteContentsSuccess = await s3Wrapper.DeleteBucketContentsAsync(bucketName); + if (deleteContentsSuccess) + { + Console.WriteLine($"Successfully deleted contents of {bucketName}.\n"); + } + else + { + Console.WriteLine($"Sorry, could not delete contents of {bucketName}.\n"); + } + + if (IsInteractive) + { + // Deleting the bucket too quickly after separately deleting its contents can + // cause an error that the bucket isn't empty. To delete contents and bucket in one + // operation, use AmazonS3Util.DeleteS3BucketWithObjectsAsync @@ -169,0 +263,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + } + else + { + // Add a small delay for non-interactive mode to ensure objects are fully deleted. + Console.WriteLine("Waiting a moment for objects to be fully deleted..."); + await Task.Delay(2000); + } @@ -172 +272,60 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - await S3Bucket.DeleteBucketAsync(client, bucketName);