tenable-exporter
A Prometheus exporter for Tenable.io built with pyTenable.
Exports vulnerability, asset, and compliance metrics so you can alert on them in Grafana or any Prometheus-compatible stack.
PyPI:
pip install tenable-exporter· Image:ghcr.io/polarpoint-io/tenable-exporter:latest· Chart:ghcr.io/polarpoint-io/charts/tenable-exporter· Repo: https://github.com/polarpoint-io/tenable-exporter
Metrics
Vulnerabilities
| Metric | Labels | Description |
|---|---|---|
tenable_vulnerabilities_total |
severity |
Total vulnerabilities by severity |
tenable_vulnerabilities_by_subscription_total |
provider, subscription_id, severity |
Vulns per cloud provider and subscription |
tenable_vulnerabilities_by_region_total |
provider, subscription_id, region, severity |
Vulns per subscription and region |
tenable_vulnerabilities_by_resource_group_total |
provider, subscription_id, resource_group, severity |
Vulns per Azure resource group |
tenable_vulnerabilities_by_resource_total |
provider, subscription_id, resource_id, severity |
Vulns per individual cloud resource |
tenable_vulnerabilities_by_plugin_family_total |
plugin_family, severity |
Vulns by Tenable plugin family and severity |
tenable_vulnerabilities_by_subscription_plugin_total |
provider, subscription_id, region, plugin_family, severity |
Cross-dimension vuln count |
tenable_vulnerabilities_by_state_total |
provider, subscription_id, state, severity |
Vulns by lifecycle state (OPEN, REOPENED, FIXED) — use FIXED to track remediation velocity |
tenable_vulnerabilities_by_exploit_risk_total |
cve_category, severity |
Vulns by Tenable CVE category: cisa known exploitable, ransomware, emerging threats, persistently exploited, top 50 vpr, recent active exploitation, in the news |
tenable_vulnerabilities_by_vpr_band_total |
provider, subscription_id, vpr_band |
Vulns by VPR (Vulnerability Priority Rating) band: critical (9–10), high (7–8.9), medium (4–6.9), low (<4) |
Assets
| Metric | Labels | Description |
|---|---|---|
tenable_assets_by_subscription_total |
provider, subscription_id |
Asset count per cloud provider and subscription |
tenable_assets_by_region_total |
provider, subscription_id, region |
Asset count per subscription and region |
tenable_assets_by_resource_group_total |
provider, subscription_id, resource_group |
Asset count per Azure resource group |
tenable_assets_by_resource_type_total |
provider, subscription_id, region, resource_type |
Asset count by resource type (e.g. t3.medium, Standard_D2s_v3) |
tenable_assets_by_source_total |
source |
Assets by Tenable discovery source (AWS, AZURE, GCP, NESSUS, WAS, …) |
tenable_assets_by_tag_total |
tag_category, tag_value |
Assets by Tenable tag or cloud-native resource tag. Use tag_category=asset_type with values like database, container_registry, acr, aks, rds to track specific resource classes |
Compliance
| Metric | Labels | Description |
|---|---|---|
tenable_compliance_findings_total |
provider, subscription_id, audit_name, result |
CIS/DISA STIG compliance findings by audit and result (PASSED, FAILED, WARNING, SKIPPED) |
tenable_compliance_findings_by_region_total |
provider, subscription_id, region, result |
Compliance findings per region |
tenable_compliance_findings_by_resource_group_total |
provider, subscription_id, resource_group, result |
Compliance findings per Azure resource group |
Scans & System
| Metric | Labels | Description |
|---|---|---|
tenable_scans_total |
— | Total number of scans |
tenable_scans_by_status_total |
status |
Scans by status (running, completed, aborted, …) |
tenable_plugin_set_updated_timestamp |
— | Unix timestamp of the last plugin set update |
Exporter diagnostics
| Metric | Labels | Description |
|---|---|---|
tenable_exporter_cloud_context_total |
entity, provider, dimension, status |
Count of assets or vulnerabilities with known vs unknown subscription_id, region, or resource_group labels. Use to track Tenable metadata completeness. |
tenable_exporter_vulnerability_asset_lookup_misses_total |
— | Vulnerabilities whose asset UUID was missing from the asset export index |
tenable_exporter_vulnerability_vpr_unknown_total |
— | Vulnerabilities with no VPR score from Tenable (expected for info findings) |
tenable_exporter_compliance_findings_collected_total |
— | Compliance findings aggregated in the last scrape (0 if none or export failed) |
tenable_exporter_compliance_collection_error |
— | 1 if the last compliance export raised an error, otherwise 0 |
Label values by cloud provider
| Label | AWS | Azure | GCP |
|---|---|---|---|
provider |
aws |
azure |
gcp |
subscription_id |
Account ID | Subscription UUID | Project ID |
region |
e.g. us-east-1 |
Azure location | GCP zone |
resource_group |
unknown |
Resource group name | unknown |
resource_id |
EC2 instance ID | Azure resource / VM ID | GCP instance ID |
resource_type |
EC2 instance type | VM size | Machine type |
Targeting databases, ACRs, and other resource types
Tenable doesn't have a dedicated field for resource class (database, container registry, etc.). The recommended approaches:
Option 1 — Tenable tags (most reliable): In the Tenable UI, create a tag category AssetType and assign values like database, acr, aks, rds, cosmos_db to assets. These appear immediately in tenable_assets_by_tag_total{tag_category="assettype"}.
Option 2 — Cloud-native resource tags: Enable include_resource_tags=True (already on). Any AWS tag, Azure tag, or GCP label on the resource appears as a tenable_assets_by_tag_total time series. For example, an Azure ACR tagged {"resource_type": "container_registry"} surfaces as tag_category="resource_type", tag_value="container_registry".
Option 3 — Plugin family: Database vulnerabilities land in the Databases plugin family — visible in tenable_vulnerabilities_by_plugin_family_total{plugin_family="databases"}.
Option 4 — Discovery source filter: Scope the exporter to specific sources via TENABLE_FILTER_PROVIDERS. For ACR-specific scanning, Tenable uses the AZURE source; container-specific findings come from the Containers plugin family.
Grafana dashboard
Import dashboards/tenable-exporter-overview.json for a pre-built overview including:
- Severity stats, subscription/region breakdowns, and VPR band (excluding
unknownfrom the pie chart) - Chained Provider → Subscription → Region template variables
- Exporter diagnostics row (
tenable_exporter_cloud_context_total, asset lookup misses, VPR unknown count)
Quick start
pip
pip install tenable-exporter
export TENABLE_ACCESS_KEY=your_access_key
export TENABLE_SECRET_KEY=your_secret_key
tenable-exporter
Metrics will be available at http://localhost:9190/metrics.
Docker
docker run -p 9190:9190 \
-e TENABLE_ACCESS_KEY=your_access_key \
-e TENABLE_SECRET_KEY=your_secret_key \
ghcr.io/polarpoint-io/tenable-exporter:latest
Docker Compose
cp .env.example .env
# Fill in your Tenable credentials in .env
docker compose up -d
Helm
helm registry login ghcr.io --username <github-user> --password <github-pat>
helm install tenable-exporter oci://ghcr.io/polarpoint-io/charts/tenable-exporter \
--namespace monitoring --create-namespace \
--set tenable.accessKey=<TENABLE_ACCESS_KEY> \
--set tenable.secretKey=<TENABLE_SECRET_KEY>
Or reference an existing Kubernetes Secret:
kubectl create secret generic tenable-credentials \
--from-literal=access-key=<TENABLE_ACCESS_KEY> \
--from-literal=secret-key=<TENABLE_SECRET_KEY> \
-n monitoring
helm install tenable-exporter oci://ghcr.io/polarpoint-io/charts/tenable-exporter \
--namespace monitoring \
--set tenable.existingSecret=tenable-credentials
Key chart values:
| Value | Default | Description |
|---|---|---|
tenable.accessKey |
"" |
Tenable.io access key |
tenable.secretKey |
"" |
Tenable.io secret key |
tenable.existingSecret |
"" |
Name of an existing Secret with access-key and secret-key |
tenable.scrapeInterval |
300 |
Seconds between Tenable API scrapes |
tenable.filterProviders |
"" |
Comma-separated providers to include (aws,azure,gcp) |
tenable.filterSubscriptions |
"" |
Comma-separated subscription / account / project IDs |
image.tag |
chart appVersion |
Override the image tag |
resources.requests.memory |
64Mi |
Memory request |
service.type |
ClusterIP |
Kubernetes service type |
Full values reference: charts/tenable-exporter/values.yaml
Configuration
| Environment variable | Default | Description |
|---|---|---|
TENABLE_ACCESS_KEY |
required | Tenable.io API access key |
TENABLE_SECRET_KEY |
required | Tenable.io API secret key |
EXPORTER_PORT |
9190 |
Port to expose metrics on |
SCRAPE_INTERVAL |
300 |
Seconds between Tenable API scrapes |
TENABLE_FILTER_PROVIDERS |
(all) | Comma-separated providers to include: aws, azure, gcp |
TENABLE_FILTER_SUBSCRIPTIONS |
(all) | Comma-separated subscription IDs to include (AWS account IDs, Azure subscription UUIDs, or GCP project IDs) |
TENABLE_COMPLIANCE_ENABLED |
true |
Set to false to skip compliance export collection |
TENABLE_COMPLIANCE_EXPORT_TIMEOUT |
(none) | Optional compliance export queue timeout in seconds |
Docker image tags
| Tag | When pushed |
|---|---|
latest |
Every merge to main |
sha-<short> |
Every merge to main |
1.2.3 / 1.2 |
On a semantic-release version bump |
Required GitHub secrets
Add these at GitHub repo → Settings → Secrets and variables → Actions:
| Secret | Description |
|---|---|
POL_GH_TOKEN |
Personal access token with repo + write:packages scope |
PYPI_TOKEN |
PyPI API token for the tenable-exporter project |
Development
git clone https://github.com/polarpoint-io/tenable-exporter.git
cd tenable-exporter
pip install -e ".[dev]"
export TENABLE_ACCESS_KEY=...
export TENABLE_SECRET_KEY=...
tenable-exporter
License
MIT — see LICENSE.
Metadata
Release files for tenable-exporter 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tenable_exporter-1.2.0.tar.gz | 22.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tenable_exporter-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.8 kB
Release files / tenable_exporter-1.2.0.tar.gz
| Download URL | tenable_exporter-1.2.0.tar.gz |
|---|---|
| Size | 22.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f1346fd60fec7ba2e97b7b5931203ff3b0b88e0738ad347e6a891ef53fa1fa6a
|
|
BLAKE2b-256 checksum How to use checksums |
f9444a56d5fbc3212de93fc365760385a09c06068f51ce093ed941207ccce7a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / tenable_exporter-1.2.0-py3-none-any.whl
| Download URL | tenable_exporter-1.2.0-py3-none-any.whl |
|---|---|
| Size | 16.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
302cf8a3e6462837a48729d35f309b6c6ba69d8414eb62cc168e94429bfdba36
|
|
BLAKE2b-256 checksum How to use checksums |
1f792dd2c1fb4d8b3234ce6b3ccbc71acab5bb94ea6efbde706f9141101539ea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|