tool

Script-GraphSigninsAbuseIP

·3 min read

Repository

graph_signins_abuseip.py python script

Overview

Microsoft Graph Sign-in Audit & AbuseIPDB Threat Intel goes one step further than the plain sign-in audit: it pulls the sign-in logs of an account from Microsoft Graph (/auditLogs/signIns) and enriches every unique source IP with real-time reputation data from the AbuseIPDB API v2. Results land in a CSV file and an interactive HTML dashboard.

Key features

  • No app registration needed: public Azure CLI client ID with interactive PKCE login and forced account picker.
  • AbuseIPDB enrichment: abuse confidence score, total reports, ISP and attack categories (Brute-Force, SSH, Web App Attack…).
  • In-memory IP cache & private IP filter: each IP is checked once per run and RFC 1918 / loopback addresses never hit the API.
  • API key rotation pool: moves to the next AbuseIPDB key automatically on HTTP 429.
  • Error code translation for common Entra ID failures (50126, 50053, 53003…).
  • Quiet or verbose console (-v) and a custom time window with -d.
  • HTML dashboard with live search and filters: All / Success / Failure / Malicious / Suspicious / Clean.
  • Corporate proxy ready: works behind SSL/TLS inspection.

How it works

  1. Authentication with MSAL and the delegated scope AuditLog.Read.All (browser login + MFA).
  2. OData query built from a UTC cutoff and the target user.
  3. Retrieval of every page of https://graph.microsoft.com/v1.0/auditLogs/signIns.
  4. Threat intel: private IPs are tagged as internal; new public IPs are sent to the AbuseIPDB /check endpoint and cached; keys rotate on rate limits.
  5. Reports: console summary, signins_intel_<user>_<days>d_<timestamp>.csv and the matching .html dashboard.

Requirements

  • Python 3.8+ (standard Python or Anaconda).
  • Libraries: msal, requests, urllib3.
  • Microsoft Entra ID P1 or P2 (or Microsoft 365 E3/E5).
  • Delegated permission: AuditLog.Read.All.
  • One or more free or paid API keys from AbuseIPDB.

The analyst account must have one of these roles:

  • Security Reader (recommended for SOC analysts)
  • Reports Reader
  • Global Reader
  • Security Administrator
  • Global Administrator

Installation

bash
pip install msal requests urllib3

Configuration

Open graph_signins_abuseip.py and paste your keys in the ABUSEIPDB_API_KEYS list near the top of the file:

python
ABUSEIPDB_API_KEYS = [
    "YOUR_ABUSEIPDB_KEY_1",
    "YOUR_ABUSEIPDB_KEY_2"
]

Usage

bash
# Default: last 15 days, quiet progress mode
python graph_signins_abuseip.py -u user@company.com

# Custom time window
python graph_signins_abuseip.py -u user@company.com -d 30

# Verbose, full metadata per event
python graph_signins_abuseip.py -u user@company.com -d 30 -v
ArgumentDefaultRequiredDescription
-u, --user—YesTarget UserPrincipalName or email.
-d, --days15NoNumber of past days to inspect.
-v, --verboseFalseNoEvent-by-event output in the terminal.

Outputs

  • signins_intel_<user>_<days>d_<timestamp>.csv — every sign-in plus its threat intelligence rating.
  • signins_intel_<user>_<days>d_<timestamp>.html — dashboard with metric cards, search and reputation filters.

Corporate proxy & SSL

Behind a corporate proxy doing SSL/TLS inspection, Python HTTPS calls can fail with CERTIFICATE_VERIFY_FAILED. The script handles it by silencing urllib3 warnings and using verify=False on outbound requests:

python
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

requests.get(url, headers=headers, verify=False)

View on GitHub ↗