Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Certificate installation scripts

Scripts to install a CA certificate, configure Node/npm and Python (pip, uv, Hugging Face Hub, and related TLS clients), and clear Docker Hub credentials that can break redirected Docker Hub pulls.
Scripts to install a CA certificate, configure Node/npm, Python (pip, uv, Hugging Face Hub, and related TLS clients), Ruby where supported, and clear Docker Hub credentials that can break redirected Docker Hub pulls.

This document describes the certificate installation and validation scripts for **macOS**, **Linux (Debian/Ubuntu)**, and **Windows**.

Expand All @@ -10,7 +10,7 @@ This document describes the certificate installation and validation scripts for
| **validate_install_macos.sh** | macOS | Validate PEM and env config |
| **install_certs_debian_ubuntu.sh** | Debian/Ubuntu | Install cert into system trust + profile.d + user shell rc + Docker cleanup |
| **validate_certs_debian_ubuntu.sh** | Debian/Ubuntu | Validate PEM and env config |
| **install_certs_windows.ps1** | Windows | Install cert, set env vars (Node/Python), and clear Docker Hub credentials |
| **install_certs_windows.ps1** | Windows | Install cert, set env vars (Node/Python/Ruby), and clear Docker Hub credentials |
| **validate_install_windows.ps1** | Windows | Validate PEM and env config |

Environment variables by platform (see each section for details):
Expand All @@ -22,7 +22,7 @@ Environment variables by platform (see each section for details):
| `UV_NATIVE_TLS=true` / `1` | Python **uv** | macOS uses `true`; Windows uses `1`; **not** set by the Debian/Ubuntu script |
| `UV_SYSTEM_CERTS=true` | Python **uv** | Set by macOS for **`python`**, **`huggingface`**, or **`all`** |
| `REQUESTS_CA_BUNDLE=<path>` | Python **requests** / many HTTPS stacks | PEM or bundle path |
| `SSL_CERT_FILE=<path>` | OpenSSL-backed tools | Set on **Debian/Ubuntu** for **`python`**, **`huggingface`**, or **`all`** to the system CA bundle |
| `SSL_CERT_FILE=<path>` | OpenSSL-backed tools, including Ruby | Set on **Debian/Ubuntu** for **`python`**, **`huggingface`**, or **`all`** to the system CA bundle; set on **Windows** for **`python`**, **`huggingface`**, **`ruby`**, or **`all`** to a generated bundle |
| `HF_HUB_DISABLE_XET=1` | Python **huggingface_hub** | Set when **`huggingface` or `all`**: disables XET (not supported with typical MITM / Artifactory redirect flows) |
| `HF_HUB_ETAG_TIMEOUT=86400` | Python **huggingface_hub** | Set when **`huggingface` or `all`**: ETag check timeout (seconds); reduces spurious failures on slow paths |
| `HF_HUB_DOWNLOAD_TIMEOUT=86400` | Python **huggingface_hub** | Set when **`huggingface` or `all`**: download timeout (seconds) |
Expand Down Expand Up @@ -203,7 +203,7 @@ Tests are black-box (exit codes and stderr).

#### Windows tests

**test_install_certs_windows.ps1** runs automated tests for **install_certs_windows.ps1** (CLI and parameter validation; **-UseCert -Package python** sets Python TLS only and leaves existing `HF_HUB_*` unchanged; **-Package huggingface** adds `HF_HUB_*`; **-Package all** sets npm + TLS + HF; when run as admin) and **validate_install_windows.ps1** (-ExpectedSubject required, env-based validation: valid PEM, missing file, invalid PEM, subject match and no-match, and system-level env when run as admin). **Run the test script as Administrator** so install script tests and system-level validate tests execute; the script uses a temp directory and an embedded PEM.
**test_install_certs_windows.ps1** runs automated tests for **install_certs_windows.ps1** (CLI and parameter validation; **-UseCert -Package python** sets Python TLS to a generated bundle and leaves existing `HF_HUB_*` unchanged; **-Package ruby** sets `SSL_CERT_FILE`; **-Package huggingface** adds `HF_HUB_*`; **-Package all** sets npm + TLS + Ruby + HF; when run as admin) and **validate_install_windows.ps1** (-ExpectedSubject required, env-based validation: valid PEM, missing file, invalid PEM, subject match and no-match, and system-level env when run as admin). **Run the test script as Administrator** so install script tests and system-level validate tests execute; the script uses a temp directory and an embedded PEM.

**Requirements:** Windows with PowerShell. The install and validate scripts must be in the parent of `testing/` (repo root).

Expand All @@ -218,8 +218,8 @@ Exit code 0 if all tests pass, 1 otherwise. Output shows pass/fail per test and

