Skip to content

Add mTLS authentication support#102

Merged
pchuri merged 2 commits into
pchuri:mainfrom
anandghegde:feat/mtls-auth-support
Apr 14, 2026
Merged

Add mTLS authentication support#102
pchuri merged 2 commits into
pchuri:mainfrom
anandghegde:feat/mtls-auth-support

Conversation

@anandghegde
Copy link
Copy Markdown
Contributor

Summary

This adds support for Confluence deployments that authenticate at the TLS layer with client certificates instead of Basic or Bearer credentials.

Changes

  • add mtls as a supported --auth-type
  • add CLI flags for --tls-client-cert, --tls-client-key, and --tls-ca-cert
  • support mTLS config in saved profiles and environment variables
  • configure the HTTP client with an https.Agent using the provided cert/key/CA files
  • skip the Authorization header in mTLS mode
  • validate that mTLS mode has the required client certificate and key
  • document mTLS usage in the README
  • add tests covering profile/env parsing and client setup

Validation

  • npm test -- --runInBand
  • npm run lint

@pchuri
Copy link
Copy Markdown
Owner

pchuri commented Apr 14, 2026

Thanks for putting this together, @anandghegde! mTLS support is a solid addition for self-hosted and reverse-proxied Confluence environments. The overall approach is clean — you've covered CLI flags, environment variables, and profile storage consistently, and the existing auth flows remain untouched.

I left a few notes after reviewing the diff:

Issues & Suggestions

1. Certificate file existence check (Medium)

In buildHttpsAgent() (lib/confluence-client.js), fs.readFileSync will throw a raw ENOENT if a certificate path doesn't exist. A friendlier error message would improve the user experience:

if (this.mtls.clientCert) {
  if (!fs.existsSync(this.mtls.clientCert)) {
    throw new Error(`Client certificate file not found: ${this.mtls.clientCert}`);
  }
  options.cert = fs.readFileSync(this.mtls.clientCert);
}

2. Validate file paths at save time (Low)

validateMtlsConfig checks for presence but not whether the paths actually exist on disk. Validating at initConfig save time would prevent saving broken configs.

3. Complex ternary in getConfig env logic (Low)

This line in lib/config.js is a bit hard to follow:

const authType = normalizeAuthType(envAuthType || (envMtls && !envToken ? 'mtls' : envAuthType), Boolean(envEmail));

Extracting it into a separate variable improves readability:

const inferredAuthType = envAuthType || (envMtls && !envToken ? 'mtls' : undefined);
const authType = normalizeAuthType(inferredAuthType, Boolean(envEmail));

4. authType=mtls with protocol=http silently ignored (Low)

buildHttpsAgent() returns null when protocol !== 'https', so mTLS is silently skipped over HTTP. Consider warning or erroring during config validation when authType=mtls is combined with protocol=http.

5. Interactive wizard missing cert path prompts (Low)

When a user selects mTLS in the interactive confluence init flow, the token prompt is correctly skipped (when: authType !== 'mtls'), but there are no follow-up prompts for certificate/key paths. This means mTLS can only be configured non-interactively today. Worth either adding the prompts or documenting this limitation.

6. Test temp file cleanup (Nit)

In tests/confluence-client.test.js, removeDirRecursive(tmpDir) won't run if an assertion fails before it. Wrapping in afterEach or try/finally would be more robust.


Items 1 and 5 are the ones I'd recommend addressing before merge. The rest are minor improvements that can be follow-ups. Great work overall!

- Add fs.existsSync checks before readFileSync in buildHttpsAgent for
  friendlier error messages when cert files are missing
- Validate cert/key/CA file paths exist at config save time in
  validateMtlsConfig
- Simplify complex ternary in getConfig env logic into separate variable
- Error when authType=mtls is combined with protocol=http in CLI
  validation, env config, and profile config
- Add interactive wizard prompts for client cert, client key, and CA
  cert paths when mTLS auth is selected during 'confluence init'
- Wrap mTLS test bodies in try/finally for reliable temp file cleanup
@anandghegde
Copy link
Copy Markdown
Contributor Author

Thank you for the feedback @pchuri . I have made few changes. Let me know if this works

Copy link
Copy Markdown
Owner

@pchuri pchuri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — well-structured addition that integrates mTLS cleanly across CLI flags, env vars, profiles, and the interactive wizard without disturbing existing auth flows. A few suggestions below, none blocking.

Suggestions

Private key file permission check (follow-up PR)

buildHttpsAgent() reads the client key file without verifying its permissions. On Unix systems, a private key readable by other users (e.g., 0644) is a security risk. Consider adding a warning or error when the key file mode is more permissive than 0600.

Prompt validation duplication

The when/validate logic for tlsClientCert, tlsClientKey, and tlsCaCert is nearly identical in three places — promptForMissingValues(), the interactive wizard in initConfig(), and validateCliOptions(). Extracting a shared helper (e.g., mtlsCertQuestion(name, message, required)) would reduce maintenance surface. Not blocking, but worth a follow-up refactor.

README paths should be platform-neutral

The mTLS examples use macOS-specific paths (/Users/you/.certs/). Suggest changing to /path/to/client.pem or ~/.certs/ for cross-platform readability. This is small enough to fix before merge if you'd like.

Minor nits

  • The --token validation change (&&!== undefined) is unrelated to mTLS — consider splitting into a separate commit for cleaner history.
  • The http + mtls incompatibility check is duplicated in CLI validation, env config, and profile config. Could share a single helper.

@pchuri pchuri merged commit d7bed5b into pchuri:main Apr 14, 2026
5 of 6 checks passed
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 1.30.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants