vulnerability management

Implementing Rapid7 InsightVM for Scanning

Deploy and configure Rapid7 InsightVM Security Console and Scan Engines for authenticated and unauthenticated vulnerability scanning across enterprise environments.

asset-discoveryauthenticated-scanninginsightvmnexposerapid7scan-enginevulnerability-scanning
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Rapid7 InsightVM (formerly Nexpose) is an enterprise vulnerability management platform that combines on-premises scanning via Security Console and Scan Engines with cloud-based analytics through the Insight Platform. InsightVM leverages Rapid7's vulnerability research library, Metasploit exploit knowledge, global attacker behavior data, internet-wide scanning telemetry, and real-time reporting to provide comprehensive vulnerability visibility. This skill covers deploying the Security Console, configuring Scan Engines, setting up scan templates, credentialed scanning, and integrating with the Insight Agent for continuous assessment.

When to Use

  • When deploying or configuring implementing rapid7 insightvm for scanning capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation

Prerequisites

  • Server meeting minimum requirements: 16 GB RAM, 4 CPU cores, 500 GB disk (Security Console)
  • Scan Engine: 8 GB RAM, 4 CPU cores, 100 GB disk
  • Network access to target subnets (ports vary by scan type)
  • Administrative credentials for authenticated scanning (SSH, WMI, SNMP)
  • Rapid7 InsightVM license and Insight Platform account
  • PostgreSQL database (bundled with Security Console)

Core Concepts

InsightVM Architecture Components

Security Console

The central management server that:

  • Hosts the web-based management interface (default port 3780)
  • Stores scan results in an embedded PostgreSQL database
  • Manages Scan Engine deployments and scan schedules
  • Generates reports and dashboards
  • Connects to Rapid7 Insight Platform for cloud analytics

Note: Security Console is NOT supported in containerized environments.

Scan Engines

Distributed scanning components that:

  • Perform active network scanning against target assets
  • Can be deployed across network segments for segmented environments
  • Available as container images on Docker Hub for flexible deployment
  • Report results back to the Security Console

Insight Agent

Lightweight endpoint agent providing:

  • Continuous vulnerability assessment without network scans
  • Assessment of remote/roaming endpoints
  • Complement to engine-based scanning for comprehensive coverage
  • Real-time asset inventory updates

Scan Template Types

Template Use Case Depth
Discovery Scan Asset inventory, host enumeration Low
Full Audit without Web Spider Standard vulnerability assessment Medium
Full Audit Enhanced Logging Deep assessment with verbose logging High
HIPAA Compliance Healthcare regulatory compliance High
PCI ASV Audit PCI DSS external scanning requirement High
CIS Policy Compliance Configuration benchmarking Medium
Web Spider Web application discovery and assessment Medium

Workflow

Step 1: Install Security Console

# Download InsightVM installer (Linux)
chmod +x Rapid7Setup-Linux64.bin
./Rapid7Setup-Linux64.bin -c
 
# Verify service is running
systemctl status nexposeconsole.service
 
# Access web interface
# https://<console-ip>:3780

Initial configuration:

  1. Navigate to https://localhost:3780
  2. Complete the setup wizard with license key
  3. Configure database settings (embedded PostgreSQL recommended)
  4. Set administrator credentials
  5. Activate Insight Platform connection for cloud analytics

Step 2: Deploy Distributed Scan Engines

# Install Scan Engine on remote server
./Rapid7Setup-Linux64.bin -c
 
# During installation, select "Scan Engine only"
# Pair with Security Console using shared secret
 
# Docker-based Scan Engine deployment
docker pull rapid7/insightvm-scan-engine
docker run -d \
  --name scan-engine \
  -p 40814:40814 \
  -e CONSOLE_HOST=<console-ip> \
  -e CONSOLE_PORT=3780 \
  -e ENGINE_NAME=DMZ-Scanner \
  -e SHARED_SECRET=<pairing-secret> \
  rapid7/insightvm-scan-engine

Pair engines in Security Console:

  1. Administration > Scan Engines > New Scan Engine
  2. Enter engine hostname/IP and port (default 40814)
  3. Use shared secret for authentication
  4. Verify connectivity status shows "Active"

Step 3: Configure Asset Discovery Sites

Site Configuration:
  Name:           Production-Network
  Scan Engine:    Primary-Engine-01
  Scan Template:  Full Audit without Web Spider
 
  Included Assets:
    - 10.0.0.0/8     (Internal network)
    - 172.16.0.0/12   (DMZ network)
 
  Excluded Assets:
    - 10.0.0.1        (Core router - fragile)
    - 10.0.100.0/24   (ICS/SCADA segment)
 
  Schedule:
    Frequency:    Weekly
    Day:          Sunday
    Time:         02:00 AM
    Max Duration: 8 hours

Step 4: Configure Authenticated Scanning

Windows Credentials (WMI)

Credential Type:    Microsoft Windows/Samba (SMB/CIFS)
Domain:             CORP.EXAMPLE.COM
Username:           svc_insightvm_scan
Password:           <service-account-password>
Authentication:     NTLM
 
Privilege Elevation:
  Type:   None (use domain admin or local admin)

Linux/Unix Credentials (SSH)

Credential Type:    Secure Shell (SSH)
Username:           insightvm_scan
Authentication:     SSH Key (preferred) or Password
SSH Private Key:    /opt/rapid7/.ssh/scan_key
Port:               22
 
Privilege Elevation:
  Type:             sudo
  sudo User:        root
  sudo Password:    <sudo-password>

Database Credentials

Credential Type:    Microsoft SQL Server
Instance:           MSSQLSERVER
Domain:             CORP
Username:           insightvm_db_scan
Authentication:     Windows Authentication
 
Credential Type:    Oracle
Port:               1521
SID:                ORCL
Username:           insightvm_scan

Step 5: Configure Scan Templates

Custom scan template for balanced scanning:

Template Name:      Enterprise-Standard-Scan
 
Service Discovery:
  TCP Ports:        Well-known (1-1024) + common services
  UDP Ports:        DNS(53), SNMP(161), NTP(123), TFTP(69)
  Method:           SYN scan (stealth)
 
Vulnerability Checks:
  Safe checks only: Enabled
  Skip potential:   Disabled
  Web spidering:    Disabled (separate template)
  Policy checks:    Enabled (CIS benchmarks)
 
Performance:
  Max parallel assets:     10
  Max requests per second: 100
  Timeout per asset:       30 minutes
  Retries:                 2

Step 6: Set Up Insight Agent Deployment

# Windows Agent Installation (via GPO or SCCM)
msiexec /i agentInstaller-x86_64.msi /quiet /norestart `
  CUSTOMTOKEN=<platform-token> `
  CUSTOMCONFIG=<agent-config>
 
# Linux Agent Installation
chmod +x agent_installer.sh
./agent_installer.sh install_start \
  --token <platform-token>
 
# Verify agent connectivity
# Check InsightVM console: Assets > Agent Management

Step 7: Configure Remediation Workflows

Remediation Project:
  Name:             Q1-2025-Critical-Remediation
 
  Scope:
    Severity:       Critical + High
    CVSS Score:     >= 7.0
    Assets:         Production-Network site
 
  Assignment:
    Team:           Infrastructure-Ops
    Due Date:       2025-03-31
 
  Tracking:
    Auto-verify:    Enabled (re-scan on next scheduled scan)
    Notification:   Email on overdue items
    Escalation:     Manager notification at 75% SLA

Step 8: API Integration for Automation

import requests
import json
 
class InsightVMClient:
    """Rapid7 InsightVM API v3 client for automation."""
 
    def __init__(self, console_url, api_key):
        self.base_url = f"{console_url}/api/3"
        self.session = requests.Session()
        self.session.headers.update({
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}"
        })
        self.session.verify = not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true"  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
 
    def get_sites(self):
        """List all configured scan sites."""
        response = self.session.get(f"{self.base_url}/sites")
        response.raise_for_status()
        return response.json().get("resources", [])
 
    def start_scan(self, site_id, engine_id=None, template_id=None):
        """Trigger an ad-hoc scan for a site."""
        payload = {}
        if engine_id:
            payload["engineId"] = engine_id
        if template_id:
            payload["templateId"] = template_id
 
        response = self.session.post(
            f"{self.base_url}/sites/{site_id}/scans",
            json=payload
        )
        response.raise_for_status()
        return response.json()
 
    def get_asset_vulnerabilities(self, asset_id):
        """Retrieve vulnerabilities for a specific asset."""
        response = self.session.get(
            f"{self.base_url}/assets/{asset_id}/vulnerabilities"
        )
        response.raise_for_status()
        return response.json().get("resources", [])
 
    def get_scan_status(self, scan_id):
        """Check the status of a running scan."""
        response = self.session.get(f"{self.base_url}/scans/{scan_id}")
        response.raise_for_status()
        return response.json()
 
    def create_remediation_project(self, name, description, assets, vulns):
        """Create a remediation tracking project."""
        payload = {
            "name": name,
            "description": description,
            "assets": {"includedTargets": {"addresses": assets}},
            "vulnerabilities": {"includedVulnerabilities": vulns}
        }
        response = self.session.post(
            f"{self.base_url}/remediations",
            json=payload
        )
        response.raise_for_status()
        return response.json()
 
 
# Usage
client = InsightVMClient("https://insightvm-console:3780", "api-key-here")
sites = client.get_sites()
for site in sites:
    print(f"Site: {site['name']} - Assets: {site.get('assets', 0)}")

Best Practices

  1. Deploy Scan Engines close to target networks to minimize scan traffic traversing firewalls
  2. Use Insight Agents for roaming laptops and remote workers that are not always reachable by network scans
  3. Combine agent-based and engine-based scanning for the most accurate vulnerability view
  4. Configure scan blackout windows during business-critical hours to avoid operational impact
  5. Use credential testing before full scans to validate authentication works
  6. Enable safe checks to prevent accidental denial of service on production systems
  7. Separate scan sites by network segment, business unit, or compliance scope
  8. Leverage tag-based asset groups for dynamic reporting and remediation tracking

Common Pitfalls

  • Running full scans during business hours causing network congestion or service degradation
  • Using unauthenticated scans only, missing 60-80% of local vulnerabilities
  • Not excluding fragile devices (printers, ICS/SCADA, medical devices) from aggressive scan templates
  • Failing to distribute Scan Engines across network segments, causing firewall bottlenecks
  • Ignoring scan engine resource utilization leading to incomplete scans
  • Not configuring scan duration limits, allowing runaway scans to consume resources indefinitely
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md4.6 KB

API Reference: Rapid7 InsightVM Vulnerability Scanning

Libraries Used

Library Purpose
requests HTTP client for InsightVM REST API v3
json Parse scan results and vulnerability data
base64 Encode Basic Auth credentials
os Read INSIGHTVM_URL, INSIGHTVM_USER, INSIGHTVM_PASS

Installation

pip install requests

Authentication

InsightVM API v3 uses HTTP Basic Authentication:

import requests
import os
from requests.auth import HTTPBasicAuth
 
INSIGHTVM_URL = os.environ.get("INSIGHTVM_URL", "https://insightvm.example.com:3780")
auth = HTTPBasicAuth(
    os.environ["INSIGHTVM_USER"],
    os.environ["INSIGHTVM_PASS"],
)

REST API v3 Endpoints

Method Endpoint Description
GET /api/3/sites List all scan sites
GET /api/3/sites/{id} Get site details
POST /api/3/sites Create a new site
GET /api/3/sites/{id}/assets List assets in a site
POST /api/3/sites/{id}/scans Launch a scan on a site
GET /api/3/scans List all scans
GET /api/3/scans/{id} Get scan status and details
GET /api/3/assets List all assets
GET /api/3/assets/{id} Get asset details
GET /api/3/assets/{id}/vulnerabilities Get vulnerabilities for asset
GET /api/3/vulnerabilities List all known vulnerabilities
GET /api/3/vulnerabilities/{id} Get vulnerability details
GET /api/3/vulnerability_checks List vulnerability checks
GET /api/3/scan_engines List scan engines
GET /api/3/reports List generated reports
POST /api/3/reports Create a report configuration
POST /api/3/reports/{id}/generate Generate a report
GET /api/3/tags List all tags
GET /api/3/policies List compliance policies

Core Operations

List Sites

resp = requests.get(
    f"{INSIGHTVM_URL}/api/3/sites",
    auth=auth,
    params={"page": 0, "size": 100},
    timeout=30,
    verify=True,
)
for site in resp.json().get("resources", []):
    print(f"Site: {site['name']} (ID: {site['id']}) — {site.get('description', '')}")

Launch a Scan

resp = requests.post(
    f"{INSIGHTVM_URL}/api/3/sites/{site_id}/scans",
    auth=auth,
    json={"engineId": engine_id},
    timeout=30,
    verify=True,
)
scan_id = resp.json()["id"]

Poll Scan Status

import time
 
while True:
    resp = requests.get(
        f"{INSIGHTVM_URL}/api/3/scans/{scan_id}",
        auth=auth,
        timeout=30,
        verify=True,
    )
    status = resp.json()["status"]
    if status in ("finished", "stopped", "error"):
        break
    time.sleep(30)

Get Asset Vulnerabilities

resp = requests.get(
    f"{INSIGHTVM_URL}/api/3/assets/{asset_id}/vulnerabilities",
    auth=auth,
    params={"page": 0, "size": 500},
    timeout=60,
    verify=True,
)
vulns = resp.json().get("resources", [])
for v in vulns:
    print(f"  {v['id']} — CVSS: {v.get('cvssV3Score', 'N/A')}{v.get('status')}")

Get Vulnerability Details

resp = requests.get(
    f"{INSIGHTVM_URL}/api/3/vulnerabilities/{vuln_id}",
    auth=auth,
    timeout=30,
    verify=True,
)
vuln = resp.json()
# Fields: title, description, cvss, severity, publishedDate, references, exploits

Generate a Report

report_config = {
    "name": "Monthly Vuln Report",
    "format": "pdf",
    "scope": {"sites": [site_id]},
    "template": "audit-report",
}
resp = requests.post(
    f"{INSIGHTVM_URL}/api/3/reports",
    auth=auth,
    json=report_config,
    timeout=30,
    verify=True,
)
report_id = resp.json()["id"]
 
# Generate the report
requests.post(
    f"{INSIGHTVM_URL}/api/3/reports/{report_id}/generate",
    auth=auth,
    timeout=30,
    verify=True,
)

