56 lines
2.8 KiB
Markdown
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.
|