73 lines
2.7 KiB
Markdown
73 lines
2.7 KiB
Markdown
# Zscaler Root Certificate
|
|
|
|
On the corporate network Zscaler terminates TLS and re-signs traffic with its own root
|
|
certificate. Every tool that ships its own certificate store — Node, Python, git, cargo —
|
|
rejects those connections until the Zscaler root is trusted explicitly.
|
|
|
|
Typical symptoms: `unable to get local issuer certificate`, `SELF_SIGNED_CERT_IN_CHAIN`,
|
|
`SSL: CERTIFICATE_VERIFY_FAILED`, `server certificate verification failed`.
|
|
|
|
## The certificate
|
|
|
|
The root certificate ships in this folder as `ZscalerRootCertificate-2048-SHA256.crt`.
|
|
It is PEM-encoded — the `.crt` / `.cer` / `.pem` extension makes no difference, the tools
|
|
below only care about the content.
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| Subject | `CN=Zscaler Root CA, O=Zscaler Inc.` |
|
|
| Valid until | 2042-05-06 |
|
|
| SHA-256 | `04:F6:1F:1D:13:AA:E1:D1:65:73:DC:2C:37:F7:96:FD:F4:AC:97:71:3A:69:59:EB:B1:1D:24:73:95:8B:1A:53` |
|
|
|
|
Copy it to a permanent location outside any repository — the rest of this document assumes
|
|
`C:\certs\ZscalerRootCertificate-2048-SHA256.crt`.
|
|
|
|
Verify the copy before trusting it:
|
|
|
|
```bash
|
|
openssl x509 -in C:/certs/ZscalerRootCertificate-2048-SHA256.crt -noout -fingerprint -sha256
|
|
```
|
|
|
|
## Environment variables
|
|
|
|
Set these as **user** variables on Windows:
|
|
|
|
1. `Win + R` → `sysdm.cpl` → **Advanced → Environment Variables**
|
|
2. Under **User variables** → **New**
|
|
3. Enter the name and value from the table
|
|
4. OK → restart VS Code and every open terminal, otherwise the old value stays in effect
|
|
|
|
| Variable | Used by | Value |
|
|
|----------|---------|-------|
|
|
| `NODE_EXTRA_CA_CERTS` | Node.js, npm, Electron, VS Code extensions | `C:\certs\ZscalerRootCertificate-2048-SHA256.crt` |
|
|
| `REQUESTS_CA_BUNDLE` | Python `requests`, Poetry, pip | same path |
|
|
| `SSL_CERT_FILE` | OpenSSL, Python `ssl` / `httpx` / `aiohttp` | same path |
|
|
| `CURL_CA_BUNDLE` | curl | same path |
|
|
| `CARGO_HTTP_CAINFO` | cargo, crates.io | same path |
|
|
|
|
`SSL_CERT_FILE` covers most Python clients, but `requests` prefers `REQUESTS_CA_BUNDLE` —
|
|
set both.
|
|
|
|
## Git
|
|
|
|
Git reads none of those variables. Configure it directly, with **forward slashes** — git
|
|
treats a backslash in a config value as an escape character:
|
|
|
|
```bash
|
|
git config --global http.sslCAInfo "C:/certs/ZscalerRootCertificate-2048-SHA256.crt"
|
|
```
|
|
|
|
Never use `http.sslVerify=false` as a workaround — it disables verification for every
|
|
remote, not just the ones behind Zscaler.
|
|
|
|
## Verifying the setup
|
|
|
|
```bash
|
|
curl -sSI https://pypi.org | head -1
|
|
git ls-remote https://github.com/git/git HEAD
|
|
node -e "require('https').get('https://registry.npmjs.org', r => console.log(r.statusCode))"
|
|
poetry run python -c "import requests; print(requests.get('https://pypi.org', timeout=10).status_code)"
|
|
```
|
|
|
|
All four must succeed without a certificate error.
|