Add proxy auth mode for Atlassian CLIs#411
Conversation
There was a problem hiding this comment.
The PR updated cfl/integration-tests.md's Test Execution Checklist (line 592) to say "Run the full checklist with separate passes to ensure each auth path works" and covers all three methods. The equivalent section at the bottom of jtk/integration-tests.md was not updated — it almost certainly still says "Run the full checklist twice with separate passes to ensure both auth paths work." A tester following the jtk checklist would not know a third Proxy Auth pass is required. Add a "Pass 3: Proxy Auth" block and update the checklist preamble to match the updated cfl version.
Reply inline to this comment.
| @@ -287,22 +318,23 @@ func runInit(ctx context.Context, opts *root.Options, prefillURL, prefillEmail, | |||
|
|
|||
There was a problem hiding this comment.
api.New is now called unconditionally before the if !noVerify block, changing the semantics of --no-verify. Previously, the client was constructed only inside the verify branch, so --no-verify also bypassed client construction. For basic auth, api.New returns ErrAPITokenRequired when cfg.APIToken is empty. A user running jtk init --no-verify in interactive mode who completes the form without entering a token (intending to populate via set-credential later) will now get a client-construction failure where the old code would have saved the config successfully.
The test suite has no case asserting that basic-auth --no-verify can save a URL+email config when the token is absent, so this regression is invisible to CI.
Fix: move client construction back inside the if !noVerify block alongside the verification call, restoring the original invariant that --no-verify skips all client interaction. If eager config validation is the intent, add an explicit guard that skips api.New when noVerify && cfg.APIToken == "" for basic auth, and add a test documenting the allowed-to-save-without-token path.
Reply inline to this comment.
| } | ||
| } | ||
|
|
||
| // NewProxyClient creates a Confluence client for a trusted proxy that injects |
There was a problem hiding this comment.
NewProxyClient skips the loopback-HTTP safety check that newProxyClient (jtk) enforces at the client boundary.
The invariant introduced by this diff is: proxy auth must never send unauthenticated requests to a non-loopback cleartext endpoint. tools/jtk/api/client.go:newProxyClient enforces this at client-construction time:
if strings.HasPrefix(baseURL, "http://") && !url.IsLoopbackHTTP(baseURL) {
return nil, ErrProxyURLRequiresHTTPS
}tools/cfl/api/client.go:NewProxyClient has no such check — it passes the URL straight to normalizeWikiBaseURL and client.New. The cfl path relies entirely on config.Validate() being called during cfl init, but Validate() is not called at runtime from root.go's APIClient(). A manually edited config (auth_method: proxy, url: http://external-host/...) would bypass validation and silently send unauthenticated requests to an arbitrary cleartext server.
Fix: add the identical guard in NewProxyClient before calling normalizeWikiBaseURL:
func NewProxyClient(baseURL string) (*Client, error) {
normalized := normalizeWikiBaseURL(baseURL)
if strings.HasPrefix(normalized, "http://") && !sharedurl.IsLoopbackHTTP(normalized) {
return nil, ErrProxyURLRequiresHTTPS // add this sentinel error
}
return &Client{Client: client.New(normalized, "", "", &client.Options{SkipAuthHeader: true})}, nil
}This also makes the two tools' public API surfaces symmetric.
Reply inline to this comment.
| @@ -426,24 +464,41 @@ func finalizeInit( | |||
| if cfg.AuthMethod == auth.AuthMethodBearer { | |||
There was a problem hiding this comment.
The normalizeAuthConfig function introduced here is byte-for-byte identical to the one added in tools/jtk/internal/cmd/initcmd/initcmd.go. The logic it encodes — defaulting an empty auth_method to basic, and scrubbing Email/APIToken/CloudID for proxy auth — is auth-method policy, not tool-local behaviour. Duplicating it across two tool cmd packages means future auth method additions must be applied in two places. Move it to a shared package (e.g. shared/auth alongside ValidateAuthMethod, or a new shared/authconfig helper), expose it as a single exported function, and have both tools call it.
Reply inline to this comment.
Automated PR ReviewReviewed commit: Summary
go:implementation-tests (1 finding)Minor -
|
| Field | Value |
|---|---|
| Model | claude-sonnet-4-6 |
| Reviewers | go:implementation-tests, policies:conventions, structure:repo-health, documentation:docs |
| Engine | claude_cli · claude-sonnet-4-6 |
| Reviewed by | cr · piekstra-dev |
| Duration | 8m 11s wall · 8m 10s compute |
| Cost | ~$1.04 (est.) |
| Tokens | 26 in / 10.7k out |
Per-workstream usage
| Workstream | Model | In | Out | Cache read | Cache create | Cost | Duration |
|---|---|---|---|---|---|---|---|
| orchestrator-selection | claude-sonnet-4-6 | 4 | 1.6k | 0 | 20.5k | ~$0.10 (est.) | 26s |
| go:implementation-tests | claude-sonnet-4-6 | 6 | 1.1k | 199.9k | 76.7k | ~$0.36 (est.) | 3m 02s |
| policies:conventions | claude-sonnet-4-6 | 4 | 2.8k | 7.2k | 24.2k | ~$0.14 (est.) | 53s |
| structure:repo-health | claude-sonnet-4-6 | 4 | 2.9k | 7.2k | 27.6k | ~$0.15 (est.) | 53s |
| documentation:docs | claude-sonnet-4-6 | 4 | 1.3k | 3.9k | 44.5k | ~$0.19 (est.) | 1m 54s |
| orchestrator-rollup | claude-sonnet-4-6 | 4 | 975 | 24.1k | 20.5k | ~$0.10 (est.) | 59s |
piekstra-dev
left a comment
There was a problem hiding this comment.
Automated PR review completed with outcome: comment.
Summary
proxyas a supported auth method forjtkandcflAuthorizationheader in proxy mode and require only a URLhttp://proxy URLs while continuing to reject arbitrary cleartext URLsWhy
Some users run Atlassian CLI tools through a trusted local or managed proxy that handles upstream authentication. The existing
basicandbearermodes require the CLI to own credentials and emit an auth header, which makes those proxy setups difficult or impossible to configure cleanly.Implementation Notes
Proxy auth is explicit via
ATLASSIAN_AUTH_METHOD=proxy,JIRA_AUTH_METHOD=proxy, orCFL_AUTH_METHOD=proxy. In this mode, the CLI constructs normal Jira or Confluence API URLs but deliberately omitsAuthorization. HTTPS proxy URLs are accepted, andhttp://is limited to loopback hosts for local proxy workflows.Bearer auth keeps existing behavior by default and adds
ATLASSIAN_GATEWAY_BASE_URL,JIRA_GATEWAY_BASE_URL, andCFL_GATEWAY_BASE_URLfor environments that need to override the Atlassian gateway base.Tests
go test ./...insharedgo test ./...intools/jtkgo test ./...intools/cfl