From 60b752742cfe6a0c50381abc9c9d1a685a282e80 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Jun 2026 04:14:35 +0000 Subject: [PATCH] Fix PKI initialization and improve diagnostics - Remove unsupported '--ip' flag from step ca init command (newer step versions don't support this flag; IP assignment is handled by Docker networking) - Improve error diagnostics in PKI handler with detailed logging of step command invocation and failure reasons - Add step CLI version check to preflight diagnostics for early detection of PKI compatibility issues - Better error messages guide users when step CLI is missing or incompatible Fixes Phase 3 PKI initialization failure with newer step-ca images that removed the --ip flag. Co-Authored-By: Claude Haiku 4.5 Claude-Session: https://claude.ai/code/session_01YZeM5c3NRxL5jVCNGtbcCD --- netengine/diagnostic/preflight.py | 48 +++++++++++++++++++++++++++++++ netengine/handlers/pki_handler.py | 13 +++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/netengine/diagnostic/preflight.py b/netengine/diagnostic/preflight.py index a87b6d8..7ffd178 100644 --- a/netengine/diagnostic/preflight.py +++ b/netengine/diagnostic/preflight.py @@ -455,6 +455,53 @@ def _check_optional_commands(ctx: DoctorContext) -> list[DoctorCheckResult]: return [_check_command(name, required=False) for name in ctx.optional_commands] +def _check_step_version() -> DoctorCheckResult: + """Check step CLI version for PKI compatibility.""" + import shutil + + step_path = shutil.which("step") + if not step_path: + return DoctorCheckResult( + "step version", + DoctorStatus.SKIP, + "step CLI not found; PKI features will be unavailable", + None, + "host", + required=False, + ) + + try: + result = _run(["step", "version"]) + if result.returncode == 0: + version_output = result.stdout.strip() + return DoctorCheckResult( + "step version", + DoctorStatus.OK, + f"step CLI available: {version_output.split()[0] if version_output else 'unknown'}", + None, + "host", + required=False, + ) + except Exception as exc: + return DoctorCheckResult( + "step version", + DoctorStatus.WARN, + f"Could not determine step version: {exc}", + "Ensure step CLI is installed and working correctly.", + "host", + required=False, + ) + + return DoctorCheckResult( + "step version", + DoctorStatus.WARN, + "step version check failed", + "Ensure step CLI is properly installed.", + "host", + required=False, + ) + + def _check_database(ctx: DoctorContext) -> list[DoctorCheckResult]: if (ctx.feature_flags or {}).get("skip_db", False): return [ @@ -505,6 +552,7 @@ def standard_probes() -> tuple[DoctorProbe, ...]: lambda ctx: _check_python(), _check_required_commands, _check_optional_commands, + lambda ctx: _check_step_version(), lambda ctx: _check_docker_daemon(), lambda ctx: _check_compose(), _check_database, diff --git a/netengine/handlers/pki_handler.py b/netengine/handlers/pki_handler.py index cc29374..960461d 100644 --- a/netengine/handlers/pki_handler.py +++ b/netengine/handlers/pki_handler.py @@ -99,19 +99,26 @@ async def _generate_ca(self) -> None: "NetEngines Root CA", "--dns", self.ca_dns, - "--ip", - self.ca_ip, "--provisioner", "acme", "--password-file", "/tmp/pass/password.txt", "--no-start", ] + logger.info(f"Running step ca init with command: {' '.join(cmd)}") result = await self.docker.run_container_one_off( image=self.image, command=cmd, volumes=volumes, environment={} ) if result["exit_code"] != 0: - raise PKIError(f"step ca init failed: {result['logs']}") + logger.error(f"step ca init failed with exit code {result['exit_code']}") + logger.error(f"Command: {' '.join(cmd)}") + logger.error(f"Output: {result['logs']}") + raise PKIError( + f"step ca init failed: {result['logs']}. " + f"Ensure step CLI version is compatible (current image: {self.image}). " + f"The '--ip' flag is not supported in newer step versions; " + f"container IP is assigned by Docker networking instead." + ) # Persist password to volume so _start_server can retrieve it persist_result = await self.docker.run_container_one_off(