| Area | Covered |
|------|--------|
| **install_certs_windows.ps1** | When run as admin: script passes admin check (no "must run as Administrator" error). No cert source (parameter set error); invalid `-Package`; `-CertName` without `-ExtractPath` (and reverse); `-UseCert` and `-CertName` together; `-UseCert` with nonexistent file; `-UseCert` with invalid PEM; `-UseCert` with valid PEM (no "not a file" or "Invalid PEM" error). **Packages:** `-UseCert -Package python` sets TLS-only Machine vars and does not remove pre-existing `HF_HUB_*`; `-Package huggingface` adds `HF_HUB_*`; `-Package all` sets npm + TLS + HF. |
| **validate_install_windows.ps1** | `-ExpectedSubject` required (exit 1 if missing); current user env (no paths → exit 0); env path to valid PEM (exit 0), missing file (exit 1), invalid PEM (exit 1); subject mismatch (exit 1, FAIL message); system-level (Machine) env when run as admin. |
| **install_certs_windows.ps1** | When run as admin: script passes admin check (no "must run as Administrator" error). No cert source (parameter set error); invalid `-Package`; `-CertName` without `-ExtractPath` (and reverse); `-UseCert` and `-CertName` together; `-UseCert` with nonexistent file; `-UseCert` with invalid PEM; `-UseCert` with valid PEM (no "not a file" or "Invalid PEM" error). **Packages:** `-UseCert -Package python` sets TLS-only Machine vars to a generated bundle and does not remove pre-existing `HF_HUB_*`; `-Package ruby` sets `SSL_CERT_FILE` to the generated bundle; `-Package huggingface` adds `HF_HUB_*`; `-Package all` sets npm + TLS + Ruby + HF. |
| **validate_install_windows.ps1** | `-ExpectedSubject` required (exit 1 if missing); current user env (no paths → exit 0); env path to valid PEM (exit 0), missing file (exit 1), invalid PEM (exit 1); subject mismatch (exit 1, FAIL message); system-level (Machine) env when run as admin. Reads `NODE_EXTRA_CA_CERTS`, `REQUESTS_CA_BUNDLE`, and `SSL_CERT_FILE`. |

Tests are black-box (exit codes and stdout/stderr). Paths are passed to the validate script via a temp file when invoking as a child process to avoid command-line parsing issues with backslashes.

Expand Down Expand Up @@ -353,14 +353,14 @@ sudo ./validate_certs_debian_ubuntu.sh --all-users --expected-subject "O=Example

### Overview

`install_certs_windows.ps1` configures **Node/npm** and/or **Python** on Windows to use a custom CA certificate. **It must be run as Administrator (or SYSTEM);** the script exits with an error otherwise.
`install_certs_windows.ps1` configures **Node/npm**, **Python**, and/or **Ruby** on Windows to use a custom CA certificate. **It must be run as Administrator (or SYSTEM);** the script exits with an error otherwise.

- Either **extracts** a certificate from the Windows cert store (LocalMachine\Root) by **subject substring** (`-CertName`), or **uses an existing** PEM file you provide (**-UseCert**). If **multiple** certs match the pattern, the script logs a warning and picks one (prefers a subject containing `Root`, otherwise the first match).
- With **-CertName** and **-ExtractPath:** writes **package-route.pem** per user under each user’s profile and sets **User**-level env vars in the registry for each user. **npm:** `NODE_USE_SYSTEM_CA`, `NODE_EXTRA_CA_CERTS`. **Python TLS** (`python`, `huggingface`, or `all`): `UV_NATIVE_TLS`, `REQUESTS_CA_BUNDLE`. **Hugging Face Hub** (`huggingface` or `all`): `HF_HUB_DISABLE_XET`, `HF_HUB_ETAG_TIMEOUT`, `HF_HUB_DOWNLOAD_TIMEOUT`.
- With **-UseCert:** does **not** write a PEM file; sets **Machine**-level env vars. The script **deletes** overlapping **User**-level vars so they do not override Machine (User wins over Machine on Windows). Which vars are set or cleared depends on `-Package` (see env table above).
- With **-CertName** and **-ExtractPath:** writes **package-route.pem** per user under each user’s profile and sets **User**-level env vars in the registry for each user. When Python or Ruby is configured, this file is a combined bundle: the selected cert first, then Windows trusted roots, then valid certs from previously configured bundles (dedupe by SHA-256 fingerprint). **npm:** `NODE_USE_SYSTEM_CA`, `NODE_EXTRA_CA_CERTS`. **Python TLS** (`python`, `huggingface`, or `all`): `UV_NATIVE_TLS`, `REQUESTS_CA_BUNDLE`, `SSL_CERT_FILE`. **Ruby** (`ruby` or `all`): `SSL_CERT_FILE`. **Hugging Face Hub** (`huggingface` or `all`): `HF_HUB_DISABLE_XET`, `HF_HUB_ETAG_TIMEOUT`, `HF_HUB_DOWNLOAD_TIMEOUT`.
- With **-UseCert:** keeps npm pointed at your PEM, and writes a generated combined bundle under `C:\ProgramData\package-reroute\package-route-bundle.pem` for Python/Ruby OpenSSL-style clients. The script sets **Machine**-level env vars and **deletes** overlapping **User**-level vars so they do not override Machine (User wins over Machine on Windows). Which vars are set or cleared depends on `-Package` (see env table above).
- Clears Docker Hub credentials for the current PowerShell user. When running as `SYSTEM`, this cleanup is skipped with a warning because it must run in the user's Windows session.

