# OpenWAF Origin CA

> Free certificates for your origin servers, trusted by the OpenWAF edge in Full (strict). Generated key or your own CSR, up to 15 years.

The **OpenWAF Origin CA** is a certificate authority run by OpenWAF that issues free certificates for your origin servers. The OpenWAF edge trusts it in [Full (strict)](https://developers.openwaf.dev/ssl/origin-tls/#full-strict) alongside the public CAs. Browsers don't trust it, and they never need to: visitors only ever see the [edge certificate](https://developers.openwaf.dev/ssl/edge-certificates/).

Use an origin certificate when:

- the origin has no public certificate, or you don't want to renew one every few months;
- the name the edge verifies doesn't resolve to the origin, or the origin isn't reachable from the Internet, so a public CA can't validate it.

> **Caution**
>
> Use origin certificates only behind the OpenWAF proxy. Anyone who reaches the origin directly gets a certificate their browser doesn't trust.


## What you can request

| Field | Rules | Default |
|---|---|---|
| Names (`hostnames`) | 1–100 names: the zone itself, names below it (`www.example.com`) or wildcards `*.<name>` (`*.example.com`, `*.shop.example.com`). Nothing outside the zone and no IP addresses. Names are lower-cased and de-duplicated. | — |
| Key (`key_type`) | `ecdsa_p256` or `rsa2048`, generated by OpenWAF, **or** your own CSR (`csr`). | `ecdsa_p256` |
| CSR (`csr`) | A PEM certificate request made on your server, with an ECDSA P-256/P-384 or RSA 2048–8192 key. Only its public key is used: its subject and extensions are ignored and the names come from `hostnames`. | — |
| Validity (`validity_days`) | 7, 30, 90, 365, 730, 1095 or 5475 days. | 5475 (15 years) |

The certificate carries the names as DNS subject alternative names, the *serverAuth* extended key usage, a random 128-bit serial number and the first name as its common name.

## The private key is shown once

When OpenWAF generates the key, it is returned **only in the answer that issues the certificate**. OpenWAF doesn't store it or write it to any log, including the audit log. Save it straight away; if you lose it, issue another certificate and revoke the old one.

With a CSR, no private key is generated and yours never leaves your server. This is the safer option.

## Issue a certificate

You need the `tech` or `admin` role; `readonly` can list certificates.

**Dashboard**

1. Go to **SSL/TLS › Origin › Origin certificates** and select **Create certificate**.
2. Enter the names, one per line.
3. Under **Private key**, choose **Generate an ECDSA P-256 key (recommended)**, **Generate an RSA 2048 key** or **Use my own CSR**, and pick a **Validity**.
4. Select **Create**, then copy or download the certificate and the key. They can't be shown again.

**CLI**

```sh
# Key generated by OpenWAF, written to a 0600 file and never printed:
openwaf-cloud ctl origin-certs create example.com example.com '*.example.com' \
  --cert-out origin.pem --key-out origin.key --reason "origin certificate"

# RSA key, valid for one year:
openwaf-cloud ctl origin-certs create example.com www.example.com --key-type rsa --days 365 \
  --cert-out origin.pem --key-out origin.key --reason "origin certificate"

# With a CSR: the key stays on your server.
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes \
  -keyout origin.key -out origin.csr -subj "/CN=example.com"
openwaf-cloud ctl origin-certs create example.com example.com '*.example.com' --csr origin.csr \
  --cert-out origin.pem --reason "origin certificate"
```

`--cert-out` receives the certificate followed by the Origin CA certificate. Existing files are never overwritten. Like every change, the command simulates first and asks for confirmation (`--yes` without a terminal, `--dry-run` only checks).

**API**

```sh
curl -s -X POST https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/origin-certs \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Change-Reason: origin certificate" \
  -d '{"hostnames": ["example.com", "*.example.com"], "key_type": "ecdsa_p256", "validity_days": 5475}'
```

The answer is `201` with `certificate` (its metadata), `certificate_pem`, `private_key_pem` (absent with a `csr`) and `ca_pem`, sent with `Cache-Control: no-store`. Add `?dry_run=1` to validate without issuing. Validation errors are `422` with `code` `invalid` and the offending `field` (`hostnames`, `key_type`, `validity_days` or `csr`).

**MCP**

`create_origin_cert` works in two steps: `confirm=false` checks the request, `confirm=true` issues. Prefer passing a `csr`, so no private key goes through the conversation.

```json
{"zone": "example.com", "hostnames": ["example.com", "*.example.com"], "csr": "-----BEGIN CERTIFICATE REQUEST-----\n…", "reason": "origin certificate", "confirm": false}
```


Next: [install the certificate on your server](https://developers.openwaf.dev/ssl/install-origin-certificate/).

## List certificates

Each certificate has a `status`: `active`, `revoked` or `expired`, plus its names, key type, serial, SHA-256 fingerprint and validity. Keys are never included.

**Dashboard**

**SSL/TLS › Origin › Origin certificates**.

**CLI**

```sh
openwaf-cloud ctl origin-certs list example.com
```

**API**

```sh
curl -s https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/origin-certs \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**MCP**

`list_origin_certs` with `{"zone": "example.com"}`.


## Revoke a certificate

Revoke a certificate whose key may have leaked or that you no longer use. The edge nodes receive the revocation with their next configuration, usually within a minute, and from then on reject the certificate in Full (strict): an origin still serving it answers `526`. Revocation can't be undone; issue a new certificate instead. The certificate stays in the list with `status` `revoked`, who revoked it and when.

**Dashboard**

In **SSL/TLS › Origin › Origin certificates**, select **Revoke** on the certificate and confirm.

**CLI**

```sh
openwaf-cloud ctl origin-certs revoke example.com <id> --reason "key leaked"
```

**API**

```sh
curl -s -X DELETE https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/origin-certs/$CERT_ID \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: key leaked"
```

The call is idempotent. A certificate of another zone or organization answers `404`.

**MCP**

`revoke_origin_cert` with the certificate `id` from `list_origin_certs`: `confirm=false` shows the certificate, `confirm=true` revokes it.


Certificates of a **deleted zone** count as revoked, even if another organization adds the same domain later.

## Download the Origin CA certificate

The Origin CA certificate is public. You don't need it on a server that only talks to the OpenWAF edge, but some tools want the full chain:

```sh
curl -fsS https://dash.openwaf.dev/v1/origin-tls/origin-ca.pem -o openwaf-origin-ca.pem
# or
openwaf-cloud ctl origin-tls ca
```

The URL returns every unexpired Origin CA certificate; during a rotation there is more than one.

## Audit and history

Issuing and revoking are recorded in the organization's audit log (`zone.origin_cert.issue`, `zone.origin_cert.revoke`) with the names, the serial and the reason. Origin certificates live on your server, not in the zone configuration, so they don't create zone versions and reverting a version doesn't touch them.
