sprints completion. new product advisories prepared
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// LocalRbacBundleExtensions.cs
|
||||
// Sprint: SPRINT_20260112_018_AUTH_local_rbac_fallback
|
||||
// Task: RBAC-010
|
||||
// Description: Extensions for including local RBAC policy in offline kit bundles.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.AirGap.Bundle.Models;
|
||||
|
||||
namespace StellaOps.AirGap.Bundle.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for including local RBAC policy in offline kit bundles.
|
||||
/// </summary>
|
||||
public static class LocalRbacBundleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Default policy file name in the offline kit.
|
||||
/// </summary>
|
||||
public const string DefaultPolicyFileName = "local-policy.yaml";
|
||||
|
||||
/// <summary>
|
||||
/// Default policy directory in the offline kit.
|
||||
/// </summary>
|
||||
public const string DefaultPolicyDirectory = "authority";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a policy build config for including local RBAC policy in an offline kit bundle.
|
||||
/// </summary>
|
||||
/// <param name="sourcePolicyPath">Source path to the local RBAC policy file (YAML or JSON).</param>
|
||||
/// <param name="version">Policy version string.</param>
|
||||
/// <param name="relativePath">Optional relative path in the bundle (defaults to "authority/local-policy.yaml").</param>
|
||||
/// <returns>PolicyBuildConfig ready for inclusion in BundleBuildRequest.</returns>
|
||||
public static PolicyBuildConfig CreateLocalRbacPolicyConfig(
|
||||
string sourcePolicyPath,
|
||||
string version,
|
||||
string? relativePath = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(sourcePolicyPath);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(version);
|
||||
|
||||
if (!File.Exists(sourcePolicyPath))
|
||||
{
|
||||
throw new FileNotFoundException(
|
||||
"Local RBAC policy file not found. Ensure the policy file exists before building the offline kit.",
|
||||
sourcePolicyPath);
|
||||
}
|
||||
|
||||
var fileName = Path.GetFileName(sourcePolicyPath);
|
||||
var targetPath = relativePath ?? Path.Combine(DefaultPolicyDirectory, fileName);
|
||||
|
||||
return new PolicyBuildConfig(
|
||||
PolicyId: "local-rbac-policy",
|
||||
Name: "Local RBAC Policy",
|
||||
Version: version,
|
||||
SourcePath: sourcePolicyPath,
|
||||
RelativePath: targetPath,
|
||||
Type: PolicyType.LocalRbac);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds local RBAC policies to a list of policy build configs.
|
||||
/// </summary>
|
||||
/// <param name="policies">Existing list of policy build configs.</param>
|
||||
/// <param name="sourcePolicyPath">Source path to the local RBAC policy file.</param>
|
||||
/// <param name="version">Policy version string.</param>
|
||||
/// <returns>New list with the local RBAC policy added.</returns>
|
||||
public static IReadOnlyList<PolicyBuildConfig> WithLocalRbacPolicy(
|
||||
this IReadOnlyList<PolicyBuildConfig> policies,
|
||||
string sourcePolicyPath,
|
||||
string version)
|
||||
{
|
||||
var list = new List<PolicyBuildConfig>(policies);
|
||||
list.Add(CreateLocalRbacPolicyConfig(sourcePolicyPath, version));
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a bundle manifest contains local RBAC policy.
|
||||
/// </summary>
|
||||
/// <param name="manifest">Bundle manifest to check.</param>
|
||||
/// <returns>True if the manifest contains local RBAC policy.</returns>
|
||||
public static bool HasLocalRbacPolicy(this BundleManifest manifest)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(manifest);
|
||||
|
||||
foreach (var policy in manifest.Policies)
|
||||
{
|
||||
if (policy.Type == PolicyType.LocalRbac)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the local RBAC policy component from a bundle manifest.
|
||||
/// </summary>
|
||||
/// <param name="manifest">Bundle manifest to search.</param>
|
||||
/// <returns>The local RBAC policy component, or null if not found.</returns>
|
||||
public static PolicyComponent? GetLocalRbacPolicy(this BundleManifest manifest)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(manifest);
|
||||
|
||||
foreach (var policy in manifest.Policies)
|
||||
{
|
||||
if (policy.Type == PolicyType.LocalRbac)
|
||||
{
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts and installs local RBAC policy from a bundle to the target path.
|
||||
/// </summary>
|
||||
/// <param name="bundlePath">Path to the extracted bundle.</param>
|
||||
/// <param name="manifest">Bundle manifest.</param>
|
||||
/// <param name="targetPolicyPath">Target path to install the policy file.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>True if the policy was installed successfully.</returns>
|
||||
public static async Task<bool> InstallLocalRbacPolicyAsync(
|
||||
string bundlePath,
|
||||
BundleManifest manifest,
|
||||
string targetPolicyPath,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(bundlePath);
|
||||
ArgumentNullException.ThrowIfNull(manifest);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(targetPolicyPath);
|
||||
|
||||
var policy = manifest.GetLocalRbacPolicy();
|
||||
if (policy is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var sourcePath = Path.Combine(bundlePath, policy.RelativePath);
|
||||
if (!File.Exists(sourcePath))
|
||||
{
|
||||
throw new FileNotFoundException(
|
||||
$"Local RBAC policy not found in bundle at expected path: {policy.RelativePath}",
|
||||
sourcePath);
|
||||
}
|
||||
|
||||
// Ensure target directory exists
|
||||
var targetDir = Path.GetDirectoryName(targetPolicyPath);
|
||||
if (!string.IsNullOrEmpty(targetDir))
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
}
|
||||
|
||||
// Copy with verification
|
||||
await using var sourceStream = File.OpenRead(sourcePath);
|
||||
await using var targetStream = File.Create(targetPolicyPath);
|
||||
await sourceStream.CopyToAsync(targetStream, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result of local RBAC policy installation from an offline kit.
|
||||
/// </summary>
|
||||
public sealed record LocalRbacInstallResult(
|
||||
bool Success,
|
||||
string? InstalledPath,
|
||||
string? PolicyVersion,
|
||||
string? PolicyDigest,
|
||||
string? Error);
|
||||
Reference in New Issue
Block a user