Files
git.stella-ops.org/src/Registry/__Tests/StellaOps.Registry.TokenService.Tests/RegistryTokenIssuerTests.cs

114 lines
3.5 KiB
C#

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using Microsoft.Extensions.Options;
using StellaOps.Registry.TokenService;
using StellaOps.Registry.TokenService.Observability;
using StellaOps.TestKit;
namespace StellaOps.Registry.TokenService.Tests;
public sealed class RegistryTokenIssuerTests : IDisposable
{
private readonly List<string> _tempFiles = new();
[Trait("Category", TestCategories.Unit)]
[Fact]
public void IssueToken_GeneratesJwtWithAccessClaim()
{
var pemPath = CreatePemKey();
var options = new RegistryTokenServiceOptions
{
Authority = new RegistryTokenServiceOptions.AuthorityOptions
{
Issuer = "https://authority.localhost",
RequireHttpsMetadata = false,
},
Signing = new RegistryTokenServiceOptions.SigningOptions
{
Issuer = "https://registry.localhost/token",
KeyPath = pemPath,
Lifetime = TimeSpan.FromMinutes(5)
},
Registry = new RegistryTokenServiceOptions.RegistryOptions
{
Realm = "https://registry.localhost/v2/token"
},
Plans =
{
new RegistryTokenServiceOptions.PlanRule
{
Name = "community",
Repositories =
{
new RegistryTokenServiceOptions.RepositoryRule
{
Pattern = "stella-ops/public/*",
Actions = new [] { "pull" }
}
}
}
}
};
options.Validate();
var issuer = new RegistryTokenIssuer(
Options.Create(options),
new PlanRegistry(options),
new RegistryTokenMetrics(),
TimeProvider.System);
var principal = new ClaimsPrincipal(new ClaimsIdentity(new[]
{
new Claim("sub", "client-1"),
new Claim("stellaops:plan", "community")
}, "test"));
var accessRequests = new[]
{
new RegistryAccessRequest("repository", "stella-ops/public/base", new [] { "pull" })
};
var response = issuer.IssueToken(principal, "registry.localhost", accessRequests);
Assert.NotEmpty(response.Token);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(response.Token);
Assert.Equal("https://registry.localhost/token", jwt.Issuer);
Assert.True(jwt.Payload.TryGetValue("access", out var access));
Assert.NotNull(access);
}
private string CreatePemKey()
{
using var rsa = RSA.Create(2048);
var builder = new StringWriter();
builder.WriteLine("-----BEGIN PRIVATE KEY-----");
builder.WriteLine(Convert.ToBase64String(rsa.ExportPkcs8PrivateKey(), Base64FormattingOptions.InsertLineBreaks));
builder.WriteLine("-----END PRIVATE KEY-----");
var path = Path.GetTempFileName();
File.WriteAllText(path, builder.ToString());
_tempFiles.Add(path);
return path;
}
public void Dispose()
{
foreach (var file in _tempFiles)
{
try
{
File.Delete(file);
}
catch
{
// ignore
}
}
}
}