elsa-core/test/unit/Elsa.Secrets.UnitTests/SecretStoreTests.cs
Sipke Schoorstra e2e00ff235
Add secrets module (#7468)
* Add secrets module

* Address Greptile feedback for secrets module

* Handle unavailable secrets in provider adapter

* Address path combine review comments

* Address additional Greptile secrets review

* Address final Greptile secrets feedback

* Handle secrets test payload failures

* address greptile feedback on secrets rotation

* fix secret recreation concurrency

* address greptile secrets followups

* address greptile secrets reliability feedback

* align secret store capabilities
2026-05-20 11:48:01 +02:00

121 lines
4.5 KiB
C#

using Elsa.Secrets.Models;
using Elsa.Secrets.Options;
using Elsa.Secrets.Repositories;
using Microsoft.Extensions.Configuration;
using Xunit;
namespace Elsa.Secrets.UnitTests;
public class SecretStoreTests
{
[Fact]
public void Registries_ExposeBuiltInTypesAndStores()
{
var fixture = new SecretTestFixture();
Assert.Contains(fixture.TypeRegistry.List(), x => x.Name == SecretTypeNames.Text);
Assert.Contains(fixture.TypeRegistry.List(), x => x.Name == SecretTypeNames.RsaKey);
Assert.Contains(fixture.TypeRegistry.List(), x => x.Name == SecretTypeNames.X509Certificate);
Assert.Contains(fixture.StoreRegistry.List(), x => x.Name == SecretStoreNames.Encrypted);
Assert.Contains(fixture.StoreRegistry.List(), x => x.Name == SecretStoreNames.Configuration);
}
[Fact]
public async Task ConfigurationStore_ResolvesConfiguredValue()
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?> { ["Elsa:Secrets:SmtpPassword"] = "configured-secret" })
.Build();
var fixture = new SecretTestFixture(configuration);
await fixture.Manager.CreateAsync(new CreateSecretRequest
{
Name = "smtp:password",
StoreName = SecretStoreNames.Configuration,
ConfigurationKey = "SmtpPassword"
});
var value = await fixture.Resolver.ResolveAsync("smtp:password");
Assert.Equal("configured-secret", value);
}
[Fact]
public async Task FileRepository_PersistsSecretAggregate()
{
var path = Path.Join(Path.GetTempPath(), $"elsa-secrets-{Guid.NewGuid():N}.json");
try
{
var repository = new FileSecretRepository(Microsoft.Extensions.Options.Options.Create(new SecretsOptions { RepositoryFilePath = path }));
var secret = new Secret
{
Name = "smtp:password",
DisplayName = "SMTP password",
Tags = ["API-Key"],
Versions = { new SecretVersion { Version = 1, Payload = new SecretPayload { Value = "stored", Metadata = { ["ProtectedValue"] = "ciphertext" } } } }
};
await repository.AddAsync(secret);
var reloadedRepository = new FileSecretRepository(Microsoft.Extensions.Options.Options.Create(new SecretsOptions { RepositoryFilePath = path }));
var reloaded = await reloadedRepository.GetAsync("smtp:password");
Assert.NotNull(reloaded);
Assert.Equal("SMTP password", reloaded.DisplayName);
Assert.Contains("api-key", reloaded.Tags);
Assert.True(reloaded.Versions.Single().Payload.Metadata.ContainsKey("protectedvalue"));
Assert.Equal(1, reloaded.Versions.Single().Version);
}
finally
{
if (File.Exists(path))
File.Delete(path);
}
}
[Fact]
public async Task FileRepository_RecoversFromCorruptJson()
{
var path = Path.Join(Path.GetTempPath(), $"elsa-secrets-{Guid.NewGuid():N}.json");
try
{
await File.WriteAllTextAsync(path, "{not-valid-json");
var repository = new FileSecretRepository(Microsoft.Extensions.Options.Options.Create(new SecretsOptions { RepositoryFilePath = path }));
var secrets = await repository.ListAsync();
await repository.AddAsync(new Secret { Name = "smtp:password", DisplayName = "SMTP password" });
var reloaded = await repository.GetAsync("smtp:password");
Assert.Empty(secrets);
Assert.NotNull(reloaded);
}
finally
{
if (File.Exists(path))
File.Delete(path);
}
}
[Fact]
public async Task InMemoryRepository_ReturnsCopies()
{
var repository = new InMemorySecretRepository();
await repository.AddAsync(new Secret
{
Name = "smtp:password",
DisplayName = "SMTP password",
Versions = { new SecretVersion { Version = 1, Payload = new SecretPayload { Metadata = { ["protectedValue"] = "ciphertext" } } } }
});
var loaded = await repository.GetAsync("smtp:password");
loaded!.Versions.Clear();
loaded.DisplayName = "Changed";
var reloaded = await repository.GetAsync("smtp:password");
Assert.Equal("SMTP password", reloaded!.DisplayName);
Assert.Single(reloaded.Versions);
Assert.True(reloaded.Versions.Single().Payload.Metadata.ContainsKey("protectedValue"));
}
}