Add Authority Advisory AI and API Lifecycle Configuration
- Introduced AuthorityAdvisoryAiOptions and related classes for managing advisory AI configurations, including remote inference options and tenant-specific settings. - Added AuthorityApiLifecycleOptions to control API lifecycle settings, including legacy OAuth endpoint configurations. - Implemented validation and normalization methods for both advisory AI and API lifecycle options to ensure proper configuration. - Created AuthorityNotificationsOptions and its related classes for managing notification settings, including ack tokens, webhooks, and escalation options. - Developed IssuerDirectoryClient and related models for interacting with the issuer directory service, including caching mechanisms and HTTP client configurations. - Added support for dependency injection through ServiceCollectionExtensions for the Issuer Directory Client. - Updated project file to include necessary package references for the new Issuer Directory Client library.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using StellaOps.Scanner.Surface.Secrets;
|
||||
using StellaOps.Scanner.Surface.Secrets.Providers;
|
||||
|
||||
namespace StellaOps.Scanner.Surface.Secrets.Tests;
|
||||
|
||||
public sealed class FileSurfaceSecretProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetAsync_ReturnsSecret_FromJson()
|
||||
{
|
||||
var rootDirectory = Directory.CreateTempSubdirectory();
|
||||
var root = rootDirectory.FullName;
|
||||
var request = new SurfaceSecretRequest("tenant", "component", "registry");
|
||||
var path = Path.Combine(root, request.Tenant, request.Component, request.SecretType);
|
||||
Directory.CreateDirectory(path);
|
||||
var payloadPath = Path.Combine(path, "default.json");
|
||||
await File.WriteAllTextAsync(payloadPath, JsonSerializer.Serialize(new
|
||||
{
|
||||
Payload = Convert.ToBase64String(new byte[] { 10, 20, 30 }),
|
||||
Metadata = new Dictionary<string, string> { ["username"] = "demo" }
|
||||
}));
|
||||
|
||||
try
|
||||
{
|
||||
var provider = new FileSurfaceSecretProvider(root);
|
||||
var handle = await provider.GetAsync(request);
|
||||
try
|
||||
{
|
||||
Assert.Equal(new byte[] { 10, 20, 30 }, handle.AsBytes().ToArray());
|
||||
Assert.Equal("demo", handle.Metadata["username"]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
handle.Dispose();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
rootDirectory.Delete(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Scanner.Surface.Env;
|
||||
using StellaOps.Scanner.Surface.Secrets;
|
||||
using StellaOps.Scanner.Surface.Secrets.Providers;
|
||||
|
||||
namespace StellaOps.Scanner.Surface.Secrets.Tests;
|
||||
|
||||
public sealed class InlineSurfaceSecretProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetAsync_ReturnsSecret_WhenInlineAllowed()
|
||||
{
|
||||
var configuration = new SurfaceSecretsConfiguration("inline", "tenant", null, null, null, AllowInline: true);
|
||||
var provider = new InlineSurfaceSecretProvider(configuration);
|
||||
var request = new SurfaceSecretRequest("tenant", "component", "registry");
|
||||
var key = "SURFACE_SECRET_TENANT_COMPONENT_REGISTRY_DEFAULT";
|
||||
try
|
||||
{
|
||||
Environment.SetEnvironmentVariable(key, Convert.ToBase64String(new byte[] { 1, 2, 3 }));
|
||||
var handle = await provider.GetAsync(request);
|
||||
Assert.Equal(new byte[] { 1, 2, 3 }, handle.AsBytes().ToArray());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.SetEnvironmentVariable(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAsync_Throws_WhenInlineDisallowed()
|
||||
{
|
||||
var configuration = new SurfaceSecretsConfiguration("inline", "tenant", null, null, null, AllowInline: false);
|
||||
var provider = new InlineSurfaceSecretProvider(configuration);
|
||||
var request = new SurfaceSecretRequest("tenant", "component", "registry");
|
||||
await Assert.ThrowsAsync<SurfaceSecretNotFoundException>(async () => await provider.GetAsync(request));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<IsPackable>false</IsPackable>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Scanner.Surface.Env/StellaOps.Scanner.Surface.Env.csproj" />
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Scanner.Surface.Secrets/StellaOps.Scanner.Surface.Secrets.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Scanner.Surface.Env;
|
||||
using StellaOps.Scanner.Surface.Secrets;
|
||||
|
||||
namespace StellaOps.Scanner.Surface.Secrets.Tests
|
||||
{
|
||||
public sealed class SurfaceSecretsServiceCollectionExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddSurfaceSecrets_RegistersProvider()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<ISurfaceEnvironment>(_ => new TestSurfaceEnvironment());
|
||||
services.AddLogging(builder => builder.ClearProviders());
|
||||
services.AddSurfaceSecrets();
|
||||
|
||||
using var provider = services.BuildServiceProvider();
|
||||
var secretProvider = provider.GetRequiredService<ISurfaceSecretProvider>();
|
||||
Assert.NotNull(secretProvider);
|
||||
}
|
||||
|
||||
private sealed class TestSurfaceEnvironment : ISurfaceEnvironment
|
||||
{
|
||||
public SurfaceEnvironmentSettings Settings { get; }
|
||||
public IReadOnlyDictionary<string, string> RawVariables { get; }
|
||||
|
||||
public TestSurfaceEnvironment()
|
||||
{
|
||||
Settings = new SurfaceEnvironmentSettings(
|
||||
new Uri("https://surface.example"),
|
||||
"surface",
|
||||
null,
|
||||
new DirectoryInfo(Path.GetTempPath()),
|
||||
1024,
|
||||
false,
|
||||
Array.Empty<string>(),
|
||||
new SurfaceSecretsConfiguration("file", "tenant", Root: Path.GetTempPath(), Namespace: null, FallbackProvider: null, AllowInline: true),
|
||||
"tenant",
|
||||
new SurfaceTlsConfiguration(null, null, null))
|
||||
{
|
||||
CreatedAtUtc = DateTimeOffset.UtcNow
|
||||
};
|
||||
|
||||
RawVariables = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user