Files
git.stella-ops.org/src/StellaOps.Scanner.Storage/ObjectStore/S3ArtifactObjectStore.cs
master daa6a4ae8c
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
up
2025-10-19 10:38:55 +03:00

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);
}
}