· 3 min read
Extracting PagerDuty Incident Notes for Security Audits
Background
In a security-focused environment, tracking incident response actions is essential to ensure accountability and improve future response strategies. As part of our security audit process, we need to extract and review PagerDuty incident notes to analyze how engineers react to incidents. This script automates the retrieval of incident notes from PagerDuty and organizes them into an easy-to-review HTML report for management.
Steps to Extract and Format PagerDuty Incident Notes
1. Setting Up API Authentication and Parameters
Before fetching incident data, we set up API authentication and define parameters to retrieve incidents from the last 7 days.
import requests
from datetime import datetime, timedelta
import warnings
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# Replace these with your actual API key and team ID
API_KEY = 'xxx'
TEAM_ID = 'xxx'
# Calculate the date 7 days ago
seven_days_ago = (datetime.utcnow() - timedelta(days=7)).isoformat() + 'Z'
# Suppress only the InsecureRequestWarning from urllib3
warnings.simplefilter('ignore', InsecureRequestWarning)
# Headers for the API request
headers = {
'Authorization': f'Token token={API_KEY}',
'Accept': 'application/vnd.pagerduty+json;version=2',
'Content-Type': 'application/json'
}2. Fetching Incident Data
We define a function to fetch all incidents within the specified timeframe. The function handles pagination to ensure all incidents are retrieved.
# Function to fetch all incidents with pagination
def fetch_all_incidents(url, headers, params):
incidents = []
index = 0
page_size = 100
while url:
params = {
'team_ids[]': TEAM_ID,
'since': seven_days_ago,
'time_zone': 'UTC',
'limit': page_size,
'offset': index
}
response = requests.get(url, headers=headers, params=params, verify=False)
if response.status_code == 200:
data = response.json()
incidents.extend(data.get('incidents', []))
if len(data.get('incidents', [])) == 0:
break
index += page_size
else:
print(f"Failed to fetch incidents. Status code: {response.status_code}")
print(f"Response: {response.text}")
break
return incidents3. Retrieving Notes for Each Incident
For each retrieved incident, we query the PagerDuty API for its notes and compile them into an HTML table.
# Fetch all incidents
incidents_url = 'https://api.pagerduty.com/incidents'
incidents = fetch_all_incidents(incidents_url, headers, params)
# Initialize HTML content
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PagerDuty Incident Notes</title>
<style>
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 8px; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<h1>PagerDuty Incident Notes</h1>
<table>
<thead>
<tr>
<th>Incident ID</th>
<th>Incident</th>
<th>Created At</th>
<th>User</th>
<th>Content</th>
</tr>
</thead>
<tbody>
"""
for incident in incidents:
incident_id = incident['id']
notes_url = f'https://api.pagerduty.com/incidents/{incident_id}/notes'
notes_response = requests.get(notes_url, headers=headers, verify=False)
if notes_response.status_code == 200:
notes = notes_response.json().get('notes', [])
for note in notes:
html_content += f"""
<tr>
<td>{incident_id}</td>
<td>{incident['title']}</td>
<td>{note['created_at']}</td>
<td>{note['user']['summary']}</td>
<td>{note['content']}</td>
</tr>
"""
else:
print(f"Failed to fetch notes for incident {incident_id}. Status code: {notes_response.status_code}")
print(f"Response: {notes_response.text}")4. Generating the HTML Report
After gathering all the notes, we finalize the HTML structure and save it to a file for review.
html_content += """
</tbody>
</table>
</body>
</html>
"""
# Write the HTML content to a file
with open('pagerduty_incident_notes.html', 'w', encoding='utf-8') as file:
file.write(html_content)
print("HTML file has been created successfully.")Summary
This script automates the extraction of PagerDuty incident notes for security audits, providing a structured HTML report that allows management to review engineers’ responses to incidents. By fetching incidents, retrieving notes, and generating an HTML table, this solution enhances transparency and improves security response analysis. The generated report helps teams refine their incident handling procedures and ensures better preparedness for future incidents.