fix: allow public coordinator egress starts

This commit is contained in:
Peter Steinberger 2026-05-07 06:16:26 +01:00
parent b40d36458a
commit d0b2c2379f
No known key found for this signature in database
4 changed files with 38 additions and 2 deletions

View File

@ -8,6 +8,7 @@
### Fixed
- Fixed `egress start --coordinator` so live public-route egress starts work when the local default coordinator is Cloudflare Access-protected.
- Fixed Tailscale exit-node bootstrap paths to prefer tailnet metadata and fail clearly when remote exit-node egress is not active.
- Fixed `run --no-sync` timing summaries so they report `sync_skipped=true`.
- Fixed native Windows command output so first-use PowerShell progress records do not leak CLIXML into run logs.

View File

@ -86,6 +86,7 @@ Common:
```text
--listen 127.0.0.1:3128
--daemon
--coordinator <public-coordinator-url>
--target linux
--network auto|tailscale|public
```

View File

@ -159,6 +159,7 @@ func (a App) egressStart(ctx context.Context, args []string) error {
profile := fs.String("profile", "", "egress profile name")
allowCSV := fs.String("allow", "", "comma-separated allowed host patterns")
listen := fs.String("listen", defaultEgressListen, "lease-local proxy listen address")
coordinatorURL := fs.String("coordinator", "", "coordinator URL override")
daemon := fs.Bool("daemon", false, "start the local host bridge in the background")
targetFlags := registerTargetFlags(fs, defaults)
networkFlags := registerNetworkModeFlag(fs, defaults)
@ -180,8 +181,9 @@ func (a App) egressStart(ctx context.Context, args []string) error {
if err != nil {
return err
}
if egressCoordinatorNeedsAccess(cfg.Access) {
return exit(2, "egress start cannot install a remote client when coordinator Access credentials are configured; use a public coordinator route or run egress client manually with safe credentials")
cfg, err = egressStartCoordinatorConfig(cfg, *coordinatorURL)
if err != nil {
return err
}
coord, useCoordinator, err := newTargetCoordinatorClient(cfg)
if err != nil {
@ -722,6 +724,18 @@ func egressCoordinatorNeedsAccess(access AccessConfig) bool {
strings.TrimSpace(access.Token) != ""
}
func egressStartCoordinatorConfig(cfg Config, coordinatorURL string) (Config, error) {
if override := strings.TrimSpace(coordinatorURL); override != "" {
cfg.Coordinator = strings.TrimRight(override, "/")
cfg.Access = AccessConfig{}
return cfg, nil
}
if egressCoordinatorNeedsAccess(cfg.Access) {
return cfg, exit(2, "egress start cannot install a remote client when coordinator Access credentials are configured; use --coordinator with a public coordinator route or run egress client manually with safe credentials")
}
return cfg, nil
}
func egressAgentURL(base, leaseID, role, ticket string) string {
u, err := url.Parse(base)
if err != nil {

View File

@ -62,6 +62,26 @@ func TestEgressCoordinatorNeedsAccess(t *testing.T) {
}
}
func TestEgressStartCoordinatorOverrideUsesPublicRoute(t *testing.T) {
cfg := Config{
Coordinator: "https://crabbox-access.openclaw.ai",
Access: AccessConfig{ClientID: "client", ClientSecret: "secret", Token: "jwt"},
}
got, err := egressStartCoordinatorConfig(cfg, "https://crabbox.openclaw.ai/")
if err != nil {
t.Fatal(err)
}
if got.Coordinator != "https://crabbox.openclaw.ai" {
t.Fatalf("coordinator=%q", got.Coordinator)
}
if egressCoordinatorNeedsAccess(got.Access) {
t.Fatalf("override should clear access headers for remote-safe start: %#v", got.Access)
}
if _, err := egressStartCoordinatorConfig(cfg, ""); err == nil {
t.Fatal("expected access-protected coordinator without override to be rejected")
}
}
func TestEgressClientBinaryRejectsNonLinuxTargets(t *testing.T) {
_, cleanup, err := egressClientBinaryForTarget(context.Background(), SSHTarget{TargetOS: targetWindows})
defer cleanup()