Skip to content

feat(pam): add KCM database connector for pam project import#1904

Open
jlima8900 wants to merge 18 commits intoKeeper-Security:masterfrom
jlima8900:feat/pam-kcm-import-pr1889
Open

feat(pam): add KCM database connector for pam project import#1904
jlima8900 wants to merge 18 commits intoKeeper-Security:masterfrom
jlima8900:feat/pam-kcm-import-pr1889

Conversation

@jlima8900
Copy link
Copy Markdown

Summary

Adds pam project kcm-import command for migrating KCM/Guacamole connections into Keeper PAM.

  • Connects to MySQL or PostgreSQL KCM database
  • Maps 150+ KCM parameters to PAM record fields
  • Creates PAM configurations with proper folder structure

Test plan

  • Tested with MySQL and PostgreSQL KCM databases
  • Verified parameter mapping for SSH, RDP, VNC, Kubernetes connection types

ukumar-ks and others added 18 commits March 12, 2026 09:05
* commander KC - (1128, 1115, 1114) bug fix chnages

* File flag fix under "epm deployment download" in commander

* confirmation promp added  for kepm agent delete command without --force flag

* Kepm PR review changes
* Fixed double new lines on some terminals (Linux, MacOS)
* Improved handling of non-terminal protocols
* Update to keeper_pam_webrtc_rs>=2.1.5
Corrects logic in needs_security_audit: remove the erroneous "or None" that forced password mismatch to always be true, and determine alignment by comparing stored score and breach-watch revisions only when a current password exists. Adds retrieval of score_revision and sec_revision and updates needs_alignment accordingly. Includes new unit and integration tests (unit-tests/test_security_audit.py and tests/test_security_audit_refresh.py) to validate revision-based alignment, password removal, and other audit-refresh scenarios.
* Added "Connect As" options allowing for aditional records to provide credentials and host:port

* Added keeper webrtc version to SDP attribute a=keeper-webrtc:X.Y.Z
The execute_rest() function previously retried throttled (403) responses
every 10 seconds with no maximum retry count. This caused Commander to
hang indefinitely when throttled, and the 10-second retry interval
prevented the server's cooldown timer from expiring.

Changes:
- Add max retry count (3 attempts) before raising KeeperApiError
- Parse the server's "try again in X minutes/seconds" message
- Use exponential backoff (30s, 60s, 120s) capped at server's suggestion
- Cap server wait time at 300s to prevent excessive delays
- Log throttle attempts as warnings instead of debug
- After max retries, raise KeeperApiError so callers can handle it

The --fail-on-throttle flag continues to work as before (immediate error).

Unit tests (9 cases):
- Normal request unaffected by throttle logic
- Throttle twice then succeed (backoff 30s, 60s)
- KeeperApiError raised after 3 retries
- --fail-on-throttle skips retries entirely
- Parses "try again in X seconds" correctly
- Parses "try again in X minutes" correctly
- Caps server wait at 300s
- Exponential backoff progression (30s, 60s, 120s)
- Missing message defaults to 60s
…er-Security#1885)

- Make record argument optional; session-only probes run without it
  - Add Python-side network probes: DNS, HTTPS, WebSocket, TCP/UDP STUN,
    TURN Allocate, UDP port sweep across ephemeral range
  - Add PAM Configuration section (record required): DAG load, config
    linkage, gateway registered/online, connections/portForwards
  - Add --verbose flag for DAG allowedSettings table and record typed fields
…tion

Adds `pam project kcm-import` command that connects to a KCM/Guacamole
database, extracts connections/users/groups, maps 150+ parameters, and
imports into Keeper PAM via the existing import/extend engine.

Features: --db-ssl, --docker-detect, --db-password-record, --gateway
(interactive selection), --max-instances (pool sizing), --dry-run,
--output, --folder-mode, --skip-users, --include-disabled.

Prints Docker/K8s deploy commands after gateway creation.
Same pattern as Keeper-Security#1873 — os.open mode only applies on creation, not
existing files. Add os.fchmod(fd, 0o600) to ensure owner-only
permissions regardless.
Security improvements:
- Block remote connections without SSL by default (require --db-ssl or
  --allow-cleartext to override)
- Clear connector.password and db_password after use
- Clear docker inspect stdout after parsing (contains all container
  env vars including other secrets)
- Remove db username from docker detect log output
- Add os.fchmod for existing output files
- Use e.__class__.__name__ instead of type(e).__name__ for consistency

Add 8 tests for SSL enforcement, credential cleanup, and log
sanitization.
Live E2E tests (skip when DB offline):
- Real DB connection, schema validation, data extraction
- Parameter mapping with real KCM data (SSH + RDP connections)
- All 3 folder modes (ksm/exact/flat) against real groups
- Docker detect against real guacamole-postgres container
- Full execute() pipeline: dry-run, output file, skip-users,
  include-disabled, custom project name, all folder modes
- Error paths: wrong password, wrong db name, wrong port
- Remote SSL enforcement, nonexistent Docker container

Unit tests:
- Gateway resolution: not found, found by name, offline warning
- _find_config_for_gateway: match and no-match paths
- Deploy instructions output verification
- _is_local_host: localhost, IPv4/IPv6, RFC1918, public IPs
- Docker container name passthrough (custom + default)
- DB flag passthrough: port, db_name, db_user, default ports
- Error paths: connection failure, schema failure, invalid port,
  Docker timeout, Docker not installed
Bugs found during live E2E testing against real vault:
- PAMController protobuf has no `isOnline` attribute — replaced with
  router_get_connected_gateways() cross-reference to determine online
  status
- PAMController has no `version` attribute — removed from display
- Unused import (pam_configurations_get_all) replaced with
  router_helper

Verified full E2E: DB connect → extract → transform → vault import →
gateway creation → folder structure → shared folders → PAM config →
KSM app. 8 records created successfully (3 resources, 3 users,
1 config, 1 app).
f'Use --db-ssl to encrypt, or --allow-cleartext to override.')
logging.warning(
'WARNING: Connecting to remote database %s without SSL/TLS. '
'Credentials and extracted data will transit in cleartext.', db_host)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
db_type, db_host, db_port, db_user, db_password, db_name, ssl=db_ssl
)
try:
logging.info('Connecting to KCM database at %s:%d...', db_host, db_port)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
db_type, db_host, db_port, db_user, db_password, db_name, ssl=db_ssl
)
try:
logging.info('Connecting to KCM database at %s:%d...', db_host, db_port)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
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.

8 participants