up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-13 00:20:26 +02:00
parent e1f1bef4c1
commit 564df71bfb
2376 changed files with 334389 additions and 328032 deletions

View File

@@ -1,109 +1,109 @@
using System.Security.Claims;
using Microsoft.Extensions.Options;
using StellaOps.Registry.TokenService;
namespace StellaOps.Registry.TokenService.Tests;
public sealed class PlanRegistryTests
{
private static RegistryTokenServiceOptions CreateOptions()
{
return new RegistryTokenServiceOptions
{
Authority = new RegistryTokenServiceOptions.AuthorityOptions
{
Issuer = "https://authority.localhost",
RequireHttpsMetadata = false,
},
Signing = new RegistryTokenServiceOptions.SigningOptions
{
Issuer = "https://registry.localhost/token",
KeyPath = Path.GetTempFileName(),
},
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" }
}
}
},
new RegistryTokenServiceOptions.PlanRule
{
Name = "enterprise",
Repositories =
{
new RegistryTokenServiceOptions.RepositoryRule
{
Pattern = "stella-ops/public/*",
Actions = new [] { "pull" }
},
new RegistryTokenServiceOptions.RepositoryRule
{
Pattern = "stella-ops/enterprise/*",
Actions = new [] { "pull", "push" }
}
}
}
}
};
}
[Fact]
public void Authorize_AllowsMatchingPlan()
{
var options = CreateOptions();
options.Signing.Validate();
options.Registry.Validate();
foreach (var plan in options.Plans)
{
plan.Validate();
}
var registry = new PlanRegistry(options);
var principal = new ClaimsPrincipal(new ClaimsIdentity(new[]
{
new Claim("stellaops:plan", "enterprise")
}, "test"));
var decision = registry.Authorize(principal, new[]
{
new RegistryAccessRequest("repository", "stella-ops/enterprise/cache", new [] { "pull" })
});
Assert.True(decision.Allowed);
}
[Fact]
public void Authorize_DeniesUnknownPlan()
{
var options = CreateOptions();
options.Signing.Validate();
options.Registry.Validate();
foreach (var plan in options.Plans)
{
plan.Validate();
}
var registry = new PlanRegistry(options);
var principal = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { }, "test"));
var decision = registry.Authorize(principal, new[]
{
new RegistryAccessRequest("repository", "stella-ops/enterprise/cache", new [] { "pull" })
});
Assert.False(decision.Allowed);
}
}
using System.Security.Claims;
using Microsoft.Extensions.Options;
using StellaOps.Registry.TokenService;
namespace StellaOps.Registry.TokenService.Tests;
public sealed class PlanRegistryTests
{
private static RegistryTokenServiceOptions CreateOptions()
{
return new RegistryTokenServiceOptions
{
Authority = new RegistryTokenServiceOptions.AuthorityOptions
{
Issuer = "https://authority.localhost",
RequireHttpsMetadata = false,
},
Signing = new RegistryTokenServiceOptions.SigningOptions
{
Issuer = "https://registry.localhost/token",
KeyPath = Path.GetTempFileName(),
},
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" }
}
}
},
new RegistryTokenServiceOptions.PlanRule
{
Name = "enterprise",
Repositories =
{
new RegistryTokenServiceOptions.RepositoryRule
{
Pattern = "stella-ops/public/*",
Actions = new [] { "pull" }
},
new RegistryTokenServiceOptions.RepositoryRule
{
Pattern = "stella-ops/enterprise/*",
Actions = new [] { "pull", "push" }
}
}
}
}
};
}
[Fact]
public void Authorize_AllowsMatchingPlan()
{
var options = CreateOptions();
options.Signing.Validate();
options.Registry.Validate();
foreach (var plan in options.Plans)
{
plan.Validate();
}
var registry = new PlanRegistry(options);
var principal = new ClaimsPrincipal(new ClaimsIdentity(new[]
{
new Claim("stellaops:plan", "enterprise")
}, "test"));
var decision = registry.Authorize(principal, new[]
{
new RegistryAccessRequest("repository", "stella-ops/enterprise/cache", new [] { "pull" })
});
Assert.True(decision.Allowed);
}
[Fact]
public void Authorize_DeniesUnknownPlan()
{
var options = CreateOptions();
options.Signing.Validate();
options.Registry.Validate();
foreach (var plan in options.Plans)
{
plan.Validate();
}
var registry = new PlanRegistry(options);
var principal = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { }, "test"));
var decision = registry.Authorize(principal, new[]
{
new RegistryAccessRequest("repository", "stella-ops/enterprise/cache", new [] { "pull" })
});
Assert.False(decision.Allowed);
}
}

