Skip to content

feat: trust internal CAs when pushing to Kibana#1150

Draft
shahzad31 wants to merge 1 commit into
browser-monitor-internal-cafrom
cli-internal-ca
Draft

feat: trust internal CAs when pushing to Kibana#1150
shahzad31 wants to merge 1 commit into
browser-monitor-internal-cafrom
cli-internal-ca

Conversation

@shahzad31

@shahzad31 shahzad31 commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Stacked on #1149 — review/merge that first. The base will auto-retarget to main once #1149 merges.

Summary

The push / locations CLI talks to Kibana over undici. When Kibana is fronted by an internal/private CA, these commands fail with unable to get local issuer certificate, and the usual escapes (NODE_TLS_REJECT_UNAUTHORIZED=0, npm config strict-ssl false) don't help (see #746).

This PR makes the CLI honor the same certificateAuthorities option introduced in #1149:

  • setGlobalProxy now builds a CA bundle of Node's built-in roots + the user provided CAs and passes it to the undici dispatcher (EnvHttpProxyAgent's connect.ca, or ProxyAgent's requestTls.ca when a proxy is configured).
  • Public roots are preserved, so adding an internal CA never silently drops trust for publicly signed endpoints.
  • NODE_EXTRA_CA_CERTS continues to work out of the box (undici honors it); this option just additionally supports config/flag-provided CAs.

Closes #746

Usage

Same certificateAuthorities option as #1149 — it now also covers the CLI -> Kibana connection. Use it on push (and locations):

Config (synthetics.config.ts):

import type { SyntheticsConfig } from '@elastic/synthetics';

export default (): SyntheticsConfig => ({
  certificateAuthorities: ['./certs/internal-ca.crt'],
});

CLI:

# push a project to a Kibana fronted by an internal CA
npx @elastic/synthetics push \
  --certificate-authorities ./certs/internal-ca.crt \
  --url https://kibana.internal.corp.local --id my-project

# or via the env var Node/undici already honor
NODE_EXTRA_CA_CERTS=./certs/internal-ca.crt npx @elastic/synthetics push ...

Try it locally

Reproduce the failure and the fix without a real Kibana:

# 1. private CA + a localhost server cert signed by it
mkdir -p certs && cd certs
openssl req -x509 -newkey rsa:2048 -nodes -keyout internal-ca.key \
  -out internal-ca.crt -days 3650 -subj "/CN=Example Internal CA"
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=localhost"
openssl x509 -req -in server.csr -CA internal-ca.crt -CAkey internal-ca.key \
  -CAcreateserial -out server.crt -days 825 \
  -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1")
cd ..

# 2. serve HTTPS with that cert (leave running)
node -e "require('https').createServer({key:require('fs').readFileSync('certs/server.key'),cert:require('fs').readFileSync('certs/server.crt')},(_,res)=>res.end('{\"ok\":true}')).listen(8443,()=>console.log('up'))" &

# 3. undici WITHOUT the CA -> rejects with UNABLE_TO_GET_ISSUER_CERT_LOCALLY
node -e "const{request}=require('undici');request('https://localhost:8443/').then(()=>console.log('ok')).catch(e=>console.log('FAIL',e.code))"

# 4. undici WITH the CA via setGlobalProxy -> succeeds
node -e "const{setGlobalProxy}=require('./dist');const{request}=require('undici');setGlobalProxy({},['./certs/internal-ca.crt'].map(p=>require('fs').readFileSync(p,'utf-8')));request('https://localhost:8443/').then(r=>r.body.text()).then(b=>console.log('ok',b)).catch(e=>console.log('FAIL',e.code))"

(The automated integration test below does exactly this against a fixture CA.)

Test plan

  • buildCABundle unit test: returns undefined with no CA, and roots + extra otherwise (__tests__/core/certs.test.ts)
  • Integration test against an internally-signed HTTPS server: undici rejects without the CA and succeeds once it's configured via setGlobalProxy (__tests__/core/proxy-ca.test.ts)
  • Existing locations proxy tests still pass
  • tsc, eslint, prettier --check, full unit suite green

Made with Cursor

The push/locations CLI talks to Kibana via undici. When Kibana sits
behind an internal/private CA the request fails with "unable to get
local issuer certificate", and neither NODE_TLS_REJECT_UNAUTHORIZED nor
strict-ssl helped.

Honor the `certificateAuthorities` option for the CLI by appending the
provided CAs to Node's built-in roots and passing the bundle to the
undici dispatcher (EnvHttpProxyAgent connect / ProxyAgent requestTls).
Public roots are preserved so trust for publicly signed endpoints is
never dropped, and `NODE_EXTRA_CA_CERTS` keeps working as before.

Relates to #746.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant