Skip to main content
Five Steps for Cloud Compliance Readiness·A practical playbook for security teamsDownload
Free tool

Read-only PowerShell script generator

Pick the reports you need and get one script that writes each to CSV. It only reads, runs on your machine and sends nothing to us.

Microsoft Entra ID (Microsoft Graph)
Exchange Online
SharePoint Online
Azure
configcobra-reports.ps1 · 4 reports
# ConfigCobra read-only report script
# Built at https://configcobra.com/tools/powershell-script-generator
#
# Read-only: besides signing in it only calls Get-*, Search-* and Resolve-* cmdlets, and writes CSV files to .\configcobra-reports.
# Nothing is sent to ConfigCobra. Run it in PowerShell 7 (SharePoint: Windows PowerShell 5.1).
#
# Install the modules once:
#   Install-Module Microsoft.Graph -Scope CurrentUser

$ErrorActionPreference = 'Stop'
$InactiveDays = 90
$ExpiryDays = 30

$OutDir = Join-Path (Get-Location) 'configcobra-reports'
New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
function Save-Report($Rows, $Name) {
  $rows = @($Rows)
  $path = Join-Path $OutDir "$Name.csv"
  if ($rows.Count) { $rows | Export-Csv -Path $path -NoTypeInformation -Encoding utf8 }
  Write-Host ('{0,-34} {1,6} rows{2}' -f $Name, $rows.Count, $(if ($rows.Count) { "  -> $path" } else { '' }))
}

# ─── Microsoft Entra ID (Microsoft Graph) ────────────────────────

Connect-MgGraph -Scopes 'User.Read.All','AuditLog.Read.All','Application.Read.All' -NoWelcome
# One read of all users, shared by the user reports (sign-in dates need Entra ID P1/P2).
$Users = Get-MgUser -All -Property id,displayName,userPrincipalName,mail,userType,accountEnabled,createdDateTime,externalUserState,signInActivity
function Get-LastSignIn($u) {
  @($u.SignInActivity.LastSignInDateTime, $u.SignInActivity.LastNonInteractiveSignInDateTime, $u.SignInActivity.LastSuccessfulSignInDateTime) |
    Where-Object { $_ } | Sort-Object -Descending | Select-Object -First 1
}

# Users inactive 90 days
$cutoff = (Get-Date).AddDays(-$InactiveDays)
$rows = $Users | Where-Object { $_.UserType -eq 'Member' -and $_.AccountEnabled -and (Get-LastSignIn $_) -and (Get-LastSignIn $_) -lt $cutoff } |
  Select-Object DisplayName, UserPrincipalName, @{n='LastSignIn';e={ Get-LastSignIn $_ }}, CreatedDateTime
Save-Report $rows 'inactive-users'

# Guests who never signed in
$rows = $Users | Where-Object { $_.UserType -eq 'Guest' -and -not (Get-LastSignIn $_) } |
  Select-Object DisplayName, Mail, ExternalUserState, CreatedDateTime
Save-Report $rows 'guests-never-signed-in'

# Users with no MFA registered
$rows = Get-MgReportAuthenticationMethodUserRegistrationDetail -All |
  Where-Object { -not $_.IsMfaRegistered } |
  Select-Object UserDisplayName, UserPrincipalName, UserType, IsAdmin, @{n='MethodsRegistered';e={ $_.MethodsRegistered -join ', ' }}
Save-Report $rows 'users-without-mfa'

# Expired or soon-expiring app credentials
$limit = (Get-Date).AddDays($ExpiryDays)
$rows = Get-MgApplication -All -Property displayName,appId,passwordCredentials,keyCredentials | ForEach-Object {
  $app = $_
  foreach ($c in $app.PasswordCredentials) { [pscustomobject]@{ App = $app.DisplayName; AppId = $app.AppId; Type = 'Secret'; Name = $c.DisplayName; Expires = $c.EndDateTime } }
  foreach ($c in $app.KeyCredentials) { [pscustomobject]@{ App = $app.DisplayName; AppId = $app.AppId; Type = 'Certificate'; Name = $c.DisplayName; Expires = $c.EndDateTime } }
} | Where-Object { $_.Expires -and $_.Expires -lt $limit } |
  Select-Object App, AppId, Type, Name, Expires, @{n='Status';e={ if ($_.Expires -lt (Get-Date)) { 'Expired' } else { 'Expiring' } }} |
  Sort-Object Expires
Save-Report $rows 'expiring-app-credentials'

Disconnect-MgGraph | Out-Null

Write-Host "Done. Reports are in $OutDir"

Read the script before you run it — it is short on purpose. Run it from the folder where you want the CSVs.

How the script works

Read-only by design

Apart from signing in, every report uses Get-*, Search-* or Resolve-* cmdlets only, and Microsoft Graph is asked for .Read. scopes only. The script cannot change users, mailboxes, sites or resources.

Runs on your machine

You run the script yourself, signed in as yourself. The results go to CSV files in a local folder; nothing is uploaded anywhere, including to ConfigCobra.

Permissions it asks for

Microsoft Graph shows a consent prompt listing exactly the read scopes of the reports you picked. Exchange, SharePoint and Azure use the roles you already have; Reader is enough for Azure.

Licences

Sign-in dates and MFA registration details come from Microsoft Entra ID P1 or P2. Without them those reports come back empty; the others work on any tenant.

Want these reports without running scripts?

ConfigCobra's inventory has these risk views built in, next to the CIS benchmark checks. Read-only.

Get in touch

Let's talk.

Whether you're evaluating ConfigCobra, running an audit, or managing a client fleet — we respond within one business day.

Free trial