up
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
using System.Security.Cryptography;
|
||||
using StellaOps.Cryptography.Kms;
|
||||
|
||||
namespace StellaOps.Cryptography.Kms.Tests;
|
||||
|
||||
public sealed class FileKmsClientTests : IDisposable
|
||||
{
|
||||
private readonly string _rootPath;
|
||||
|
||||
public FileKmsClientTests()
|
||||
{
|
||||
_rootPath = Path.Combine(Path.GetTempPath(), $"kms-tests-{Guid.NewGuid():N}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RotateSignVerifyLifecycle_Works()
|
||||
{
|
||||
using var client = CreateClient();
|
||||
var keyId = "kms-test-key";
|
||||
|
||||
// Initial rotate creates the key.
|
||||
var metadata = await client.RotateAsync(keyId);
|
||||
Assert.Equal(keyId, metadata.KeyId);
|
||||
Assert.Single(metadata.Versions);
|
||||
Assert.Equal(KmsKeyState.Active, metadata.State);
|
||||
var version = metadata.Versions[0];
|
||||
Assert.Equal(KmsKeyState.Active, version.State);
|
||||
|
||||
var firstData = RandomNumberGenerator.GetBytes(256);
|
||||
var firstSignature = await client.SignAsync(keyId, null, firstData);
|
||||
Assert.Equal(keyId, firstSignature.KeyId);
|
||||
Assert.Equal(KmsAlgorithms.Es256, firstSignature.Algorithm);
|
||||
Assert.True(await client.VerifyAsync(keyId, firstSignature.VersionId, firstData, firstSignature.Signature));
|
||||
|
||||
// Rotate again and ensure metadata reflects both versions.
|
||||
var rotated = await client.RotateAsync(keyId);
|
||||
Assert.Equal(2, rotated.Versions.Length);
|
||||
var activeVersion = rotated.Versions.Single(v => v.State == KmsKeyState.Active);
|
||||
Assert.Equal(rotated.Versions.Max(v => v.VersionId), activeVersion.VersionId);
|
||||
var previousVersion = rotated.Versions.Single(v => v.State != KmsKeyState.Active);
|
||||
Assert.Equal(KmsKeyState.PendingRotation, previousVersion.State);
|
||||
|
||||
var newData = RandomNumberGenerator.GetBytes(128);
|
||||
var activeSignature = await client.SignAsync(keyId, null, newData);
|
||||
Assert.Equal(activeVersion.VersionId, activeSignature.VersionId);
|
||||
Assert.True(await client.VerifyAsync(keyId, null, newData, activeSignature.Signature));
|
||||
|
||||
// Explicit version verify should still pass for previous version using the old signature.
|
||||
Assert.True(await client.VerifyAsync(keyId, previousVersion.VersionId, firstData, firstSignature.Signature));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RevokePreventsSigning()
|
||||
{
|
||||
using var client = CreateClient();
|
||||
var keyId = "kms-revoke";
|
||||
|
||||
await client.RotateAsync(keyId);
|
||||
await client.RevokeAsync(keyId);
|
||||
|
||||
var metadata = await client.GetMetadataAsync(keyId);
|
||||
Assert.Equal(KmsKeyState.Revoked, metadata.State);
|
||||
Assert.All(metadata.Versions, v => Assert.Equal(KmsKeyState.Revoked, v.State));
|
||||
|
||||
var data = RandomNumberGenerator.GetBytes(32);
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => client.SignAsync(keyId, null, data));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExportAsync_ReturnsKeyMaterial()
|
||||
{
|
||||
using var client = CreateClient();
|
||||
var keyId = "kms-export";
|
||||
|
||||
await client.RotateAsync(keyId);
|
||||
var material = await client.ExportAsync(keyId, null);
|
||||
|
||||
Assert.Equal(keyId, material.KeyId);
|
||||
Assert.Equal(KmsAlgorithms.Es256, material.Algorithm);
|
||||
Assert.Equal("nistP256", material.Curve);
|
||||
Assert.NotEmpty(material.D);
|
||||
Assert.NotEmpty(material.Qx);
|
||||
Assert.NotEmpty(material.Qy);
|
||||
}
|
||||
|
||||
private FileKmsClient CreateClient()
|
||||
{
|
||||
var options = new FileKmsOptions
|
||||
{
|
||||
RootPath = _rootPath,
|
||||
Password = "P@ssw0rd!",
|
||||
Algorithm = KmsAlgorithms.Es256,
|
||||
};
|
||||
|
||||
return new FileKmsClient(options);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(_rootPath))
|
||||
{
|
||||
Directory.Delete(_rootPath, recursive: true);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseConcelierTestInfra>false</UseConcelierTestInfra>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../StellaOps.Cryptography.Kms/StellaOps.Cryptography.Kms.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user