65 lines
2.6 KiB
C#
65 lines
2.6 KiB
C#
// Copyright (c) StellaOps. Licensed under the BUSL-1.1.
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using StellaOps.Auth.Abstractions;
|
|
|
|
namespace StellaOps.AirGap.Controller.Security;
|
|
|
|
/// <summary>
|
|
/// Named authorization policy constants for the AirGap Controller service.
|
|
/// Policies are registered via assertion-based policies in Program.cs using
|
|
/// <see cref="AirGapScopeAssertion"/> to evaluate claims from the HeaderScope
|
|
/// authentication handler.
|
|
/// </summary>
|
|
internal static class AirGapPolicies
|
|
{
|
|
/// <summary>Policy for reading air-gap status and staleness information. Requires airgap:status:read scope.</summary>
|
|
public const string StatusRead = "AirGap.StatusRead";
|
|
|
|
/// <summary>Policy for sealing and unsealing the air-gap environment. Requires airgap:seal scope.</summary>
|
|
public const string Seal = "AirGap.Seal";
|
|
|
|
/// <summary>Policy for importing offline bundles while in air-gapped mode. Requires airgap:import scope.</summary>
|
|
public const string Import = "AirGap.Import";
|
|
|
|
/// <summary>Policy for verifying air-gap state against policy hash and replay evidence. Requires airgap:verify scope.</summary>
|
|
public const string Verify = "AirGap.Verify";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scope assertion helper for AirGap policies. Evaluates scope claims populated by
|
|
/// the HeaderScope authentication handler against a required scope string.
|
|
/// </summary>
|
|
internal static class AirGapScopeAssertion
|
|
{
|
|
/// <summary>
|
|
/// Returns <c>true</c> when the authenticated principal carries the required scope
|
|
/// in either <see cref="StellaOpsClaimTypes.ScopeItem"/> or space-delimited
|
|
/// <see cref="StellaOpsClaimTypes.Scope"/> / <c>scp</c> claims.
|
|
/// </summary>
|
|
public static bool HasScope(AuthorizationHandlerContext context, string requiredScope)
|
|
{
|
|
var user = context.User;
|
|
|
|
if (user.HasClaim(c => c.Type == StellaOpsClaimTypes.ScopeItem))
|
|
{
|
|
return user.FindAll(StellaOpsClaimTypes.ScopeItem)
|
|
.Select(c => c.Value)
|
|
.Contains(requiredScope, StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
|
|
var scopes = user.FindAll(StellaOpsClaimTypes.Scope)
|
|
.SelectMany(c => c.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
|
.ToArray();
|
|
|
|
if (scopes.Length == 0)
|
|
{
|
|
scopes = user.FindAll("scp")
|
|
.SelectMany(c => c.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
|
.ToArray();
|
|
}
|
|
|
|
return scopes.Contains(requiredScope, StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
}
|