Security Multi-cloud

Set Up Tenable.io Vulnerability Scanning with Nessus Agents and Cloud Connectors

A mid-size SaaS company fails a customer security review on a single line: “you cannot produce an authenticated vulnerability scan of your production estate on demand.” Their old setup was a quarterly unauthenticated network scan from one appliance that could not even see half the cloud accounts, let alone log into a host. The mandate from the new CISO is concrete: every Linux and Windows workload across three AWS accounts, two Azure subscriptions, and one GCP project must be under continuous, authenticated scanning within a sprint, with findings risk-scored, deduplicated against cloud asset inventory, and auto-ticketed to the owning team. This guide builds exactly that with Tenable Vulnerability Management (still universally called Tenable.io) — agent-based authenticated scanning for the hosts you control, cloud connectors for the inventory and the ephemeral fleet you cannot put an agent on, and a prioritisation model that patches what is exploitable rather than what merely scores a high CVSS.

Tenable.io is a SaaS vulnerability management platform. You do not run its brain; you feed it from sensorsNessus scanners (network-reachable engines that scan targets over the wire), Nessus Agents (lightweight processes on each host that scan from the inside and upload results outbound), and cloud connectors (read-only API integrations that pull live asset inventory from AWS, Azure and GCP). Those three sensor types, plus the scan policies you point at them and the prioritisation and remediation workflow on top, are the whole system. This is an implementation guide, so the centrepiece is a copy-pasteable hands-on lab that stands up a trial container, links a real agent, builds an agent scan, and pulls VPR-sorted findings — but before the lab you will learn every moving part in enough depth to run this in production, not just pass the demo.

By the end you will stop guessing at coverage. You will know which sensor answers which question, why an agent scan needs no network credentials while a network scan needs a full credential vault, why VPR (Vulnerability Priority Rating) and CVSS disagree and which one to ticket on, and how a dynamic tag turns “every internet-facing prod host missing an agent” from a spreadsheet into a live, self-updating asset list that drives a scan, a report, and a ServiceNow queue on its own.

What problem this solves

Vulnerability management fails in three predictable ways, and Tenable.io’s architecture targets each. Coverage gaps: an unauthenticated network scan sees open ports and banners, not the patch level inside the host — it will call an SSH service “OpenSSH 8.x” and shrug, while a credentialed scan reads the actual package database and finds the eleven unpatched CVEs. Half your estate lives in cloud accounts a central appliance cannot even reach, and a third of it is ephemeral — autoscaled instances that boot and die inside a scan window. Prioritisation noise: a raw scan of a real estate returns tens of thousands of findings, most rated “Critical” by CVSS, and a team that tries to patch by CVSS burns weeks on a theoretical CVSS 10 with no known exploit while a CVSS 7 under active mass-exploitation sits open. No closed loop: findings that do not become owned, SLA-tracked tickets are findings nobody fixes; the scan report goes stale in a shared drive and the next audit finds the same CVEs.

What breaks without this: the failed customer review is the visible symptom, but the real cost is a production estate where nobody can answer “are we exposed to this CVE, on which hosts, and who owns the fix” in under a day. Ransomware and breach post-mortems almost always find the entry vulnerability was known and scored months earlier — it just never became a ticket with an owner and a clock.

Who hits this: any organisation with a mixed on-prem/multi-cloud estate under a compliance regime (SOC 2, PCI-DSS, ISO 27001, FedRAMP) that mandates authenticated scanning and demonstrable remediation SLAs. It bites hardest on teams with large autoscaled fleets (agents must self-enrol from the golden image or the instance is never scanned), teams running credentialed network scans against network gear and databases an agent cannot live on, and anyone whose “vulnerability program” is a quarterly PDF nobody actions.

To frame the field before the deep dive, here is every sensor type this guide covers, the question it answers, and where it fits:

Sensor What it is Answers Best for Cannot do
Nessus Agent Lightweight process on each host, scans from inside, uploads outbound “What is unpatched inside this host I control?” Servers, workstations, autoscaled VMs you own Scan devices you can’t install on (network gear, DBs, appliances)
Nessus scanner (network) Network-reachable engine scanning targets over the wire “What is exposed / unpatched on this reachable target?” Network devices, hypervisors, DBs, hosts without agents Read inside a host without credentials; reach isolated subnets it can’t route to
Cloud connector (AWS/Azure/GCP) Read-only API integration pulling asset inventory “What should exist, per the cloud provider’s truth?” Reconciling agents vs reality; tagging; ephemeral fleet awareness Scan for CVEs — it inventories, it does not assess
Tenable Nessus (scanner) linked to Tenable.io On-prem/cloud scanner engine you deploy and link “What can I reach that the cloud scanners can’t?” Internal subnets, air-gapped-ish segments, latency-sensitive scans Anything an agent already covers better (from-inside detail)

Learning objectives

By the end of this article you can:

Prerequisites & where this fits

You should be comfortable with cloud IAM (creating scoped read-only roles/service principals in at least one of AWS/Azure/GCP), basic Linux/Windows host administration (installing a package and a service), and reading JSON from a REST API with curl and jq. You do not need prior Tenable experience — this guide builds from the console up — but you should understand what a CVE and a CVSS score are.

You need:

This sits in the Cloud Security & Vulnerability Management track. It pairs with posture management — Roll Out Wiz CSPM Across a Multi-Account AWS Organization and Configure CrowdStrike Falcon Cloud Security (CSPM) on AWS find misconfigurations and exposure paths while Tenable supplies the authenticated in-host CVE detail; you correlate the two for real attack-path priority. It feeds the remediation loop in Automate ServiceNow Change Requests from CI/CD and the secrets discipline in Set Up External Secrets Operator with Vault. The scanning-vs-posture distinction is the same one drawn in the Well-Architected Security Pillar deep dive.

A quick map of who owns what, so you route work to the right team:

Layer What lives here Who usually owns it Failure it causes if wrong
Agent on host Local scan, outbound upload Platform / server team Coverage gap (host has no agent reporting)
Linking key Account-wide agent enrolment secret Security / platform Agents can’t join; or a leaked key linking rogue agents
Agent group Scan-targeting unit Security Wrong hosts in a scan (dev host in a prod scan)
Cloud connector IAM Read-only inventory access Cloud team No inventory sync; or over-broad role (audit finding)
Scan policy / credentials What plugins run, how auth happens Security Uncredentialed scan = shallow findings
VPR / tags Prioritisation + dynamic grouping Security Team patches the wrong things; stale lists
Export / ServiceNow The closed remediation loop Security + ITSM Findings never become owned tickets

Core concepts

Six mental models make every later step obvious.

Sensors feed a SaaS brain; you never run the brain. Tenable.io is the analytics, storage, scoring and workflow platform. Your job is to attach sensors and point scans at them. A scan is a job that binds a policy (which plugins run, how they authenticate, timing) to a target (an agent group, or a list of IPs/hostnames for a network scan) on a schedule. Results flow up, get de-duplicated onto assets, scored, tagged, and made queryable.

Agent scanning inverts the credential problem. A network scan reaches into a host over SSH/WinRM/SMB using credentials you supply — those credentials must be stored, rotated, and they traverse your network. A Nessus Agent already runs as a privileged local service, so the “authentication” is simply the host’s own context: no credentials cross the network, no scan engine holds host secrets, no inbound ports open. The agent is the answer to “how do I get credentialed depth without a credential vault and without opening my hosts to a scanner.” The trade-off: an agent can only scan the host it lives on — it cannot assess a network switch, a database appliance, or a printer, which is exactly where network scanners earn their place.

The linking key joins agents; the API key drives the console. These are two entirely different secrets that new users constantly conflate. The linking key is a single account-wide value an agent presents at enrolment to join your container (optionally into a named group). The API key pair (accessKey + secretKey) is per-user and authenticates REST calls. Using one where the other is expected fails — often with a silent 403. Both belong in a secrets manager, never in an image layer or a committed repo.

Cloud connectors inventory; they do not scan. A connector is read-only API access into a cloud account that pulls the list of assets (EC2 instances, Azure VMs, GCP Compute instances) plus their tags, state and metadata on a schedule. It answers “what should exist” so Tenable can reconcile it against “what is reporting an agent.” An instance that AWS lists but that has no agent is your coverage gap; an instance AWS reports terminated lets Tenable age out stale findings. The connector never runs a plugin or finds a CVE — pairing it with Tenable Cloud Security (Nessus agentless assessment / the CNAPP tier) is a separate, additive capability.

VPR is CVSS re-weighted by real-world threat. CVSS (Common Vulnerability Scoring System) is a static, theoretical severity from the vulnerability’s intrinsic properties. VPR (Vulnerability Priority Rating, 0.1–10) blends CVSS with dynamic threat intelligence — is there a public exploit, is it in active exploitation, is it trending in threat feeds, how old, how likely to be weaponised. A CVSS 9.8 with no exploit in the wild can carry a lower VPR than a CVSS 7.5 being mass-exploited today. You sort and ticket on VPR so the team fixes what is genuinely dangerous now, not what merely scores high on paper.

Assets are the de-dup anchor; tags are the dynamic grouping. Every finding attaches to an asset (a host, identified across scans by a stable fingerprint — UUID, MAC, cloud instance id). Tags are key/value labels; a static tag is applied by hand, a dynamic tag is a saved rule (“operating_system contains Windows AND aws:tag:env = prod”) that auto-applies to any asset matching it, now and in future. Tags are how you drive everything downstream: target a scan at a tag, filter a report by a tag, route a ServiceNow queue by a tag. Get the tags right and the rest of the program self-populates.

The vocabulary in one table

Term One-line definition Where it lives Why it matters
Container Your isolated Tenable.io tenant SaaS The boundary all your data lives in
Sensor A source of scan data Agents / scanners / connectors Determines coverage and depth
Nessus Agent Local process scanning from inside On each host Credentialed depth, no network creds
Agent group A named set of agents Tenable.io The unit you target with agent scans
Linking key Account-wide agent-enrolment secret Settings → Sensors Joins agents; guard it
Scanner Network scan engine (cloud or linked) Cloud / your infra Reaches targets an agent can’t
Cloud connector Read-only cloud inventory feed Settings → Connectors Reconciliation, tagging, ephemeral awareness
Scan policy Reusable set of plugin + auth + timing settings Policies library Defines how a scan runs
Template Tenable-provided starting policy Editor The base you customise
Credential Stored secret for network auth Managed credentials Depth for network scans
Plugin One vulnerability/compliance check Tenable feed The detection unit
VPR Threat-weighted priority score (0.1–10) Per finding What you actually patch by
CVSS Static theoretical severity Per finding Compliance baseline; not your patch order
Asset A de-duplicated host record Assets store The finding anchor
Tag Key/value label (static or dynamic rule) Assets Dynamic grouping drives everything
Exclusion / exclusion window Time/target a scan must skip Scan settings Change freezes, sensitive hosts
Recast / accept Rules that re-severity or hide a finding Findings Managing false positives & accepted risk

Sensors in depth: which one answers which question

The single most important architectural decision is which sensor scans which target. Get it wrong and you either miss depth (uncredentialed network scan where an agent belonged) or miss coverage entirely (no sensor at all can reach the target).

Nessus Agents — depth without network access

An agent is a small service (nessusagent on Linux, a Windows service) that links to your container, receives scan policy from the cloud, runs plugins locally against the host it lives on, and uploads results outbound over 443. It is the right sensor for every server, workstation and cloud VM you own and can install software on. Because it runs as root/SYSTEM it reads the package database, registry, installed software and config directly — the same depth a credentialed network scan gets, without you storing or transmitting any host credentials.

Agents check in on their own clock within a scan window you set, so a fleet of thousands does not stampede a single engine — there is no engine, the work is distributed onto each host. The cost is that agents cannot scan anything but their own host, and they need a rollout mechanism (config management for static hosts, self-enrolment from the golden image for ephemeral ones).

Agent property Detail Why it matters
Install footprint ~one package, idle until its window Negligible host overhead
Auth model Local host context (runs privileged) No network creds stored/transmitted
Network Outbound 443 only, polls out No inbound ports; NAT/firewall-friendly
Targeting unit Agent group Scope scans per environment
Scan timing scan_time_window (minutes) Spreads check-ins; no engine to size
Coverage limit Only its own host Can’t scan network gear, DBs, appliances
Enrolment Linking key (+ optional group at link) Self-enrol from golden image for autoscale
Data flow Results uploaded to Tenable.io No credentialed data leaves your host to a scanner

Nessus scanners — reach and network-level detail

A Nessus scanner is a network-reachable engine that scans targets over the wire. Tenable.io ships cloud scanners (Tenable’s own, for internet-facing targets) and lets you deploy your own linked Nessus scanner inside a VPC/subnet to reach internal targets. Network scans do the things agents cannot: host discovery (what is even alive on this subnet), scanning devices you cannot install an agent on (switches, routers, firewalls, storage arrays, databases, hypervisors, IoT), and credentialed network scans where you supply SSH/WinRM/SNMP/database credentials for depth on hosts without agents.

Scanner type Where it runs Reaches Typical use
Tenable cloud scanner Tenable’s infrastructure Public internet-facing targets External perimeter scans, discovery of public IPs
Linked Nessus scanner Your VPC/on-prem, linked to Tenable.io Internal subnets it can route to Internal network devices, DBs, agentless hosts
Scanner group Logical grouping of linked scanners Distributes/loads-balances scans Large internal estates, multi-region
Nessus Agent (for contrast) On the host Only itself From-inside host CVE depth

Cloud connectors — the inventory truth

A connector is not a scanner. It is a read-only API integration that, on a schedule, pulls the list of assets from a cloud provider (instances, their tags, AMI/image, lifecycle state, network placement) and merges that into the Tenable asset store. This is what lets Tenable answer “you have 412 EC2 instances in prod, 398 are reporting an agent, here are the 14 that are not” and “these 30 instances AWS reports terminated — age out their findings.” Connectors run per account/subscription/project and authenticate with the cloud’s native read-only primitive.

Provider Identity primitive Least-priv role What syncs
AWS IAM role, assumed by Tenable with an external ID SecurityAudit (managed) EC2 instances, tags, AMI, state, VPC/subnet
Azure Entra app registration + client secret Reader on subscription VMs, tags, resource group, region, state
GCP Service account + JSON key roles/viewer Compute instances, labels, zone, state

The decision, distilled — pick the sensor from the target class:

Target class Right sensor Why Fallback
Linux/Windows server you own Nessus Agent Credentialed depth, no network creds Credentialed network scan if agent can’t be installed
Autoscaled/ephemeral VM you own Nessus Agent (self-enrol from image) Boots pre-linked, scans in-window Connector at least inventories it as a gap
Network switch / router / firewall Network scan (SNMP creds) Can’t install an agent
Database / storage appliance Credentialed network scan Agent can’t live there
Public IP / external perimeter Tenable cloud scanner Reaches from the outside
Isolated internal subnet Linked Nessus scanner in that subnet Cloud scanner can’t route there Agents on the hosts if installable
“What should exist” reconciliation Cloud connector Provider’s inventory truth

Agent groups, linking keys and enrolment at scale

Agents register into agent groups, which are the unit a scan targets. Create one group per environment so a production scan never accidentally sweeps a dev host and vice versa. Groups are cheap; make as many as your scan-scoping needs.

The linking key is a single account-wide secret. Any host with the key can join your container, so treat it like a shared credential: source it from a secrets manager on each host, never a plaintext var in your Ansible repo or a layer in a public AMI. You can join a group at link time with --groups, which makes a host scan-eligible immediately without a second API call.

Agent lifecycle states you will see in the console, and what each means:

State Meaning Action if unexpected
on / connected Linked and checking in Healthy — none
off Linked but not currently checked in Check host up / egress 443
init Linking in progress Wait; if stuck, check key + egress
unlinked Removed from the container Re-link if the host should be covered
Stale last_connect Connected but not seen recently Egress filtered? Agent service down? Coverage hole

Enrolment paths by fleet type — match the path to how the host is born:

Fleet type Enrolment path Mechanism Gotcha
Static VMs Config management Ansible/Chef pushes package + agent link Long-lived; re-check after re-image
Golden image / AMI Bake-in + self-link Package baked; agent link from cloud-init user-data Don’t bake the linked state (clones share UUID) — link on first boot
Autoscaled group Self-enrol on boot user-data runs agent link --groups=<env> Must link before the scan window or it’s never scanned
Windows fleet MSI + nessuscli.exe agent link GPO / config management Same key; Windows service name differs
Containers/PaaS Usually not agented Use connector inventory + platform-native scanning Agent is for hosts, not every workload

A critical subtlety for images: bake the agent package into the golden image, but run the agent link command on first boot (from user-data / a systemd oneshot), not at bake time. If you link during the bake, every clone inherits the same agent identity and they collide in the console. Linking on first boot gives each instance its own identity and its own findings.

Scan types, templates and policies

A scan binds a policy to a target on a schedule. Tenable ships templates (pre-built policies) you clone and customise. The first fork is agent vs network; the second is what the scan is for (discovery, full assessment, compliance).

Agent vs network scans

Dimension Agent scan Network scan
Runs where On each host From a scanner engine toward targets
Auth Host’s local context (no creds) Supplied credentials (SSH/WinRM/SNMP/DB) for depth
Target Agent group(s) IP ranges / hostnames / tags
Depth Full from-inside (packages, registry, config) Full if credentialed; shallow if not
Timing scan_time_window; hosts run on own clock Scheduled run against reachable targets
Load Distributed to hosts; no engine to size Concentrated on the scanner; size it
Best for Hosts you own Devices you can’t agent; discovery; perimeter

The templates you will actually use

Tenable provides many templates; these are the ones that matter for this build. Names are the Tenable UI names (the API name field is the lowercased/underscored form shown).

Template API name What it does When to use
Advanced Agent Scan agent_advanced Full-control agent scan, all settings exposed Production agent scans you tune
Basic Agent Scan agent_basic Simplified agent scan Quick start / small fleets
Advanced Network Scan advanced Full-control network scan Credentialed network scans you tune
Basic Network Scan basic Standard network vuln scan General network assessment
Host Discovery discovery Live-host + port discovery only Map a subnet before assessing it
Policy Compliance Auditing compliance Runs compliance audit files (CIS/DISA) Config-hardening / audit evidence
Web Application Tests webapp Scans web apps for app-layer issues App scanning (separate from host CVEs)
Malware Scan malware Hunts known-bad files/hashes IOC sweeps

Scan settings that matter (agent scans)

Setting What it controls Typical value Gotcha
agent_group_id Which agent group(s) to scan Your prod group id Wrong group = wrong hosts scanned
scan_time_window Minutes agents have to check in and run 90–180 Too tight → slow/asleep hosts miss the scan
launch / rrules Schedule (DAILY/WEEKLY + RRULE) DAILY / FREQ=DAILY;INTERVAL=1 Set timezone too, or it runs at the wrong local hour
enabled Whether the schedule is active true A created-but-disabled scan never runs
starttime First scheduled run YYYYMMDDThhmmss Must be future; matches timezone

Scan settings that matter (network scans)

Setting What it controls Typical value Gotcha
text_targets IPs/ranges/hostnames to scan 10.0.0.0/24 Overlapping ranges waste engine time
scanner_id Which scanner/scanner-group runs it Your linked scanner Cloud scanner can’t reach internal IPs
Credentials SSH/WinRM/SNMP/DB secrets for depth From managed credentials Uncredentialed = shallow findings
Port scan range Which ports to probe default or explicit Full 1–65535 is slow; scope it
max_checks_per_host / throttling Scan intensity Template defaults Too aggressive can stress fragile devices

Credentialed scanning: why it changes everything

The difference between an uncredentialed and a credentialed scan is the difference between guessing from the outside and reading from the inside. Uncredentialed, a network scan sees open ports and service banners and infers vulnerabilities probabilistically — it produces a lot of “potential” findings and misses everything not exposed on the network. Credentialed, it logs in and reads the truth: exact package versions, missing patches, registry settings, config file contents. Findings jump in both volume (you now see local vulns) and accuracy (far fewer false positives).

Agents sidestep this entirely — they are credentialed by virtue of running locally. Credentialed network scans matter for the hosts you cannot agent (databases, appliances, network gear) and for discovery of hosts before agents are deployed.

Credential types Tenable.io supports for network scans, and the least-privilege pattern for each:

Credential type Target class Least-priv approach Storage
SSH (key or password) Linux/Unix hosts Dedicated scan user, sudo to read pkg db; not full root Managed credentials / Vault
Windows (WinRM/SMB) Windows hosts Dedicated account, local admin on target scope only Managed credentials / gMSA
SNMP (v3 preferred) Network devices Read-only SNMPv3 with auth+priv Managed credentials
Database (Oracle/MSSQL/etc.) DB engines Read-only audit role Managed credentials
API/cloud Cloud services Scoped read-only Managed credentials

Use managed credentials (stored once, referenced by scans) rather than pasting secrets into each scan — one rotation point, and secrets never live in a scan definition you might export. Prefer key-based SSH and SNMPv3 with auth+priv over passwords and community strings.

Cloud connectors: read-only inventory sync in practice

Connectors are the reconciliation and tagging backbone. Each connects one cloud account with a read-only identity and syncs inventory on a schedule (hourly is common). Here is what each provider needs and the exact least-privilege setup.

AWS connector — assume-role with external ID

Tenable assumes a role in your account (never long-lived keys). The role trusts Tenable’s connector account and is gated by a per-connector external ID so a leaked role ARN is useless without it. Attach the AWS-managed SecurityAudit policy — read-only, sufficient for inventory.

data "aws_iam_policy_document" "tenable_trust" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::012615275169:root"] # Tenable's connector account
    }
    condition {
      test     = "StringEquals"
      variable = "sts:ExternalId"
      values   = [var.tenable_external_id]  # generated in the Tenable UI, per connector
    }
  }
}

resource "aws_iam_role" "tenable_connector" {
  name               = "tenable-io-connector"
  assume_role_policy = data.aws_iam_policy_document.tenable_trust.json
}

resource "aws_iam_role_policy_attachment" "ro" {
  role       = aws_iam_role.tenable_connector.name
  policy_arn = "arn:aws:iam::aws:policy/SecurityAudit" # read-only inventory access
}

Register the connector via the API, passing the role ARN and the external ID Tenable generated:

tio POST /settings/connectors -d '{
  "connector": {
    "type": "aws",
    "name": "aws-prod-account",
    "schedule": {"units": "hours", "value": "4"},
    "params": {
      "role_arn": "arn:aws:iam::111122223333:role/tenable-io-connector",
      "external_id": "'"${TENABLE_EXTERNAL_ID}"'",
      "regions": ["us-east-1", "eu-west-1"],
      "import_ec2": true
    }
  }
}'

Repeat per account. Within each cycle Tenable populates inventory with every EC2 instance plus its tags, AMI and state — which is how it spots an instance that exists in AWS but has no agent reporting (your coverage gap) and suppresses findings on instances AWS reports terminated.

Azure connector — Entra app + Reader

Azure uses an Entra app registration with a client secret and the Reader role on the subscription:

APP_ID=$(az ad app create --display-name "tenable-io-connector" --query appId -o tsv)
az ad sp create --id "$APP_ID"
SECRET=$(az ad app credential reset --id "$APP_ID" --query password -o tsv)
SUB_ID=$(az account show --query id -o tsv)
TENANT_ID=$(az account show --query tenantId -o tsv)
az role assignment create --assignee "$APP_ID" --role "Reader" \
  --scope "/subscriptions/${SUB_ID}"

tio POST /settings/connectors -d '{
  "connector": {"type":"azure","name":"azure-prod-sub",
    "schedule":{"units":"hours","value":"4"},
    "params":{"subscription_id":"'"${SUB_ID}"'","tenant_id":"'"${TENANT_ID}"'",
      "client_id":"'"${APP_ID}"'","client_secret":"'"${SECRET}"'"}}}'

GCP connector — service account + viewer

GCP uses a service account with roles/viewer, authenticating with the JSON key:

gcloud iam service-accounts create tenable-io-connector \
  --display-name="Tenable.io connector"
PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member="serviceAccount:tenable-io-connector@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/viewer"
gcloud iam service-accounts keys create /tmp/tenable-gcp.json \
  --iam-account="tenable-io-connector@${PROJECT_ID}.iam.gserviceaccount.com"

KEY_B64=$(base64 -w0 /tmp/tenable-gcp.json)
tio POST /settings/connectors -d '{
  "connector":{"type":"gcp","name":"gcp-prod-project",
    "schedule":{"units":"hours","value":"4"},
    "params":{"service_account_key":"'"${KEY_B64}"'","project_id":"'"${PROJECT_ID}"'"}}}'
shred -u /tmp/tenable-gcp.json   # do not leave the key on disk

Store the Azure secret and the GCP key JSON in a secrets manager, not shell history — rotate both on your policy cadence. Connector health you should monitor:

Connector signal Where Healthy value If not
Last sync time GET /settings/connectors Within the schedule interval Check IAM validity / secret expiry
last_sync_status Same success Read the error; usually perms or expired secret
Asset count vs cloud Reconcile monthly Matches provider console Investigate drift (region missed?)
Aged-out assets Assets with terminated state Findings suppressed Confirm connector sees termination

VPR vs CVSS: prioritising what is actually exploitable

This is where a vulnerability management program diverges from a vulnerability scanning one. A real scan of a real estate returns tens of thousands of findings; most carry a high CVSS because CVSS measures theoretical worst-case severity. Patching by CVSS means chasing every CVSS 10 regardless of whether anyone can or does exploit it — a treadmill that never gets ahead of actual risk.

VPR re-ranks by current, real-world threat. It ingests threat intelligence and machine learning over exploit availability, exploitation activity, exploit maturity, chatter in threat feeds, and age, then blends that with CVSS to produce a 0.1–10 score that answers “how dangerous is this right now.” The practical rule: sort and ticket on VPR, keep CVSS as the compliance baseline.

Dimension CVSS VPR
Nature Static, theoretical Dynamic, threat-aware
Inputs Intrinsic vuln properties (attack vector, complexity, impact) CVSS + exploit availability, active exploitation, threat-feed activity, age, ML
Changes over time? No (fixed at publication) Yes (re-scored as threat evolves)
Answers “How bad could this be?” “How dangerous is this now?”
Range 0.0–10.0 0.1–10.0
Use it for Compliance baseline, coverage Patch prioritisation / ticketing
Failure if used alone Wastes effort on non-exploited highs (Pair with CVSS for compliance evidence)

VPR severity bands and the SLA you might attach:

VPR band Severity Example SLA (illustrative)
9.0–10.0 Critical Patch in 7 days
7.0–8.9 High Patch in 14 days
4.0–6.9 Medium Patch in 30 days
0.1–3.9 Low Patch in 90 days / risk-accept

The canonical example: a CVSS 9.8 remote code execution with no public exploit and no observed exploitation may carry a VPR of 6.x, while a CVSS 7.5 with a weaponised exploit under active mass-exploitation carries a VPR of 9.x. Ticket the second first. Query the top of your estate by VPR:

tio POST /workbenches/vulnerabilities -d '{
  "filters":[{"filter":"severity","quality":"gte","value":"high"}],
  "sort":[{"order":"desc","property":"vpr_score"}]
}' | jq -r '.vulnerabilities[:15][]
  | [(.vpr_score|tostring), .plugin_name, (.count|tostring)] | @tsv'

Tags and dynamic asset lists

Tags are the automation substrate. A static tag you apply by hand (“crown-jewels”); a dynamic tag is a saved rule that auto-applies to any asset matching it — apply it once, and every future asset that fits gets tagged with no further action. You then target scans, filter reports, and route tickets by tag.

Common dynamic-tag rules and what they enable:

Tag (key:value) Rule Enables
env:prod aws:tag:Environment = production OR azure:tag:env = prod Prod-only scans, reports, SLAs
os:windows operating_system contains Windows OS-specific scan policies/patching
exposure:internet-facing aws:public_ip is not empty Prioritise perimeter; tighter SLA
owner:team-payments aws:tag:owner = payments Route ServiceNow tickets by owner
coverage:no-agent has_agent = false Live coverage-gap list to close
compliance:pci aws:tag:scope = pci Compliance scan scope + evidence

Create a dynamic tag via the API (a category + value + a filter rule):

tio POST /tags/values -d '{
  "category_name": "env",
  "value": "prod",
  "filters": {
    "asset": {
      "and": [
        {"field":"aws_ec2_instance_state_name","operator":"eq","value":"running"},
        {"field":"cloud_tags","operator":"set-has","value":"Environment:production"}
      ]
    }
  }
}'

Now a scan can target env:prod instead of a hand-maintained group, a report can filter to exposure:internet-facing, and a ServiceNow rule can route by owner:* — all self-updating as the connector syncs new instances.

Remediation workflow, reporting and exclusions

Findings become work only when they are exported, prioritised, owned and tracked, and when noise is managed with recast/accept rules and exclusions.

The export pipeline

The vulnerability export is the source feed for ticketing and SIEM. Filter it to what matters (high VPR, prod), then poll to completion and download chunks:

EXPORT_UUID=$(tio POST /vulns/export -d '{
  "filters":{"severity":["high","critical"],"vpr_score":{"gte":7.0}},
  "num_assets":500
}' | jq -r '.export_uuid')

# poll until FINISHED, then download chunks
tio GET /vulns/export/${EXPORT_UUID}/status | jq '.status'
tio GET /vulns/export/${EXPORT_UUID}/chunks/1 > /tmp/tio-high-vpr.json

Managing noise: recast, accept, exclude

Mechanism What it does When to use Caution
Recast rule Changes a finding’s severity A finding is real but lower risk in your context Document why; review periodically
Accept rule Hides a finding (accepted risk) Confirmed false positive or business-accepted risk Time-box and re-review; don’t accept away real risk
Exclusion window Scan skips a target/time Change freezes, fragile hosts, maintenance An excluded host is unscanned — track it
Asset age-out Retire assets not seen in N days Ephemeral fleet churn Set to match your instance lifecycle

Exclusions matter for both accuracy and safety: a scan during a change freeze can trip alarms, and some fragile devices misbehave under scanning. Set an exclusion window rather than pausing the whole scan.

Reporting

Tenable.io reports/dashboards answer the audit and the exec. Practical report cuts:

Report Filter Audience
Executive risk summary By VPR band, trend over time CISO / leadership
Remediation SLA compliance Findings vs SLA age Ops / audit
Coverage gap has_agent=false, by account Platform team
Per-owner backlog Grouped by owner:* tag Owning teams
Compliance evidence Compliance-scan pass/fail Auditors

Architecture at a glance

Three planes meet in Tenable.io, and the diagram traces how data moves through them. Read it as three feeds converging on the SaaS platform, then one flow out to remediation.

The agent plane is every host you own running a Nessus Agent that authenticates locally and uploads results outbound over 443 — no scan engine reaches into your network, no credentials traverse it. Agents belong to agent groups (prod, dev) that scans target. The connector plane is read-only API access into AWS (assume-role + external ID), Azure (Entra app + Reader) and GCP (service account + viewer) that pulls live asset inventory — instances, tags, lifecycle state — so Tenable can reconcile what should exist against what is reporting, flag the no-agent coverage gaps, and age out terminated hosts. For targets no agent can live on, the scanner plane — Tenable cloud scanners for the perimeter, a linked Nessus scanner inside a subnet for internal gear — runs credentialed network scans. All three feed the Tenable.io platform, which de-duplicates findings onto assets, scores them with VPR (not just CVSS), and lets dynamic tags slice the estate live. The remediation plane flows outward: a filtered export of high-VPR findings drives a ServiceNow ticket per finding routed by the asset’s owner tag, cross-correlated with CSPM/EDR posture data, so the SLA clock and closure record — the paper trail the failed customer review demanded — live in your ITSM.

Tenable.io vulnerability management architecture: three sensor planes feeding the SaaS platform and flowing out to remediation. Left, the agent plane shows Linux and Windows hosts running Nessus Agents linked by an account-wide linking key into prod and dev agent groups, uploading results outbound over HTTPS 443 to sensor.cloud.tenable.com. Below it, the connector plane shows read-only cloud connectors into AWS (IAM assume-role with external ID, SecurityAudit policy), Azure (Entra app registration with Reader on the subscription) and GCP (service account with roles/viewer) syncing asset inventory — instances, tags and lifecycle state. Right of the agents, the scanner plane shows Tenable cloud scanners reaching the internet-facing perimeter and a linked Nessus scanner inside an internal subnet running credentialed network scans against databases and network devices. All three planes feed the central Tenable.io platform, which de-duplicates findings onto assets, scores them with VPR blending CVSS and threat intelligence, and applies dynamic tags such as env:prod, exposure:internet-facing and owner:team. From the platform, a filtered high-VPR export flows out to the remediation plane — ServiceNow tickets routed by owner tag with SLA tracking, correlated with CSPM and EDR posture data.

The mental model to carry from the diagram: three feeds in, one loop out. Agents give depth on hosts you own, connectors give the inventory truth to find gaps, scanners cover what agents cannot reach, VPR decides order, tags decide routing, and the export closes the loop into owned, time-bound tickets.

Real-world scenario

Northwind Ledger, a fintech SaaS (~180 engineers), failed a Series-B customer’s security review on the exact line in this article’s opening: no on-demand authenticated scan of production. Their estate: 3 AWS accounts (~410 EC2 instances, half in an autoscaling group), 2 Azure subscriptions (~120 VMs), 1 GCP project (~40 Compute instances for data pipelines), plus ~25 network devices (firewalls, switches) and 6 database appliances an agent cannot touch. The existing program was a quarterly unauthenticated Nessus scan from one appliance in a single VPC that reached maybe 40% of the estate and found mostly banner-grade “potential” findings. The CISO gave the platform team one sprint.

The rollout ran in the order this guide teaches. Day 1–2: mint API keys, create prod, dev and data agent groups, pull the linking key into Vault. Day 2–4: Ansible pushed the agent to the ~380 static VMs and linked them into prod; for the autoscaling group they baked the agent package into the AMI and added an agent link --groups=prod step to user-data so new instances self-enrolled within a minute of boot. Within a day the console showed ~500 agents on. Day 3–5: wired the AWS (×3), Azure (×2) and GCP connectors with read-only roles; the first sync revealed the truth that mattered — 31 EC2 instances reporting no agent, all in a legacy account nobody had put in the Ansible inventory, plus 14 the connector showed AWS had already terminated (stale findings, aged out).

The coverage gap became a dynamic tag coverage:no-agent, which drove both a ServiceNow queue to the owning team and a daily-shrinking metric on the CISO dashboard. For the network devices and databases, they deployed a linked Nessus scanner inside the shared-services VPC and built a credentialed network scan (SNMPv3 for the switches, read-only DB accounts for the appliances) — the only sensor that could reach them. Day 5: an agent_advanced daily scan against prod with a 120-minute window seeded results; a workbench query sorted by VPR surfaced the real fires.

The prioritisation payoff was immediate and countable. The raw scan returned ~9,400 findings, of which ~1,100 were CVSS “Critical.” Sorting by VPR ≥ 7.0 collapsed the actionable set to ~140 findings — the ones with real exploit activity — and the very top of that list was a CVSS 7.5 web-framework flaw under active mass-exploitation that the old CVSS-ordered process would have buried under hundreds of theoretical CVSS 10s. Those 140 became ServiceNow tickets routed by the owner:* tag with a 14-day SLA. Six weeks later the customer re-ran the review; Northwind produced an on-demand authenticated scan report, a coverage number (99.2% of licensed assets agented), and an SLA-compliance chart. They passed. Tenable is licensed per asset, so the spend tracked their ~700 licensed assets — and because scan frequency is free, moving from quarterly to daily authenticated scanning added nothing to the bill; the only cost discipline was excluding short-lived CI hosts from licensing and aging out terminated instances to keep the count honest.