Pagination

All list endpoints support cursor-based pagination:

def paginate(endpoint, auth, params=None):
    params = params or {}
    params.setdefault("size", 500)
    page = 0
    while True:
        params["page"] = page
        resp = requests.get(endpoint, auth=auth, params=params, timeout=60, verify=True)
        data = resp.json()
        yield from data.get("resources", [])
        if page >= data.get("page", {}).get("totalPages", 1) - 1:
            break
        page += 1

Output Format

{
  "id": 12345,
  "status": "finished",
  "vulnerabilities": {
    "critical": 3,
    "severe": 12,
    "moderate": 45,
    "total": 60
  },
  "assets": 128,
  "startTime": "2025-01-15T08:00:00Z",
  "endTime": "2025-01-15T09:45:00Z",
  "engineName": "Local Scan Engine"
}
standards.md1.5 KB

Standards and References - Rapid7 InsightVM

Official Documentation

Scan Configuration References

Industry Standards

  • NIST SP 800-115: Technical Guide to Information Security Testing and Assessment
  • NIST SP 800-40 Rev 4: Guide to Enterprise Patch Management Planning
  • PCI DSS v4.0 Req 11.3: External and internal vulnerability scanning
  • CIS Controls v8.1 Control 7: Continuous Vulnerability Management
  • ISO 27001:2022 A.8.8: Management of technical vulnerabilities

Compliance Scan Templates

Standard InsightVM Template Frequency
PCI DSS PCI ASV External Audit Quarterly
HIPAA HIPAA Compliance Quarterly
CIS Benchmarks CIS Policy Compliance Monthly
DISA STIG DISA STIG Compliance Monthly
NIST 800-53 Full Audit Enhanced Quarterly
workflows.md5.7 KB

Workflows - Rapid7 InsightVM Deployment

Workflow 1: InsightVM Deployment Pipeline

┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│ Install Security │────>│ Deploy Scan      │────>│ Pair Engines     │
│ Console          │     │ Engines          │     │ with Console     │
└──────────────────┘     └──────────────────┘     └──────────────────┘

        ┌────────────────────────────────────────────────┘
        v
┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│ Configure Scan   │────>│ Set Up Credential│────>│ Create Sites &   │
│ Templates        │     │ Store            │     │ Asset Groups     │
└──────────────────┘     └──────────────────┘     └──────────────────┘

        v
┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│ Schedule Scans   │────>│ Deploy Insight   │────>│ Configure        │
│                  │     │ Agents           │     │ Reports & Alerts │
└──────────────────┘     └──────────────────┘     └──────────────────┘

Workflow 2: Scan Execution Cycle

For each scheduled scan:
    1. Console dispatches scan job to assigned Scan Engine
    2. Engine performs host discovery (ARP, ICMP, TCP SYN)
    3. Engine fingerprints OS and services on discovered hosts
    4. Engine selects vulnerability checks based on fingerprint
    5. If credentials configured: authenticate and perform local checks
    6. Engine reports findings back to Console database
    7. Console correlates with previous scan data (new/fixed/unchanged)
    8. Console updates risk scores and remediation projects
    9. Notifications sent for new critical/high findings
   10. Dashboard and reports refreshed automatically

Workflow 3: Hybrid Scanning Strategy

┌─────────────────────────────────────────────────────┐
│                 Enterprise Network                    │
├─────────────────────────────────────────────────────┤
│                                                       │
│  ┌──────────────┐  Engine Scan   ┌────────────────┐ │
│  │ Data Center  │ <───────────── │ DC Scan Engine │ │
│  │ Servers      │                └────────────────┘ │
│  └──────────────┘                                    │
│                                                       │
│  ┌──────────────┐  Engine Scan   ┌────────────────┐ │
│  │ DMZ Servers  │ <───────────── │ DMZ Scan Engine│ │
│  └──────────────┘                └────────────────┘ │
│                                                       │
│  ┌──────────────┐  Agent-Based   ┌────────────────┐ │
│  │ Laptops /    │ <───────────── │ Insight Agent  │ │
│  │ Remote Users │                │ (on endpoint)  │ │
│  └──────────────┘                └────────────────┘ │
│                                                       │
│  ┌──────────────┐  Agent-Based   ┌────────────────┐ │
│  │ Cloud VMs    │ <───────────── │ Insight Agent  │ │
│  │ (AWS/Azure)  │                │ (on instance)  │ │
│  └──────────────┘                └────────────────┘ │
│                                                       │
│           All results ──> Security Console            │
│                        ──> Insight Platform (Cloud)   │
└─────────────────────────────────────────────────────┘

Workflow 4: Remediation Tracking

Phase Action Owner Timeline
Discovery Scan identifies vulnerability InsightVM Automated
Triage Severity confirmed, assigned to team Security Ops 24 hours
Remediation Patch/config change applied IT Operations Per SLA
Validation Re-scan confirms fix InsightVM Next scan cycle
Closure Remediation project updated Security Ops Automated

