Conversation
- Introduced Tailscale configuration and management in the service. - Added functions for installing, starting, and managing Tailscale daemons and funnels. - Enhanced ProcessInfo to track Tailscale status and ports. - Updated ServiceManager to handle Tailscale alongside existing tunneling options (ngrok, Cloudflare). - Implemented validation for Tailscale configuration parameters. - Created a new TailscaleConfigurator class for managing Tailscale setup and validation. - Added logging for Tailscale subprocess activities. - Updated unit tests to cover new Tailscale functionality.
- Introduced `tailscale_advertise_tags` to ServiceConfig and related classes. - Updated ServiceConfigHandler to handle new argument for Tailscale. - Modified TailscaleConfigurator to utilize advertise tags during authentication. - Adjusted validation logic to check for presence of Tailscale auth key and tags. - Enhanced installation and daemon management functions to ensure proper handling of Tailscale. - Updated unit tests to cover new `tailscale_advertise_tags` parameter.
…2365) (#2379) * Fix Gateway Name not displayed in pam rotation info output * Add UID type normalization and graceful error handling to gateway name resolution * Improve gateway name resolution: add UID validation and specific exception logging * Prevent None == None false positive by explicitly checking target_uid before gateway lookup
#2372) * Block Service Mode from ever accessing its own config records * Fix copilot review comments * Fix claude review comments * Fix review comments
…ess (#2383) (#2385) * Protect Integration config records from Service Mode API access * Add terraform backward compatability and test cases * Fix review comments * Fix failing test case in windows * Restrict folder access via Service Mode for all *-setup commands * Prevent config and service config json file attachments * Fix claude review comments
- Introduced Tailscale configuration and management in the service. - Added functions for installing, starting, and managing Tailscale daemons and funnels. - Enhanced ProcessInfo to track Tailscale status and ports. - Updated ServiceManager to handle Tailscale alongside existing tunneling options (ngrok, Cloudflare). - Implemented validation for Tailscale configuration parameters. - Created a new TailscaleConfigurator class for managing Tailscale setup and validation. - Added logging for Tailscale subprocess activities. - Updated unit tests to cover new Tailscale functionality.
- Introduced `tailscale_advertise_tags` to ServiceConfig and related classes. - Updated ServiceConfigHandler to handle new argument for Tailscale. - Modified TailscaleConfigurator to utilize advertise tags during authentication. - Adjusted validation logic to check for presence of Tailscale auth key and tags. - Enhanced installation and daemon management functions to ensure proper handling of Tailscale. - Updated unit tests to cover new `tailscale_advertise_tags` parameter.
…ithub.com/Keeper-Security/Commander into feature/tailscale-funnel-service-mode-int
|
|
||
| except Exception as e: | ||
| logger.error(f"Failed to start service subprocess: {e}") | ||
| raise |
There was a problem hiding this comment.
Tailscale Funnel is started before the Commander service subprocess is successfully created. If spawn_detached_process() or ProcessInfo.save() fails here, the exception path does not stop the Tailscale Funnel that was already configured at lines 118-120. This can leave the Funnel publicly exposed while the Commander service is not running. Can we add Tailscale cleanup to this rollback path?
There was a problem hiding this comment.
fixed, the outer exception handler now stops the Funnel if it was already up before the subprocess/Flask app failed to start.
| except psutil.NoSuchProcess: | ||
| ProcessInfo.clear() | ||
| pass |
There was a problem hiding this comment.
When the Commander process is no longer running, this clears ProcessInfo but leaves the Tailscale Funnel configuration active. Since Funnel is managed by tailscaled and not tied to the Commander process lifecycle, an unexpected Commander crash/SIGKILL can leave the public Funnel endpoint enabled. Should we reconcile/disable the Commander-managed Funnel when detecting that the service process is gone?
There was a problem hiding this comment.
Fixed — get_status() now stops the Funnel too when it detects the process is gone, not just on an explicit service-stop
| # Tailscale Funnel only accepts one of these as the external-facing port; | ||
| # the local target port (the Commander service port) is unrestricted and | ||
| # separate. 443 is the default so the public URL needs no port suffix. | ||
| TAILSCALE_FUNNEL_ALLOWED_PORTS = (443, 8443, 10000) |
There was a problem hiding this comment.
TAILSCALE_FUNNEL_ALLOWED_PORTS defines the supported external Funnel ports, but start_tailscale_funnel() doesn't validate funnel_port against it. Should we validate the port here before invoking the CLI, or remove the unused constant?
There was a problem hiding this comment.
Added validation using the existing constant instead of removing it. The parameter is retained for future extensibility and keeps the signature consistent with get_tailscale_funnel_url and stop_tailscale_funnel, so validating it now prevents invalid values from reaching the Tailscale CLI and failing there.
… in configuration
There was a problem hiding this comment.
Do not commit log file and log folder
|
|
||
| guidance = guidance_fn() | ||
| logger.error(guidance) | ||
| print(guidance) |
There was a problem hiding this comment.
Can you explain why guidance is printed?
There was a problem hiding this comment.
This flow handles two checks: the Tailscale CLI being missing and the daemon not running. In either case, we show the manual fix before offering auto-fix, so the user always knows what to do if they decline or auto-fix fails
Guidance here printed for the manual fix
Adds Tailscale Funnel as a new tunnel option for Commander Service Mode, alongside the existing Ngrok and Cloudflare integrations. Users can now expose the Service Mode REST API over a public HTTPS URL using their own Tailscale account, with no changes to how Ngrok/Cloudflare already work.
Features
-ts, --tailscale <auth-key>/-tst, --tailscale_advertise_tags <tags>, following the same single-flag convention as-ng/-cf. Mutually exclusive with Ngrok/Cloudflare.tailscaledisn't running.tailscale up; never touches the Service Mode API Key, which continues to gate every API request unchanged.service-create/service-start/service-status/service-stop. Startup failures roll back cleanly (including already-started Ngrok/Cloudflare processes).service-status, and included in Docker vault-record metadata (-ur).--auth-key=file:...) instead of a raw CLI argument, avoiding exposure viapsto other local users. Never logged.Design notes
service-stoponly resets the Funnel exposure — it doesn't log the machine out of Tailscale or stop the daemon, sincetailscaledis system-wide and may be used for other things on the same machine.-ts <key>as a single flag) intentionally matches the existing-ng/-cfconvention rather than a separate enable+key pair.Files changed
keepercommander/service/config/tailscale_config.py(new)ngrok_config.py/cloudflare_config.pykeepercommander/service/util/tunneling.pytailscaleCLI wrapper functions (install, daemon start, auth, Funnel start/stop/status, URL lookup)keepercommander/service/core/service_manager.pystart_service/stop_service/get_status, including rollback-on-failure and interrupt handlingkeepercommander/service/core/process_info.pytailscale_enabled/tailscale_portlifecycle tracking (no PID — Tailscale has no Commander-owned subprocess)keepercommander/service/core/globals.pykeepercommander/service/commands/create_service.py-ts/-tstCLI flags and config schema fieldskeepercommander/service/commands/service_config_handlers.pykeepercommander/service/commands/integrations/vault_metadata.pyget_service_url()helper; fixes Docker metadata write-back timing so it waits for the real URLkeepercommander/service/config/config_validation.pyvalidate_tailscale_auth_keykeepercommander/service/config/models.py/service_config.pytailscale,tailscale_auth_key,tailscale_advertise_tags,tailscale_public_urlconfig fields, defaults, and backward-compat migrationkeepercommander/resources/service_config.inikeepercommander/service/README.md--force-reauth/single-use-key noteunit-tests/service/test_create_service.pyCompatibility
No changes to
ngrok_config.pyorcloudflare_config.py. All changes to shared files are additive, confirmed via diff review. Full existing test suite (279 tests) passes unchanged.