Files
cert-portal/README.md
T
nick 7967dbf9f0
Container / test (push) Successful in 38s
Container / docker (push) Failing after 37s
gitea actions
2026-09-18 20:08:29 -07:00

56 lines
2.8 KiB
Markdown

# Certificate Portal
OIDC-authenticated web portal that issues a **user certificate** from Active Directory Certificate Services and delivers it as a **signed Apple `.mobileconfig`**.
This is **Design B**: the portal talks to the CA itself. There is no NDES and no SCEP. The device never contacts AD CS.
```
Sign in (OIDC) → LDAP objectSid → RSA key + CSR in memory
→ POST /certsrv/certfnsh.asp (NTLM) → PKCS#12 inside .mobileconfig
→ CMS-sign the profile → download over HTTPS
```
## Tradeoff
The **private key is generated on the server**, packed into a PKCS#12, and sent to the device. It is kept in memory only for that request and is not written to disk. That is commonly accepted for user Wi-Fi certificates. Do not use this portal for keys that must never leave the device (SCEP / on-device generation is a different design).
## Documentation
| Doc | Contents |
| --- | --- |
| [docs/architecture.md](docs/architecture.md) | Request flow, the two PKCS#12s, why phones never talk to the CA |
| [docs/setup.md](docs/setup.md) | OIDC, LDAP, certsrv, TLS, Docker / `python -m cert_portal` |
| [docs/gitea.md](docs/gitea.md) | Gitea Actions: build and publish to the container registry |
| [docs/adcs.md](docs/adcs.md) | Web Enrollment, template flags, SID URI / strong mapping |
| [docs/profile-signing.md](docs/profile-signing.md) | Signing identity, device trust, CMS format |
| [docs/security.md](docs/security.md) | Key lifetime, logging, sessions, who can download |
| [.env.example](.env.example) | Every setting, commented |
After sign-in, operators and users can also open **Help** in the app (`/help`) without cloning this repo.
## Quick start
1. Copy `.env.example` to `.env` and fill in OIDC, LDAP, certsrv, and the profile-signing PKCS#12 path.
2. Python 3.12+: `pip install -e ".[dev]"` then `python -m cert_portal`
3. Or pull `git.atlashorizon.net/nick/cert-portal:latest` from the Gitea registry (see [docs/gitea.md](docs/gitea.md)), or `docker build -t cert-portal .` locally. Run with `--env-file .env`, publishing port 8000, mounting the signing P12.
Put a reverse proxy in front for TLS. Set `PUBLIC_BASE_URL` and `OIDC_REDIRECT_URI` to that HTTPS origin (`/auth/callback`).
## What you need on the Windows side
- AD CS **Web Enrollment** (`https://ca.example.com/certsrv`) reachable from the Linux host
- A template the portal service account can **Enroll**, with subject and SAN **supplied in the request**
- A domain account for NTLM to certsrv (and a separate LDAP bind account, or the same one)
- A certificate (and private key) used only to **sign** `.mobileconfig` files, already trusted on devices
Details: [docs/adcs.md](docs/adcs.md) and [docs/profile-signing.md](docs/profile-signing.md).
## Development
```bash
pip install -e ".[dev]"
pytest
```
Tests mock the CA. They do not need live AD CS, LDAP, or an IdP.