Scripts 2

agent.py9.1 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Rapid7 InsightVM vulnerability scanning agent.

Interfaces with the InsightVM (Nexpose) REST API to manage scan
configurations, launch scans, retrieve vulnerability results, and
generate remediation reports. Supports site management, asset
discovery, and vulnerability prioritization.
"""
import argparse
import json
import os
import sys
import time
from datetime import datetime, timezone

try:
    import requests
    from requests.auth import HTTPBasicAuth
except ImportError:
    print("[!] 'requests' required: pip install requests", file=sys.stderr)
    sys.exit(1)


def get_insightvm_config():
    """Return InsightVM API connection config."""
    host = os.environ.get("INSIGHTVM_HOST", "localhost")
    port = os.environ.get("INSIGHTVM_PORT", "3780")
    user = os.environ.get("INSIGHTVM_USER", "")
    password = os.environ.get("INSIGHTVM_PASSWORD", "")
    return f"https://{host}:{port}", user, password


def api_call(base_url, endpoint, user, password, method="GET",
             data=None, params=None):
    """Make authenticated API call to InsightVM."""
    url = f"{base_url}/api/3{endpoint}"
    auth = HTTPBasicAuth(user, password)
    headers = {"Content-Type": "application/json", "Accept": "application/json"}
    if method == "POST":
        resp = requests.post(url, auth=auth, headers=headers, json=data,
                             params=params,
                             verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=60)  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
    elif method == "PUT":
        resp = requests.put(url, auth=auth, headers=headers, json=data,
                            verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=60)  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
    else:
        resp = requests.get(url, auth=auth, headers=headers, params=params,
                            verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=60)  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
    resp.raise_for_status()
    return resp.json()


def list_sites(base_url, user, password):
    """List all scan sites."""
    print("[*] Listing sites...")
    data = api_call(base_url, "/sites", user, password, params={"size": 500})
    sites = []
    for site in data.get("resources", []):
        sites.append({
            "id": site.get("id"),
            "name": site.get("name", ""),
            "description": site.get("description", ""),
            "type": site.get("type", ""),
            "assets": site.get("assets", 0),
            "last_scan_time": site.get("lastScanTime", ""),
            "risk_score": site.get("riskScore", 0),
        })
    print(f"[+] Found {len(sites)} sites")
    return sites


def get_site_vulnerabilities(base_url, user, password, site_id):
    """Get vulnerabilities for a specific site."""
    print(f"[*] Fetching vulnerabilities for site {site_id}...")
    vulns = []
    page = 0
    while True:
        data = api_call(base_url, f"/sites/{site_id}/vulnerabilities",
                        user, password, params={"page": page, "size": 100})
        resources = data.get("resources", [])
        if not resources:
            break
        for v in resources:
            vulns.append({
                "id": v.get("id", ""),
                "title": v.get("title", ""),
                "severity": v.get("severity", ""),
                "cvss_v3_score": v.get("cvss", {}).get("v3", {}).get("score", 0),
                "risk_score": v.get("riskScore", 0),
                "instances": v.get("instances", 0),
                "status": v.get("status", ""),
            })
        page += 1
        total_pages = data.get("page", {}).get("totalPages", 1)
        if page >= total_pages:
            break

    print(f"[+] Retrieved {len(vulns)} vulnerabilities")
    return vulns


def launch_scan(base_url, user, password, site_id, scan_name=None):
    """Launch a scan on a site."""
    if not scan_name:
        scan_name = f"agent-scan-{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M%S')}"
    print(f"[*] Launching scan '{scan_name}' on site {site_id}...")
    data = api_call(base_url, f"/sites/{site_id}/scans", user, password,
                    method="POST", data={"name": scan_name})
    scan_id = data.get("id")
    print(f"[+] Scan started, ID: {scan_id}")
    return scan_id


def poll_scan_status(base_url, user, password, scan_id, max_wait=1800):
    """Poll scan status until completion."""
    print(f"[*] Waiting for scan {scan_id} to complete...")
    elapsed = 0
    interval = 30
    while elapsed < max_wait:
        data = api_call(base_url, f"/scans/{scan_id}", user, password)
        status = data.get("status", "unknown")
        if status in ("finished", "stopped", "error"):
            print(f"[+] Scan {status}")
            return status, data
        print(f"    Status: {status} ({elapsed}s)")
        time.sleep(interval)
        elapsed += interval
    print("[!] Scan timed out")
    return "timeout", {}


def get_scan_report(base_url, user, password, scan_id):
    """Get scan results summary."""
    data = api_call(base_url, f"/scans/{scan_id}", user, password)
    return {
        "scan_id": scan_id,
        "status": data.get("status", ""),
        "start_time": data.get("startTime", ""),
        "end_time": data.get("endTime", ""),
        "duration": data.get("duration", ""),
        "assets_discovered": data.get("assets", 0),
        "vulnerabilities": data.get("vulnerabilities", {}),
    }


def format_summary(sites, vulns=None, scan_report=None):
    """Print summary."""
    print(f"\n{'='*60}")
    print(f"  Rapid7 InsightVM Report")
    print(f"{'='*60}")

    if sites:
        print(f"\n  Sites ({len(sites)}):")
        for s in sites:
            print(f"    {s['name']:30s} | Assets: {s['assets']:5d} | "
                  f"Risk: {s['risk_score']:8.1f}")

    if vulns:
        severity_counts = {}
        for v in vulns:
            sev = v.get("severity", "unknown")
            severity_counts[sev] = severity_counts.get(sev, 0) + 1
        print(f"\n  Vulnerabilities ({len(vulns)}):")
        for sev in sorted(severity_counts.keys()):
            print(f"    {sev:15s}: {severity_counts[sev]}")

    if scan_report:
        print(f"\n  Scan Report:")
        print(f"    Status    : {scan_report.get('status', 'N/A')}")
        print(f"    Assets    : {scan_report.get('assets_discovered', 0)}")


def main():
    parser = argparse.ArgumentParser(description="Rapid7 InsightVM scanning agent")
    sub = parser.add_subparsers(dest="command")

    sub.add_parser("list-sites", help="List scan sites")

    p_vulns = sub.add_parser("get-vulns", help="Get site vulnerabilities")
    p_vulns.add_argument("--site-id", required=True, type=int)

    p_scan = sub.add_parser("scan", help="Launch a scan")
    p_scan.add_argument("--site-id", required=True, type=int)
    p_scan.add_argument("--wait", action="store_true", help="Wait for completion")
    p_scan.add_argument("--max-wait", type=int, default=1800)

    parser.add_argument("--host", help="InsightVM host (or INSIGHTVM_HOST env)")
    parser.add_argument("--user", help="Username (or INSIGHTVM_USER env)")
    parser.add_argument("--password", help="Password (or INSIGHTVM_PASSWORD env)")
    parser.add_argument("--output", "-o", help="Output JSON report")
    parser.add_argument("--verbose", "-v", action="store_true")
    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        sys.exit(1)

    if args.host:
        os.environ["INSIGHTVM_HOST"] = args.host
    if args.user:
        os.environ["INSIGHTVM_USER"] = args.user
    if args.password:
        os.environ["INSIGHTVM_PASSWORD"] = args.password

    base_url, user, password = get_insightvm_config()
    if not user or not password:
        print("[!] Set INSIGHTVM_USER and INSIGHTVM_PASSWORD", file=sys.stderr)
        sys.exit(1)

    result = {}
    if args.command == "list-sites":
        sites = list_sites(base_url, user, password)
        format_summary(sites)
        result = {"sites": sites}
    elif args.command == "get-vulns":
        vulns = get_site_vulnerabilities(base_url, user, password, args.site_id)
        format_summary([], vulns)
        result = {"site_id": args.site_id, "vulnerabilities": vulns}
    elif args.command == "scan":
        scan_id = launch_scan(base_url, user, password, args.site_id)
        if args.wait:
            status, data = poll_scan_status(base_url, user, password, scan_id, args.max_wait)
            scan_report = get_scan_report(base_url, user, password, scan_id)
            format_summary([], scan_report=scan_report)
            result = {"scan_id": scan_id, "report": scan_report}
        else:
            result = {"scan_id": scan_id, "status": "launched"}

    report = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "tool": "Rapid7 InsightVM",
        "command": args.command,
        "result": result,
    }

    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2)
        print(f"\n[+] Report saved to {args.output}")
    elif args.verbose:
        print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()
process.py11.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Rapid7 InsightVM Scan Automation and Reporting Tool

Automates scan operations, asset queries, and vulnerability reporting
via the InsightVM API v3.

Requirements:
    pip install requests pandas tabulate

Usage:
    python process.py sites                          # List all sites
    python process.py scan --site-id 1               # Start scan for site
    python process.py status --scan-id 12345         # Check scan status
    python process.py vulns --asset-id 42            # Get asset vulnerabilities
    python process.py report --site-id 1 --output report.csv  # Export report
"""

import argparse
import json
import os
import sys
import time
import urllib3
from datetime import datetime

import pandas as pd
import requests

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


class InsightVMAPI:
    """Rapid7 InsightVM API v3 client."""

    def __init__(self, console_url, username=None, password=None, api_key=None):
        self.base_url = f"{console_url.rstrip('/')}/api/3"
        self.session = requests.Session()
        self.session.verify = not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true"  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments

        if api_key:
            self.session.headers.update({
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json"
            })
        elif username and password:
            self.session.auth = (username, password)
            self.session.headers.update({"Content-Type": "application/json"})
        else:
            raise ValueError("Provide either api_key or username/password")

    def _get_paginated(self, endpoint, params=None):
        """Fetch all pages from a paginated endpoint."""
        all_resources = []
        page = 0
        while True:
            p = params.copy() if params else {}
            p["page"] = page
            p["size"] = 100
            response = self.session.get(
                f"{self.base_url}/{endpoint}", params=p, timeout=60
            )
            response.raise_for_status()
            data = response.json()
            resources = data.get("resources", [])
            all_resources.extend(resources)
            total_pages = data.get("page", {}).get("totalPages", 1)
            page += 1
            if page >= total_pages:
                break
        return all_resources

    def list_sites(self):
        """List all scan sites."""
        return self._get_paginated("sites")

    def get_site(self, site_id):
        """Get details for a specific site."""
        response = self.session.get(
            f"{self.base_url}/sites/{site_id}", timeout=30
        )
        response.raise_for_status()
        return response.json()

    def start_scan(self, site_id, engine_id=None, template_id=None, hosts=None):
        """Start a scan for a site."""
        payload = {}
        if engine_id:
            payload["engineId"] = engine_id
        if template_id:
            payload["templateId"] = template_id
        if hosts:
            payload["hosts"] = hosts

        response = self.session.post(
            f"{self.base_url}/sites/{site_id}/scans",
            json=payload, timeout=30
        )
        response.raise_for_status()
        return response.json()

    def get_scan_status(self, scan_id):
        """Get the status of a scan."""
        response = self.session.get(
            f"{self.base_url}/scans/{scan_id}", timeout=30
        )
        response.raise_for_status()
        return response.json()

    def wait_for_scan(self, scan_id, poll_interval=30, timeout=3600):
        """Wait for a scan to complete."""
        start_time = time.time()
        while time.time() - start_time < timeout:
            status = self.get_scan_status(scan_id)
            state = status.get("status", "unknown")
            print(f"  Scan {scan_id}: {state} "
                  f"({status.get('assets', 0)} assets, "
                  f"{status.get('vulnerabilities', {}).get('total', 0)} vulns)")
            if state in ("finished", "stopped", "error", "aborted"):
                return status
            time.sleep(poll_interval)
        print(f"  [!] Scan timeout after {timeout}s")
        return None

    def get_site_assets(self, site_id):
        """Get all assets for a site."""
        return self._get_paginated(f"sites/{site_id}/assets")

    def get_asset_vulnerabilities(self, asset_id):
        """Get vulnerabilities for a specific asset."""
        return self._get_paginated(f"assets/{asset_id}/vulnerabilities")

    def get_vulnerability_details(self, vuln_id):
        """Get details for a specific vulnerability."""
        response = self.session.get(
            f"{self.base_url}/vulnerabilities/{vuln_id}", timeout=30
        )
        response.raise_for_status()
        return response.json()

    def list_scan_engines(self):
        """List all scan engines."""
        return self._get_paginated("scan_engines")

    def list_scan_templates(self):
        """List available scan templates."""
        return self._get_paginated("scan_templates")


def cmd_list_sites(api):
    """List all configured sites."""
    sites = api.list_sites()
    if not sites:
        print("No sites configured.")
        return

    print(f"\n{'ID':<6} {'Name':<35} {'Assets':<10} {'Last Scan':<20}")
    print("-" * 75)
    for site in sites:
        last_scan = site.get("lastScanTime", "Never")
        if last_scan != "Never":
            last_scan = last_scan[:19]
        print(f"{site['id']:<6} {site['name'][:34]:<35} "
              f"{site.get('assets', 0):<10} {last_scan:<20}")


def cmd_start_scan(api, site_id, engine_id=None, template_id=None, wait=False):
    """Start a scan for a site."""
    print(f"[*] Starting scan for site {site_id}...")
    result = api.start_scan(site_id, engine_id, template_id)
    scan_id = result.get("id")
    print(f"[+] Scan started: ID={scan_id}")

    if wait and scan_id:
        print("[*] Waiting for scan to complete...")
        final_status = api.wait_for_scan(scan_id)
        if final_status:
            print(f"\n[+] Scan completed: {final_status.get('status')}")
            vulns = final_status.get("vulnerabilities", {})
            print(f"    Total vulnerabilities: {vulns.get('total', 0)}")
            print(f"    Critical: {vulns.get('critical', 0)}")
            print(f"    Severe: {vulns.get('severe', 0)}")
            print(f"    Moderate: {vulns.get('moderate', 0)}")


def cmd_scan_status(api, scan_id):
    """Check scan status."""
    status = api.get_scan_status(scan_id)
    print(f"\nScan ID:     {status.get('id')}")
    print(f"Status:      {status.get('status')}")
    print(f"Start Time:  {status.get('startTime', 'N/A')}")
    print(f"End Time:    {status.get('endTime', 'N/A')}")
    print(f"Assets:      {status.get('assets', 0)}")
    vulns = status.get("vulnerabilities", {})
    print(f"Vulns Total: {vulns.get('total', 0)}")
    print(f"  Critical:  {vulns.get('critical', 0)}")
    print(f"  Severe:    {vulns.get('severe', 0)}")
    print(f"  Moderate:  {vulns.get('moderate', 0)}")


