Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
afe96f5
Test: Update CI workflow to align with NetBox plugin testing patterns
bonzo81 Jan 23, 2026
6920679
Fix: Exclude tests from package, use editable install in CI
bonzo81 Jan 23, 2026
ed5d47f
CI: Strict lint/format on all pushes, tests only on develop/master
bonzo81 Jan 23, 2026
15e6ed0
Merge pull request #208 from bonzo81/test/ci-workflow
bonzo81 Jan 26, 2026
ba86827
Add SNMPv1 support to LibreNMS add device form
bonzo81 Jan 26, 2026
1480d3a
refactor(devices): simplify SNMP version retrieval logic
bonzo81 Jan 26, 2026
7b81f07
Merge pull request #209 from bonzo81/feature/snmpv1-support
bonzo81 Jan 26, 2026
afcdd0e
Format: Fix trailing whitespace and end-of-file issues
bonzo81 Jan 26, 2026
249fad6
ci(lint-format): update Ruff commands for better output
bonzo81 Jan 26, 2026
9b165e4
feat: add two-tier permission system with plugin and object-level acc…
bonzo81 Feb 5, 2026
5774f77
chore: update copilot instructions with permission and background job…
bonzo81 Feb 5, 2026
3128059
Enhance lint-format workflow for multiple branches
bonzo81 Feb 6, 2026
5273a65
refactor(interfaces): run ruff format with versoin 0.15.1
bonzo81 Feb 16, 2026
3e3dfb0
Merge pull request #214 from bonzo81/chore/update-copilot-instructions
bonzo81 Feb 16, 2026
663e36b
refactor(interfaces): run ruff format with version 0.15.1
bonzo81 Feb 16, 2026
2509607
fix: prevent open-redirect via HTTP_REFERER in permission redirects
bonzo81 Feb 16, 2026
1f61c94
fix: add virtualchassis permission check and validate object_type
bonzo81 Feb 16, 2026
42a251d
docs: fix heading grammar, typo, and outdated troubleshooting note
bonzo81 Feb 16, 2026
aa7d15b
fix: use flash message + redirect for import permission denied
bonzo81 Feb 16, 2026
bef41ab
test: add tests for redirect validation, VC perm, and object_type
bonzo81 Feb 16, 2026
d665ea1
Merge pull request #213 from bonzo81/feature/permissions
bonzo81 Feb 16, 2026
99308f2
docs: add docstrings to models, tables, views, forms, and API modules
marcinpsk Feb 17, 2026
97d200f
feat: add empty state cards for sync tabs
marcinpsk Feb 17, 2026
349330a
fix: correct device redirect URL and inaccurate docstrings
marcinpsk Feb 19, 2026
fb99b88
Merge pull request #226 from marcinpsk/chore/add-docstrings
bonzo81 Feb 19, 2026
24615e2
feat: add proxy/MITM support for devcontainer
marcinpsk Feb 17, 2026
548ded1
refactor: devcontainer script improvements and alias consolidation
marcinpsk Feb 17, 2026
1e8c8e2
fix: raise KeyError for missing non-default server keys in LibreNMSAPI
marcinpsk Feb 17, 2026
cc26ef4
test: add tests for KeyError on missing server key and default fallback
marcinpsk Feb 19, 2026
305ea6a
Merge pull request #220 from marcinpsk/feature/librenms-api-keyerror
bonzo81 Feb 19, 2026
8424baa
Merge pull request #223 from marcinpsk/feat/sync-empty-state-cards
bonzo81 Feb 19, 2026
2fca2b2
Merge branch 'develop' into feature/devcontainer-proxy
marcinpsk Feb 20, 2026
5984b57
fix: address review feedback on proxy/MITM devcontainer support
marcinpsk Feb 20, 2026
1729f94
Merge pull request #218 from marcinpsk/feature/devcontainer-proxy
bonzo81 Feb 20, 2026
19b8404
feat(vlan-sync): add LibreNMS VLAN API methods
bonzo81 Jan 29, 2026
62df101
feat(vlan-sync): add VLAN tables for sync display
bonzo81 Jan 29, 2026
b9dd3d2
feat(vlan-sync): add VlanAssignmentMixin and BaseVLANTableView
bonzo81 Jan 29, 2026
ac36031
feat(vlan-sync): add VLAN sync views
bonzo81 Jan 29, 2026
089bb22
feat(vlan-sync): add VLAN sync templates
bonzo81 Jan 29, 2026
f02c259
feat(vlan-sync): add URL routes and JavaScript handlers
bonzo81 Jan 29, 2026
432de27
test(vlan-sync): add unit tests for VLAN sync feature
bonzo81 Jan 29, 2026
0136b72
refactor: update existing sync views to support VLAN integration
bonzo81 Jan 29, 2026
61bdd25
refactor: simplify VLAN enrichment with with_vlans param and per-VLAN…
bonzo81 Feb 19, 2026
bda9e12
feat: support per-VLAN group assignment during interface sync
bonzo81 Feb 19, 2026
fff20b6
feat: add SingleVlanGroupVerifyView endpoint for live VLAN verification
bonzo81 Feb 19, 2026
7961425
feat: redesign VLAN column with color-coded summary, edit modal, and …
bonzo81 Feb 19, 2026
4232592
Merge branch 'develop' into feature/devcontainer-refactor
marcinpsk Feb 20, 2026
ef9e6c3
refactor: improve VLAN sync backend with permissions, per-row groups,…
bonzo81 Feb 23, 2026
dda39ee
feat: add VLAN verification endpoints and group override persistence
bonzo81 Feb 23, 2026
97f667b
feat: redesign VLAN sync UI with per-row verification and form spinners
bonzo81 Feb 23, 2026
30efecd
test: add tests for get_vlan_sync_css_class utility
bonzo81 Feb 23, 2026
ff793b1
docs: update documentation for VLAN sync feature and view architecture
bonzo81 Feb 23, 2026
a39bfeb
fix: security hardening — XSS escaping, input validation, and safety …
marcinpsk Feb 17, 2026
2754943
fix: address PR review — VC member validation, error fallback, and tr…
marcinpsk Feb 17, 2026
351918f
fix: remove found_in_librenms logic change from hardening PR
marcinpsk Feb 23, 2026
f2b16f7
fix(docs): correct typos and improve clarity in README
bonzo81 Feb 23, 2026
41b135b
Merge pull request #229 from bonzo81/feature/vlan-sync
bonzo81 Feb 23, 2026
e03a64c
fix: make device name mismatch informational instead of blocking (#228)
marcinpsk Feb 23, 2026
139842b
refactor(sync): improve device name matching logic
bonzo81 Feb 23, 2026
7092b51
feat(ui): add device identity mismatch modal and update status display
bonzo81 Feb 23, 2026
ca42c41
test(mismatch): enhance identity cross-matching tests
bonzo81 Feb 23, 2026
56fcb8f
Update netbox_librenms_plugin/views/base/librenms_sync_view.py
bonzo81 Feb 24, 2026
96d67fa
Merge pull request #230 from marcinpsk/fix/sync-view-mismatch-228
bonzo81 Feb 24, 2026
c33ecc3
Merge pull request #225 from marcinpsk/fix/security-hardening
bonzo81 Feb 24, 2026
6e6aa67
Merge pull request #219 from marcinpsk/feature/devcontainer-refactor
bonzo81 Feb 24, 2026
dee0470
feat: per-user preference persistence for import toggles and interfac…
marcinpsk Feb 17, 2026
2b9aa85
refactor: address PR review feedback for user preferences
marcinpsk Feb 24, 2026
0220337
Merge pull request #222 from marcinpsk/feat/user-preferences
bonzo81 Feb 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .devcontainer/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,25 @@ SKIP_SUPERUSER=false
# .devcontainer/plugin-config.py.example → .devcontainer/plugin-config.py
# Advanced NetBox configuration (optional):
# .devcontainer/extra-configuration.py.example → .devcontainer/extra-configuration.py

# Proxy Configuration (optional, for corporate networks with MITM proxies)
# Uncomment and set these if you're behind a proxy
# HTTP_PROXY=http://proxy.example.com:8080
# HTTPS_PROXY=http://proxy.example.com:8080
# NO_PROXY=localhost,127.0.0.1,postgres,redis
#
# CA bundle configuration:
# Normally you SHOULD NOT set REQUESTS_CA_BUNDLE, SSL_CERT_FILE, or CURL_CA_BUNDLE here.
# Instead, place a ca-bundle.crt file in the workspace root and setup.sh will install it
# into the system trust store and set these variables automatically to:
# /etc/ssl/certs/ca-certificates.crt
# Only set the following manually for custom CA setups that cannot use the automatic
# configuration provided by setup.sh.
# REQUESTS_CA_BUNDLE=/custom/path/to/ca-bundle.crt
# SSL_CERT_FILE=/custom/path/to/ca-bundle.crt
# CURL_CA_BUNDLE=/custom/path/to/ca-bundle.crt

# Git SSL verification override (default: false)
# Only set to true if behind a MITM proxy and you cannot provide a CA bundle.
# Prefer placing a ca-bundle.crt in the workspace root instead.
# ALLOW_GIT_SSL_DISABLE=false
88 changes: 88 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ If you need to test with a LibreNMS instance on a private network (local lab, co
- **GitHub CLI**: Automatically configured for easy PR submission
- **Logs**: Use `netbox-logs` to debug issues in real-time


### 📡 LibreNMS Server Configuration

You need a LibreNMS instance to use this plugin. Configure your LibreNMS server(s) in `plugin-config.py`:

1. Copy the example config:

```bash
cp .devcontainer/config/plugin-config.py.example .devcontainer/config/plugin-config.py
```

2. Edit it with your LibreNMS server URL(s) and API token(s)
3. Restart NetBox: `netbox-restart`

## Out-of-the-box defaults

Below are the dev container defaults. The field name to change these defaults is listed below each line.
Expand Down Expand Up @@ -139,6 +153,80 @@ You might experience issues with database schemas and migrations when changing N
- Database: `DB_HOST`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`
- Redis: `REDIS_HOST`, `REDIS_PASSWORD`
- Superuser: `SUPERUSER_NAME`, `SUPERUSER_EMAIL`, `SUPERUSER_PASSWORD`, `SKIP_SUPERUSER`
- Proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, `REQUESTS_CA_BUNDLE`, `SSL_CERT_FILE`, `CURL_CA_BUNDLE`

### 🌐 Proxy Configuration (MITM Proxies)

If you're behind a corporate proxy or MITM proxy (like Zscaler, BlueCoat, etc.), you need to configure the proxy at two levels: the Docker client (for building) and the container runtime (for package installation inside the container).

**Step 1: Configure Docker client proxy** (`~/.docker/config.json`)

This is **required** so that `apt-get`, `curl`, etc. work during the container image build (e.g., when installing devcontainer features like `git` and `github-cli`).

Create or edit `~/.docker/config.json`:

```json
{
"proxies": {
"default": {
"httpProxy": "http://proxy.example.com:8080",
"httpsProxy": "http://proxy.example.com:8080",
"noProxy": "localhost,127.0.0.1,postgres,redis"
}
}
}
```

Docker automatically injects these as environment variables into every `RUN` instruction during `docker build`. No VS Code restart is needed — this takes effect immediately.

> **Docker Desktop users:** You can configure the same settings via Docker Desktop Settings → Resources → Proxies, which writes this file for you.

**Step 2: Create `.devcontainer/.env`** (for container runtime)

```bash
cp .devcontainer/.env.example .devcontainer/.env
```

Add your proxy settings to `.devcontainer/.env`:

```bash
# Proxy Configuration
HTTP_PROXY=http://proxy.example.com:8080
HTTPS_PROXY=http://proxy.example.com:8080
NO_PROXY=localhost,127.0.0.1,postgres,redis
```

> **Note:** You do **not** need to set `REQUESTS_CA_BUNDLE`, `SSL_CERT_FILE`, or `CURL_CA_BUNDLE` manually. When a `ca-bundle.crt` file is present in the workspace root, `setup.sh` automatically installs it into the system trust store and sets these variables to `/etc/ssl/certs/ca-certificates.crt`.

**Step 3: Add your CA certificate** (optional, only if your proxy intercepts TLS):
- Export your proxy's CA certificate (usually available from your IT department or browser)
- Save it as `ca-bundle.crt` in the root of your workspace
- `setup.sh` will automatically install it and configure CA bundle environment variables

**Step 4: Rebuild the container**:
- VS Code: Ctrl+Shift+P → "Dev Containers: Rebuild Container"

**What gets configured:**
- `~/.docker/config.json` → proxy for Docker build steps (devcontainer features, apt in Dockerfile)
- `.devcontainer/.env` → proxy for running containers (apt, pip, curl at runtime)
- `setup.sh` auto-configures apt proxy and git SSL settings inside the container

**Important Notes:**
- The `.env` file is ignored by git, so your proxy credentials stay private
- `~/.docker/config.json` is a per-user file outside the repo
- Add internal service names to `NO_PROXY` to avoid routing internal Docker traffic through the proxy
- **Proxy authentication:** Embedding credentials directly in the proxy URL (e.g., `http://username:password@proxy.example.com:8080`) is insecure — credentials can be visible in process listings, environment dumps, `docker inspect` output, and logs. Prefer safer alternatives such as Docker's `config.json` with `credsStore` or a secret manager for storing proxy credentials securely.

**Common Issues:**

*"Could not connect to archive.ubuntu.com" during build*
- → `~/.docker/config.json` is missing or has wrong proxy URL

*"SSL certificate errors" during build*
- → Your proxy uses a MITM certificate. Export it and add it to the system trust store, or set `SSL_CERT_FILE` in `.env`

*Container builds but apt/pip fails inside*
- → .env file is missing or has wrong proxy settings. Check .env matches Docker Desktop settings


After any `.env` change, rebuild the dev container to apply environment updates.
Expand Down
6 changes: 3 additions & 3 deletions .devcontainer/config/plugin-config.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ Default plugin configuration for the NetBox LibreNMS Plugin in the dev container
- Copy this file to .devcontainer/plugin-config.py
- Edit values as needed.

- Add config for all other plugins here if any.
- Add config for all other plugins here if any.
"""

# Ensure our plugin is enabled in dev (the loader sets this as a default too)
PLUGINS = [
"netbox_librenms_plugin",
]

# Sample configuration with three example servers
# Sample configuration with example servers
PLUGINS_CONFIG = {
"netbox_librenms_plugin": {
"servers": {
"production": {
"display_name": "Production LibreNMS",
"librenms_url": "https://librenms-prod.exampel.com",
"librenms_url": "https://librenms-prod.example.com",
"api_token": "your-prod-token",
"cache_timeout": 300,
"verify_ssl": True,
Expand Down
19 changes: 13 additions & 6 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,19 @@
"SUPERUSER_NAME": "${localEnv:SUPERUSER_NAME:admin}",
"SUPERUSER_EMAIL": "${localEnv:SUPERUSER_EMAIL:admin@example.com}",
"SUPERUSER_PASSWORD": "${localEnv:SUPERUSER_PASSWORD:admin}",
"SKIP_SUPERUSER": "${localEnv:SKIP_SUPERUSER:false}"
},
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
"SKIP_SUPERUSER": "${localEnv:SKIP_SUPERUSER:false}",
"HTTP_PROXY": "${localEnv:HTTP_PROXY}",
"HTTPS_PROXY": "${localEnv:HTTPS_PROXY}",
"http_proxy": "${localEnv:HTTP_PROXY}",
"https_proxy": "${localEnv:HTTPS_PROXY}",
"NO_PROXY": "${localEnv:NO_PROXY}",
"no_proxy": "${localEnv:NO_PROXY}",
"REQUESTS_CA_BUNDLE": "${localEnv:REQUESTS_CA_BUNDLE}",
"SSL_CERT_FILE": "${localEnv:SSL_CERT_FILE}",
"CURL_CA_BUNDLE": "${localEnv:CURL_CA_BUNDLE}",
Comment on lines +44 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Python requests library REQUESTS_CA_BUNDLE empty string environment variable SSL error

💡 Result:

If REQUESTS_CA_BUNDLE is set, requests treats it as the path to a CA bundle file (or directory). If you set it to the empty string (""), you’re effectively telling requests to verify TLS using “a CA bundle at path ''”, which is not a valid file path—so you typically get errors like:

  • OSError: Could not find a suitable TLS CA certificate bundle, invalid path: ...
  • or an SSLError cascading from the failed CA loading. [1]

Fix

  1. Unset the variable (recommended)

    • macOS/Linux:
      unset REQUESTS_CA_BUNDLE
      unset CURL_CA_BUNDLE
    • Windows (PowerShell):
      Remove-Item Env:REQUESTS_CA_BUNDLE
      Remove-Item Env:CURL_CA_BUNDLE

    Unsetting is a common resolution when the variable was set incorrectly. [1]

  2. Or set it to a real CA bundle path (e.g., your corporate root bundle, or a certifi-derived bundle you’ve extended): REQUESTS_CA_BUNDLE=/path/to/bundle.pem. [2][3]

Notes

  • requests supports both REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE for overriding the trusted CA bundle; CURL_CA_BUNDLE is used as a fallback if REQUESTS_CA_BUNDLE isn’t set. [2][4]
  • Some guides suggest using an empty string to “disable verification”, but that’s not a safe or reliable approach with requests; if you truly must bypass verification, do it explicitly per call (verify=False) and understand the security risk. [5]

Sources:
[1] Stack Overflow: fix by unsetting REQUESTS_CA_BUNDLE when it causes “invalid path” TLS bundle errors. (stackoverflow.com)
[2] Conda docs: REQUESTS_CA_BUNDLE is the setting requests uses for non-standard certs. (docs.conda.io)
[3] hvac docs (quoting requests behavior): REQUESTS_CA_BUNDLE should point to a CA bundle file. (python-hvac.org)
[4] “SSL Yes Verify” docs: mentions REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE override. (ssl-yes-verify.dev)
[5] Stack Overflow discussion includes advice around empty env vars and fallback behavior; use with caution. (stackoverflow.com)

Citations:


🌐 Web query:

devcontainer.json localEnv variable substitution default value

💡 Result:

In devcontainer.json, you can provide a default for a missing host env var by adding a 2nd : segment:

{
  "build": {
    "args": {
      "REMOTE_UID": "${localEnv:REMOTE_UID:1000}"
    }
  },
  "containerEnv": {
    "IMAGE_TAG": "${localEnv:IMAGE_TAG:latest}"
  }
}
  • ${localEnv:VARIABLE_NAME} resolves to the host env var value; if unset it’s blank.
  • ${localEnv:VARIABLE_NAME:default_value} uses default_value when the host env var is not set.
  • Same pattern also applies to ${containerEnv:VARIABLE_NAME:default_value}. [1]

Sources: Dev Container spec “Variables in devcontainer.json”. [1]

[1] (containers.dev)

Citations:


🌐 Web query:

Python requests library verify SSL_CERT_FILE empty string handling

💡 Result:

  • requests does not look at SSL_CERT_FILE (the OpenSSL/Python-stdlib env var). It only supports REQUESTS_CA_BUNDLE, with CURL_CA_BUNDLE as a fallback. So if you set SSL_CERT_FILE="" (empty string), it generally has no effect on requests unless some other layer in your environment is influencing trust configuration. [1][2]
  • What SSL_CERT_FILE is: it’s the OpenSSL default environment key name for overriding the CA file used by OpenSSL/Python’s ssl defaults (i.e., things using SSLContext.set_default_verify_paths() / ssl.get_default_verify_paths()), not something Requests promises to honor. [3][4]
  • Empty-string env var behavior in Requests (important regression fix): historically, setting CURL_CA_BUNDLE="" could disable verification in Requests; this was fixed in Requests 2.28.0 (so an empty string should no longer “turn off” verification). [5]
  • If you pass an empty string directly to Requests (e.g., requests.get(url, verify="")), Requests treats it as a CA-bundle path, and TLS setup will typically fail because "" isn’t a valid CA file path (expect an SSLError / underlying file/path error). [1]

Sources:
[1] Requests docs (SSL verification + supported env vars) (docs.python-requests.org)
[2] Requests issue requesting SSL_CERT_FILE support (shows it isn’t supported) (github.com)
[3] Python ssl.get_default_verify_paths() docs (mentions OpenSSL env keys like SSL_CERT_FILE) (docs.python.org)
[4] OpenSSL docs (X509_get_default_cert_file_env / env var mechanism) (docs.openssl.org)
[5] StackOverflow answer/comment citing Requests 2.28.0 fix for CURL_CA_BUNDLE="" disabling verification (stackoverflow.com)

Citations:


Empty REQUESTS_CA_BUNDLE / CURL_CA_BUNDLE will break HTTPS.

${localEnv:VAR} (no default) evaluates to an empty string when the host variable is not set. Passing REQUESTS_CA_BUNDLE="" or CURL_CA_BUNDLE="" into the container causes the Python requests library to treat it as an explicit (invalid) CA bundle path, raising SSL errors like "Could not find a suitable TLS CA certificate bundle, invalid path" for all HTTPS calls.

Note: SSL_CERT_FILE is not used by the requests library (it only honors REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE); only guard the latter two.

The safeguard using : as a default (e.g., ${localEnv:REQUESTS_CA_BUNDLE:}) still results in an empty string and does not prevent this issue. Instead, conditionally set these variables inside setup.sh only when the host variables are non-empty, or omit them from containerEnv entirely if not strictly required.

Conditional approach (setup.sh)
if [ -n "$REQUESTS_CA_BUNDLE" ]; then
  export REQUESTS_CA_BUNDLE
fi
if [ -n "$CURL_CA_BUNDLE" ]; then
  export CURL_CA_BUNDLE
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.devcontainer/devcontainer.json around lines 44 - 46, The devcontainer
currently unconditionally injects REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE using
${localEnv:...}, which can pass empty strings and break Python HTTPS requests;
instead, remove these two from the containerEnv and implement a conditional
export in setup.sh (or environment bootstrap) that only exports
REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE when the corresponding host vars are
non-empty (check with -n or equivalent), leaving SSL_CERT_FILE untouched since
requests ignores it; this ensures REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE are only
set inside the container when valid values exist.

"ALLOW_GIT_SSL_DISABLE": "${localEnv:ALLOW_GIT_SSL_DISABLE:false}"
},
"features": {},
"customizations": {
"vscode": {
"extensions": [
Expand Down Expand Up @@ -72,4 +79,4 @@
"postCreateCommand": "bash .devcontainer/scripts/setup.sh",
"postAttachCommand": "bash .devcontainer/scripts/welcome.sh",
"remoteUser": "root"
}
}
11 changes: 11 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ services:
SUPERUSER_EMAIL: ${SUPERUSER_EMAIL:-admin@example.com}
SUPERUSER_PASSWORD: ${SUPERUSER_PASSWORD:-admin}
SKIP_SUPERUSER: ${SKIP_SUPERUSER:-false}
# Proxy settings (optional)
HTTP_PROXY: ${HTTP_PROXY:-}
HTTPS_PROXY: ${HTTPS_PROXY:-}
http_proxy: ${HTTP_PROXY:-}
https_proxy: ${HTTPS_PROXY:-}
NO_PROXY: ${NO_PROXY:-}
no_proxy: ${NO_PROXY:-}
REQUESTS_CA_BUNDLE: ${REQUESTS_CA_BUNDLE:-}
SSL_CERT_FILE: ${SSL_CERT_FILE:-}
CURL_CA_BUNDLE: ${CURL_CA_BUNDLE:-}
Comment on lines +32 to +34

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Empty-string defaults for CA bundle env vars will silently break or disable TLS verification.

Setting REQUESTS_CA_BUNDLE to an empty string "effectively disables SSL verification for all requests made using the requests library." Additionally, REQUESTS_CA_BUNDLE= with session.verify = True raises an SSLError (certificate verify failed against the empty path). The behavior varies by requests version — in either case it's wrong.

The ${VAR:-} syntax unconditionally exports these variables as "" into the container when the host hasn't set them. This directly contradicts the guidance in .env.example which says "Normally you SHOULD NOT set REQUESTS_CA_BUNDLE, SSL_CERT_FILE, or CURL_CA_BUNDLE here".

Every developer without a custom CA bundle will have these exported as empty strings, breaking TLS for all requests calls inside the container.

🛠️ Proposed fix — omit the variables when not explicitly set

Use bare variable references (no default): Docker Compose will inherit them from the host if set, and leave them absent from the container environment if not set on the host.

-      REQUESTS_CA_BUNDLE: ${REQUESTS_CA_BUNDLE:-}
-      SSL_CERT_FILE: ${SSL_CERT_FILE:-}
-      CURL_CA_BUNDLE: ${CURL_CA_BUNDLE:-}
+      REQUESTS_CA_BUNDLE: ${REQUESTS_CA_BUNDLE}
+      SSL_CERT_FILE: ${SSL_CERT_FILE}
+      CURL_CA_BUNDLE: ${CURL_CA_BUNDLE}

With this change, Docker Compose will omit the variable from the container environment when it is unset on the host, preserving requests' default certifi CA resolution.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
REQUESTS_CA_BUNDLE: ${REQUESTS_CA_BUNDLE:-}
SSL_CERT_FILE: ${SSL_CERT_FILE:-}
CURL_CA_BUNDLE: ${CURL_CA_BUNDLE:-}
REQUESTS_CA_BUNDLE: ${REQUESTS_CA_BUNDLE}
SSL_CERT_FILE: ${SSL_CERT_FILE}
CURL_CA_BUNDLE: ${CURL_CA_BUNDLE}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.devcontainer/docker-compose.yml around lines 32 - 34, The compose file
currently exports REQUESTS_CA_BUNDLE, SSL_CERT_FILE, and CURL_CA_BUNDLE with
empty-string defaults using ${VAR:-}, which forces empty values into the
container and breaks TLS; change those environment entries to use bare variable
references (e.g., ${REQUESTS_CA_BUNDLE}, ${SSL_CERT_FILE}, ${CURL_CA_BUNDLE}) so
Docker Compose will inherit them from the host if set and omit them entirely if
unset, preserving normal requests/certifi behavior; update the lines referencing
REQUESTS_CA_BUNDLE, SSL_CERT_FILE, and CURL_CA_BUNDLE in
.devcontainer/docker-compose.yml accordingly.

ALLOW_GIT_SSL_DISABLE: ${ALLOW_GIT_SSL_DISABLE:-false}
depends_on:
postgres:
condition: service_healthy
Expand Down
5 changes: 4 additions & 1 deletion .devcontainer/scripts/load-aliases.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ alias rq-jobs="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate &&
alias rq-failed="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \"from django_rq import get_failed_queue; q = get_failed_queue(); print(f'Failed jobs: {len(q)}'); [print(f' {job.id[:8]}: {job.func_name}') for job in q.jobs[:10]]\""
alias rq-recent="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \"from core.models import Job; jobs = Job.objects.all().order_by('-created')[:10]; [print(f'{j.id}: {j.name[:50]} - {getattr(j.status, \\\"value\\\", j.status)} ({j.user})') for j in jobs]\""

echo "✅ Aliases loaded! Try: rq-status, rq-stats, rq-recent"
# Help
alias dev-help='echo "🎯 NetBox LibreNMS Plugin Development Commands:"; echo ""; echo "📊 NetBox Server Management:"; echo " netbox-run-bg : Start NetBox in background"; echo " netbox-run : Start NetBox in foreground (for debugging)"; echo " netbox-stop : Stop NetBox and RQ worker"; echo " netbox-restart : Restart NetBox and RQ worker"; echo " netbox-reload : Reinstall plugin and restart NetBox"; echo " netbox-status : Check if NetBox and RQ worker are running"; echo " netbox-logs : View NetBox server logs"; echo ""; echo "⚙️ Background Jobs (RQ Worker):"; echo " rq-status : Check if RQ worker is running"; echo " rq-logs : View RQ worker logs"; echo " rq-stats : Show RQ queue statistics"; echo " rq-jobs : List jobs in default queue"; echo " rq-failed : List failed jobs"; echo " rq-recent : Show recent NetBox jobs"; echo ""; echo "🛠️ Development Tools:"; echo " netbox-shell : Open NetBox Django shell"; echo " netbox-test : Run plugin tests"; echo " netbox-manage : Run Django management commands"; echo " plugin-install : Reinstall plugin in development mode"; echo ""; echo "🧹 Code Quality:"; echo " ruff-check : Check code with Ruff"; echo " ruff-format : Format code with Ruff"; echo " ruff-fix : Auto-fix code issues with Ruff"; echo ""; echo "🔎 Diagnostics:"; echo " diagnose : Run startup diagnostics"; echo " dev-help : Show this help message"; echo ""; echo "📖 NetBox available at: http://localhost:8000 (admin/admin)"; echo ""'

echo "✅ Aliases loaded! Try: rq-status, rq-stats, rq-recent, dev-help"
Loading