mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-28 04:09:40 +03:00
Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
Copyright (c) 2025 Mahipal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# Agentless Vulnerability Scanning - API Reference
|
||||
|
||||
## AWS Inspector2 (boto3)
|
||||
|
||||
### Enable Inspector
|
||||
```python
|
||||
client = boto3.client("inspector2")
|
||||
client.enable(resourceTypes=["EC2", "ECR", "LAMBDA"],
|
||||
accountIds=["123456789012"])
|
||||
```
|
||||
|
||||
### Check Account Status
|
||||
```python
|
||||
client.batch_get_account_status(accountIds=["123456789012"])
|
||||
```
|
||||
|
||||
### List Coverage
|
||||
```python
|
||||
paginator = client.get_paginator("list_coverage")
|
||||
for page in paginator.paginate(
|
||||
filterCriteria={"resourceType": [{"comparison": "EQUALS", "value": "AWS_EC2_INSTANCE"}]}
|
||||
):
|
||||
for resource in page["coveredResources"]:
|
||||
print(resource["resourceId"], resource["scanStatus"]["statusCode"])
|
||||
```
|
||||
|
||||
### List Findings
|
||||
```python
|
||||
paginator = client.get_paginator("list_findings")
|
||||
for page in paginator.paginate(
|
||||
filterCriteria={"severity": [{"comparison": "EQUALS", "value": "CRITICAL"}]}
|
||||
):
|
||||
for finding in page["findings"]:
|
||||
print(finding["title"], finding["severity"])
|
||||
```
|
||||
|
||||
### Finding Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `findingArn` | string | Unique finding ARN |
|
||||
| `title` | string | Vulnerability title |
|
||||
| `severity` | string | CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL |
|
||||
| `status` | string | ACTIVE, SUPPRESSED, CLOSED |
|
||||
| `type` | string | NETWORK_REACHABILITY or PACKAGE_VULNERABILITY |
|
||||
| `resources` | array | Affected AWS resources |
|
||||
| `packageVulnerabilityDetails.vulnerabilityId` | string | CVE ID |
|
||||
| `packageVulnerabilityDetails.cvss` | array | CVSS scores |
|
||||
| `packageVulnerabilityDetails.fixedInVersion` | string | Patched version |
|
||||
|
||||
## Agentless Scanning via EBS Snapshots
|
||||
|
||||
Inspector2 supports agentless scanning by:
|
||||
1. Creating EBS snapshots of instance volumes
|
||||
2. Mounting snapshots in Inspector service account
|
||||
3. Scanning file system for vulnerable packages
|
||||
4. No agent installation required on target instances
|
||||
|
||||
### Create Snapshot (boto3 EC2)
|
||||
```python
|
||||
ec2 = boto3.client("ec2")
|
||||
ec2.create_snapshot(
|
||||
VolumeId="vol-xxx",
|
||||
Description="Agentless scan",
|
||||
TagSpecifications=[{"ResourceType": "snapshot",
|
||||
"Tags": [{"Key": "Purpose", "Value": "VulnScan"}]}]
|
||||
)
|
||||
```
|
||||
|
||||
## SSM Inventory (Alternative)
|
||||
|
||||
AWS Systems Manager Inventory collects software inventory without custom agents:
|
||||
```python
|
||||
ssm = boto3.client("ssm")
|
||||
ssm.get_inventory(
|
||||
Filters=[{"Key": "AWS:Application.Name", "Values": ["openssl"]}]
|
||||
)
|
||||
```
|
||||
|
||||
## Scan Types
|
||||
|
||||
| Type | Method | Agent Required |
|
||||
|------|--------|---------------|
|
||||
| Inspector Classic | AWS agent | Yes |
|
||||
| Inspector2 Agent | SSM agent | Yes (auto-installed) |
|
||||
| Inspector2 Agentless | EBS snapshot | No |
|
||||
| SSM Inventory | SSM agent | Yes |
|
||||
|
||||
## Output Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"report": "agentless_vulnerability_scanning",
|
||||
"inspector_status": {"enabled": true},
|
||||
"total_resources_scanned": 50,
|
||||
"uncovered_resources": 3,
|
||||
"total_findings": 125,
|
||||
"severity_summary": {"CRITICAL": 5, "HIGH": 30, "MEDIUM": 60, "LOW": 30}
|
||||
}
|
||||
```
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
python agent.py --region us-east-1 --severity CRITICAL HIGH --output report.json
|
||||
```
|
||||
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agentless Vulnerability Scanning agent - uses AWS Inspector2 and SSM APIs
|
||||
via boto3 to perform agentless scans of EC2 instances through EBS snapshot
|
||||
analysis without requiring installed agents."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from collections import Counter
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
except ImportError:
|
||||
print("Install boto3: pip install boto3", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_inspector_client(region: str = "us-east-1", profile: str = None):
|
||||
"""Create AWS Inspector2 client."""
|
||||
session = boto3.Session(profile_name=profile, region_name=region)
|
||||
return session.client("inspector2")
|
||||
|
||||
|
||||
def get_ec2_client(region: str = "us-east-1", profile: str = None):
|
||||
"""Create EC2 client."""
|
||||
session = boto3.Session(profile_name=profile, region_name=region)
|
||||
return session.client("ec2")
|
||||
|
||||
|
||||
def check_inspector_status(client) -> dict:
|
||||
"""Check Inspector2 enablement status."""
|
||||
try:
|
||||
response = client.batch_get_account_status(
|
||||
accountIds=[boto3.client("sts").get_caller_identity()["Account"]]
|
||||
)
|
||||
accounts = response.get("accounts", [])
|
||||
if accounts:
|
||||
status = accounts[0].get("state", {}).get("status", "UNKNOWN")
|
||||
return {"enabled": status == "ENABLED", "status": status}
|
||||
return {"enabled": False, "status": "NO_DATA"}
|
||||
except ClientError as e:
|
||||
return {"enabled": False, "error": str(e)}
|
||||
|
||||
|
||||
def list_ec2_scan_coverage(client) -> list[dict]:
|
||||
"""List EC2 instances and their scan coverage status."""
|
||||
coverage = []
|
||||
paginator = client.get_paginator("list_coverage")
|
||||
for page in paginator.paginate(
|
||||
filterCriteria={"resourceType": [{"comparison": "EQUALS", "value": "AWS_EC2_INSTANCE"}]}
|
||||
):
|
||||
for item in page.get("coveredResources", []):
|
||||
coverage.append({
|
||||
"resource_id": item.get("resourceId", ""),
|
||||
"resource_type": item.get("resourceType", ""),
|
||||
"scan_status": item.get("scanStatus", {}).get("statusCode", "UNKNOWN"),
|
||||
"scan_type": item.get("scanType", ""),
|
||||
"account_id": item.get("accountId", ""),
|
||||
})
|
||||
return coverage
|
||||
|
||||
|
||||
def list_findings(client, severity_filter: list[str] = None,
|
||||
max_results: int = 500) -> list[dict]:
|
||||
"""List vulnerability findings from Inspector2."""
|
||||
filter_criteria = {}
|
||||
if severity_filter:
|
||||
filter_criteria["severity"] = [
|
||||
{"comparison": "EQUALS", "value": s} for s in severity_filter
|
||||
]
|
||||
findings = []
|
||||
paginator = client.get_paginator("list_findings")
|
||||
params = {"filterCriteria": filter_criteria, "maxResults": min(max_results, 100)}
|
||||
count = 0
|
||||
for page in paginator.paginate(**params):
|
||||
for finding in page.get("findings", []):
|
||||
findings.append({
|
||||
"finding_arn": finding.get("findingArn", ""),
|
||||
"title": finding.get("title", ""),
|
||||
"severity": finding.get("severity", ""),
|
||||
"status": finding.get("status", ""),
|
||||
"type": finding.get("type", ""),
|
||||
"resource_id": finding.get("resources", [{}])[0].get("id", ""),
|
||||
"resource_type": finding.get("resources", [{}])[0].get("type", ""),
|
||||
"vulnerability_id": finding.get("packageVulnerabilityDetails", {}).get("vulnerabilityId", ""),
|
||||
"cvss_score": finding.get("packageVulnerabilityDetails", {}).get("cvss", [{}])[0].get("baseScore", 0),
|
||||
"fixed_in": finding.get("packageVulnerabilityDetails", {}).get("fixedInVersion", ""),
|
||||
"first_observed": str(finding.get("firstObservedAt", "")),
|
||||
})
|
||||
count += 1
|
||||
if count >= max_results:
|
||||
return findings
|
||||
return findings
|
||||
|
||||
|
||||
def create_ebs_snapshot_scan(ec2_client, instance_id: str) -> dict:
|
||||
"""Create EBS snapshots for agentless scanning."""
|
||||
try:
|
||||
volumes = ec2_client.describe_volumes(
|
||||
Filters=[{"Name": "attachment.instance-id", "Values": [instance_id]}]
|
||||
)
|
||||
snapshots = []
|
||||
for vol in volumes.get("Volumes", []):
|
||||
snap = ec2_client.create_snapshot(
|
||||
VolumeId=vol["VolumeId"],
|
||||
Description=f"Agentless scan snapshot for {instance_id}",
|
||||
TagSpecifications=[{
|
||||
"ResourceType": "snapshot",
|
||||
"Tags": [{"Key": "Purpose", "Value": "AgentlessVulnScan"},
|
||||
{"Key": "SourceInstance", "Value": instance_id}]
|
||||
}]
|
||||
)
|
||||
snapshots.append({"volume_id": vol["VolumeId"], "snapshot_id": snap["SnapshotId"]})
|
||||
return {"instance_id": instance_id, "snapshots": snapshots}
|
||||
except ClientError as e:
|
||||
return {"instance_id": instance_id, "error": str(e)}
|
||||
|
||||
|
||||
def generate_report(region: str, profile: str = None,
|
||||
severity_filter: list[str] = None) -> dict:
|
||||
"""Run agentless scanning assessment and build report."""
|
||||
inspector = get_inspector_client(region, profile)
|
||||
status = check_inspector_status(inspector)
|
||||
coverage = list_ec2_scan_coverage(inspector)
|
||||
findings = list_findings(inspector, severity_filter)
|
||||
|
||||
severity_counts = Counter(f["severity"] for f in findings)
|
||||
uncovered = [c for c in coverage if c["scan_status"] != "ACTIVE"]
|
||||
return {
|
||||
"report": "agentless_vulnerability_scanning",
|
||||
"generated_at": datetime.utcnow().isoformat() + "Z",
|
||||
"region": region,
|
||||
"inspector_status": status,
|
||||
"total_resources_scanned": len(coverage),
|
||||
"uncovered_resources": len(uncovered),
|
||||
"total_findings": len(findings),
|
||||
"severity_summary": dict(severity_counts),
|
||||
"uncovered_resources_list": uncovered[:20],
|
||||
"findings": findings,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Agentless Vulnerability Scanning Agent")
|
||||
parser.add_argument("--region", default="us-east-1", help="AWS region")
|
||||
parser.add_argument("--profile", help="AWS CLI profile name")
|
||||
parser.add_argument("--severity", nargs="+", choices=["CRITICAL", "HIGH", "MEDIUM", "LOW"],
|
||||
help="Filter by severity")
|
||||
parser.add_argument("--output", help="Output JSON file path")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = generate_report(args.region, args.profile, args.severity)
|
||||
output = json.dumps(report, indent=2)
|
||||
if args.output:
|
||||
Path(args.output).write_text(output, encoding="utf-8")
|
||||
print(f"Report written to {args.output}")
|
||||
else:
|
||||
print(output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user