Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			Build Test Deploy / build-test (push) Has been cancelled
				
			Build Test Deploy / authority-container (push) Has been cancelled
				
			Build Test Deploy / docs (push) Has been cancelled
				
			Build Test Deploy / deploy (push) Has been cancelled
				
			
		
			
				
	
	
		
			76 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using Amazon.S3;
 | |
| using Amazon.S3.Model;
 | |
| using Microsoft.Extensions.Logging;
 | |
| using Microsoft.Extensions.Options;
 | |
| 
 | |
| namespace StellaOps.Scanner.Storage.ObjectStore;
 | |
| 
 | |
| public sealed class S3ArtifactObjectStore : IArtifactObjectStore
 | |
| {
 | |
|     private readonly IAmazonS3 _s3;
 | |
|     private readonly ObjectStoreOptions _options;
 | |
|     private readonly ILogger<S3ArtifactObjectStore> _logger;
 | |
| 
 | |
|     public S3ArtifactObjectStore(IAmazonS3 s3, IOptions<ScannerStorageOptions> options, ILogger<S3ArtifactObjectStore> logger)
 | |
|     {
 | |
|         _s3 = s3 ?? throw new ArgumentNullException(nameof(s3));
 | |
|         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
 | |
|         _options = (options ?? throw new ArgumentNullException(nameof(options))).Value.ObjectStore;
 | |
|     }
 | |
| 
 | |
|     public async Task PutAsync(ArtifactObjectDescriptor descriptor, Stream content, CancellationToken cancellationToken)
 | |
|     {
 | |
|         ArgumentNullException.ThrowIfNull(descriptor);
 | |
|         ArgumentNullException.ThrowIfNull(content);
 | |
| 
 | |
|         var request = new PutObjectRequest
 | |
|         {
 | |
|             BucketName = descriptor.Bucket,
 | |
|             Key = descriptor.Key,
 | |
|             InputStream = content,
 | |
|             AutoCloseStream = false,
 | |
|         };
 | |
| 
 | |
|         if (descriptor.Immutable && _options.EnableObjectLock)
 | |
|         {
 | |
|             request.ObjectLockMode = ObjectLockMode.Compliance;
 | |
|             if (descriptor.RetainFor is { } retention && retention > TimeSpan.Zero)
 | |
|             {
 | |
|                 request.ObjectLockRetainUntilDate = DateTime.UtcNow + retention;
 | |
|             }
 | |
|             else if (_options.ComplianceRetention is { } defaultRetention && defaultRetention > TimeSpan.Zero)
 | |
|             {
 | |
|                 request.ObjectLockRetainUntilDate = DateTime.UtcNow + defaultRetention;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         await _s3.PutObjectAsync(request, cancellationToken).ConfigureAwait(false);
 | |
|         _logger.LogDebug("Uploaded scanner object {Bucket}/{Key}", descriptor.Bucket, descriptor.Key);
 | |
|     }
 | |
| 
 | |
|     public async Task<Stream?> GetAsync(ArtifactObjectDescriptor descriptor, CancellationToken cancellationToken)
 | |
|     {
 | |
|         ArgumentNullException.ThrowIfNull(descriptor);
 | |
|         try
 | |
|         {
 | |
|             var response = await _s3.GetObjectAsync(descriptor.Bucket, descriptor.Key, cancellationToken).ConfigureAwait(false);
 | |
|             var buffer = new MemoryStream();
 | |
|             await response.ResponseStream.CopyToAsync(buffer, cancellationToken).ConfigureAwait(false);
 | |
|             buffer.Position = 0;
 | |
|             return buffer;
 | |
|         }
 | |
|         catch (AmazonS3Exception ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
 | |
|         {
 | |
|             _logger.LogDebug("Scanner object {Bucket}/{Key} not found", descriptor.Bucket, descriptor.Key);
 | |
|             return null;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public async Task DeleteAsync(ArtifactObjectDescriptor descriptor, CancellationToken cancellationToken)
 | |
|     {
 | |
|         ArgumentNullException.ThrowIfNull(descriptor);
 | |
|         await _s3.DeleteObjectAsync(descriptor.Bucket, descriptor.Key, cancellationToken).ConfigureAwait(false);
 | |
|         _logger.LogDebug("Deleted scanner object {Bucket}/{Key}", descriptor.Bucket, descriptor.Key);
 | |
|     }
 | |
| }
 |