def cmd_asset_vulns(api, asset_id):
    """List vulnerabilities for an asset."""
    vulns = api.get_asset_vulnerabilities(asset_id)
    if not vulns:
        print(f"No vulnerabilities found for asset {asset_id}.")
        return

    print(f"\nVulnerabilities for asset {asset_id}: {len(vulns)} total\n")
    print(f"{'Vuln ID':<40} {'Severity':<10} {'CVSS':<8} {'Status':<12}")
    print("-" * 72)
    for v in sorted(vulns, key=lambda x: x.get("severity", ""), reverse=True):
        print(f"{v.get('id', 'N/A')[:39]:<40} "
              f"{v.get('severity', 'N/A'):<10} "
              f"{v.get('cvssV3Score', 'N/A'):<8} "
              f"{v.get('status', 'N/A'):<12}")


def cmd_export_report(api, site_id, output_file):
    """Export vulnerability report for a site to CSV."""
    print(f"[*] Fetching assets for site {site_id}...")
    assets = api.get_site_assets(site_id)
    print(f"[+] Found {len(assets)} assets")

    all_findings = []
    for asset in assets:
        asset_id = asset.get("id")
        hostname = asset.get("hostName", asset.get("ip", "unknown"))
        ip = asset.get("ip", "N/A")
        os_name = asset.get("os", {}).get("description", "Unknown")

        vulns = api.get_asset_vulnerabilities(asset_id)
        for v in vulns:
            all_findings.append({
                "asset_id": asset_id,
                "hostname": hostname,
                "ip_address": ip,
                "os": os_name,
                "vulnerability_id": v.get("id", ""),
                "severity": v.get("severity", ""),
                "cvss_v3_score": v.get("cvssV3Score", ""),
                "status": v.get("status", ""),
                "first_found": v.get("since", ""),
            })

        print(f"  Processed {hostname}: {len(vulns)} vulnerabilities")

    if all_findings:
        df = pd.DataFrame(all_findings)
        df = df.sort_values(["cvss_v3_score", "severity"], ascending=[False, False])
        df.to_csv(output_file, index=False)
        print(f"\n[+] Report exported to {output_file}")
        print(f"    Total findings: {len(all_findings)}")
        print(f"\n    Severity Distribution:")
        print(df["severity"].value_counts().to_string())
    else:
        print("[!] No findings to export.")


def main():
    parser = argparse.ArgumentParser(
        description="Rapid7 InsightVM Scan Automation Tool"
    )
    parser.add_argument("--console", default="https://localhost:3780",
                        help="InsightVM console URL")
    parser.add_argument("--username", help="Console username")
    parser.add_argument("--password", help="Console password")
    parser.add_argument("--api-key", help="API key (alternative to user/pass)")

    subparsers = parser.add_subparsers(dest="command")

    subparsers.add_parser("sites", help="List all scan sites")

    scan_p = subparsers.add_parser("scan", help="Start a scan")
    scan_p.add_argument("--site-id", type=int, required=True)
    scan_p.add_argument("--engine-id", type=int)
    scan_p.add_argument("--template-id", type=str)
    scan_p.add_argument("--wait", action="store_true")

    status_p = subparsers.add_parser("status", help="Check scan status")
    status_p.add_argument("--scan-id", type=int, required=True)

    vuln_p = subparsers.add_parser("vulns", help="List asset vulnerabilities")
    vuln_p.add_argument("--asset-id", type=int, required=True)

    report_p = subparsers.add_parser("report", help="Export vulnerability report")
    report_p.add_argument("--site-id", type=int, required=True)
    report_p.add_argument("--output", default="insightvm_report.csv")

    subparsers.add_parser("engines", help="List scan engines")
    subparsers.add_parser("templates", help="List scan templates")

    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        sys.exit(1)

    api = InsightVMAPI(
        args.console,
        username=args.username,
        password=args.password,
        api_key=args.api_key
    )

    if args.command == "sites":
        cmd_list_sites(api)
    elif args.command == "scan":
        cmd_start_scan(api, args.site_id, args.engine_id,
                       args.template_id, args.wait)
    elif args.command == "status":
        cmd_scan_status(api, args.scan_id)
    elif args.command == "vulns":
        cmd_asset_vulns(api, args.asset_id)
    elif args.command == "report":
        cmd_export_report(api, args.site_id, args.output)
    elif args.command == "engines":
        engines = api.list_scan_engines()
        for e in engines:
            print(f"  Engine {e['id']}: {e['name']} - {e.get('address', 'N/A')}")
    elif args.command == "templates":
        templates = api.list_scan_templates()
        for t in templates:
            print(f"  {t['id']}: {t['name']}")


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 1.4 KB
Keep exploring