Skip to content

feat(security): implement SEC13-01 mutual TLS validation#538

Open
abegnoche wants to merge 4 commits into
mainfrom
cursor/sec13-01-mtls-12d5
Open

feat(security): implement SEC13-01 mutual TLS validation#538
abegnoche wants to merge 4 commits into
mainfrom
cursor/sec13-01-mtls-12d5

Conversation

@abegnoche

@abegnoche abegnoche commented Jul 13, 2026

Copy link
Copy Markdown
Member

Summary

Implements M7 Batch B network-security issue:

Issue Test ID Check
#309 SEC13-01 SEC13-01 MutualTlsCheck

Changes

  • Add MutualTlsCheck requiring tests.north_south_mtls_enforced + tests.east_west_mtls_enforced
  • Shared probe (providers/shared/mutual_tls_test.py): anonymous reject + client-cert accept
  • AWS wrapper: probes EDGE_ENDPOINTS when certs are set; marks east-west provider_hidden unless EAST_WEST_ENDPOINTS is set; structured skip when nothing configured
  • my-isv DEMO_MODE wiring for make demo-test

Operator env (real probes)

  • EDGE_ENDPOINTS / EAST_WEST_ENDPOINTShost:port,...
  • MTLS_CA_CERT_PATH, MTLS_CLIENT_CERT_PATH, MTLS_CLIENT_KEY_PATH

Test plan

  • pytest isvtest/tests/test_security.py::TestMutualTlsCheck scripts/tests/test_mutual_tls_probe.py
  • ISVCTL_DEMO_MODE=1 ISVTEST_INCLUDE_UNRELEASED=1 my-isv security (MutualTlsCheck PASS)
  • Default demo still PASS (check SKIPPED as unreleased)
  • make lint

Closes #309

Open in Web Open in Cursor 

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Added mutual TLS (SEC13-01) validation for north-south and east-west traffic, including structured success/failure/skip and provider-hidden handling.
    • Extended security suite and AWS/provider configs to run the mutual TLS check and report its results; security checklist now reflects the new test.
  • Bug Fixes
    • Improved AWS tenant teardown polling for instances stuck in pending and enhanced cleanup timeout/error handling.
  • Tests
    • Added unit/integration coverage for mutual TLS probing, SEC13-01 validation behavior, and AWS cleanup scenarios.

Add MutualTlsCheck for north-south and east-west mTLS (or equivalent),
with a shared probe, AWS wrapper (east-west provider-hidden by default),
and my-isv DEMO_MODE wiring.

Closes #309

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Alexandre Begnoche <abegnoche@users.noreply.github.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4a90481a-ea28-4174-b491-981a4bb7a9cb

📥 Commits

Reviewing files that changed from the base of the PR and between 0f8b1be and ee05570.

📒 Files selected for processing (3)
  • isvctl/configs/providers/aws/scripts/security/tenant_isolation_test.py
  • isvctl/configs/providers/shared/mutual_tls_test.py
  • scripts/tests/test_mutual_tls_probe.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • isvctl/configs/providers/aws/scripts/security/tenant_isolation_test.py
  • isvctl/configs/providers/shared/mutual_tls_test.py

📝 Walkthrough

Walkthrough

Adds SEC13-01 mutual TLS probing, structured validation, provider and suite integration, and tests. AWS tenant teardown now uses bounded polling that handles pending EC2 termination states before network cleanup.

Changes

Mutual TLS validation

Layer / File(s) Summary
Mutual TLS probe and result contract
isvctl/configs/providers/shared/mutual_tls_test.py, scripts/tests/test_mutual_tls_probe.py
Adds endpoint parsing, anonymous and authenticated TLS handshakes, per-plane aggregation, structured skip/failure/success results, provider-hidden handling, CLI execution, and automated coverage.
Provider and suite integration
isvctl/configs/providers/aws/config/security.yaml, isvctl/configs/providers/my-isv/config/security.yaml, isvctl/configs/suites/*, docs/test-plan.yaml
Registers the mutual TLS step, supplies provider endpoint and certificate settings, updates suite metadata, and adds network/security labels.
SEC13-01 validation
isvtest/src/isvtest/validations/security.py, isvtest/src/isvtest/validations/__init__.py, isvtest/tests/test_security.py
Adds and exports MutualTlsCheck, validates probe contracts and endpoint counts, handles structured skips, and tests the result paths.

AWS tenant teardown polling

Layer / File(s) Summary
Bounded tenant instance teardown
isvctl/configs/providers/aws/scripts/security/tenant_isolation_test.py, isvctl/tests/providers/aws/test_aws_security_scripts.py
Polls EC2 termination through pending states with a timeout, updates teardown error handling, and verifies subsequent security group, subnet, and VPC cleanup.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SecurityCommand
  participant mutual_tls_test
  participant TLSEndpoint
  participant MutualTlsCheck
  SecurityCommand->>mutual_tls_test: Run SEC13-01 probe
  mutual_tls_test->>TLSEndpoint: Test anonymous and authenticated TLS
  TLSEndpoint-->>mutual_tls_test: Return handshake results
  mutual_tls_test-->>MutualTlsCheck: Provide structured JSON contract
  MutualTlsCheck-->>SecurityCommand: Report validation status
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The SEC11-01 tenant teardown/poller changes and tests are unrelated to SEC13-01. Split the SEC11-01 teardown/poller updates and their tests into a separate PR unless they are required for the SEC13-01 work.
Docstring Coverage ⚠️ Warning Docstring coverage is 72.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the main change: SEC13-01 mutual TLS validation for security.
Linked Issues check ✅ Passed The PR implements SEC13-01 mTLS or equivalent checks for north-south and east-west traffic as requested.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/sec13-01-mtls-12d5

Comment @coderabbitai help to get the list of available commands.

abegnoche and others added 2 commits July 13, 2026 15:31
boto3's InstanceTerminated waiter treats pending as terminal failure, so
terminating a still-booting tenant fixture failed the step after probes
passed. Wait for running on launch and poll terminate without that race.

Signed-off-by: Alexandre Begnoche <abegnoche@nvidia.com>
…apper

Wire aws/config/security.yaml straight to the shared mutual TLS probe
via --east-west-provider-hidden-message instead of a 131-line wrapper
that re-implemented the shared main() and reached into its private
helpers. In the shared probe, collapse the duplicate skip payload into
a single guard, extract _bad_input_result, loop over the two traffic
planes instead of copy-pasting them, build the SSL contexts once per
run instead of two per endpoint, and reduce the handshake except tuple
to OSError.

Also drop the instance_running launch waiter from the SEC11 tenant
fixture: the pending-tolerant terminate poller already covers the race
it guarded, and the waiter cost up to a minute per tenant of setup
wall-clock on every run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Alexandre Begnoche <abegnoche@nvidia.com>
@abegnoche abegnoche marked this pull request as ready for review July 13, 2026 20:06
@abegnoche abegnoche requested a review from a team as a code owner July 13, 2026 20:06
@abegnoche

Copy link
Copy Markdown
Member Author

/ok to test 0f8b1be

@github-actions

Copy link
Copy Markdown

🔐 TruffleHog Secret Scan

No secrets or credentials found!

Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉

🔗 View scan details

🕐 Last updated: 2026-07-13 20:07:17 UTC | Commit: 0f8b1be

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🧹 Nitpick comments (2)
isvctl/tests/providers/aws/test_aws_security_scripts.py (1)

3644-3708: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage of the pending-tolerant path; consider adding the two untested branches.

_wait_instance_terminated's InvalidInstanceID.NotFound short-circuit and its TimeoutError path (instance never reaches terminated) aren't exercised by any test. Both are cheap to add and cover failure modes on a resource-cleanup path.

♻️ Example additional tests
def test_wait_instance_terminated_returns_on_not_found(
    monkeypatch: pytest.MonkeyPatch,
    tenant_isolation_module: ModuleType,
) -> None:
    """Already-gone instances should not be treated as a failure."""

    class FakeEc2:
        def describe_instances(self, InstanceIds: list[str]) -> dict[str, Any]:
            raise tenant_isolation_module.ClientError(
                {"Error": {"Code": "InvalidInstanceID.NotFound", "Message": "gone"}},
                "DescribeInstances",
            )

    monkeypatch.setattr(tenant_isolation_module.time, "sleep", lambda _seconds: None)
    tenant_isolation_module._wait_instance_terminated(FakeEc2(), "i-gone123", delay=0.0, max_attempts=3)


def test_wait_instance_terminated_times_out(
    monkeypatch: pytest.MonkeyPatch,
    tenant_isolation_module: ModuleType,
) -> None:
    """An instance stuck in shutting-down must raise TimeoutError, not hang forever."""

    class FakeEc2:
        def describe_instances(self, InstanceIds: list[str]) -> dict[str, Any]:
            return {"Reservations": [{"Instances": [{"State": {"Name": "shutting-down"}}]}]}

    monkeypatch.setattr(tenant_isolation_module.time, "sleep", lambda _seconds: None)
    with pytest.raises(TimeoutError):
        tenant_isolation_module._wait_instance_terminated(FakeEc2(), "i-stuck123", delay=0.0, max_attempts=3)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@isvctl/tests/providers/aws/test_aws_security_scripts.py` around lines 3644 -
3708, Add tests for the two untested branches of _wait_instance_terminated:
verify an InvalidInstanceID.NotFound ClientError returns without failure, and
verify an instance remaining in shutting-down raises TimeoutError after
max_attempts. Reuse the existing monkeypatched sleep and FakeEc2 test patterns.
isvtest/src/isvtest/validations/security.py (1)

251-260: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consolidate the skipped-step guard BaseValidation.execute() already skips before run() is entered, so this branch only duplicates the control flow and can drift from the shared skip message.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@isvtest/src/isvtest/validations/security.py` around lines 251 - 260, Remove
the step_output["skipped"] guard from the mTLS validation run method, leaving
skip handling to BaseValidation.execute(). Preserve the existing failure
handling for unsuccessful step output and the remaining validation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@isvctl/configs/providers/aws/scripts/security/tenant_isolation_test.py`:
- Around line 413-424: Update the instance teardown handling around
ec2.terminate_instances and _wait_instance_terminated to also catch
BotoCoreError alongside the existing ClientError and TimeoutError cases, append
the failure to errors, and allow the remaining tenant cleanup steps to continue.

In `@isvctl/configs/providers/shared/mutual_tls_test.py`:
- Around line 145-166: Update _handshake and probe_mtls_endpoint so DNS,
connection, timeout, and other transport failures return a distinct
transport-error classification rather than accepted=False. Compute
anonymous_rejected only when the anonymous attempt has a TLS-level rejection,
while preserving authenticated_accepted only for a successful authenticated
handshake.
- Around line 292-320: The missing-plane handling in the loop over planes
currently treats every omitted plane as passed. Update this logic so
_provider_hidden_plane is used only for the explicit AWS east-west provider
exception; return a failing missing-configuration result for all other absent
required planes, while preserving the existing endpoint aggregation and
REQUIRED_TESTS success calculation.
- Around line 120-126: Update the SSLContext configuration in the mutual TLS
setup to keep server hostname verification enabled by removing the assignment
that disables check_hostname, while preserving the existing CA verification and
client certificate loading behavior.

In `@scripts/tests/test_mutual_tls_probe.py`:
- Around line 98-106: Add a PEP 257-compliant docstring directly inside the test
helper function fake_probe, describing its purpose and relevant probe parameters
while leaving its signature and behavior unchanged.

---

Nitpick comments:
In `@isvctl/tests/providers/aws/test_aws_security_scripts.py`:
- Around line 3644-3708: Add tests for the two untested branches of
_wait_instance_terminated: verify an InvalidInstanceID.NotFound ClientError
returns without failure, and verify an instance remaining in shutting-down
raises TimeoutError after max_attempts. Reuse the existing monkeypatched sleep
and FakeEc2 test patterns.

In `@isvtest/src/isvtest/validations/security.py`:
- Around line 251-260: Remove the step_output["skipped"] guard from the mTLS
validation run method, leaving skip handling to BaseValidation.execute().
Preserve the existing failure handling for unsuccessful step output and the
remaining validation behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2b9da885-2043-4ffd-bf1c-2227c0b95ce7

📥 Commits

Reviewing files that changed from the base of the PR and between 25e3849 and 0f8b1be.

📒 Files selected for processing (12)
  • docs/test-plan.yaml
  • isvctl/configs/providers/aws/config/security.yaml
  • isvctl/configs/providers/aws/scripts/security/tenant_isolation_test.py
  • isvctl/configs/providers/my-isv/config/security.yaml
  • isvctl/configs/providers/shared/mutual_tls_test.py
  • isvctl/configs/suites/README.md
  • isvctl/configs/suites/security.yaml
  • isvctl/tests/providers/aws/test_aws_security_scripts.py
  • isvtest/src/isvtest/validations/__init__.py
  • isvtest/src/isvtest/validations/security.py
  • isvtest/tests/test_security.py
  • scripts/tests/test_mutual_tls_probe.py

Comment thread isvctl/configs/providers/shared/mutual_tls_test.py
Comment thread isvctl/configs/providers/shared/mutual_tls_test.py
Comment thread isvctl/configs/providers/shared/mutual_tls_test.py
Comment thread scripts/tests/test_mutual_tls_probe.py
Enable hostname verification with a CA, require TLS-layer rejection for
anonymous probes, fail omitted planes unless east-west is explicitly
provider-hidden, catch BotoCoreError during SEC11 terminate waits, and
document the probe test helper.

Signed-off-by: Alexandre Begnoche <abegnoche@nvidia.com>
@abegnoche

Copy link
Copy Markdown
Member Author

/ok to test ee05570

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.

SEC13-01: Verify mTLS (or equivalent) for all east-west and north-south traffic

2 participants