Skip to main content

NetBox Certificates Plugin

NetBox Python License

NetBox Certificates Plugin adds X.509 certificate inventory, encrypted private-key storage, CSRs, cryptographic bundles, root CA identities, hierarchical artifact groups, relationship tracking, import/export workflows, and certificate-expiration alerting to NetBox.

AI-assisted development disclosure: Substantial portions of the initial implementation, testing strategy, technical documentation, and release engineering for this project were produced with assistance from ChatGPT by OpenAI, under human direction and review. The human maintainer is responsible for the code and releases. OpenAI does not maintain, sponsor, or endorse this project. See AI_ASSISTANCE.md and NOTICE.

Status

Release: 0.4.11

This release has been extensively validated on NetBox 4.5.9. The plugin declares compatibility with NetBox 4.5.9 through 4.5.10.

NetBox version Status Reason
4.5.9 Validated / supported Full live integration, API, cryptographic, authentication, and ObjectPermission testing was performed on 4.5.9.
4.5.10 Supported by compatibility gate Same 4.5 patch series; 4.5.10 is a bug-fix release. It has not received the same exhaustive live validation as 4.5.9.
4.5.8 and below Unsupported / rejected PluginConfig.min_version is 4.5.9. NetBox 4.5.9 also fixed constrained ObjectPermission scope filtering, which this plugin relies on.
4.6.0 and above Unsupported / rejected PluginConfig.max_version is 4.5.10. NetBox 4.6 moved to Django 6.0 and introduced/deprecated plugin APIs; a separate compatibility release and test cycle is required.

Python 3.12+ is required by the package. NetBox 4.5 itself requires Python 3.12, 3.13, or 3.14. This plugin's production validation was performed with Python 3.12.

Do not bypass the NetBox version gate in production. A future NetBox minor release can change plugin APIs even when the Python package imports successfully.

Why this plugin exists

NetBox is excellent at modeling infrastructure, but it does not natively model the complete cryptographic lifecycle of certificates, private keys, CSRs, matching identities, exportable bundles, and expiration-delivery history. This plugin adds that layer while using NetBox-native concepts such as PrimaryModel metadata, owners, tags, custom fields, ObjectPermissions, REST APIs, jobs, and change logging.

The plugin is designed for operators who need to answer questions such as:

  • Which certificates are about to expire?
  • Which private key belongs to a certificate or CSR?
  • Is a bundle cryptographically complete?
  • Which objects were imported together?
  • Which root CA does a certificate chain resolve to?
  • Who may view metadata versus download sensitive material?
  • Can a non-admin export a public bundle without gaining access to a private key?
  • Which expiration notifications were actually delivered?

Data model

flowchart LR
    G[Artifact Group] --- C[Certificate]
    G --- K[Private Key]
    G --- R[CSR]
    G --- B[Bundle]

    CA[Certificate Authority\nroot identity] -->|authority| C
    C -->|primary certificate| B
    K -->|primary private key| B
    R -->|primary CSR| B
    C2[Chain Certificates] -->|chain members| B

    C -. public-key identity .- K
    K -. public-key identity .- R
    C -. public-key identity .- R

    L[Artifact Link] -. generic relation .-> C
    L -. generic relation .-> K
    L -. generic relation .-> R
    L -. generic relation .-> B

    CFG[Expiration Alert Configuration] --> EV[Expiration Alert Events]
    EV --> C

Certificate

Represents an X.509 certificate and stores the parsed cryptographic metadata required for inventory and expiration management. Important fields include SHA-256 fingerprint, public-key fingerprint, serial number, subject, issuer, SANs, validity window, signature algorithm, key type/size/curve, CA flag, root CA identity, parent/supersession relationships, owner, groups, tags, and alert trigger settings.

Certificate material is stored because certificates are public objects by design. Downloading it through the protected download action still requires the plugin's custom download permission and a write-enabled NetBox API token for API access.

Private Key

Represents a private key. Raw private-key material is never exposed in normal list/detail serializers. It is encrypted before database storage using a Fernet key supplied through PLUGINS_CONFIG.

The model records metadata such as SHA-256 material fingerprint, public-key fingerprint, key type/size, import-encryption state, groups, owner, tags, description, and comments.

Private-key material has an additional security boundary: creation/replacement/download of material through the API is restricted to a NetBox superuser using a write-enabled API token, even when a normal user has the model's add/change/download ObjectPermission.

CSR

Represents a PKCS#10 Certificate Signing Request. The plugin parses subject, SANs, signature algorithm, key properties, request fingerprint, and public-key fingerprint. The public-key fingerprint allows a CSR to be matched to a certificate and/or private key.

The UI/API can also generate a CSR and a matching private key. Because generation creates private-key material, the generation action is superuser-only through the API.

