Password Rotation PowerShell Script
# Verify Script Permissions
$executionPolicy = Get-ExecutionPolicy
if ($executionPolicy -eq "Restricted") {
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force
}
# Import Required Modules
Import-Module Microsoft.Graph.Authentication -Force
Import-Module Microsoft.Graph.Users -Force
Import-Module Microsoft.Graph.Identity.DirectoryManagement -Force
# Hudu Configuration
$huduApiKey = "your-hudu-api-key"
$huduBaseUrl = "https://your-hudu-domain/api/v1"
$huduHeaders = @{
"x-api-key" = $huduApiKey
"Content-Type" = "application/json"
}
# Function to Get Companies from Hudu
function Get-HuduCompanies {
try {
$response = Invoke-RestMethod -Uri "$huduBaseUrl/companies" -Method Get -Headers $huduHeaders
return $response.companies
} catch {
Write-Host "Failed to retrieve companies from Hudu: $_" -ForegroundColor Red
return $null
}
}
# Establish the connection to the M365 Tenant
function Connect-M365Tenant {
param (
[string]$TenantId,
[string]$ClientId,
[string]$ClientSecret
)
try {
$tokenBody = @{
client_id = $ClientId
scope = "https://graph.microsoft.com/.default"
client_secret = $ClientSecret
grant_type = "client_credentials"
}
$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -Method Post -Body $tokenBody
# Convert the access token to a SecureString
$secureToken = ConvertTo-SecureString -String $tokenResponse.access_token -AsPlainText -Force
# Connect using the SecureString token
Connect-MgGraph -AccessToken $secureToken
Write-Host "Connected to Tenant: $TenantId" -ForegroundColor Green
return $true
} catch {
Write-Host "Failed to connect to Tenant $TenantId : $_" -ForegroundColor Red
return $false
}
}
# Generate the secure new password
function Generate-SecurePassword {
$Chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()"
return -join ((1..16) | ForEach-Object { Get-Random -InputObject $Chars.ToCharArray() })
}
# Get the ID of the Microsoft Tenant
function Get-TenantID {
param ([string]$Domain)
try {
$TenantInfo = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$Domain/v2.0/.well-known/openid-configuration" -Method Get
$TenantID = $TenantInfo.issuer -replace "https://login.microsoftonline.com/", "" -replace "/v2.0", ""
return $TenantID
} catch {
Write-Host "❌ Failed to retrieve Tenant ID for domain: $Domain" -ForegroundColor Red
return $null
}
}
function Update-AdminPassword {
param (
[string]$userId,
[string]$newPassword
)
try {
$passwordProfile = @{
passwordProfile = @{
forceChangePasswordNextSignIn = $false
password = $newPassword
}
}
Update-MgUser -UserId $userId -BodyParameter $passwordProfile
Write-Host "Successfully updated admin password" -ForegroundColor Green
} catch {
Write-Host "Failed to update password: $_" -ForegroundColor Red
}
}
# [Keep your existing functions: Get-HuduCredentials, Update-HuduPassword, Generate-SecurePassword, Get-TenantID, Connect-M365Tenant, Update-AdminPassword, Get-TenantPrimaryDomain]
# Main Execution
# Fetch companies dynamically from Hudu
$huduCompanies = Get-HuduCompanies
if (-not $huduCompanies) {
Write-Host "No companies retrieved from Hudu. Exiting." -ForegroundColor Red
}
# Build tenants array dynamically
$tenants = @()
foreach ($company in $huduCompanies) {
# Assuming you store ClientId and ClientSecret in Hudu company fields or elsewhere
# Adjust these based on how you store Microsoft 365 app credentials
$tenant = @{
Domain = "$($company.slug).onmicrosoft.com" # Adjust based on actual domain storage
CompanyId = $company.id
ClientId = "your_client_id" # Replace with logic to fetch from Hudu or another source
ClientSecret = "your_client_secret" # Replace with logic to fetch from Hudu or another source
}
$tenants += $tenant
}
# Process each tenant
foreach ($tenant in $tenants) {
Write-Host "Processing tenant: $($tenant.Domain)" -ForegroundColor Cyan
# Get Tenant ID
$tenantId = Get-TenantID -Domain $tenant.Domain
if (-not $tenantId) { continue }
# Connect to Tenant
$connected = Connect-M365Tenant -TenantId $tenantId -ClientId $tenant.ClientId -ClientSecret $tenant.ClientSecret
if (-not $connected) { continue }
# Get the actual published domain (optional)
#$publishedDomain = Get-TenantPrimaryDomain -TenantId $tenantId
#Write-Host "Published domain: $publishedDomain" -ForegroundColor Yellow
# Get current credentials from Hudu
$credentials = Get-HuduCredentials -companyId $tenant.CompanyId
if (-not $credentials) { continue }
# Generate new password
$newPassword = Generate-SecurePassword
# Update password in Microsoft
Update-AdminPassword -userId $credentials.Username -newPassword $newPassword
# Update password in Hudu
Update-HuduPassword -passwordId $credentials.Id -newPassword $newPassword -username $credentials.Username
# Disconnect from Graph
Disconnect-MgGraph
Write-Host "Completed processing $($tenant.Domain)" -ForegroundColor Green
Write-Host "------------------------"
}