The rollout as a timeline, because the order is the lesson:

Day Action Result Why this order
1–2 API keys, agent groups, linking key → Vault Foundation ready Everything downstream needs these
2–4 Ansible + AMI self-enrol → agents link ~500 agents on Depth on hosts you own, first
3–5 AWS/Azure/GCP connectors 31 gaps + 14 stale found Inventory truth reveals coverage
5 Linked scanner + credentialed net scan DBs/switches covered The only sensor that reaches them
5 agent_advanced daily scan on prod 9,400 findings seeded Now there’s data to prioritise
5–6 Sort by VPR ≥ 7 9,400 → 140 actionable Fix exploitable, not theoretical
6+ Export → ServiceNow by owner tag 140 owned, SLA-tracked Close the loop; audit trail

Advantages and disadvantages

The agent-plus-connector model is powerful but has real trade-offs — weigh them honestly:

Advantages Disadvantages
Agents give credentialed depth with no network creds stored or transmitted Agents only scan their own host — network gear, DBs, appliances still need network scans + credentials
No inbound ports; agents poll outbound — firewall/NAT-friendly You must roll out and maintain agents; ephemeral hosts must self-enrol or they’re never scanned
Distributed load — no scan engine to size; thousands of hosts don’t stampede You give up central scan scheduling control; a host asleep past its window is missed
Connectors reconcile agents vs reality — coverage gaps and stale assets are visible Connectors inventory only — they find no CVEs; full agentless assessment is a separate (CNAPP) capability + cost
VPR cuts a 9,400-finding estate to ~140 actionable — patch what’s exploitable VPR is Tenable-proprietary; auditors may still demand CVSS-based evidence (keep both)
Dynamic tags make scans/reports/tickets self-populating Tag rules are only as good as your cloud tagging hygiene — bad owner tags misroute tickets
Per-asset licensing means scan frequency is free — daily costs the same as weekly License tracks asset count; ghost/terminated assets inflate the bill if you don’t age them out
Native ServiceNow/SIEM integrations close the remediation loop The closed loop only works if owning teams act on tickets — tooling doesn’t fix culture

The model is right when you have a mixed estate you mostly own (agents shine) plus edge cases you cannot agent (network scanners cover them) and a compliance mandate for authenticated scanning and SLAs. It is over-engineered for a tiny all-PaaS shop with no VMs (there, cloud-native scanning + a CSPM tool may suffice). It bites hardest on teams with poor cloud tagging (dynamic tags misfire), large ephemeral fleets that never self-enrol (perpetual coverage gaps), and anyone who lets the asset count drift with terminated ghosts (license waste).

Hands-on lab

This lab stands up the core loop on a free Tenable.io evaluation container and one throwaway VM: mint keys, create an agent group, link a real Nessus Agent, build and run an agent scan, and pull VPR-sorted findings. It is intentionally small and fully teardown-able. You need a Linux VM you can install a package on (a cloud VM or a local Ubuntu/RHEL box) and shell access to it.

Step 1 — Mint API keys and set up the CLI workspace. In the Tenable.io console: Settings → My Account → API Keys → Generate. You get an accessKey and secretKey shown once. Export them and define a thin wrapper so the rest is copy-paste:

export TIO_ACCESS_KEY="a1b2c3..."
export TIO_SECRET_KEY="d4e5f6..."
export TIO_BASE="https://cloud.tenable.com"

tio() {
  local method="$1" path="$2"; shift 2
  curl -sS -X "$method" "${TIO_BASE}${path}" \
    -H "X-ApiKeys: accessKey=${TIO_ACCESS_KEY}; secretKey=${TIO_SECRET_KEY}" \
    -H "Accept: application/json" -H "Content-Type: application/json" "$@"
}

# smoke test — should return your container's session
tio GET /session | jq '{name: .name, container: .container_name}'

Expected: a JSON object with your user name and container name. If you get a 403, the keys are wrong or the header is malformed. Do not bake these keys into images or commit them.

Step 2 — Create an agent group. Groups are the unit an agent scan targets:

LAB_GROUP_ID=$(tio POST /scanners/null/agent-groups \
  -d '{"name":"lab-linux"}' | jq -r '.id')
echo "lab agent group id: ${LAB_GROUP_ID}"

Expected: a numeric group id. Verify it exists:

tio GET /scanners/null/agent-groups | jq -r '.groups[] | [.id, .name] | @tsv'

Step 3 — Get the linking key. The linking key lives in the UI at Settings → Sensors → Linked Agents → (linking key shown at top). Copy it. (It is a single account-wide value; it is not your API key.)

export LINK_KEY="<paste-linking-key-from-UI>"

Step 4 — Install and link the Nessus Agent on your lab VM. SSH to the VM. On Debian/Ubuntu:

# download + install (Ubuntu example; use the current package for your distro)
curl -sSL -o /tmp/nessusagent.deb \
  "https://www.tenable.com/downloads/api/v2/pages/nessus-agents/files/NessusAgent-latest-ubuntu1604_amd64.deb"
sudo dpkg -i /tmp/nessusagent.deb || sudo apt-get -f install -y

# link to Tenable.io and join the lab group
sudo /opt/nessus_agent/sbin/nessuscli agent link \
  --key="${LINK_KEY}" \
  --groups=lab-linux \
  --cloud \
  --name="$(hostname)"

sudo systemctl enable --now nessusagent

The --cloud flag points the agent at sensor.cloud.tenable.com (not an on-prem manager); --groups joins at link time so it is scan-eligible immediately. Verify locally:

sudo /opt/nessus_agent/sbin/nessuscli agent status
# expect: "Link status: Connected to cloud.tenable.com:443"
#         "Agent is registered to a manager."

Step 5 — Confirm the agent appears in the console. Back on your workstation:

tio GET "/scanners/null/agents?limit=100" \
  | jq -r '.agents[] | [.name, .status, .platform] | @tsv'

Expected: your hostname with status on (it may briefly show init). If it never appears, check outbound 443 from the VM to sensor.cloud.tenable.com.

Step 6 — Build and launch an agent scan. Find the Advanced Agent Scan template, then create a scan bound to the lab group and launch it once:

TEMPLATE=$(tio GET /editor/scan/templates \
  | jq -r '.templates[] | select(.name=="agent_advanced") | .uuid')
echo "template uuid: ${TEMPLATE}"

SCAN_ID=$(tio POST /scans -d '{
  "uuid":"'"${TEMPLATE}"'",
  "settings":{
    "name":"lab-agent-scan",
    "enabled":true,
    "agent_group_id":['"${LAB_GROUP_ID}"'],
    "scan_time_window":60
  }
}' | jq -r '.scan.id')
echo "scan id: ${SCAN_ID}"

# launch a one-off run now to seed results
tio POST /scans/${SCAN_ID}/launch | jq

Expected: a scan_uuid in the launch response. The agent runs on its own clock within the 60-minute window — give it a few minutes.

Step 7 — Watch the scan and pull VPR-sorted findings. Check status, then query the workbench:

# scan status
tio GET /scans/${SCAN_ID} | jq -r '.info | {status, name, timestamp}'