Bundle

A Bundle represents a set of cryptographic objects sharing the same public-key identity.

The three primary artifacts are:

  1. Certificate
  2. Private Key
  3. CSR

A Bundle is:

  • Partial when any two matching primary artifacts are present.
  • Complete only when all three matching primary artifacts are present.

A Bundle can additionally hold chain certificates, import metadata, source/archive format, an optional preserved encrypted archive, groups, owner, tags, description, and comments.

Direct REST POST to the Bundle endpoint is intentionally disabled. Use Import Objects (/import-objects/) so cryptographic identity validation occurs before the Bundle is created.

Certificate Authority

Represents a root CA identity derived from imported self-signed root certificates. It is not a second copy of a certificate. Certificates point to the resolved root authority when a complete root path can be established.

The REST Certificate Authority endpoint is intentionally read-only. CA identities are maintained from certificate material rather than manually created through the API.

Artifact Group

A user-managed hierarchical grouping mechanism for Certificates, Private Keys, CSRs, and Bundles. Groups can have a parent group; cycles and self-parenting are rejected.

Groups are independent of NetBox authentication groups. ArtifactGroup is an inventory organization object; users.Group is an authorization object.

Artifact Link

Represents a generic relationship between supported artifact objects. Links may be:

  • automatic, generated from cryptographic relationships; or
  • manual, created by an operator.

Automatic links cannot be changed/deleted through the REST API. Manual links can be managed when the user has the appropriate ObjectPermission and can see both endpoints.

Expiration Alert Configuration

A singleton object controlling the expiration worker policy and notification transport configuration. It includes scan interval/repeat behavior, SMTP configuration, webhook configuration, and encrypted transport secrets.

The singleton cannot be deleted through the API. Disable the configured delivery methods instead.

Expiration Alert Event

A delivery-history record generated by the expiration worker for a certificate/method/trigger occurrence. Events are intentionally read/delete only through the API; operators do not create or edit them manually.

Imports and cryptographic matching

The Import Objects workflow inspects uploaded content instead of trusting the filename extension. Supported content includes PEM/DER X.509 certificates, private keys, CSRs, PKCS#7/CMS containers, PKCS#12/PFX, and supported archives. Optional RAR support is available through the rar package extra.

The main safety rule is the public-key fingerprint. A certificate, private key, and CSR may become primary members of the same Bundle only when their public keys match. A mismatched primary set is rejected atomically: the transaction is rolled back rather than leaving partially-created artifacts.

Current upload limits are:

  • Combined upload: 25 MiB
  • Archive entries: 250 files
  • Maximum uncompressed archive content: 100 MiB

Export behavior

Bundles can be exported as ZIP or TAR. Public-only bundles may be exported by authorized non-superusers. If the Bundle contains a Private Key, export becomes a sensitive operation and requires superuser access through the API.

PFX/PKCS#12 export requires a Certificate, matching Private Key, and password, and is always treated as a sensitive operation.

Downloaded sensitive responses set cache-prevention/security headers, and archive members containing cryptographic material are created with restrictive file modes.

UI

The plugin base URL is /plugins/ssl-certificates/.

Important routes:

  • expiration-dashboard/ — expiration overview
  • inventory/ — consolidated artifact inventory
  • certificate-authorities/ — root CA identities
  • certificates/ — certificate management
  • private-keys/ — private-key metadata management
  • csrs/ — CSR management and generation
  • bundles/ — Bundle management/export
  • groups/ — hierarchical artifact groups
  • import/ — unified import
  • expiration-alerts/ — alert configuration/history

Most PrimaryModel objects support NetBox-native filtering, bulk editing, ownership, tags, custom fields, descriptions/comments, and change logging.

REST API

The API base is:

/api/plugins/ssl-certificates/

See docs/API.md for endpoint details, authentication rules, custom actions, examples, status-code behavior, and security restrictions.

Permissions

This plugin uses NetBox ObjectPermissions. Standard CRUD actions use NetBox's native actions (view, add, change, delete). The plugin also defines custom actions.

Standard and custom actions

Object Standard actions Custom action string Django permission codename
Artifact Group view/add/change/delete
Certificate Authority view/add/change/delete*
Certificate view/add/change/delete download netbox_certificates.download_certificate
Private Key view/add/change/delete download netbox_certificates.download_privatekey
CSR view/add/change/delete download netbox_certificates.download_csr
Bundle view/add/change/delete export, export_pfx netbox_certificates.export_bundle, netbox_certificates.export_pfx_bundle
Artifact Link view/add/change/delete
Expiration Alert Configuration view/add/change test netbox_certificates.test_expiryalertconfiguration
Expiration Alert Event view/delete

* The Certificate Authority model has normal model permissions, but its REST API is deliberately read-only. A permission does not override an endpoint's method contract.

Creating permissions in the NetBox UI

Go to Admin → Object Permissions and create a permission with:

  1. The plugin object type(s).
  2. One or more users/groups.
  3. Standard actions and/or the custom action.
  4. Optional JSON constraints.

On NetBox versions where a plugin custom action is not shown as a dedicated checkbox, use the ObjectPermission form's Additional actions field and enter the action string exactly as listed above: download, export, export_pfx, or test.

Custom actions still require the object's view scope to resolve the target object. In practical terms, grant the corresponding view action together with a custom action unless the user already receives view permission from another ObjectPermission.

Creating custom-action ObjectPermissions from the shell

The following example creates permissions directly using NetBox's real ObjectPermission objects. It is useful when the NetBox 4.5 UI does not surface a plugin action the way you want.

cd /opt/netbox
sudo -u netbox ./venv/bin/python ./netbox/manage.py shell <<'PY'
from core.models import ObjectType
from users.models import Group, ObjectPermission
from netbox_certificates.models import Certificate, CSR, Bundle

operator_group = Group.objects.get(name="Certificate Operators")


def grant(name, model, actions, constraints=None):
    permission, _ = ObjectPermission.objects.get_or_create(
        name=name,
        defaults={"enabled": True, "actions": list(actions), "constraints": constraints or {}},
    )
    permission.enabled = True
    permission.actions = list(actions)
    permission.constraints = constraints or {}
    permission.save()
    permission.object_types.set([ObjectType.objects.get_for_model(model)])
    operator_group.object_permissions.add(permission)
    return permission


grant("Certificate Operators - certificate download", Certificate, ["view", "download"])
grant("Certificate Operators - CSR download", CSR, ["view", "download"])
grant("Certificate Operators - public Bundle export", Bundle, ["view", "export"])
PY

NetBox constraints can be added as normal JSON/ORM-style filters, for example:

{"name__startswith": "PROD-"}

The plugin has been validated with constrained reads and constrained creates, including NetBox's transactional rollback when a newly-created object falls outside the permission constraint.

Permissions do not bypass sensitive-operation overlays

Even if a non-superuser is granted add_privatekey, change_privatekey, download_privatekey, export_pfx_bundle, or other related permissions, the following API operations remain superuser-only where private-key material is involved:

  • creating/replacing Private Key material;
  • downloading Private Key material;
  • generating CSR + Private Key;
  • exporting a Bundle that contains a Private Key;
  • exporting PFX/PKCS#12.

This is deliberate defense in depth.

Configuration

Enable the plugin with its Python module name, not its PyPI distribution name:

PLUGINS = [
    "netbox_certificates",
]

The plugin currently has one required PLUGINS_CONFIG setting: encryption_key.

PLUGINS_CONFIG = {
    "netbox_certificates": {
        "encryption_key": "REPLACE_WITH_A_FERNET_KEY",
    }
}

Generate the encryption key

Generate a Fernet key with the same Python/cryptography environment used by NetBox:

/opt/netbox/venv/bin/python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())'

The result is a URL-safe base64 Fernet key. Copy it exactly into the plugin configuration or provide it from a secret-management/environment mechanism.

A configuration using an environment variable can look like:

import os

PLUGINS_CONFIG = {
    "netbox_certificates": {
        "encryption_key": os.environ["NETBOX_CERTIFICATES_ENCRYPTION_KEY"],
    }
}

If you use an environment variable, make sure the NetBox WSGI and RQ systemd services receive it; setting it only in your interactive shell is not enough.

Critical: Back up the encryption key separately from the database. Do not casually rotate it. Existing encrypted Private Keys, SMTP passwords, webhook URLs/tokens, and other plugin secrets become undecryptable if the key changes without a migration/re-encryption procedure.

SMTP and webhook values are configured in the plugin's Expiration Alerts UI/database singleton. They are not additional configuration.py plugin settings.

Installation from PyPI

The distribution name is netbox-certificates-plugin and the NetBox plugin module is netbox_certificates.

For a production NetBox installation, record the package in /opt/netbox/local_requirements.txt so NetBox reinstalls it when rebuilding the virtual environment:

netbox-certificates-plugin==0.4.11

For RAR import support:

netbox-certificates-plugin[rar]==0.4.11

Install/update local requirements using NetBox's normal upgrade process, then enable/configure the plugin and apply migrations/static assets:

sudo /opt/netbox/upgrade.sh

cd /opt/netbox
sudo -u netbox ./venv/bin/python ./netbox/manage.py migrate
sudo ./venv/bin/python ./netbox/manage.py collectstatic --no-input
sudo -u netbox ./venv/bin/python ./netbox/manage.py check
sudo systemctl restart netbox netbox-rq

If /opt/netbox/upgrade.sh was run after the plugin was already enabled and configured, it may already have performed the migration/static steps. Running migrate and collectstatic again is safe and makes the installation state explicit.

Installation from a GitHub tag

Git installation is useful for validating a release tag before/alongside PyPI:

netbox-certificates-plugin @ git+https://github.com/Fokkert/netbox-certificates-plugin.git@v0.4.11

Put that line in /opt/netbox/local_requirements.txt, run /opt/netbox/upgrade.sh, configure the plugin, migrate, collect static files, run manage.py check, and restart NetBox.

Existing package/module name collision

There is an older third-party GitHub project named NetworkSeb/netbox-certificates which also uses the Python import module netbox_certificates. It is a different project and data model.

Because Python packages with the same import module cannot safely coexist in one virtual environment, do not install both plugins into the same NetBox environment. The PyPI distribution name for this project is different (netbox-certificates-plugin), but the import-module collision still matters.

Background jobs and maintenance commands

The plugin registers background behavior for certificate status and expiration processing. Two useful management commands are also available:

cd /opt/netbox
sudo -u netbox ./venv/bin/python ./netbox/manage.py refresh_certificate_status
sudo -u netbox ./venv/bin/python ./netbox/manage.py reconcile_certificate_links

refresh_certificate_status recalculates stored status from certificate validity timestamps. reconcile_certificate_links rebuilds automatic cryptographic/issuer relationships.

Validation summary

Release 0.4.11 was validated on a live NetBox 4.5.9 installation with API authentication, cryptographic identity checks, import/export behavior, PFX/ZIP handling, read-only and write-enabled NetBox v2 tokens, non-admin permission boundaries, and all plugin ObjectPermission actions.

The final non-admin ObjectPermission matrix executed 146 successful checks, 0 failures, 1 intentional skip, covering 39/39 permission actions. The single skip avoided sending an additional real SMTP/webhook test message to production destinations.

See VALIDATION.md for release notes and maintain your own staging/integration validation before upgrading NetBox or this plugin.

API documentation

Full API documentation: docs/API.md.

Publishing and release engineering

Maintainer instructions for GitHub, TestPyPI, PyPI Trusted Publishing, and release tags are in docs/PUBLISHING.md.

Removal

Destructive clean-removal instructions are in docs/UNINSTALL.md. Back up the database and encryption key before removing the plugin.

License and attribution

Licensed under the Apache License 2.0. See LICENSE and NOTICE.

Apache-2.0 allows use, modification, redistribution, commercial use, and forks. Distributed derivatives must comply with the license's preservation/attribution requirements, including applicable NOTICE content and notices of modified files. The canonical-source attribution is intentionally placed in NOTICE so it travels with redistributed derivatives.

See CONTRIBUTING.md for contribution guidelines.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

netbox_certificates_plugin-0.4.11.tar.gz (120.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

netbox_certificates_plugin-0.4.11-py3-none-any.whl (128.0 kB view details)

Uploaded Python 3

File details

Details for the file netbox_certificates_plugin-0.4.11.tar.gz.

File metadata

File hashes

Hashes for netbox_certificates_plugin-0.4.11.tar.gz
Algorithm Hash digest
SHA256 7a4d39d877c4e7da464564ff3af278561585398f1e8bff806d5747fdbd985b00
MD5 e17c3ee3ca94a8a68c2a1d75cf887141
BLAKE2b-256 4fa927db258b3147240180c9ded7fdee22c5f16779e0815a1b6e3ad74aaefc07

See more details on using hashes here.

Provenance

The following attestation bundles were made for netbox_certificates_plugin-0.4.11.tar.gz:

Publisher: release.yml on Fokkert/netbox-certificates-plugin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file netbox_certificates_plugin-0.4.11-py3-none-any.whl.

File metadata

File hashes

Hashes for netbox_certificates_plugin-0.4.11-py3-none-any.whl
Algorithm Hash digest
SHA256 154d00ee4d1667b730de193495a9afa1d07f3b1e0308a006e7c56ced710d4d73
MD5 1c7827c418144bc46de646672d2fdda0
BLAKE2b-256 6418bea6ff3aa3167e937d581aaad322de36e38586d43203073d1d3a234acf59

See more details on using hashes here.

Provenance

The following attestation bundles were made for netbox_certificates_plugin-0.4.11-py3-none-any.whl:

Publisher: release.yml on Fokkert/netbox-certificates-plugin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.3.2

2 files

1.3.1

2 files

1.3.0

2 files

1.2.0

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.5

2 files

1.0.4

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

0.5.0

2 files

This release

0.4.11 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page