View File

@@ -1,38 +1,38 @@
using Microsoft.AspNetCore.Http;
using StellaOps.Registry.TokenService;
namespace StellaOps.Registry.TokenService.Tests;
public sealed class RegistryScopeParserTests
{
[Fact]
public void Parse_SingleScope_DefaultsPull()
{
var query = new QueryCollection(new Dictionary<string, Microsoft.Extensions.Primitives.StringValues>
{
["scope"] = "repository:stella-ops/public/base"
});
var result = RegistryScopeParser.Parse(query);
Assert.Single(result);
Assert.Equal("repository", result[0].Type);
Assert.Equal("stella-ops/public/base", result[0].Name);
Assert.Equal(new[] { "pull" }, result[0].Actions);
}
[Fact]
public void Parse_MultipleScopes()
{
var query = new QueryCollection(new Dictionary<string, Microsoft.Extensions.Primitives.StringValues>
{
["scope"] = new[] { "repository:stella/public/api:pull,push", "repository:stella/private/api:pull" }
});
var result = RegistryScopeParser.Parse(query);
Assert.Equal(2, result.Count);
Assert.Equal(new[] { "pull", "push" }, result[0].Actions);
Assert.Equal(new[] { "pull" }, result[1].Actions);
}
}
using Microsoft.AspNetCore.Http;
using StellaOps.Registry.TokenService;
namespace StellaOps.Registry.TokenService.Tests;
public sealed class RegistryScopeParserTests
{
[Fact]
public void Parse_SingleScope_DefaultsPull()
{
var query = new QueryCollection(new Dictionary<string, Microsoft.Extensions.Primitives.StringValues>
{
["scope"] = "repository:stella-ops/public/base"
});
var result = RegistryScopeParser.Parse(query);
Assert.Single(result);
Assert.Equal("repository", result[0].Type);
Assert.Equal("stella-ops/public/base", result[0].Name);
Assert.Equal(new[] { "pull" }, result[0].Actions);
}
[Fact]
public void Parse_MultipleScopes()
{
var query = new QueryCollection(new Dictionary<string, Microsoft.Extensions.Primitives.StringValues>
{
["scope"] = new[] { "repository:stella/public/api:pull,push", "repository:stella/private/api:pull" }
});
var result = RegistryScopeParser.Parse(query);
Assert.Equal(2, result.Count);
Assert.Equal(new[] { "pull", "push" }, result[0].Actions);
Assert.Equal(new[] { "pull" }, result[1].Actions);
}
}

View File

@@ -1,110 +1,110 @@
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;
namespace StellaOps.Registry.TokenService.Tests;
public sealed class RegistryTokenIssuerTests : IDisposable
{
private readonly List<string> _tempFiles = new();
[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
}
}
}
}
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;
namespace StellaOps.Registry.TokenService.Tests;
public sealed class RegistryTokenIssuerTests : IDisposable
{
private readonly List<string> _tempFiles = new();
[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
}
}
}
}

View File

@@ -1,10 +1,10 @@
namespace StellaOps.Registry.TokenService.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
namespace StellaOps.Registry.TokenService.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}