|
1 | | -# Cert Manager Webhook Server for Plesk XML API |
| 1 | +# Cert Manager Webhook for Plesk XML API |
2 | 2 |
|
3 | | -## Overview |
4 | | - |
5 | | -`cert-manager-plesk-webhook` is a custom DNS-01 challenge solver for [cert-manager](https://cert-manager.io) that integrates with the Plesk XML API. This project is implemented in Rust and packaged as a Docker container for easy deployment. The webhook server handles DNS record creation and cleanup via Plesk to automate the issuance of Let's Encrypt certificates. |
| 3 | +A custom DNS-01 challenge solver webhook for [cert-manager](https://cert-manager.io) that integrates with the Plesk XML API. This webhook handles DNS TXT record creation and cleanup via Plesk to automate ACME DNS-01 challenges for certificate issuance. |
6 | 4 |
|
7 | 5 | ## Features |
8 | 6 |
|
9 | | -- **DNS-01 Challenge Support**: Automatically create and delete DNS records in Plesk to complete the DNS-01 challenge for Let's Encrypt certificates. |
| 7 | +- **DNS-01 Challenge Automation**: Automatically creates and deletes DNS TXT records in Plesk. |
| 8 | +- **Multiple Hostname Support**: Can handle concurrent challenges for different hostnames. |
| 9 | +- **Self-Signed TLS**: Generates its own certificate for secure communication with cert-manager. |
| 10 | +- **HTTPS Support**: Listens on both ports 8080 (HTTP) and 8443 (HTTPS), but 8080 is not implemented yet. |
| 11 | + |
| 12 | +## Limitations |
| 13 | + |
| 14 | +- **Single TLD per instance**: Currently supports one top-level domain per deployment (configured via Plesk Site ID). |
| 15 | +- Can issue certificates for multiple subdomains or SAN certificates within that TLD. |
10 | 16 |
|
11 | 17 | ## Prerequisites |
12 | 18 |
|
13 | | -- `cert-manager` installed in your environment |
14 | | -- Access to a Plesk server with DNS management via the XML API |
| 19 | +- Kubernetes cluster with cert-manager v1.0+ installed |
| 20 | +- Plesk server with: |
| 21 | + - XML API access enabled |
| 22 | + - A site/domain configured for DNS management |
| 23 | + - API credentials (username and password) |
| 24 | + - The Site ID for your domain |
| 25 | + |
| 26 | +### Finding Your Plesk Site ID |
| 27 | + |
| 28 | +1. Log into your Plesk admin panel |
| 29 | +2. Navigate to **Websites & Domains** |
| 30 | +3. Click on DNS in the "Hosting and DNS" menu |
| 31 | +4. Check the browser URL bar: `https://your-plesk.com:8443/smb/dns-zone/records-list/id/3839/type/domain` |
| 32 | +5. The number after `/id/` is your Site ID (e.g., `123`) |
| 33 | + |
| 34 | +## Installation |
| 35 | + |
| 36 | +### Step 1: Create Secret with Plesk Credentials |
15 | 37 |
|
16 | | -## Configuring Cert-Manager |
| 38 | +```bash |
| 39 | +kubectl create secret generic custom-plesk-solver-secret \ |
| 40 | + --namespace cert-manager \ |
| 41 | + --from-literal=cmpw_plesk_username='your-plesk-username' \ |
| 42 | + --from-literal=cmpw_plesk_password='your-plesk-password' |
| 43 | +``` |
| 44 | + |
| 45 | +Recommended alternative: Use an external secret provider such as HashiCorp Vault. |
17 | 46 |
|
18 | | -Update the ClusterIssuer or Issuer configuration in cert-manager to use this webhook: |
| 47 | +### Step 2: Deploy the Webhook |
19 | 48 |
|
| 49 | +Create the following Kubernetes resources: |
20 | 50 | ```yaml |
21 | | -TBD |
| 51 | +apiVersion: apps/v1 |
| 52 | +kind: Deployment |
| 53 | +metadata: |
| 54 | + name: custom-plesk-solver-webhook |
| 55 | + namespace: cert-manager |
| 56 | +spec: |
| 57 | + replicas: 1 |
| 58 | + selector: |
| 59 | + matchLabels: |
| 60 | + app: custom-plesk-solver-webhook |
| 61 | + template: |
| 62 | + metadata: |
| 63 | + labels: |
| 64 | + app: custom-plesk-solver-webhook |
| 65 | + spec: |
| 66 | + serviceAccountName: custom-plesk-solver-sa |
| 67 | + containers: |
| 68 | + - name: custom-plesk-solver |
| 69 | + image: ghcr.io/jwndlng/cert-manager-plesk-webhook:latest |
| 70 | + imagePullPolicy: Always |
| 71 | + ports: |
| 72 | + - name: http |
| 73 | + containerPort: 8080 |
| 74 | + - name: https |
| 75 | + containerPort: 8443 |
| 76 | + env: |
| 77 | + - name: CMPW_PLESK_SITEID |
| 78 | + value: "123" # Your Plesk Site ID |
| 79 | + - name: CMPW_PLESK_URL |
| 80 | + value: "https://your-plesk-server.com:8443" # Your Plesk API URL |
| 81 | + - name: CMPW_COMMON_GROUPNAME |
| 82 | + value: "acme.example.com" # Must match Issuer groupName |
| 83 | + - name: CMPW_COMMON_SOLVERNAME |
| 84 | + value: "plesk-solver" # Must match Issuer solverName |
| 85 | + - name: CMPW_COMMON_SOLVERVERSION |
| 86 | + value: "v1" # Must match APIService version |
| 87 | + - name: CMPW_PLESK_USERNAME |
| 88 | + valueFrom: |
| 89 | + secretKeyRef: |
| 90 | + name: custom-plesk-solver-secret |
| 91 | + key: cmpw_plesk_username |
| 92 | + - name: CMPW_PLESK_PASSWORD |
| 93 | + valueFrom: |
| 94 | + secretKeyRef: |
| 95 | + name: custom-plesk-solver-secret |
| 96 | + key: cmpw_plesk_password |
| 97 | +``` |
| 98 | +Create the Service: |
| 99 | +
|
| 100 | +```yaml |
| 101 | +apiVersion: v1 |
| 102 | +kind: Service |
| 103 | +metadata: |
| 104 | + name: custom-plesk-solver-webhook |
| 105 | + namespace: cert-manager |
| 106 | +spec: |
| 107 | + selector: |
| 108 | + app: custom-plesk-solver-webhook |
| 109 | + ports: |
| 110 | + - name: https |
| 111 | + protocol: TCP |
| 112 | + port: 443 |
| 113 | + targetPort: 8443 |
| 114 | +``` |
| 115 | +
|
| 116 | +### Step 3: Finish your Cert-Manager and Certificate configuration |
| 117 | +
|
| 118 | +Please review official guides and documentation on how to configure your cert-manager and certificate configuration. |
| 119 | +
|
| 120 | +## Configuration Reference |
| 121 | +
|
| 122 | +| Environment Variable | Required | Description | Example | |
| 123 | +|---------------------|----------|-------------|----------| |
| 124 | +| `CMPW_PLESK_URL` | Yes | Plesk API endpoint URL (including port) | `https://plesk.example.com:8443` | |
| 125 | +| `CMPW_PLESK_SITEID` | Yes | Plesk Site ID for your domain | `123` | |
| 126 | +| `CMPW_PLESK_USERNAME` | Yes | Plesk API username | `admin` | |
| 127 | +| `CMPW_PLESK_PASSWORD` | Yes | Plesk API password | (from secret) | |
| 128 | +| `CMPW_COMMON_GROUPNAME` | Yes | API group name - must match Issuer `groupName` and APIService `group` | `acme.example.com` | |
| 129 | +| `CMPW_COMMON_SOLVERNAME` | Yes | Solver name - must match Issuer `solverName` | `plesk-solver` | |
| 130 | +| `CMPW_COMMON_SOLVERVERSION` | Yes | API version - must match APIService `version` | `v1` | |
| 131 | + |
| 132 | +**Important:** The `CMPW_COMMON_GROUPNAME`, `CMPW_COMMON_SOLVERNAME`, and `CMPW_COMMON_SOLVERVERSION` must be consistent across: |
| 133 | +- Webhook deployment environment variables |
| 134 | +- APIService manifest |
| 135 | +- Your Issuer/ClusterIssuer webhook solver configuration |
| 136 | + |
| 137 | +## Development |
| 138 | + |
| 139 | +### Building from Source |
| 140 | + |
| 141 | +```bash |
| 142 | +# Build the binary |
| 143 | +cargo build --release |
| 144 | +
|
| 145 | +# Build Docker image |
| 146 | +docker build -t cert-manager-plesk-webhook:dev . |
22 | 147 | ``` |
23 | 148 |
|
| 149 | +### Running Locally |
| 150 | + |
| 151 | +```bash |
| 152 | +# Set environment variables |
| 153 | +export CMPW_PLESK_URL="https://your-plesk.com:8443" |
| 154 | +export CMPW_PLESK_SITEID="123" |
| 155 | +export CMPW_PLESK_USERNAME="admin" |
| 156 | +export CMPW_PLESK_PASSWORD="your-password" |
| 157 | +export CMPW_COMMON_GROUPNAME="acme.example.com" |
| 158 | +export CMPW_COMMON_SOLVERNAME="plesk-solver" |
| 159 | +export CMPW_COMMON_SOLVERVERSION="v1" |
| 160 | +
|
| 161 | +# Run the webhook |
| 162 | +cargo run |
| 163 | +``` |
| 164 | + |
| 165 | +The webhook will listen on: |
| 166 | +- HTTP: `http://localhost:8080` (Not implemented) |
| 167 | +- HTTPS: `https://localhost:8443` |
| 168 | + |
| 169 | + |
24 | 170 | ## Contributing |
25 | 171 | Contributions are welcome! Feel free to submit a PR if you think the project is missing something or has a bug :-). |
26 | 172 |
|
|
0 commit comments