# 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 ``` ### Using Python directly ```bash python main.py ``` ### 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 `//cert.pem` 4. Export the private key to `//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