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
41 changes: 41 additions & 0 deletions .github/workflows/setup-ca-linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Linux setup CA commands

# Focused instruction qualification; not a new publication prerequisite.
on:
pull_request:
paths:
- 'amplifier_web/setup_page.py'
- 'scripts/check_setup_ca_linux.py'
- 'scripts/qualify_setup_ca_linux_ci.py'
- 'tests/test_setup_ca_linux_harness.py'
- 'docs/DEPLOYMENT.md'
- '.github/workflows/setup-ca-linux.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
setup-ca-linux:
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Exercise exact rendered commands in one disposable Debian guest
env:
EXPECTED_SOURCE: ${{ github.event.pull_request.head.sha || github.sha }}
run: python scripts/qualify_setup_ca_linux_ci.py
- name: Retain checks, negative control and exact cleanup evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: setup-ca-linux-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/setup-ca-evidence/
if-no-files-found: error
retention-days: 14
48 changes: 46 additions & 2 deletions amplifier_web/setup_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Platform(str, Enum):
WINDOWS = "windows"
ANDROID = "android"
IOS = "ios"
LINUX = "linux"
OTHER = "other"


Expand All @@ -25,6 +26,8 @@ def detect_platform(user_agent: str | None) -> Platform:
if "macintosh" in value or "mac os x" in value:
# iPad desktop mode identifies itself as Macintosh. Do not overclaim.
return Platform.MACOS
if "linux" in value:
return Platform.LINUX
return Platform.OTHER


Expand Down Expand Up @@ -69,9 +72,48 @@ def detect_platform(user_agent: str | None) -> Platform:
""",
Platform.OTHER: """
<ol start="4">
<li>Install the verified CA using this operating system’s native trust-store tool. On Debian/Ubuntu, copy it to <code>/usr/local/share/ca-certificates/</code> and run <code>sudo update-ca-certificates</code>.</li>
<li>Restart the browser. Firefox may use a separate certificate store.</li>
<li>Install the verified CA using this operating system’s approved trust-store tool. For Ubuntu or Debian, use the Linux section.</li>
<li>Check your browser’s certificate settings; browser trust can differ from operating-system trust.</li>
</ol>
""",
Platform.LINUX: """
<p>These commands are for <strong>Ubuntu and Debian</strong>, on the computer running your browser, not the Unified server. Other Linux distributions need their own approved trust-store procedure. WSL trust does not configure a Windows browser.</p>
<p>Use a normal-user terminal with administrator access through <code>sudo</code>. The tools <code>openssl</code>, <code>install</code> and <code>update-ca-certificates</code> must be available (Ubuntu/Debian packages <code>openssl</code>, <code>coreutils</code> and <code>ca-certificates</code>). Ask your administrator if they are missing or policy blocks installation.</p>
<ol start="4">
<li>Set the exact path of the public CA obtained through the trusted transfer above. For a browser download on an already trusted connection:
<pre><code id="linux-ca-file">ca_file="$HOME/Downloads/amplifier-unified-ca.crt"</code></pre>
If the browser saved a duplicate, use this <strong>instead</strong>:
<pre><code id="linux-ca-duplicate">ca_file="$HOME/Downloads/amplifier-unified-ca (1).crt"</code></pre>
Keep the quotes around spaces and parentheses. Adjust the directory if needed; do not use a wildcard or select an arbitrary downloaded certificate.
<pre><code id="linux-ca-fingerprint">openssl x509 -in "$ca_file" -noout -subject -issuer -fingerprint -sha256</code></pre></li>
<li><strong>Stop and compare the SHA-256 fingerprint</strong> with <code>amplifier-unified setup-tls status</code> run on the intended Unified host through a trusted console or verified SSH connection. Use that host’s actual data directory if non-default. This page and the downloaded file are not independent proof. Do not install if the fingerprints differ or the CA’s origin is uncertain. A trusted root can authenticate other sites, not just Unified.</li>
<li>Only after that comparison, install this one verified PEM certificate into the <strong>system</strong> trust store. The destination starts with <code>/usr</code>, <strong>not <code>~/usr</code></strong> (which means a folder under your home). Use the same terminal:
<pre><code id="linux-ca-install">ca_dest=/usr/local/share/ca-certificates/amplifier-unified-ca.crt
if [ -e "$ca_dest" ] || [ -L "$ca_dest" ]; then
printf '%s\\n' "Stop: $ca_dest already exists; ask your administrator to check it." &gt;&amp;2
false
elif [ "$(grep -c -- '-----BEGIN ' "$ca_file")" != 1 ] ||
[ "$(grep -c -- '-----END ' "$ca_file")" != 1 ]; then
printf '%s\\n' "Stop: expected exactly one PEM certificate, not a bundle." &gt;&amp;2
false
else
sudo install -d -m 0755 /usr/local/share/ca-certificates &amp;&amp;
sudo install -m 0644 -- "$ca_file" "$ca_dest" &amp;&amp;
sudo update-ca-certificates
fi</code></pre>
This uses a stable <code>.crt</code> filename and readable public-certificate permissions. An existing destination is not overwritten; another host’s CA needs a distinct name. Stop on any command error.</li>
<li>Check OS trust for this CA, using the generated certificate bundle:
<pre><code id="linux-ca-verify">openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt "$ca_file"</code></pre>
Expect the selected filename followed by <code>OK</code>. OpenSSL can also consult its configured default trust locations. This checks OS trust for the CA, not the remote server’s hostname, connection, or browser trust.</li>
<li>Save your browser work, then fully quit and reopen it yourself. Open the intended HTTPS address and confirm there is no certificate warning before signing in. <strong>Firefox, Chromium, Chrome and Edge on Linux can use different certificate stores</strong>, depending on version, packaging, profile and policy (including confined Snap packages). OS success is not proof of browser success.</li>
</ol>
<p><strong>Still “Not secure”?</strong> Open the browser’s connection/certificate details and read the exact error before importing anything again. If the browser says security warnings were turned off for this site, save any unsent work, turn warnings back on, and reload without proceeding past a warning. Check that the served certificate belongs to the intended host and chains to the verified CA. Match the URL hostname against the certificate’s Subject Alternative Name (SAN), not just its Common Name (CN). A hostname mismatch needs the correct URL or a server-certificate repair; a date error needs a clock/validity check. Neither is fixed by another CA import.</p>
<p>If the error is an untrusted issuer and the host/CA identity checks match, inspect the browser’s certificate manager for that verified CA. Firefox has a separate Authorities store; Chromium/Chrome and Edge versions can expose different local-certificate controls. Use the installed browser’s certificate settings or your administrator’s approved procedure to import the same verified CA for website trust. Do not disable verification, bypass the warning, or run NSS/certutil commands against a guessed profile/database.</p>
<p class="note">A rehash warning about <code>ca-certificates.crt</code> containing more than one certificate normally refers to the generated multi-certificate bundle. It does not prove your CA or browser is correct. A warning naming your individual CA file needs investigation: each local <code>.crt</code> file must contain exactly one PEM certificate.</p>
<p><strong>Undo only this installation:</strong> if you installed the new file at the exact destination above, remove only that file and rebuild the bundle. Do not remove a pre-existing CA or use a wildcard.</p>
<pre><code id="linux-ca-remove">sudo rm -- /usr/local/share/ca-certificates/amplifier-unified-ca.crt &amp;&amp;
sudo update-ca-certificates --fresh</code></pre>
<p>Any separate browser import must also be removed from that browser’s certificate settings. Save work before restarting it.</p>
""",
}

Expand Down Expand Up @@ -100,6 +142,7 @@ def render_setup_page(platform: Platform, certificate_available: bool, fingerpri
(Platform.WINDOWS, "Windows"),
(Platform.ANDROID, "Android"),
(Platform.IOS, "iOS and iPadOS"),
(Platform.LINUX, "Linux — Ubuntu and Debian"),
(Platform.OTHER, "Other platforms"),
)
)
Expand All @@ -110,6 +153,7 @@ def render_setup_page(platform: Platform, certificate_available: bool, fingerpri
body {{ color: #17212b; font: 16px/1.5 system-ui, sans-serif; margin: 0; background: #f4f7f9; }}
main {{ background: white; box-sizing: border-box; margin: 2rem auto; max-width: 52rem; padding: clamp(1rem, 4vw, 3rem); }}
h1 {{ line-height: 1.2; }} code {{ overflow-wrap: anywhere; }} details {{ border-top: 1px solid #ccd5dd; padding: .75rem 0; }}
pre {{ white-space: pre-wrap; overflow-wrap: anywhere; padding: .75rem; background: #f4f7f9; }}
summary {{ cursor: pointer; font-weight: 700; }} .download {{ font-size: 1.1rem; font-weight: 700; }}
.warning {{ border-left: .3rem solid #a95700; padding-left: 1rem; }} .note {{ color: #4a5560; }}
@media (max-width: 35rem) {{ body {{ background: white; }} main {{ margin: 0; }} ol {{ padding-left: 1.4rem; }} }}
Expand Down
107 changes: 106 additions & 1 deletion docs/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,115 @@ scp '<owner>@<host>:/absolute/path/amplifier-unified-ca.crt' .
openssl x509 -in amplifier-unified-ca.crt -noout -fingerprint -sha256
```

Compare that fingerprint with the trusted host's `amplifier-unified setup-tls status` output. Import the CA into the user trust store on each client device, then restart the browser. On macOS, use Keychain Access's **login** keychain and trust it for SSL. Follow your organization's approved process for mobile-device certificate trust.
Compare that fingerprint with the trusted host's `amplifier-unified setup-tls status` output. Use the same data directory as the running host if non-default. On macOS, use Keychain Access's **login** keychain and trust it for SSL. Windows can use the current user's Trusted Root Certification Authorities store. Follow your organization's approved process for mobile-device certificate trust.

The `/setup` page can provide platform-specific follow-up instructions after TLS is trusted. Its displayed fingerprint or an anonymous certificate download is not independent proof of authenticity.

### Ubuntu and Debian clients

Run these steps on the computer running the browser, not the Unified server.
WSL trust does not configure a Windows browser. Other Linux distributions need
their own approved procedure. Use a normal-user terminal with `sudo` access and
the `openssl`, `coreutils` and `ca-certificates` packages. If tools are missing or
policy blocks installation, ask your administrator; the page installs nothing.

1. Set the exact public CA path from the trusted transfer. For a download from an
**already trusted** connection:

```sh
ca_file="$HOME/Downloads/amplifier-unified-ca.crt"
```

If the browser saved a duplicate, use this **instead**:

```sh
ca_file="$HOME/Downloads/amplifier-unified-ca (1).crt"
```

Keep the quotes around spaces and parentheses. Adjust the directory if needed;
do not use a wildcard or select an arbitrary downloaded certificate.

```sh
openssl x509 -in "$ca_file" -noout -subject -issuer -fingerprint -sha256
```

2. **Stop and compare the SHA-256 fingerprint** with `amplifier-unified setup-tls
status` on the intended host, through a trusted console or verified SSH. Do
not install if the fingerprints differ or origin is uncertain. A root CA can
authenticate other sites, not just Unified.
3. After verification, install the single PEM certificate using the same terminal.
The destination is absolute `/usr/...`, **not `~/usr/...`** under your home:

```sh
ca_dest=/usr/local/share/ca-certificates/amplifier-unified-ca.crt
if [ -e "$ca_dest" ] || [ -L "$ca_dest" ]; then
printf '%s\n' "Stop: $ca_dest already exists; ask your administrator to check it." >&2
false
elif [ "$(grep -c -- '-----BEGIN ' "$ca_file")" != 1 ] ||
[ "$(grep -c -- '-----END ' "$ca_file")" != 1 ]; then
printf '%s\n' "Stop: expected exactly one PEM certificate, not a bundle." >&2
false
else
sudo install -d -m 0755 /usr/local/share/ca-certificates &&
sudo install -m 0644 -- "$ca_file" "$ca_dest" &&
sudo update-ca-certificates
fi
```

The stable `.crt` destination holds exactly one PEM certificate, readable by
applications. Do not overwrite an existing CA; another host needs a distinct
destination. Stop on any error. A rehash warning about the generated
`ca-certificates.crt` bundle containing multiple certificates is normally benign,
but a warning naming your individual CA file needs investigation.

4. Check OS trust:

```sh
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt "$ca_file"
```

Expect the selected filename followed by `OK`. OpenSSL can also consult its
configured default trust locations. This checks OS trust for the CA, not the
server's hostname/connection or the browser's trust.

5. Save browser work, fully quit and reopen the browser yourself, and open the
intended HTTPS URL. Confirm there is no certificate warning before signing in.
Firefox, Chromium/Chrome and Edge can use different stores depending on version,
packaging, profile and policy. Confined Snap packages may not inherit OS trust.
OS success is **not** proof of browser success.

If the browser still says **Not secure**, read its connection/certificate details
before importing anything again. If warnings were turned off for this site,
save unsent work, turn warnings back on and reload without proceeding past a
warning. Check the served host and chain against the verified CA. Match the
URL hostname against the Subject Alternative Name (SAN), not just the Common
Name (CN). A hostname mismatch needs the correct URL or server-certificate
repair; a date error needs a clock/validity check, not another CA import. For an
untrusted issuer with matching host/CA identities, inspect the installed browser's
certificate manager and follow its local-CA/Authorities import procedure or your
administrator's policy. Firefox has a separate Authorities store. Do not disable
verification, bypass warnings or run NSS/certutil against a guessed database.
Chromium's documented Linux NSS location has changed across versions; it is not
evidence of the location used by a particular Edge installation.

**Back out only your new installation**, after checking that this exact path is
the file you installed (not a pre-existing CA):

```sh
sudo rm -- /usr/local/share/ca-certificates/amplifier-unified-ca.crt &&
sudo update-ca-certificates --fresh
```

Remove any separately imported browser copy in that browser's certificate
settings too. OS removal alone does not prove browser removal.

References: [Ubuntu trust-store guide](https://ubuntu.com/server/docs/how-to/security/install-a-root-ca-certificate-in-the-trust-store/),
[Debian update-ca-certificates](https://manpages.debian.org/testing/ca-certificates/update-ca-certificates.8.en.html),
[Chromium Linux certificate management](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/linux/cert_management.md),
[Firefox certificate policies](https://firefox-admin-docs.mozilla.org/reference/policies/certificates/),
and [Edge root-store policy history](https://learn.microsoft.com/en-us/deployedge/microsoft-edge-policies/microsoftrootstoreenabled).
The obsolete Edge root-store policy is not a workaround.

## Keep the host running

On Linux, including a WSL distribution with systemd enabled, install and manage
Expand Down
Loading
Loading