# top findings across the estate, sorted by VPR (once results land)
tio POST /workbenches/vulnerabilities -d '{
  "filters":[{"filter":"severity","quality":"gte","value":"medium"}],
  "sort":[{"order":"desc","property":"vpr_score"}]
}' | jq -r '.vulnerabilities[:15][]
  | [(.vpr_score // "n/a"|tostring), .plugin_name, (.count|tostring)] | @tsv'

Expected: rows of VPR<TAB>plugin_name<TAB>count. On a fresh agent you will see real local findings (missing patches, outdated packages) — proof that agent scanning gives credentialed depth with zero network credentials.

Validation checklist — what each step proved:

Step What you did What it proves
1 Minted API keys, smoke-tested /session API auth works; keys ≠ linking key
2 Created an agent group Groups are the scan-targeting unit
4 Linked a real agent Outbound-only enrolment, local auth
5 Saw the agent on in console Coverage is visible and verifiable
6 Built + launched an agent scan Scan binds template → group, no creds
7 Pulled VPR-sorted findings Credentialed depth + risk scoring flow

Teardown — remove everything so nothing keeps polling or holding state:

# 1) disable + delete the scan
tio PUT  /scans/${SCAN_ID} -d '{"settings":{"enabled":false}}'
tio DELETE /scans/${SCAN_ID}

# 2) on the lab VM: unlink + remove the agent
sudo /opt/nessus_agent/sbin/nessuscli agent unlink
sudo apt-get remove --purge nessus-agent -y   # or: sudo yum remove NessusAgent

# 3) delete the agent group
tio DELETE /scanners/null/agent-groups/${LAB_GROUP_ID}

# 4) (optional) delete the API keys in the UI: Settings → My Account → API Keys

If you also wired connectors during a broader test, delete each to stop inventory pulls, then revoke cloud access at the source (destroy the AWS role / terraform destroy, az ad app delete --id "$APP_ID", gcloud iam service-accounts delete ...), and finally delete the API keys so an orphaned credential cannot be replayed.

Common mistakes & troubleshooting

The failure modes you will actually hit, with the exact confirm step and fix. Scan the table, then read the detail for the ones that bite hardest.

# Symptom Root cause Confirm Fix
1 Agent shows Connected locally but last_connect never advances in console Outbound 443 to sensor.cloud.tenable.com filtered nessuscli agent status = Connected, but console last_connect stale Open egress / set --proxy-host; re-check
2 agent link fails with 403 or “invalid key” Used the API key as the linking key (or vice versa) Compare: linking key is one account-wide value under Sensors; API key is per-user Use the linking key from Settings → Sensors
3 Connector never syncs; last_sync_status error IAM role/secret wrong, external ID mismatch, or over-scoped and denied tio GET /settings/connectors shows the error Fix trust/external ID; use SecurityAudit/Reader/viewer
4 Cloud assets show but no CVE findings on them Expected — connectors inventory, they don’t scan Asset has cloud source but no agent/scan data Deploy an agent or a credentialed network scan
5 Autoscaled instances perpetually flagged no-agent Instances boot/die before an Ansible run Connector shows them; agent list doesn’t Self-link from user-data in the golden image
6 Golden-image clones collide / share identity Agent linked at bake time (clones share UUID) Multiple hosts, one agent entry flapping Bake the package; run agent link on first boot
7 Network scan returns shallow “potential” findings only Scan ran uncredentialed Scan policy has no/failed credentials Add managed credentials (SSH/WinRM/SNMP/DB)
8 Team patching CVSS 10s but breaches persist Prioritising by CVSS, not VPR Findings sorted by cvss not vpr_score Sort/ticket on vpr_score; keep CVSS for compliance
9 Slow/asleep hosts missed by the scan scan_time_window too tight for the fleet Some agents’ last_scanned predates the run Raise window to 90–180 min
10 Findings on terminated instances linger Connector not aging out; or no connector for that account Instance state terminated in cloud, still in Tenable Ensure connector covers the account; set age-out
11 Dynamic-tag scans/tickets miss hosts Cloud tagging inconsistent (env=prod vs Environment=production) Tag rule matches fewer assets than expected Normalise cloud tags; broaden the rule with OR
12 Scan trips alarms during a change freeze No exclusion window set Scan ran against frozen/fragile targets Add an exclusion window for the freeze/target
13 License count higher than live asset count Ghost/terminated assets still licensed Reconcile Tenable count vs cloud console Age out stale assets; exclude short-lived CI hosts
14 Linked scanner can’t reach internal targets Scanner in a subnet with no route to the targets Scan results empty; scanner can’t ping Place scanner in a subnet that routes to targets

1. Agent connected locally but never uploads. The agent links fine but egress to sensor.cloud.tenable.com:443 is filtered, so results never reach the console. Confirm: nessuscli agent status shows Connected, but the console’s last_connect for that agent never advances. Fix: open the egress allow-list (or configure a proxy: nessuscli agent supports --proxy-host/--proxy-port), then confirm last_connect advances.

2. Linking key vs API key confusion. The account-wide linking key joins agents; the per-user API key drives REST calls. They are not interchangeable and swapping them fails — often a silent 403 on link. Confirm: the linking key is the single value under Settings → Sensors → Linked Agents; the API key is the pair you generated under My Account. Fix: use the linking key for agent link --key=.

4. Connectors inventory; they don’t assess. New users expect a connector to scan the cloud and are surprised there are no CVEs on connector-discovered assets. Confirm: the asset has an AWS/Azure/GCP source but no agent or scan data. Fix: a connector only tells you the host exists — put an agent on it (or run a credentialed network scan) to actually assess it. Agentless CVE assessment is a separate Tenable Cloud Security capability.

8. Treating VPR like CVSS. The most consequential program mistake: patching by CVSS burns the team on theoretical highs while an actively-exploited medium sits open. Confirm: your workbench/exports sort by cvss or raw severity, not vpr_score. Fix: sort and ticket on VPR; a CVSS 7.5 under mass-exploitation (VPR 9.x) outranks a CVSS 9.8 with no exploit (VPR 6.x). Keep CVSS as the compliance baseline, not the work queue.

Best practices

Security notes

Cost & sizing

Tenable.io licenses per asset under management, so cost tracks the inventory the connectors discover, not scan frequency — there is no penalty for scanning daily instead of weekly, which makes continuous authenticated scanning effectively free once an asset is licensed. The whole cost discipline is therefore about keeping the asset count honest, not about throttling scans.

What drives the bill and how to control it:

Cost driver What it is Lever to control it
Licensed asset count Per-asset license (the dominant cost) Age out terminated instances; exclude short-lived CI hosts where policy allows
Ghost/stale assets Terminated hosts still counted Ensure connectors see termination; set age-out to match fleet lifecycle
Scan frequency (Not billed) Scan as often as you like — daily costs the same as quarterly
Agent compute Host CPU while scanning Negligible — agent idle until its window; distributed load
Connector API calls Read-only inventory pulls Sit inside every provider’s free inventory-read tier
Add-on modules e.g. Tenable Cloud Security (agentless CNAPP), Web App Scanning Additive license — only if you need agentless assessment / app scanning

Sizing guidance:

Estate size Approach Watch-out
< 100 assets Free evaluation for PoC; small paid tier for prod Don’t over-buy; start with agents on owned hosts
Few hundred to low thousands Standard per-asset license; connectors + agents Keep the count honest — this is where ghosts inflate cost
Tens of thousands Enterprise license; scanner groups for network segments Distribute scanners; automate age-out; monthly reconciliation
Heavy ephemeral fleet License a headroom band; aggressive age-out Short-lived CI hosts can double your count if not excluded

The single biggest cost mistake is letting the asset count drift with terminated ghosts — reconcile the Tenable licensed count against the cloud console monthly, and let connectors age out anything the provider reports terminated. Agent compute and connector API calls are effectively free (idle agents, free-tier inventory reads), so the only real lever is asset hygiene.

Interview & exam questions

1. What are the three sensor types in Tenable.io and when do you use each? Nessus Agents (on hosts you own, for credentialed from-inside depth with no network credentials), Nessus scanners (network engines — cloud scanners for the perimeter, linked scanners for internal subnets — for devices you can’t agent and for discovery/credentialed network scans), and cloud connectors (read-only API inventory sync from AWS/Azure/GCP for reconciliation and tagging). Agents for owned hosts, scanners for the unagentable, connectors for the inventory truth.

2. Why does an agent scan need no credentials while a network scan does? A Nessus Agent runs locally as a privileged service, so its “authentication” is the host’s own context — it reads packages, registry and config directly. A network scan reaches into the host over SSH/WinRM/SMB and must supply credentials, which are stored and traverse the network. The agent trades away reach (only its own host) for zero credential handling.

3. Difference between the linking key and the API key? The linking key is a single account-wide secret an agent presents at enrolment to join your container; the API key pair is per-user and authenticates REST calls. They are not interchangeable — using one for the other typically fails with a 403. Guard both in a secrets manager.

4. What is VPR and how does it differ from CVSS? CVSS is a static, theoretical severity from a vulnerability’s intrinsic properties. VPR (Vulnerability Priority Rating, 0.1–10) blends CVSS with dynamic threat intelligence — exploit availability, active exploitation, threat-feed activity, age — to score how dangerous a finding is right now. You ticket on VPR (a CVSS 7.5 under mass-exploitation can outrank a CVSS 9.8 with no exploit); you keep CVSS as the compliance baseline.

5. What does a cloud connector do, and what does it not do? It syncs read-only asset inventory (instances, tags, lifecycle state) from a cloud account so Tenable can reconcile “what should exist” against “what’s reporting an agent,” flag coverage gaps, and age out terminated hosts. It does not scan for CVEs — it inventories only; assessment requires an agent or a credentialed network scan (or the separate agentless CNAPP capability).

6. How do you ensure autoscaled instances are scanned? They must self-enrol from the golden image: bake the agent package into the AMI and run agent link --groups=<env> from cloud-init/user-data on first boot (never link at bake time, or clones share an identity). An instance that relies on a later config-management run boots and dies before it’s ever scanned, showing up as a perpetual coverage gap in the connector.

7. Why keep connector IAM read-only, and how is the AWS trust scoped? The connector only reads inventory, so SecurityAudit/Reader/roles/viewer are sufficient; anything broader is an audit finding waiting to happen. The AWS connector uses assume-role with an external ID condition per connector, so a leaked role ARN is useless without the matching external ID — and temporary credentials mean nothing to rotate.

8. What are dynamic tags and why do they matter? A dynamic tag is a saved rule (e.g. operating_system contains Windows AND aws:tag:env = prod) that auto-applies to any matching asset now and in future. They let scans, reports and ServiceNow queues self-populate from live metadata instead of hand-maintained lists — the mechanism that makes the program scale as the connector discovers new assets.

9. An uncredentialed network scan returns mostly “potential” findings. Why, and what’s the fix? Without credentials the scanner only sees ports and banners and infers vulnerabilities probabilistically — high false-positive, missing all local vulns. Add managed credentials (SSH key / WinRM / SNMPv3 / read-only DB) so it logs in and reads actual package/patch/config state; findings jump in both accuracy and volume.

10. How do you keep Tenable.io licensing costs honest? License is per-asset, so scan frequency is free but ghost assets inflate the bill. Age out terminated instances (ensure connectors see termination), exclude short-lived CI/build hosts where policy allows, and reconcile the licensed count against the cloud console monthly. Agent compute and connector API calls are effectively free.

11. What’s the role of exclusion windows and recast/accept rules? Exclusion windows make a scan skip a target/time (change freezes, fragile devices) — safer than pausing the whole scan, but excluded hosts are unscanned so track them. Recast changes a finding’s severity for your context; accept hides a confirmed false-positive or business-accepted risk — both should be documented and time-boxed, never used to bury real risk.

12. Where does Tenable fit alongside a CSPM tool like Wiz or Falcon Cloud Security? They are complementary: CSPM finds misconfigurations and exposure paths (public buckets, over-permissive IAM), Tenable supplies authenticated in-host CVE detail. Correlating them gives true attack-path priority — an exploitable CVE on a host that CSPM shows is internet-facing with an over-permissive role is a top ticket. See the Well-Architected Security Pillar deep dive for the layering.

These map to security certifications and role interviews — vulnerability management program design (SSCP/CISSP domains), cloud security (CCSP), and vendor-specific Tenable credentials. A compact mapping:

Question theme Relevant to
Sensor selection, agent vs network Tenable admin / VM program design
VPR vs CVSS prioritisation CISSP/CCSP risk domains; SOC lead
Connector IAM least-privilege Cloud security engineer; auditor
Dynamic tags & remediation loop Security automation; SecOps
Licensing & asset hygiene Security program / FinOps overlap

Quick check

  1. You need CVE depth on a Linux server you own, without storing or transmitting any host credentials. Which sensor, and why does it need no credentials?
  2. A brand-new autoscaled instance shows up in the AWS connector but never in the agent list. What’s the most likely cause and the fix?
  3. Your team is patching CVSS 10s but keeps getting breached through lower-CVSS bugs. What’s the fix in one sentence?
  4. True or false: a cloud connector scans your instances for vulnerabilities.
  5. agent link returns a 403 “invalid key.” What did you most likely paste, and what should you paste instead?

Answers

  1. A Nessus Agent — it runs locally as a privileged service, so its authentication is the host’s own context; it reads packages/registry/config directly and uploads results outbound, so no credentials are stored or cross the network.
  2. The instance boots and dies before a config-management run can install the agent. Fix: self-enrol from the golden image — bake the agent package into the AMI and run agent link --groups=<env> from user-data on first boot (link on first boot, not at bake time).
  3. Sort and ticket on VPR, not CVSS — VPR re-weights by real-world exploit activity, so an actively-exploited CVSS 7.5 outranks a theoretical CVSS 9.8.
  4. False. A connector syncs read-only inventory (what exists, its tags/state); it finds no CVEs. Assessment needs an agent or a credentialed network scan.
  5. You most likely pasted your API key (per-user, for REST calls). Paste the linking key instead — the single account-wide value under Settings → Sensors → Linked Agents.

Glossary

Next steps

You can now stand up authenticated scanning across a mixed estate, reconcile it against cloud inventory, prioritise by VPR, and close the loop into tickets. Build outward:

Tenable.ioNessusNessus AgentsVulnerability ManagementVPRCloud SecurityServiceNowTerraform
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading