User API Keys¶
Each NetBox user attaches their own RIR credential to one or more RIRConfig rows. Keys are encrypted at rest and never returned by the REST API after creation.
Why per-user keys¶
The plugin assumes a multi-tenant operations model. RIR audit trails attribute every change to the credential that submitted it, so the plugin records, on every synced or written object:
synced_by-- theRIRUserKeywhose call produced the row (onRIROrganization,RIRContact,RIRNetwork).submitted_by-- theRIRUserKeythat submitted a write (onRIRTicket).
Per-user keys also avoid the operational hazard of a shared secret, and make rotation a per-user concern.
Adding a key¶
- Go to RIR Manager > User Keys and click Add.
- Pick a NetBox user (admins can create keys for other users).
- Pick the RIR Config. The pair (user, config) must be unique.
- Paste the API key into the password input.
- Save.
The form widget uses forms.PasswordInput, so the value is masked while typing. The serializer marks api_key as write_only, so it is never echoed back over the REST API.
Encryption at rest¶
The RIRUserKey.api_key column is an EncryptedCharField. Saving it transparently runs the value through Fernet encryption with a key derived from the plugin's encryption_key setting (or NetBox's SECRET_KEY when the setting is empty). Reading it (via the ORM) transparently decrypts.
Implementation details:
- KDF: HKDF-SHA256, salt
netbox-rir-manager, infoapi-key-encryption, output 32 bytes. - Cipher: Fernet (AES-128-CBC + HMAC-SHA256 + IV).
- Storage prefix:
$FERNET$<token>. Values without the prefix are returned as-is, which preserves backward compatibility with rows written before the field was added. - Decryption failure mode:
InvalidTokenreturns the stored value verbatim instead of raising. This means a misconfiguredencryption_keywill not crash the application, but write operations will fail at the RIR with confusing errors. See the warning below.
The implementation is netbox_rir_manager.fields.EncryptedCharField.
Rotation¶
Rotating a single user's RIR API key:
- Update the key with the RIR.
- Edit the
RIRUserKeyrow in NetBox and paste the new value. - Save. The new ciphertext replaces the old.
Rotating the encryption_key setting:
- Pre-flight: write a one-shot Django shell snippet that loops over every
RIRUserKey, readsapi_key(which decrypts under the old key), andsave()s it back (which re-encrypts under the same old key). This guarantees no plaintext rows remain. - Update
encryption_keyinconfiguration.py. - Restart NetBox and the RQ worker.
- Have each user re-enter their key. There is no way to recover the old ciphertext under the new key.
Lost keys are unrecoverable
Changing or losing encryption_key (or SECRET_KEY when the plugin's setting is empty) makes every previously encrypted API key unrecoverable. Treat the encryption key like a database password: store it in your secrets manager and back it up alongside the database.
REST API¶
GET /api/plugins/rir-manager/user-keys/
POST /api/plugins/rir-manager/user-keys/
GET /api/plugins/rir-manager/user-keys/{id}/
PATCH /api/plugins/rir-manager/user-keys/{id}/
DELETE /api/plugins/rir-manager/user-keys/{id}/
api_key is write_only. List and retrieve responses omit it entirely.
Example create:
curl -X POST https://netbox.example.com/api/plugins/rir-manager/user-keys/ \
-H "Authorization: Token <netbox-token>" \
-H "Content-Type: application/json" \
-d '{
"user": 1,
"rir_config": 1,
"api_key": "API-XXXX-XXXX-XXXX-XXXX"
}'
Filtering¶
The list view filters by user and rir_config_id. Search matches user.username.
Permissions¶
To use sync and write actions, a user needs:
netbox_rir_manager.view_rirconfigon the target config.netbox_rir_manager.view_riruserkeyandnetbox_rir_manager.add_riruserkeyto manage their own key.- The relevant
change_*permission on the resource being modified.
Admins managing keys for other users additionally need netbox_rir_manager.add_riruserkey and change_riruserkey. See Reference: Permissions.