feat: Implement ScannerSurfaceSecretConfigurator for web service options
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Added ScannerSurfaceSecretConfigurator to configure ScannerWebServiceOptions using surface secrets. - Integrated ISurfaceSecretProvider to fetch and apply secrets for artifact store configuration. - Enhanced logging for secret retrieval and application processes. feat: Implement ScannerStorageSurfaceSecretConfigurator for worker options - Introduced ScannerStorageSurfaceSecretConfigurator to configure ScannerStorageOptions with surface secrets. - Utilized ISurfaceSecretProvider to retrieve and apply secrets for object store settings. - Improved logging for secret handling and configuration. feat: Create SurfaceManifestPublisher for publishing surface manifests - Developed SurfaceManifestPublisher to handle the creation and storage of surface manifests. - Implemented methods for serializing manifest documents and storing payloads in the object store. - Added dual write functionality for mirror storage of manifests. feat: Add SurfaceManifestStageExecutor for processing scan stages - Created SurfaceManifestStageExecutor to execute the manifest publishing stage in scan jobs. - Integrated with SurfaceManifestPublisher to publish manifests based on collected payloads. - Enhanced logging for job processing and manifest storage. feat: Define SurfaceManifest models for manifest structure - Established SurfaceManifestDocument, SurfaceManifestSource, SurfaceManifestArtifact, and SurfaceManifestStorage records. - Implemented serialization attributes for JSON handling of manifest models. feat: Implement CasAccessSecret and SurfaceSecretParser for secret handling - Created CasAccessSecret record to represent surface access secrets. - Developed SurfaceSecretParser to parse and validate surface secrets from JSON payloads. test: Add unit tests for CasAccessSecretParser - Implemented tests for parsing CasAccessSecret from JSON payloads and metadata fallbacks. - Verified expected values and behavior for secret parsing logic. test: Add unit tests for ScannerSurfaceSecretConfigurator - Created tests for ScannerSurfaceSecretConfigurator to ensure correct application of surface secrets to web service options. - Validated artifact store settings after configuration. test: Add unit tests for ScannerStorageSurfaceSecretConfigurator - Implemented tests for ScannerStorageSurfaceSecretConfigurator to verify correct application of surface secrets to storage options. - Ensured accurate configuration of object store settings.
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scanner.Surface.Env;
|
||||
using StellaOps.Scanner.Surface.Secrets;
|
||||
using StellaOps.Scanner.WebService.Options;
|
||||
using StellaOps.Scanner.Storage;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scanner.WebService.Tests;
|
||||
|
||||
public sealed class ScannerSurfaceSecretConfiguratorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Configure_AppliesCasAccessSecretToArtifactStore()
|
||||
{
|
||||
const string json = """
|
||||
{
|
||||
"driver": "rustfs",
|
||||
"endpoint": "https://surface.api",
|
||||
"bucket": "surface-artifacts",
|
||||
"apiKey": "rust-key",
|
||||
"apiKeyHeader": "X-Surface-Api-Key",
|
||||
"region": "ap-southeast-2"
|
||||
}
|
||||
""";
|
||||
|
||||
using var handle = SurfaceSecretHandle.FromBytes(Encoding.UTF8.GetBytes(json));
|
||||
var secretProvider = new StubSecretProvider(handle);
|
||||
var environment = new StubSurfaceEnvironment();
|
||||
var options = new ScannerWebServiceOptions();
|
||||
|
||||
var configurator = new ScannerSurfaceSecretConfigurator(
|
||||
secretProvider,
|
||||
environment,
|
||||
NullLogger<ScannerSurfaceSecretConfigurator>.Instance);
|
||||
|
||||
configurator.Configure(options);
|
||||
|
||||
Assert.Equal("rustfs", options.ArtifactStore.Driver);
|
||||
Assert.Equal("https://surface.api", options.ArtifactStore.Endpoint);
|
||||
Assert.Equal("surface-artifacts", options.ArtifactStore.Bucket);
|
||||
Assert.Equal("rust-key", options.ArtifactStore.ApiKey);
|
||||
Assert.Equal("X-Surface-Api-Key", options.ArtifactStore.ApiKeyHeader);
|
||||
Assert.Equal("ap-southeast-2", options.ArtifactStore.Region);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PostConfigure_SynchronizesArtifactStoreToScannerStorageOptions()
|
||||
{
|
||||
var webOptions = Microsoft.Extensions.Options.Options.Create(new ScannerWebServiceOptions
|
||||
{
|
||||
ArtifactStore = new ScannerWebServiceOptions.ArtifactStoreOptions
|
||||
{
|
||||
Driver = "rustfs",
|
||||
Endpoint = "https://surface.sync",
|
||||
ApiKey = "sync-key",
|
||||
ApiKeyHeader = "X-Sync",
|
||||
Bucket = "sync-bucket",
|
||||
Region = "us-west-2",
|
||||
RootPrefix = "sync"
|
||||
}
|
||||
});
|
||||
|
||||
var configurator = new ScannerStorageOptionsPostConfigurator(
|
||||
new OptionsMonitorStub<ScannerWebServiceOptions>(webOptions),
|
||||
NullLogger<ScannerStorageOptionsPostConfigurator>.Instance);
|
||||
|
||||
var storageOptions = new ScannerStorageOptions();
|
||||
configurator.PostConfigure(Microsoft.Extensions.Options.Options.DefaultName, storageOptions);
|
||||
|
||||
Assert.Equal("rustfs", storageOptions.ObjectStore.Driver);
|
||||
Assert.Equal("https://surface.sync", storageOptions.ObjectStore.RustFs.BaseUrl);
|
||||
Assert.Equal("sync-bucket", storageOptions.ObjectStore.BucketName);
|
||||
Assert.Equal("sync", storageOptions.ObjectStore.RootPrefix);
|
||||
Assert.Equal("us-west-2", storageOptions.ObjectStore.Region);
|
||||
Assert.Equal("sync-key", storageOptions.ObjectStore.RustFs.ApiKey);
|
||||
Assert.Equal("X-Sync", storageOptions.ObjectStore.RustFs.ApiKeyHeader);
|
||||
}
|
||||
|
||||
private sealed class StubSecretProvider : ISurfaceSecretProvider
|
||||
{
|
||||
private readonly SurfaceSecretHandle _handle;
|
||||
|
||||
public StubSecretProvider(SurfaceSecretHandle handle)
|
||||
{
|
||||
_handle = handle;
|
||||
}
|
||||
|
||||
public ValueTask<SurfaceSecretHandle> GetAsync(SurfaceSecretRequest request, CancellationToken cancellationToken = default)
|
||||
=> ValueTask.FromResult(_handle);
|
||||
}
|
||||
|
||||
private sealed class StubSurfaceEnvironment : ISurfaceEnvironment
|
||||
{
|
||||
public StubSurfaceEnvironment()
|
||||
{
|
||||
Settings = new SurfaceEnvironmentSettings(
|
||||
new Uri("https://surface"),
|
||||
"bucket",
|
||||
"region",
|
||||
new DirectoryInfo(Path.GetTempPath()),
|
||||
256,
|
||||
false,
|
||||
Array.Empty<string>(),
|
||||
new SurfaceSecretsConfiguration("inline", "tenant", null, null, null, true),
|
||||
"tenant",
|
||||
new SurfaceTlsConfiguration(null, null, null));
|
||||
RawVariables = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public SurfaceEnvironmentSettings Settings { get; }
|
||||
|
||||
public IReadOnlyDictionary<string, string> RawVariables { get; }
|
||||
}
|
||||
|
||||
private sealed class OptionsMonitorStub<T> : IOptionsMonitor<T> where T : class
|
||||
{
|
||||
private readonly IOptions<T> _options;
|
||||
|
||||
public OptionsMonitorStub(IOptions<T> options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public T CurrentValue => _options.Value;
|
||||
|
||||
public T Get(string? name) => _options.Value;
|
||||
|
||||
public IDisposable OnChange(Action<T, string?> listener) => NullDisposable.Instance;
|
||||
|
||||
private sealed class NullDisposable : IDisposable
|
||||
{
|
||||
public static readonly NullDisposable Instance = new();
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user