mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 13:21:14 +00:00
f979e18811
Option B per user decision: production ships with empty Jwt.Issuer / Jwt.Audience in appsettings.json so the API process refuses to start unless JWT_ISSUER + JWT_AUDIENCE env vars are supplied. Development ships with grep-friendly DEV-ONLY- placeholders so local + docker flows keep working unchanged. AuthenticationServiceCollectionExtensions flips ValidateIssuer + ValidateAudience to true and wires ValidIssuer / ValidAudience via a new ResolveRequiredOrThrow helper that all three required values (secret, iss, aud) now share. JwtTokenFactory.Create + CreateExpired gain optional iss / aud parameters (default null) so existing call sites compile unchanged. JwtTestHelpers adds MintAuthenticated / MintExpired wrappers that resolve iss + aud from env, plus ResolveIssuerOrThrow / ResolveAudienceOrThrow. PerfBootstrap.MintToken + Program.cs JWT bootstrap migrated to the new surface so the perf harness and the integration runner both validate against the same contract. Adds 4 fail-fast unit tests (missing/empty issuer + audience), 2 negative integration scenarios (WrongIssuer_Returns401, WrongAudience_Returns401), and re-tags every existing integration mint site via MintAuthenticated. Compose, .env.example, run-tests.sh, run-performance-tests.sh all load + export JWT_ISSUER + JWT_AUDIENCE alongside JWT_SECRET. Resolves F-AUTH-2 (security_report.md + owasp_review.md). AC-7 (cross-repo suite/_docs/10_auth.md write) deferred — outside this workspace; tracked in deploy_cycle2.md R3 follow-up. Co-authored-by: Cursor <cursoragent@cursor.com>
98 lines
3.3 KiB
C#
98 lines
3.3 KiB
C#
using System.Security.Claims;
|
|
using SatelliteProvider.TestSupport;
|
|
using SixLabors.ImageSharp;
|
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
|
using SixLabors.ImageSharp.PixelFormats;
|
|
|
|
namespace SatelliteProvider.IntegrationTests;
|
|
|
|
// AZ-492: bootstrap helpers invoked by scripts/run-performance-tests.sh.
|
|
// Each helper is a short-circuit subcommand that prints/writes its output
|
|
// and exits before the integration-test runner does any HTTP or DB work.
|
|
// All token-minting goes through the canonical JwtTokenFactory (AZ-491)
|
|
// so the shell script does NOT inline a third copy of the JWT logic.
|
|
internal static class PerfBootstrap
|
|
{
|
|
public const string PerfSubject = "perf-tests";
|
|
public const string GpsPermission = "GPS";
|
|
public const string PermissionsClaimType = "permissions";
|
|
public static readonly TimeSpan PerfTokenLifetime = TimeSpan.FromHours(4);
|
|
|
|
public static int MintToken()
|
|
{
|
|
string secret;
|
|
string issuer;
|
|
string audience;
|
|
try
|
|
{
|
|
secret = JwtTestHelpers.ResolveSecretOrThrow();
|
|
issuer = JwtTestHelpers.ResolveIssuerOrThrow();
|
|
audience = JwtTestHelpers.ResolveAudienceOrThrow();
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
Console.Error.WriteLine($"--mint-only: {ex.Message}");
|
|
return 1;
|
|
}
|
|
|
|
var token = JwtTokenFactory.Create(
|
|
secret,
|
|
PerfSubject,
|
|
PerfTokenLifetime,
|
|
new[] { new Claim(PermissionsClaimType, GpsPermission) },
|
|
issuer: issuer,
|
|
audience: audience);
|
|
|
|
Console.Out.Write(token);
|
|
return 0;
|
|
}
|
|
|
|
public static int GenerateUavFixture(string[] args)
|
|
{
|
|
if (args.Length < 2 || string.IsNullOrWhiteSpace(args[1]))
|
|
{
|
|
Console.Error.WriteLine("--gen-uav-fixture: missing output path. Usage: --gen-uav-fixture <path>");
|
|
return 2;
|
|
}
|
|
|
|
var path = args[1];
|
|
var directory = Path.GetDirectoryName(Path.GetFullPath(path));
|
|
if (!string.IsNullOrEmpty(directory))
|
|
{
|
|
Directory.CreateDirectory(directory);
|
|
}
|
|
|
|
var bytes = CreateValidJpeg();
|
|
File.WriteAllBytes(path, bytes);
|
|
Console.Out.WriteLine(path);
|
|
return 0;
|
|
}
|
|
|
|
// Mirrors the random-noise JPEG produced by UavUploadTests.CreateValidJpeg so
|
|
// that the perf harness exercises the same quality-gate path as the integration
|
|
// tests. Pixel pattern is high-variance enough to pass the UAV quality gate.
|
|
private static byte[] CreateValidJpeg(int width = 256, int height = 256, int seed = 42)
|
|
{
|
|
using var image = new Image<Rgba32>(width, height);
|
|
var random = new Random(seed);
|
|
image.ProcessPixelRows(accessor =>
|
|
{
|
|
for (var y = 0; y < accessor.Height; y++)
|
|
{
|
|
var row = accessor.GetRowSpan(y);
|
|
for (var x = 0; x < row.Length; x++)
|
|
{
|
|
row[x] = new Rgba32(
|
|
(byte)random.Next(256),
|
|
(byte)random.Next(256),
|
|
(byte)random.Next(256));
|
|
}
|
|
}
|
|
});
|
|
|
|
using var stream = new MemoryStream();
|
|
image.Save(stream, new JpegEncoder { Quality = 95 });
|
|
return stream.ToArray();
|
|
}
|
|
}
|