235 lines
6.7 KiB
Markdown
235 lines
6.7 KiB
Markdown
# OPNsense Certificate Exporter
|
|
|
|
A Python tool to export SSL/TLS certificates and private keys from OPNsense firewalls via the API.
|
|
|
|
## Features
|
|
|
|
- Search and export certificates from OPNsense Trust store
|
|
- Exports both certificate (`cert.pem`) and private key (`privkey.pem`)
|
|
- Change detection: only writes files if content has changed
|
|
- Environment-based configuration (supports `.env` files)
|
|
- Optional systemd journal logging
|
|
- Optional file permission settings (Linux only)
|
|
|
|
## Prerequisites
|
|
|
|
- Python 3.13+
|
|
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
|
|
- OPNsense firewall with API access enabled
|
|
- API key and secret with access to Trust/Certificates
|
|
|
|
## Installation
|
|
|
|
### Using uv (recommended)
|
|
|
|
```bash
|
|
git clone https://git.project-insanity.de/gmarth/opnsense_cert_exporter.git
|
|
cd opnsense-cert-exporter
|
|
uv sync
|
|
```
|
|
|
|
### Using pip
|
|
|
|
```bash
|
|
git clone https://git.project-insanity.de/gmarth/opnsense_cert_exporter.git
|
|
cd opnsense-cert-exporter
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
### Optional: systemd journal logging
|
|
|
|
To enable native systemd journal logging (Linux only):
|
|
|
|
```bash
|
|
# Install system dependency first
|
|
sudo apt install libsystemd-dev pkg-config # Debian/Ubuntu
|
|
sudo dnf install systemd-devel pkg-config # Fedora/RHEL
|
|
|
|
# Then install the optional Python dependency
|
|
uv sync --extra systemd
|
|
```
|
|
|
|
## Configuration
|
|
|
|
1. Copy the example environment file:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
2. Edit `.env` with your settings:
|
|
|
|
```bash
|
|
# Required
|
|
OPNSENSE_API_KEY=your_api_key_here
|
|
OPNSENSE_API_SECRET=your_api_secret_here
|
|
OPNSENSE_HOST=https://your-opnsense.local
|
|
|
|
# Optional
|
|
OUTPUT_DIRECTORY=./certs
|
|
|
|
# Optional: disable SSL verification for self-signed certificates
|
|
# VERIFY_SSL=false
|
|
|
|
# Optional: file permissions (Linux only)
|
|
# FILE_OWNER=root
|
|
# FILE_GROUP=root
|
|
# FILE_MODE=0600
|
|
```
|
|
|
|
### Configuration Options
|
|
|
|
| Environment Variable | Required | Description |
|
|
|---------------------|----------|-------------|
|
|
| `OPNSENSE_API_KEY` | Yes | OPNsense API key |
|
|
| `OPNSENSE_API_SECRET` | Yes | OPNsense API secret |
|
|
| `OPNSENSE_HOST` | Yes | OPNsense URL (e.g., `https://192.168.1.1`) |
|
|
| `OUTPUT_DIRECTORY` | No | Directory to save exported certificates (default: `./certs`) |
|
|
| `VERIFY_SSL` | No | Set to `false` to disable SSL verification for self-signed certs (default: `true`) |
|
|
| `FILE_OWNER` | No | Set file owner (Linux only) |
|
|
| `FILE_GROUP` | No | Set file group (Linux only) |
|
|
| `FILE_MODE` | No | Set file permissions in octal (e.g., `0600`) |
|
|
|
|
### Setting up OPNsense API Access
|
|
|
|
For security, create a dedicated user with minimal privileges for certificate export.
|
|
|
|
#### 1. Create a Group with Certificate Manager Access
|
|
|
|
1. Log in to your OPNsense web interface
|
|
2. Go to **System > Access > Groups**
|
|
3. Click **+** to add a new group
|
|
4. Configure the group:
|
|
- **Group name:** `cert-exporter`
|
|
- **Description:** `Certificate export API access`
|
|
- **Restrict access to networks (optional):** Limit API access to specific networks (e.g., `192.168.1.0/24` or a single host `192.168.1.100/32`)
|
|
5. Click **Save**
|
|
6. Click the **Edit** (pencil icon) on the newly created group
|
|
7. Under **Assigned Privileges**, click **Edit**
|
|
8. Select only **System: Certificate Manager** from the list
|
|
9. Click **Save**
|
|
|
|
> **Security tip:** Restricting access to the network where your export script runs adds an extra layer of security. Even if the API credentials are compromised, they cannot be used from unauthorized networks.
|
|
|
|
#### 2. Create a Dedicated API User
|
|
|
|
1. Go to **System > Access > Users**
|
|
2. Click **+** to add a new user
|
|
3. Configure the user:
|
|
- **Username:** `cert-exporter`
|
|
- **Password:** Set a strong password (not used for API access, but required)
|
|
- **Group Memberships:** Select `cert-exporter`
|
|
4. Click **Save**
|
|
|
|
#### 3. Generate an API Key
|
|
|
|
1. Edit the `cert-exporter` user
|
|
2. Scroll down to **API keys** and click the **+** button
|
|
3. Download the generated key file containing the key and secret
|
|
4. Store the credentials securely - they cannot be retrieved later
|
|
|
|
## Usage
|
|
|
|
### Using uv
|
|
|
|
```bash
|
|
uv run python main.py <certificate_name>
|
|
```
|
|
|
|
### Using Python directly
|
|
|
|
```bash
|
|
python main.py <certificate_name>
|
|
```
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
# Export a single certificate
|
|
uv run python main.py mail.example.com
|
|
|
|
# Export multiple certificates
|
|
uv run python main.py mail.example.com
|
|
uv run python main.py vpn.example.com
|
|
uv run python main.py wildcard.example.com
|
|
```
|
|
|
|
The tool will:
|
|
1. Search for the certificate matching the provided name
|
|
2. Check if the certificate has changed since last export
|
|
3. Export the certificate to `<output_directory>/<certificate_name>/cert.pem`
|
|
4. Export the private key to `<output_directory>/<certificate_name>/privkey.pem`
|
|
5. Log whether the certificate was updated or unchanged
|
|
|
|
### Viewing logs
|
|
|
|
With systemd journal logging enabled:
|
|
|
|
```bash
|
|
journalctl -t opnsense-cert-exporter
|
|
journalctl -t opnsense-cert-exporter --since "1 hour ago"
|
|
journalctl -t opnsense-cert-exporter -f # follow
|
|
```
|
|
|
|
## Setting up a Cronjob for Periodic Exports
|
|
|
|
To automatically export certificates on a schedule, set up a cron job:
|
|
|
|
### 1. Open the crontab editor
|
|
|
|
```bash
|
|
crontab -e
|
|
```
|
|
|
|
### 2. Add a cron entry
|
|
|
|
The `.env` file is automatically loaded from the script directory, so no need to `cd` first.
|
|
|
|
**Daily at midnight:**
|
|
```cron
|
|
0 0 * * * /usr/local/bin/uv run python /opt/opnsense-cert-exporter/main.py mail.example.com
|
|
```
|
|
|
|
**Export multiple certificates:**
|
|
```cron
|
|
0 0 * * * /usr/local/bin/uv run python /opt/opnsense-cert-exporter/main.py mail.example.com
|
|
0 0 * * * /usr/local/bin/uv run python /opt/opnsense-cert-exporter/main.py vpn.example.com
|
|
```
|
|
|
|
**Weekly on Sunday at 2 AM:**
|
|
```cron
|
|
0 2 * * 0 /usr/local/bin/uv run python /opt/opnsense-cert-exporter/main.py mail.example.com
|
|
```
|
|
|
|
### 3. Example with service reload
|
|
|
|
```cron
|
|
# Export certificate daily at midnight and reload nginx if changed
|
|
0 0 * * * /usr/local/bin/uv run python /opt/opnsense-cert-exporter/main.py mail.example.com && systemctl reload nginx
|
|
```
|
|
|
|
### Cron Format Reference
|
|
|
|
```
|
|
┌───────────── minute (0-59)
|
|
│ ┌───────────── hour (0-23)
|
|
│ │ ┌───────────── day of month (1-31)
|
|
│ │ │ ┌───────────── month (1-12)
|
|
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
|
|
│ │ │ │ │
|
|
* * * * * command
|
|
```
|
|
|
|
### Tips
|
|
|
|
- Use absolute paths for the `uv` binary and `main.py` script
|
|
- The `.env` file is loaded from the script directory automatically
|
|
- With systemd journal logging, output automatically goes to the journal
|
|
- Test the command manually before adding to cron
|
|
- Consider adding a service reload command (e.g., `systemctl reload nginx`) after export
|
|
- Ensure the cron user has appropriate permissions to write to the output directory
|
|
|
|
## License
|
|
|
|
MIT
|