enterprise/flex-auth integration layer

This commit is contained in:
2026-05-04 17:54:52 +02:00
parent e33f296bdb
commit 6cb3b7b172
17 changed files with 1240 additions and 23 deletions

View File

@@ -52,7 +52,12 @@ from markitect_tool.generation import (
from markitect_tool.literate import tangle_markdown, weave_markdown, write_tangle_files
from markitect_tool.ops import IncludeError, compose_files, resolve_includes, transform_markdown
from markitect_tool.processor import ProcessorContext, run_fenced_processors
from markitect_tool.policy import LocalLabelPolicyGateway
from markitect_tool.policy import (
EnterprisePolicyError,
FlexAuthResourceManifest,
LocalLabelPolicyGateway,
load_enterprise_policy_subject,
)
from markitect_tool.query import (
InvalidQueryError,
extract_document,
@@ -791,6 +796,68 @@ def policy_check(
raise click.exceptions.Exit(0 if decision.get("allowed") else 1)
@policy.command("subject")
@click.argument("claims_file", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.option(
"--policy-map",
"policy_map_file",
type=click.Path(exists=True, dir_okay=False, path_type=Path),
required=True,
help="Enterprise policy map file.",
)
@click.option("--group", "groups", multiple=True, help="Additional resolved group. May be repeated.")
@click.option(
"--environment",
type=click.Choice(["development", "test", "production"], case_sensitive=False),
help="Validation environment for issuer safety checks.",
)
@click.option(
"--format",
"output_format",
type=click.Choice(["json", "yaml", "text"], case_sensitive=False),
default="text",
show_default=True,
)
def policy_subject(
claims_file: Path,
policy_map_file: Path,
groups: tuple[str, ...],
environment: str | None,
output_format: str,
) -> None:
"""Map enterprise identity claims into a Markitect policy subject."""
try:
subject = load_enterprise_policy_subject(
claims_file,
policy_map_file,
extra_groups=list(groups),
environment=environment,
)
except EnterprisePolicyError as exc:
raise click.ClickException(str(exc)) from exc
_emit_subject_result({"subject": subject.to_dict()}, output_format)
@policy.command("resource-manifest")
@click.argument("manifest_file", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.option(
"--format",
"output_format",
type=click.Choice(["json", "yaml", "text"], case_sensitive=False),
default="text",
show_default=True,
)
def policy_resource_manifest(manifest_file: Path, output_format: str) -> None:
"""Inspect a Markitect flex-auth resource registration manifest."""
try:
manifest = FlexAuthResourceManifest.from_file(manifest_file)
except EnterprisePolicyError as exc:
raise click.ClickException(str(exc)) from exc
_emit_resource_manifest_result({"manifest": manifest.to_dict()}, output_format)
@main.group("class")
def class_group() -> None:
"""Resolve deterministic content classes."""
@@ -1736,6 +1803,34 @@ def _emit_policy_result(data: dict, output_format: str) -> None:
click.echo(f"reason: {decision.get('reason')}")
def _emit_subject_result(data: dict, output_format: str) -> None:
if output_format == "json":
click.echo(json.dumps(data, indent=2, ensure_ascii=False))
elif output_format == "yaml":
click.echo(yaml.safe_dump(data, sort_keys=False))
else:
subject = data["subject"]
click.echo(f"subject: {subject.get('id')}")
click.echo(f"roles: {', '.join(subject.get('roles', [])) or '<none>'}")
click.echo(f"labels: {', '.join(subject.get('allowed_labels', [])) or '<none>'}")
click.echo(f"trust_zones: {', '.join(subject.get('trust_zones', [])) or '<none>'}")
click.echo(f"actions: {', '.join(subject.get('allowed_actions', [])) or '<none>'}")
def _emit_resource_manifest_result(data: dict, output_format: str) -> None:
if output_format == "json":
click.echo(json.dumps(data, indent=2, ensure_ascii=False))
elif output_format == "yaml":
click.echo(yaml.safe_dump(data, sort_keys=False))
else:
manifest = data["manifest"]
click.echo(f"manifest: {manifest.get('id')}")
click.echo(f"system: {manifest.get('system')}")
click.echo(f"resources: {len(manifest.get('resources', []))}")
actions = ", ".join(manifest.get("actions", [])) or "<none>"
click.echo(f"actions: {actions}")
def _emit_metrics(data: dict, output_format: str) -> None:
if output_format == "json":
click.echo(json.dumps(data, indent=2, ensure_ascii=False))