The Scans API module provides comprehensive functionality for managing vulnerability scans in InsightVM, including starting scans, monitoring progress, and controlling scan execution.
- Overview
- Quick Start
- Core Operations
- Scan Control
- Monitoring and Status
- Helper Methods
- Common Use Cases
- Best Practices
The ScansAPI class provides methods for:
- Listing and retrieving scans with pagination
- Starting scans for sites with customizable options
- Controlling scan execution (stop, pause, resume)
- Monitoring scan status and progress
- Retrieving scan history and results
- Automatic pagination for bulk operations
All operations follow the v2.0 BaseAPI pattern with proper authentication, error handling, and type hints.
from rapid7 import InsightVMClient
# Create client
client = InsightVMClient()
# List all scans
scans = client.scans.list()
print(f"Found {len(scans['resources'])} scans")
# Start a scan
scan_id = client.scans.start_site_scan(
site_id=42,
scan_name="Weekly Security Audit"
)
print(f"Started scan {scan_id}")
# Monitor scan status
scan = client.scans.get_scan(scan_id)
print(f"Status: {scan['status']}")Retrieve a paginated list of scans with optional filtering:
# Get all scans (paginated)
scans = client.scans.list(page=0, size=100)
# Get only active (running) scans
active_scans = client.scans.list(active=True)
# Get completed scans sorted by end time
completed = client.scans.list(
active=False,
sort=["endTime,DESC"]
)
# Custom pagination
scans = client.scans.list(
page=2,
size=50,
sort=["startTime,DESC"]
)Retrieve comprehensive information about a specific scan:
# Get scan by ID
scan = client.scans.get_scan(12345)
# Access scan properties
print(f"Name: {scan['scanName']}")
print(f"Status: {scan['status']}")
print(f"Assets: {scan['assets']}")
print(f"Duration: {scan['duration']}")
# Vulnerability counts
vulns = scan['vulnerabilities']
print(f"Critical: {vulns['critical']}")
print(f"Severe: {vulns['severe']}")
print(f"Total: {vulns['total']}")Retrieve all scans for a specific site:
# Get all scans for a site
site_scans = client.scans.get_site_scans(site_id=42)
# Get only active scans for site
active = client.scans.get_site_scans(
site_id=42,
active=True
)
# Get paginated site scans
scans = client.scans.get_site_scans(
site_id=42,
page=0,
size=50,
sort=["startTime,DESC"]
)Initiate a new scan with various configuration options:
# Basic scan with defaults
scan_id = client.scans.start_site_scan(site_id=42)
# Customized scan
scan_id = client.scans.start_site_scan(
site_id=42,
scan_name="Monthly Security Audit",
scan_template_id="full-audit-without-web-spider",
hosts=["192.168.1.10", "192.168.1.20"],
override_blackout=True
)
# Scan with specific engine
scan_id = client.scans.start_site_scan(
site_id=42,
engine_id=5,
scan_name="Datacenter Scan"
)
# Scan with asset groups
scan_id = client.scans.start_site_scan(
site_id=42,
asset_group_ids=[10, 11, 12],
scan_template_id="discovery"
)full-audit-without-web-spider- Comprehensive scan without web app testingfull-audit- Complete vulnerability assessment including web appsdiscovery- Quick discovery scanexhaustive- Thorough scan with all checks enabled
Stop a running or paused scan:
# Stop a scan
result = client.scans.stop_scan(scan_id=12345)
# Verify stopped
scan = client.scans.get_scan(12345)
if scan['status'] == 'stopped':
print("Scan stopped successfully")Temporarily pause a running scan:
# Pause a scan
result = client.scans.pause_scan(scan_id=12345)
# Check status
scan = client.scans.get_scan(12345)
print(f"Status: {scan['status']}") # Should be 'paused'Resume a paused scan:
# Resume a paused scan
result = client.scans.resume_scan(scan_id=12345)
# Verify resumed
scan = client.scans.get_scan(12345)
if scan['status'] == 'running':
print("Scan resumed successfully")# Check if scan is running
if client.scans.is_scan_running(12345):
print("Scan is still in progress")
else:
print("Scan has completed")
# Get detailed status
scan = client.scans.get_scan(12345)
print(f"Status: {scan['status']}")
print(f"Message: {scan['message']}")Block until a scan completes:
# Start scan and wait for completion
scan_id = client.scans.start_site_scan(site_id=42)
# Wait indefinitely
final_scan = client.scans.wait_for_scan_completion(scan_id)
print(f"Scan completed: {final_scan['status']}")
# Wait with timeout (2 hours)
try:
final_scan = client.scans.wait_for_scan_completion(
scan_id=scan_id,
poll_interval=60, # Check every 60 seconds
timeout=7200 # 2 hours max
)
print(f"Scan finished: {final_scan['endTime']}")
except TimeoutError:
print("Scan did not complete within 2 hours")Retrieve key metrics in a simplified format:
# Get scan summary
summary = client.scans.get_scan_summary(12345)
print(f"Name: {summary['name']}")
print(f"Status: {summary['status']}")
print(f"Assets Scanned: {summary['assets_scanned']}")
print(f"Duration: {summary['duration']}")
# Vulnerability breakdown
vulns = summary['vulnerabilities']
print(f"Critical: {vulns['critical']}")
print(f"Severe: {vulns['severe']}")
print(f"Moderate: {vulns['moderate']}")
print(f"Total: {vulns['total']}")Retrieve all scans automatically handling pagination:
# Get all scans
all_scans = client.scans.get_all_scans()
print(f"Total scans: {len(all_scans)}")
# Get all active scans
active_scans = client.scans.get_all_scans(active=True)
# Get all completed scans sorted
completed = client.scans.get_all_scans(
active=False,
sort=["endTime,DESC"]
)Convenience method for currently running scans:
# Get all active scans
active = client.scans.get_active_scans()
print(f"Currently running: {len(active)} scans")
for scan in active:
print(f"- {scan['scanName']}: {scan['assets']} assets scanned")Convenience method for completed scans:
# Get recent completed scans
completed = client.scans.get_completed_scans(
sort=["endTime,DESC"]
)
print(f"Last 5 completed scans:")
for scan in completed[:5]:
print(f"- {scan['scanName']}: {scan['endTime']}")from rapid7 import InsightVMClient
from datetime import datetime
# Weekly security audit workflow
def run_weekly_audit():
client = InsightVMClient()
# Start scan
scan_id = client.scans.start_site_scan(
site_id=42,
scan_name=f"Weekly Audit {datetime.now().strftime('%Y-%m-%d')}",
scan_template_id="full-audit-without-web-spider"
)
print(f"Started scan {scan_id}")
# Wait for completion
final_scan = client.scans.wait_for_scan_completion(
scan_id=scan_id,
poll_interval=300, # Check every 5 minutes
timeout=28800 # 8 hour max
)
# Get summary
summary = client.scans.get_scan_summary(scan_id)
# Report results
print(f"Scan completed in {summary['duration']}")
print(f"Found {summary['vulnerabilities']['critical']} critical vulnerabilities")
return summary
# Run the audit
results = run_weekly_audit()# Monitor all active scans
def monitor_active_scans():
active = client.scans.get_active_scans()
if not active:
print("No scans currently running")
return
print(f"Monitoring {len(active)} active scans:")
for scan in active:
summary = client.scans.get_scan_summary(scan['id'])
print(f"\n{summary['name']}:")
print(f" Status: {summary['status']}")
print(f" Assets: {summary['assets_scanned']}")
print(f" Engine: {summary['engine_name']}")
print(f" Started: {summary['start_time']}")
monitor_active_scans()# Analyze scan history for a site
def analyze_scan_history(site_id, days=30):
# Get recent scans
scans = client.scans.get_site_scans(
site_id=site_id,
active=False,
sort=["endTime,DESC"],
size=100
)
# Analyze results
total_scans = len(scans['resources'])
total_assets = sum(s['assets'] for s in scans['resources'])
print(f"Scan History for Site {site_id} (last {days} days):")
print(f"Total scans: {total_scans}")
print(f"Total assets scanned: {total_assets}")
# Show recent scan durations
if scans['resources']:
print("\nRecent scan durations:")
for scan in scans['resources'][:5]:
duration = scan.get('duration', 'N/A')
print(f"- {scan['scanName']}: {duration}")
analyze_scan_history(site_id=42)# Stop all running scans (emergency)
def emergency_stop_all():
active = client.scans.get_active_scans()
print(f"Stopping {len(active)} active scans...")
stopped = []
failed = []
for scan in active:
try:
client.scans.stop_scan(scan['id'])
stopped.append(scan['scanName'])
except Exception as e:
failed.append((scan['scanName'], str(e)))
print(f"\nStopped: {len(stopped)} scans")
print(f"Failed: {len(failed)} scans")
if failed:
print("\nFailed scans:")
for name, error in failed:
print(f"- {name}: {error}")
# Use with caution!
# emergency_stop_all()# Always set timeouts for long operations
final_scan = client.scans.wait_for_scan_completion(
scan_id=scan_id,
poll_interval=300, # Don't poll too frequently
timeout=28800 # Set reasonable timeout
)# Check scan status after completion
final_scan = client.scans.wait_for_scan_completion(scan_id)
if final_scan['status'] == 'error':
print(f"Scan failed: {final_scan['message']}")
# Handle error appropriately
elif final_scan['status'] == 'stopped':
print("Scan was stopped before completion")
else:
print("Scan completed successfully")# Choose template based on requirements
templates = {
'quick_discovery': 'discovery', # Fast, minimal checks
'standard_audit': 'full-audit-without-web-spider', # Recommended
'comprehensive': 'full-audit', # Includes web app testing
'thorough': 'exhaustive' # Most complete, longest
}
scan_id = client.scans.start_site_scan(
site_id=42,
scan_template_id=templates['standard_audit']
)# Only override blackout when necessary
scan_id = client.scans.start_site_scan(
site_id=42,
override_blackout=False # Respect configured windows
)# Check active scans before starting new ones
active = client.scans.get_active_scans()
if len(active) >= 5:
print("Too many concurrent scans, waiting...")
# Implement queuing or wait logic
else:
scan_id = client.scans.start_site_scan(site_id=42)import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Log scan lifecycle
scan_id = client.scans.start_site_scan(site_id=42)
logger.info(f"Started scan {scan_id} for site 42")
final_scan = client.scans.wait_for_scan_completion(scan_id)
summary = client.scans.get_scan_summary(scan_id)
logger.info(
f"Scan {scan_id} completed: "
f"{summary['vulnerabilities']['total']} vulnerabilities found"
)import requests
try:
scan_id = client.scans.start_site_scan(site_id=42)
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
print("Site not found")
elif e.response.status_code == 401:
print("Authentication failed")
elif e.response.status_code == 503:
print("Service unavailable, try again later")
else:
print(f"HTTP error: {e}")
except ValueError as e:
print(f"Configuration error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")# Highly customized scan
scan_id = client.scans.start_site_scan(
site_id=42,
scan_name="Custom Scan",
scan_template_id="full-audit-without-web-spider",
hosts=[
"10.0.1.0/24", # Subnet
"192.168.1.100", # Single host
"server*.example.com" # Hostname pattern
],
asset_group_ids=[5, 6, 7], # Include specific asset groups
engine_id=3, # Use specific scan engine
override_blackout=True # Override blackout windows
)import time
def poll_scan_status(scan_id, interval=30):
"""Poll scan status until completion."""
while True:
scan = client.scans.get_scan(scan_id)
status = scan['status']
if status in ['finished', 'stopped', 'error']:
return scan
print(f"Status: {status}, Assets: {scan['assets']}")
time.sleep(interval)
# Use the poller
final_scan = poll_scan_status(scan_id, interval=60)For complete API documentation, see the inline docstrings in src/rapid7/api/scans.py.
Key methods:
list()- List scans with paginationget_scan()- Get scan detailsget_site_scans()- Get scans for a sitestart_site_scan()- Start a new scanstop_scan()- Stop a scanpause_scan()- Pause a scanresume_scan()- Resume a scanwait_for_scan_completion()- Wait for scan to finishget_scan_summary()- Get scan summaryis_scan_running()- Check if scan is runningget_active_scans()- Get all active scansget_completed_scans()- Get all completed scansget_all_scans()- Get all scans with auto-pagination