Skip to content

Add CNAPP integration commands and helpers#2102

Merged
craiglurey merged 2 commits into
releasefrom
KC-1290-2
Jul 8, 2026
Merged

Add CNAPP integration commands and helpers#2102
craiglurey merged 2 commits into
releasefrom
KC-1290-2

Conversation

@jpkeepersecurity

Copy link
Copy Markdown
Contributor

Title

Add CNAPP integration commands and helpers

Summary

Adds a new pam cnapp ... command tree to Commander that drives the krouter CNAPP (Cloud-Native Application Protection Platform) REST endpoints, giving CLI parity with the vault's Cloud Security view. The initial provider is Wiz; the wire/proto layer is provider-agnostic so additional CNAPP vendors can be added without further CLI changes.

Includes the protobuf definitions, a thin helper layer that owns the wire contract, the argparse-driven command surface, and a unit-test suite that exercises the real proto serializers against a mocked router transport.

Changes

  • keepercommander/commands/discoveryrotation.py — register PAMCnappCommand under the pam group with alias cn.
  • keepercommander/commands/pam/cnapp_commands.py (new, 608 lines) — full pam cnapp command tree:
    • pam cnapp config set | test | test-encrypter | read | delete — manage the provider configuration and health-check the customer-deployed Encrypter.
    • pam cnapp queue list | associate | remediate | set-status | delete — drive the issue queue (list with optional payload decryption, attach a vault record, dispatch remediation to the gateway, update status, delete).
    • Client-side AES-256-GCM decryption of queue payloads using the Encrypter key resolved from the linked vault record. Wire format mirrors decryptCnappQueueItem in vault/cloudSecurityUtils.ts so the CLI and vault see the same plaintext.
    • --format table|json on read/list commands for scripting.
  • keepercommander/commands/pam/cnapp_helper.py (new, 241 lines) — single source of truth for the krouter wire contract. One Python function per endpoint under /api/user/cnapp/, plus enum parsers (provider_from_name, action_from_name) and UID conversion utilities. Callers pass parsed Python types; the helper builds the proto, dispatches via _post_request_to_router, and returns the typed response.
  • keepercommander/proto/cnapp_pb2.py (new, 181 lines) — generated protobuf bindings for cnapp.proto, covering CnappConfiguration, queue request/response messages, CnappProvider (currently WIZ), and CnappRemediationAction (ROTATE_CREDENTIALS, MANAGE_ACCESS, JIT_ACCESS, REMOVE_STANDING_PRIVILEGE).
  • unit-tests/pam/test_cnapp.py (new, 837 lines) — coverage for enum parsing, helper-level request shaping for every endpoint, command-level argument validation and output rendering (table + JSON), payload decryption (happy path + bad-key + missing-key fallback), and status-name → id resolution.

Cross-references

  • Server: krouter routes under /api/user/cnapp/... (configuration/{set,test,test-encrypter,read,delete}, queue, queue/{associate,remediate,set-status,delete}).
  • Vault: queue payload envelope and Encrypter-key custom-field label kept in sync with vault/cloudSecurityUtils.ts (CNAPP_ENCRYPTION_KEY_FIELD_LABEL = "Encryption Key", AES-256-GCM with nonce(12) || ciphertext || tag(16)).
  • Status enum mirrors CnappQueueStatus from CnappModels.kt / keeper.cnapp_queue_status — new statuses must be added in both places.

Notes / limitations

  • krouter currently only dispatches ROTATE_CREDENTIALS; the other remediation actions are wired through the proto but return RRC_BAD_REQUEST server-side until those flows are implemented.
  • config read never returns clientSecret; passing an empty --client-secret to config set instructs krouter to keep the previously stored value.
  • queue list falls back to showing payloads as encrypted (with a warning) when no Encrypter key can be resolved from the linked vault record; --no-decrypt opts out explicitly.

Test plan

  • python -m unittest unit-tests.pam.test_cnapp -v passes locally.
  • Against a krouter test environment with a Wiz tenant:
    • pam cnapp config set persists; pam cnapp config read returns the same network/provider/endpoint/client-id (and no secret).
    • pam cnapp config test succeeds with valid creds and fails cleanly with the provider's reason on bad creds.
    • pam cnapp config test-encrypter --url https://... returns OK for a healthy Encrypter and surfaces a clear error otherwise.
    • pam cnapp queue list --network-uid ... renders the table with decrypted summaries (severity · title · resource) when the Encrypter record is in the vault; the same call with --no-decrypt shows encrypted and a warning.
    • pam cnapp queue list --format json emits valid JSON with decryptedPayload populated and the raw payload field stripped.
    • pam cnapp queue associate then pam cnapp queue remediate ... rotate_credentials round-trips through the gateway and queue list reflects the new status.
    • pam cnapp queue set-status pending|in_progress|resolved|failed|cancelled and numeric ids both work; unknown names raise a CommandError listing the valid options.
    • pam cnapp config delete and pam cnapp queue delete succeed and subsequent reads return the expected empty/RRC_BAD_STATE responses.

@jpkeepersecurity jpkeepersecurity changed the base branch from master to release June 1, 2026 21:15
@smunoz-ks

Copy link
Copy Markdown

Hope to review this week, since not a priority today.

@sk-keeper sk-keeper force-pushed the release branch 2 times, most recently from b1183b7 to b384cf6 Compare June 7, 2026 04:05
@sk-keeper sk-keeper force-pushed the release branch 2 times, most recently from b11acff to c6ec45e Compare June 13, 2026 02:41
@sk-keeper sk-keeper force-pushed the release branch 2 times, most recently from 1b4d5b9 to 00cb187 Compare July 2, 2026 22:02
@smunoz-ks smunoz-ks requested a review from Copilot July 6, 2026 21:37

Copilot AI 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.

Pull request overview

This PR adds a new pam cnapp ... command tree plus a helper/proto layer to let Commander drive krouter’s CNAPP endpoints (initial provider: Wiz), including optional client-side AES-256-GCM payload decryption and a comprehensive unit test suite.

Changes:

  • Introduces CNAPP protobuf bindings and a helper module that builds/dispatches CNAPP proto requests to krouter.
  • Adds pam cnapp CLI commands for configuration management and queue operations (list/associate/remediate/set-status/delete), with --format table|json on read/list.
  • Adds unit tests covering helper request shaping, command argument handling, output rendering, and AES-GCM payload decryption behavior.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
keepercommander/commands/discoveryrotation.py Wires the new pam cnapp command tree into the existing PAM command group.
keepercommander/commands/pam/cnapp_commands.py Implements the argparse-driven CNAPP command surface, output formatting, and payload decryption/key-resolution.
keepercommander/commands/pam/cnapp_helper.py Provides endpoint-specific helper functions as the single source of truth for CNAPP krouter wire contracts.
keepercommander/proto/cnapp_pb2.py Adds generated protobuf bindings for CNAPP request/response messages and enums.
unit-tests/pam/test_cnapp.py Adds unit tests for enum parsing, helper calls, command behaviors, and payload decryption.
unit-tests/conftest.py Adds a pytest session fixture to preload keepercommander.commands.record to avoid an import cycle in tests.
unit-tests/pam/test_dag_layer_b_migration.py Adds a regression test ensuring AI settings requests bundle meta so krouter persists settings edges correctly.
Files not reviewed (1)
  • keepercommander/proto/cnapp_pb2.py: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 19 to 23
from datetime import datetime
from typing import Dict, Optional, Any, Set, List
from urllib.parse import urlparse, urlunparse
from typing import Optional, List

Comment thread keepercommander/commands/discoveryrotation.py Outdated
Comment thread keepercommander/commands/discoveryrotation.py Outdated
Comment on lines +68 to +70
"""Encrypter keys are typically `openssl rand -base64 32`. Try standard base64 first,
then base64url (legacy notes). 16 or 32 bytes only — anything else is rejected so we
don't pass garbage to AES-GCM."""
Comment on lines +107 to +116
for raw in labeled_raws:
key = _decode_aes_key(raw)
if key:
return key
logging.warning(
'CNAPP: "%s" field is present on encrypter record %s but is not a valid AES-256 key; '
'not using other note fields.',
CNAPP_ENCRYPTION_KEY_LABEL, config_record_uid,
)
return None
Comment thread unit-tests/pam/test_cnapp.py Outdated
Comment on lines +746 to +747
"""`_decode_aes_key` must accept both standard and url-safe base64, only when the
decoded length is 16 or 32 bytes."""
@datadog-keeper-security

This comment has been minimized.

idimov-keeper and others added 2 commits July 8, 2026 20:24
Re-applied on top of origin/release after sync-branch. Includes CNAPP command helpers, PAM graph endpoint migration, and related unit test updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move SIEM Tool mock expiration to 2030 so status detection tests remain deterministic when CI runs in UTC after the token expiry date.

Co-authored-by: Cursor <cursoragent@cursor.com>
@craiglurey craiglurey merged commit e61ccec into release Jul 8, 2026
4 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.

5 participants