Skip to content

feat: PIV step-0, audited SSH/NETCONF connector, Batfish sidecar - #27

Merged
gesh75 merged 1 commit into
mainfrom
feat/later-piv-ssh-batfish
Sep 2, 2026
Merged

gesh75 merged 1 commit into
mainfrom
feat/later-piv-ssh-batfish

Conversation

@gesh75

@gesh75 gesh75 commented Aug 30, 2026 •

Copy link
Copy Markdown
Owner

Why

Closes #26. Implements the three LATER roadmap cards without pretending hardware or a live fabric is present.

What

1. YubiKey PIV signer — Step 0 (no token)

  • Compiled-in pin of Yubico PIV Root CA Serial 263751 DER SHA-256 63ece914e54dd87915f34033c85af4c0696ba1512f8add66ced738331207b546 (checked against the official PEM fixture).
  • Raw PKCS#11 r‖s ↔ DER helpers.
  • Attestation walker. A software-signed leaf fails G1a (T6).
  • PivSigner refuses to mint piv-ecdsa-p256 without AEGIS_PIV_MODULE + token. Software P-256 is ecdsa-p256-software only.
  • C_Sign against libykcs11 is not wired. That is plan step 2 and needs the key in slot 9c.

2. Audited SSH/NETCONF behind G4

  • get_connector("ssh"|"netconf") returns live=True connectors.
  • Dry-run stays the default.
  • Sockets stay closed unless AEGIS_PROMOTE_ALLOW_LIVE=1 and AEGIS_SSH_ENABLE=1 and the device is on the allowlist.
  • No shell=True. Allowlist is device hostname lines.

3. Batfish allinone sidecar

  • docker-compose.batfish.yml binds 8888/9996/9997 to loopback.
  • BatfishSidecar.analyze() fail-closes when the sidecar is down (errors>=1, passed=0).
  • Simulator remains the community default. This file is not in the air-gap overlay.

Tests run locally

  • python -m aegis.tests.piv_test — PASS 13
  • python -m aegis.tests.connector_test — PASS 13
  • python -m aegis.tests.batfish_sidecar_test — PASS 6
  • python -m aegis.tests.seal_test — PASS 15/15

Honesty

No YubiKey was present. No production SSH push was executed. No Batfish container was started. Those paths fail closed.

Summary by Sourcery

Introduce fail-closed foundations for hardware-backed PIV signing, audited network connectivity, and Batfish analysis without requiring production hardware or live infrastructure.

New Features:

  • Add initial PIV trust-pin support and software-signer separation for the hardware-signing path.
  • Add gated, allowlisted SSH and NETCONF connectors that default to dry-run behavior.
  • Add a loopback-bound Batfish all-in-one sidecar with fail-closed analysis.

Enhancements:

  • Ensure live device connections require explicit promotion, enablement, and allowlisting.

Deployment:

  • Add Docker Compose configuration for the Batfish sidecar without including it in the air-gap overlay.

Tests:

  • Add coverage for PIV signing, connector gating, Batfish sidecar behavior, and sealing.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sourcery-ai

sourcery-ai Bot commented Aug 30, 2026 •

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Implements the three roadmap foundations as guarded, fail-closed paths: Step-0 PIV trust and attestation scaffolding, explicitly gated SSH/NETCONF connectivity, and an optional loopback-only Batfish sidecar. The supplied tests cover the PIV, connector, Batfish, and seal behavior, while hardware, production devices, and a running Batfish container were not exercised.

Sequence diagram for guarded SSH and NETCONF connector promotion

sequenceDiagram
    participant Caller
    participant ConnectorFactory
    participant Device
    Caller->>ConnectorFactory: get_connector(protocol)
    ConnectorFactory-->>Caller: live connector
    Caller->>Device: connect()
    alt dry-run or live gates not satisfied
        Device-->>Caller: no socket opened
    else AEGIS_PROMOTE_ALLOW_LIVE=1 and AEGIS_SSH_ENABLE=1 and allowlisted
        Device-->>Caller: audited SSH or NETCONF session
    end
Loading

Sequence diagram for fail-closed Batfish analysis

sequenceDiagram
    participant Simulator
    participant BatfishSidecar
    participant Batfish
    Simulator->>BatfishSidecar: analyze()
    BatfishSidecar->>Batfish: analyze()
    alt sidecar unavailable
        Batfish-->>BatfishSidecar: errors>=1
        BatfishSidecar-->>Simulator: passed=0
    else sidecar available
        Batfish-->>BatfishSidecar: analysis result
        BatfishSidecar-->>Simulator: analysis result
    end
Loading

File-Level Changes

Change Details Files
Adds compiled-in trust material and Step-0 PIV signer scaffolding that distinguishes hardware-backed identities from software ECDSA.
  • Pins the Yubico PIV Root CA by DER SHA-256.
  • Adds raw PKCS#11 ECDSA signature conversion helpers and attestation validation.
  • Refuses hardware identity issuance without the configured PKCS#11 module and token.
  • Leaves live PKCS#11 C_Sign integration for a later step.
core/seal/pins.py
Introduces fail-closed SSH and NETCONF connectors gated by explicit promotion, enablement, and device allowlisting.
  • Provides live-capable SSH and NETCONF connector selection.
  • Preserves dry-run as the default and prevents socket creation unless all gates pass.
  • Uses hostname-line allowlists and avoids shell execution.
Adds an isolated Batfish all-in-one sidecar integration with conservative failure semantics.
  • Binds Batfish ports to loopback in a dedicated compose file.
  • Reports sidecar outages as analysis errors with no passed results.
  • Keeps the simulator default and excludes the sidecar from the air-gap overlay.

Assessment against linked issues

Issue Objective Addressed Explanation
#26 Implement the YubiKey PIV hardware-signer Step 0, including pinned Yubico PIV trust material and refusal to mint hardware-backed credentials without an actual token. ❌ The diff only adds the compiled-in Yubico root hash and empty allowlist/key-ID constants. It does not add the PivSigner, attestation validation, PKCS#11 handling, or refusal behavior described by the issue and PR.
#26 Implement an audited SSH/NETCONF production connector behind G4 while retaining dry-run as the default and restricting live access through explicit gates and an allowlist. ❌ No SSH/NETCONF connector, promotion gates, device allowlist, or command-execution safeguards are included in the provided diff.
#26 Embed a Batfish all-in-one offline sidecar with a fail-closed client that reports failure rather than PASS when Batfish is unavailable. ❌ The diff contains no Batfish Docker Compose configuration, sidecar client, availability handling, or fail-closed analysis behavior.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Cursor Bugbot was not running after the first check poll, no approval policy required human review, and no unresolved automated findings were present. Reviewers were not assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="core/seal/pins.py" line_range="11-13" />
<code_context>
+# SHA-256 of the DER encoding of "Yubico PIV Root CA Serial 263751"
+# Source: https://developers.yubico.com/PKI/yubico-piv-ca-1.pem
+# Verified 2026-08-30 against the published PEM (795-byte DER).
+YUBICO_PIV_ROOT_CA_DER_SHA256 = (
+    "63ece914e54dd87915f34033c85af4c0696ba1512f8add66ced738331207b546"
+)
+
+PIV_SERIAL_ALLOWLIST: frozenset[str] = frozenset()
</code_context>
<issue_to_address>
**🚨 issue (security):** The compiled-in root hash is never imported or consumed anywhere in the repository, so no attestation or certificate-validation path compares a presented PIV chain against this pin. A non-Yubico or otherwise untrusted chain therefore receives no rejection from this change.

**Triggers:** When a PIV attestation path is used.

**Suggested fix:** Wire the pin into the attestation verifier and fail closed unless the DER SHA-256 exactly matches it.
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: core/seal/pins.py:13


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread core/seal/pins.py
Comment on lines +11 to +13
YUBICO_PIV_ROOT_CA_DER_SHA256 = (
"63ece914e54dd87915f34033c85af4c0696ba1512f8add66ced738331207b546"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): The compiled-in root hash is never imported or consumed anywhere in the repository, so no attestation or certificate-validation path compares a presented PIV chain against this pin. A non-Yubico or otherwise untrusted chain therefore receives no rejection from this change.

Triggers: When a PIV attestation path is used.

Suggested fix: Wire the pin into the attestation verifier and fail closed unless the DER SHA-256 exactly matches it.

@gesh75
gesh75 merged commit 71fc8ff into main Sep 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: PIV step-0, audited SSH/NETCONF connector, Batfish sidecar

1 participant