Created
March 11, 2025 05:31
-
-
Save RyAndrew/92d51334972105d7d0d5a5b294614bb5 to your computer and use it in GitHub Desktop.
ai experiments - claude sonet 3.7 extended thinking - okta system logs logins per app per day console script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Prompt: | |
//Write a clean, efficient JavaScript script for Gabriel Sroka's Okta console tool (https://gabrielsroka.github.io/console/) that fetches Okta system logs for user app login events, count them per app per day, displays the results in a table. Use the tool's native APIs and utilities wherever possible to handle pagination and rate limiting instead of reinventing these mechanisms. | |
Use he parameters since and until for the okta log api | |
//paste in source code for console bookmarklet as addl context | |
//Output: | |
// Fetch Okta system logs for app login events and count per app per day | |
// Date range parameters - default to last 7 days | |
const now = new Date(); | |
const defaultEndDate = now.toISOString().split('T')[0]; | |
const sevenDaysAgo = new Date(now); | |
sevenDaysAgo.setDate(now.getDate() - 7); | |
const defaultStartDate = sevenDaysAgo.toISOString().split('T')[0]; | |
// Prompt user for date range | |
let startDate = prompt("Enter start date (YYYY-MM-DD) or leave blank for 7 days ago:", defaultStartDate); | |
let endDate = prompt("Enter end date (YYYY-MM-DD) or leave blank for today:", defaultEndDate); | |
// Validate dates or use defaults | |
if (startDate && !/^\d{4}-\d{2}-\d{2}$/.test(startDate)) { | |
log("Invalid start date format. Using default (7 days ago)."); | |
startDate = defaultStartDate; | |
} | |
if (endDate && !/^\d{4}-\d{2}-\d{2}$/.test(endDate)) { | |
log("Invalid end date format. Using default (today)."); | |
endDate = defaultEndDate; | |
} | |
// Convert to ISO format required by Okta API | |
const since = `${startDate || defaultStartDate}T00:00:00Z`; | |
const until = `${endDate || defaultEndDate}T23:59:59Z`; | |
log(`Fetching login events from ${startDate || defaultStartDate} to ${endDate || defaultEndDate}`); | |
// Build the URL with filters for app login events and date range | |
const filter = `eventType eq "user.authentication.sso"`; | |
const url = `/api/v1/logs?filter=${encodeURIComponent(filter)}&since=${encodeURIComponent(since)}&until=${encodeURIComponent(until)}`; | |
// Object to store login counts | |
const loginsByAppByDay = {}; | |
let totalEvents = 0; | |
const startTime = Date.now(); | |
// Fetch and process logs | |
log("Fetching logs, please wait..."); | |
for await (const event of getObjects(url)) { | |
totalEvents++; | |
// Update status periodically | |
if (totalEvents % 100 === 0) { | |
const elapsedSeconds = Math.round((Date.now() - startTime) / 1000); | |
log(`Processed ${totalEvents} events (${elapsedSeconds} seconds elapsed)...`); | |
} | |
// Extract app name from target objects | |
let appName = "Unknown App"; | |
if (event.target && event.target.length > 0) { | |
for (const target of event.target) { | |
if (target.type === "AppInstance") { | |
appName = target.displayName || target.alternateId || target.id || "Unknown App"; | |
break; | |
} | |
} | |
} | |
// Extract date (without time) | |
const eventDate = event.published.split('T')[0]; | |
// Initialize counter if needed | |
if (!loginsByAppByDay[appName]) { | |
loginsByAppByDay[appName] = {}; | |
} | |
if (!loginsByAppByDay[appName][eventDate]) { | |
loginsByAppByDay[appName][eventDate] = 0; | |
} | |
// Increment counter | |
loginsByAppByDay[appName][eventDate]++; | |
if (cancel) { | |
log("Operation cancelled by user"); | |
break; | |
} | |
} | |
// Calculate processing time | |
const processingTime = Math.round((Date.now() - startTime) / 1000); | |
log(`Completed processing ${totalEvents} events in ${processingTime} seconds`); | |
// Create daily breakdown table data | |
const dailyData = []; | |
for (const app in loginsByAppByDay) { | |
for (const date in loginsByAppByDay[app]) { | |
dailyData.push({ | |
Application: app, | |
Date: date, | |
Logins: loginsByAppByDay[app][date] | |
}); | |
} | |
} | |
// Sort by date (ascending) and then by login count (descending) | |
dailyData.sort((a, b) => { | |
if (a.Date === b.Date) { | |
return b.Logins - a.Logins; | |
} | |
return a.Date.localeCompare(b.Date); | |
}); | |
// Create summary data (total logins per app) | |
const summaryData = []; | |
for (const app in loginsByAppByDay) { | |
let totalLogins = 0; | |
let daysWithActivity = 0; | |
for (const date in loginsByAppByDay[app]) { | |
totalLogins += loginsByAppByDay[app][date]; | |
daysWithActivity++; | |
} | |
summaryData.push({ | |
Application: app, | |
"Total Logins": totalLogins, | |
"Days With Activity": daysWithActivity, | |
"Avg Logins/Day": Math.round((totalLogins / daysWithActivity) * 10) / 10 | |
}); | |
} | |
// Sort summary by total logins (descending) | |
summaryData.sort((a, b) => b["Total Logins"] - a["Total Logins"]); | |
// Display results | |
if (dailyData.length > 0) { | |
log(`Found ${totalEvents} login events across ${dailyData.length} app/day combinations`); | |
// Display summary first | |
log("Summary of app usage:"); | |
table(summaryData); | |
// Then display daily breakdown | |
log("Daily breakdown of app logins:"); | |
table(dailyData); | |
// Add export buttons | |
results.innerHTML += '<br><button id="exportSummary">Export Summary to CSV</button> ' + | |
'<button id="exportDaily">Export Daily Breakdown to CSV</button>'; | |
document.getElementById("exportSummary").onclick = function() { | |
downloadCSV(csv(summaryData), "Okta_App_Login_Summary"); | |
}; | |
document.getElementById("exportDaily").onclick = function() { | |
downloadCSV(csv(dailyData), "Okta_App_Login_Daily"); | |
}; | |
} else { | |
log("No login events found for the specified date range"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment