Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @jajeffries @leoparente @ltucker @mfiedorowicz @MicahParks @marc-barry
* @jajeffries @leoparente @ltucker @mfiedorowicz @MicahParks @marc-barry @davidlanouette
109 changes: 109 additions & 0 deletions .github/workflows/security.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Security scan

on:
push:
branches:
- "!release"
pull_request:
schedule:
- cron: '0 6 * * *' # Daily at 06:00 UTC, to catch newly published advisories
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: read
security-events: write

jobs:
trivy:
name: Trivy dependency scan
runs-on: ubuntu-latest
timeout-minutes: 15
env:
TRIVY_DISABLE_VEX_NOTICE: "true"
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

# pyproject.toml declares open ">=" ranges, which Trivy cannot evaluate
# on their own. Resolve them to concrete installed versions and write a
# pinned requirements.txt (not committed) so the scan reflects what a
# consumer actually gets today. This is the library equivalent of the
# container scan orb-agent runs against its built image.
- name: Resolve installed dependency versions
run: |
python -m pip install --upgrade pip
pip install .
pip freeze --exclude-editable | grep -viE '^netboxlabs[._-]diode' > requirements.txt
echo "Resolved dependencies:"; cat requirements.txt

# exit-code 0 keeps this non-blocking: findings surface as GitHub
# code-scanning alerts rather than failing the build.
- name: Scan resolved dependencies and tree
uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0
with:
scan-type: fs
scan-ref: .
format: json
output: trivy-output.json
scanners: vuln,secret
severity: CRITICAL,HIGH,MEDIUM,LOW
ignore-unfixed: true
exit-code: "0"

- name: Build scan summary
if: "!cancelled()"
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const fs = require('fs');
const data = JSON.parse(fs.readFileSync('trivy-output.json', 'utf8'));
const vulns = (data.Results || []).flatMap(r =>
(r.Vulnerabilities || []).map(v => ({ ...v, target: r.Target }))
);
const secrets = (data.Results || []).flatMap(r =>
(r.Secrets || []).map(s => ({ ...s, target: r.Target }))
);

const SEVERITY_LABEL = {
CRITICAL: '🔴 **CRITICAL**',
HIGH: '🟠 **HIGH**',
MEDIUM: '🟡 MEDIUM',
LOW: '⚪ LOW'
};

let summary = `### Trivy dependency scan\n\n`;
if (vulns.length === 0) {
summary += '_No known-vulnerable dependencies found._\n';
} else {
summary += `| Package | Vulnerability | Severity | Installed | Fixed | Title |\n`;
summary += `|---|---|---|---|---|---|\n`;
for (const v of vulns) {
const title = (v.Title || '').replace(/\|/g, '\\|').substring(0, 80);
const id = v.PrimaryURL ? `[${v.VulnerabilityID}](${v.PrimaryURL})` : v.VulnerabilityID;
summary += `| ${v.PkgName} | ${id} | ${SEVERITY_LABEL[v.Severity] || v.Severity} | ${v.InstalledVersion} | ${v.FixedVersion || 'N/A'} | ${title} |\n`;
}
}
if (secrets.length > 0) {
summary += `\n**Potential secrets:** ${secrets.length} (see the Security tab for details).\n`;
}

fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, summary);

- name: Convert scan results to SARIF
if: "!cancelled()"
run: trivy convert --format sarif --output trivy-results.sarif trivy-output.json

- name: Upload SARIF to GitHub Code Scanning
if: "!cancelled()"
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with:
sarif_file: trivy-results.sarif
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pip install netboxlabs-diode-sdk
* `DIODE_SENTRY_DSN` - Optional Sentry DSN for error reporting
* `DIODE_CLIENT_ID` - Client ID for OAuth2 authentication
* `DIODE_CLIENT_SECRET` - Client Secret for OAuth2 authentication
* `DIODE_MAX_AUTH_RETRIES` - Maximum attempts for OAuth2 token fetch and gRPC re-authentication on `Unauthenticated` (default: `3`). Token fetch retries with exponential backoff on `429`, `500`, `502`, and `503`, honouring `Retry-After` when present on `429`/`503`.
* `DIODE_CERT_FILE` - Path to custom certificate file for TLS connections
* `DIODE_SKIP_TLS_VERIFY` - Skip TLS verification (default: `false`)
* `DIODE_DRY_RUN_OUTPUT_DIR` - Directory where `DiodeDryRunClient` will write JSON files
Expand Down Expand Up @@ -82,6 +83,8 @@ if __name__ == "__main__":

```

See [`docs/examples/`](./docs/examples) for per-entity examples (one file per supported NetBox object type).

### Using Metadata

Entities support attaching custom metadata as key-value pairs. Metadata can be used to store additional context, tracking information, or custom attributes that don't fit into the standard NetBox fields.
Expand Down Expand Up @@ -501,6 +504,10 @@ These attributes are added alongside standard OTLP resource attributes (`service
* ASN
* ASN Range
* Aggregate
* Cable
* Cable Bundle
* Cable Path
* Cable Termination
* Circuit
* Circuit Group
* Circuit Group Assignment
Expand All @@ -515,8 +522,12 @@ These attributes are added alongside standard OTLP resource attributes (`service
* Contact Assignment
* Contact Group
* Contact Role
* Custom Field
* Custom Field Choice Set
* Custom Link
* Device
* Device Bay
* Device Config
* Device Role
* Device Type
* FHRP Group
Expand All @@ -532,6 +543,7 @@ These attributes are added alongside standard OTLP resource attributes (`service
* Interface
* Inventory Item
* Inventory Item Role
* Journal Entry
* L2VPN
* L2VPN Termination
* Location
Expand All @@ -540,6 +552,9 @@ These attributes are added alongside standard OTLP resource attributes (`service
* Module
* Module Bay
* Module Type
* Module Type Profile
* Owner
* Owner Group
* Platform
* Power Feed
* Power Outlet
Expand All @@ -551,12 +566,15 @@ These attributes are added alongside standard OTLP resource attributes (`service
* Provider Network
* RIR
* Rack
* Rack Group
* Rack Reservation
* Rack Role
* Rack Type
* Rear Port
* Region
* Role
* Route Target
* Script Module
* Service
* Site
* Site Group
Expand All @@ -579,6 +597,7 @@ These attributes are added alongside standard OTLP resource attributes (`service
* Virtual Device Context
* Virtual Disk
* Virtual Machine
* Virtual Machine Type
* Wireless Lan
* Wireless Lan Group
* Wireless Link
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Diode Python SDK - Entity Examples

Source: NetBox v4.6.0
Generated: 2026-05-14 20:30:15Z
Generated: 2026-07-03 00:59:24Z

## Prerequisites

Expand Down
3 changes: 0 additions & 3 deletions docs/entities.md

This file was deleted.

Loading
Loading