Re-runs **merge** certs: if the target file already exists, the script saves its content, overwrites with the new cert, then appends other certs from the saved copy (dedupe by SHA-256 fingerprint). So running with a second cert adds it to the bundle instead of replacing it.
Re-runs **merge** certs: generated bundles put the custom cert first, append Windows roots, then append valid certs from previous bundles (dedupe by SHA-256 fingerprint). So running with a second cert can preserve existing custom certs instead of replacing them.

### Requirements

Expand All @@ -381,7 +381,7 @@ powershell -ExecutionPolicy Bypass -File install_certs_windows.ps1 -Package all

| Parameter | Required | Description |
|-----------|----------|-------------|
| `-Package` | No (default: **all**) | `npm`, `python`, `huggingface`, or `all` (all = npm + Python TLS + Hugging Face Hub). |
| `-Package` | No (default: **all**) | `npm`, `python`, `huggingface`, `ruby`, or `all` (all = npm + Python TLS + Ruby + Hugging Face Hub). |
| `-CertName` | Yes* | Substring used to match cert **Subject** in the store (`*CertName*` wildcard). Requires `-ExtractPath`. Cannot be used with `-UseCert`. |
| `-ExtractPath` | Yes* | Directory under each user’s profile for **package-route.pem** (rooted paths are normalized to a folder under the profile, same idea as macOS). Requires `-CertName`. |
| `-UseCert` | Yes* | Path to an existing PEM file. Cannot be used with `-CertName` / `-ExtractPath`. |
Expand All @@ -396,7 +396,7 @@ powershell -ExecutionPolicy Bypass -File install_certs_windows.ps1 -Package all
.\install_certs_windows.ps1 -Package all -CertName "Your Org Root CA" -ExtractPath certs\npm
```

**Use an existing PEM (Machine-level env; User-level cert vars are deleted):**
**Use an existing PEM (Machine-level env; Python/Ruby use a generated combined bundle; User-level cert vars are deleted):**

```powershell
.\install_certs_windows.ps1 -Package all -UseCert C:\Users\Administrator\other-ca\company-ca.pem
Expand All @@ -412,8 +412,8 @@ powershell -ExecutionPolicy Bypass -File install_certs_windows.ps1 -Package all

- **Admin required.** The script must be run as Administrator (or SYSTEM).
- **Cert source:** either store (`-CertName` + `-ExtractPath`) or file (`-UseCert`).
- **Extract path:** per-user **package-route.pem** and User-level env per `-Package` (npm / Python TLS / Hugging Face as above); re-runs merge and dedupe by fingerprint. Machine-level cert vars are **cleared** so only User applies (avoids duplication if you previously used -UseCert).
- **UseCert:** no PEM written; Machine-level env set per `-Package`; **`python`** does not set `HF_HUB_*` and does **not** clear pre-existing `HF_HUB_*` on the target scope. User-level cert vars are **deleted** so only Machine applies when using `-UseCert` as admin.
- **Extract path:** per-user **package-route.pem** and User-level env per `-Package` (npm / Python TLS / Ruby / Hugging Face as above); when Python or Ruby is selected, the file is a combined bundle of the custom cert plus Windows roots. Machine-level cert vars are **cleared** so only User applies (avoids duplication if you previously used -UseCert).
- **UseCert:** npm points at the supplied PEM; Python/Ruby point at the generated combined bundle under `C:\ProgramData\package-reroute\package-route-bundle.pem`; Machine-level env is set per `-Package`; **`python`** does not set `HF_HUB_*` and does **not** clear pre-existing `HF_HUB_*` on the target scope. User-level cert vars are **deleted** so only Machine applies when using `-UseCert` as admin.
- **Docker:** clears Docker Hub credentials for the current PowerShell user. Run the script in the user's session for this step; `SYSTEM` cannot clean up the user's Docker credential store.

Users must start a **new terminal** for env changes to take effect.
Expand All @@ -427,7 +427,7 @@ Users must start a **new terminal** for env changes to take effect.
| Parameter | Description |
|-----------|-------------|
| `-ExpectedSubject <pattern>` | **Required.** At least one cert in each PEM file (bundle) must have a subject matching `<pattern>` (case-insensitive). |
| *(default scope)* | Read `NODE_EXTRA_CA_CERTS` and `REQUESTS_CA_BUNDLE` from the current user's environment (User then Machine), then validate each referenced PEM file. |
| *(default scope)* | Read `NODE_EXTRA_CA_CERTS`, `REQUESTS_CA_BUNDLE`, and `SSL_CERT_FILE` from the current user's environment (User then Machine), then validate each referenced PEM file. |
| `-AllUsers` | **(Admin only.)** For each user in `C:\Users\*`, read their User registry env, resolve cert paths, and validate each PEM. |

**Exit code:** 0 if all checks passed, 1 if any check failed.
Expand Down
Loading
Loading