ms365-tenant-manager

Microsoft 365 tenant administration for Global Administrators. Automate M365 tenant setup, Office 365 admin tasks, Azure AD user management, Exchange Online…

INSTALLATION
npx skills add https://github.com/alirezarezvani/claude-skills --skill ms365-tenant-manager
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$28

# CSV columns: DisplayName, UserPrincipalName, Department, LicenseSku

Import-Csv .\new_users.csv | ForEach-Object {

    $passwordProfile = @{ Password = (New-Guid).ToString().Substring(0,16) + "!"; ForceChangePasswordNextSignIn = $true }

    New-MgUser -DisplayName $_.DisplayName -UserPrincipalName $_.UserPrincipalName `

               -Department $_.Department -AccountEnabled -PasswordProfile $passwordProfile

}

Create a Conditional Access Policy (MFA for Admins)

$adminRoles = (Get-MgDirectoryRole | Where-Object { $_.DisplayName -match "Admin" }).Id

$policy = @{

    DisplayName = "Require MFA for Admins"

    State = "enabledForReportingButNotEnforced"   # Start in report-only mode

    Conditions = @{ Users = @{ IncludeRoles = $adminRoles } }

    GrantControls = @{ Operator = "OR"; BuiltInControls = @("mfa") }

}

New-MgIdentityConditionalAccessPolicy -BodyParameter $policy

Workflows

Workflow 1: New Tenant Setup

Step 1: Generate Setup Checklist

Confirm prerequisites before provisioning:

  • Global Admin account created and secured with MFA
  • Custom domain purchased and accessible for DNS edits
  • License SKUs confirmed (E3 vs E5 feature requirements noted)

Step 2: Configure and Verify DNS Records

# After adding the domain in the M365 admin center, verify propagation before proceeding

$domain = "company.com"

Resolve-DnsName -Name "_msdcs.$domain" -Type NS -ErrorAction SilentlyContinue

# Also run from a shell prompt:

# nslookup -type=MX company.com

# nslookup -type=TXT company.com   # confirm SPF record

Wait for DNS propagation (up to 48 h) before bulk user creation.

Step 3: Apply Security Baseline

# Disable legacy authentication (blocks Basic Auth protocols)

$policy = @{

    DisplayName = "Block Legacy Authentication"

    State = "enabled"

    Conditions = @{ ClientAppTypes = @("exchangeActiveSync","other") }

    GrantControls = @{ Operator = "OR"; BuiltInControls = @("block") }

}

New-MgIdentityConditionalAccessPolicy -BodyParameter $policy

# Enable unified audit log

Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true

Step 4: Provision Users

$licenseSku = (Get-MgSubscribedSku | Where-Object { $_.SkuPartNumber -eq "ENTERPRISEPACK" }).SkuId

Import-Csv .\employees.csv | ForEach-Object {

    try {

        $user = New-MgUser -DisplayName $_.DisplayName -UserPrincipalName $_.UserPrincipalName `

                           -AccountEnabled -PasswordProfile @{ Password = (New-Guid).ToString().Substring(0,12)+"!"; ForceChangePasswordNextSignIn = $true }

        Set-MgUserLicense -UserId $user.Id -AddLicenses @(@{ SkuId = $licenseSku }) -RemoveLicenses @()

        Write-Host "Provisioned: $($_.UserPrincipalName)"

    } catch {

        Write-Warning "Failed $($_.UserPrincipalName): $_"

    }

}

Validation: Spot-check 3–5 accounts in the M365 admin portal; confirm licenses show "Active."

Workflow 2: Security Hardening

Step 1: Run Security Audit

Connect-MgGraph -Scopes "Directory.Read.All","Policy.Read.All","AuditLog.Read.All","Reports.Read.All"

# Export Conditional Access policy inventory

Get-MgIdentityConditionalAccessPolicy | Select-Object DisplayName, State |

    Export-Csv .\ca_policies.csv -NoTypeInformation

# Find accounts without MFA registered

$report = Get-MgReportAuthenticationMethodUserRegistrationDetail

$report | Where-Object { -not $_.IsMfaRegistered } |

    Select-Object UserPrincipalName, IsMfaRegistered |

    Export-Csv .\no_mfa_users.csv -NoTypeInformation

Write-Host "Audit complete. Review ca_policies.csv and no_mfa_users.csv."

Step 2: Create MFA Policy (report-only first)

$policy = @{

    DisplayName = "Require MFA All Users"

    State = "enabledForReportingButNotEnforced"

    Conditions = @{ Users = @{ IncludeUsers = @("All") } }

    GrantControls = @{ Operator = "OR"; BuiltInControls = @("mfa") }

}

New-MgIdentityConditionalAccessPolicy -BodyParameter $policy

Validation: After 48 h, review Sign-in logs in Entra ID; confirm expected users would be challenged, then change State to "enabled".

Step 3: Review Secure Score

# Retrieve current Secure Score and top improvement actions

Get-MgSecuritySecureScore -Top 1 | Select-Object CurrentScore, MaxScore, ActiveUserCount

Get-MgSecuritySecureScoreControlProfile | Sort-Object -Property ActionType |

    Select-Object Title, ImplementationStatus, MaxScore | Format-Table -AutoSize

Workflow 3: User Offboarding

Step 1: Block Sign-in and Revoke Sessions

$upn = "departing.user@company.com"

$user = Get-MgUser -Filter "userPrincipalName eq '$upn'"

# Block sign-in immediately

Update-MgUser -UserId $user.Id -AccountEnabled:$false

# Revoke all active tokens

Invoke-MgInvalidateAllUserRefreshToken -UserId $user.Id

Write-Host "Sign-in blocked and sessions revoked for $upn"

Step 2: Preview with -WhatIf (license removal)

# Identify assigned licenses

$licenses = (Get-MgUserLicenseDetail -UserId $user.Id).SkuId

# Dry-run: print what would be removed

$licenses | ForEach-Object { Write-Host "[WhatIf] Would remove SKU: $_" }

Step 3: Execute Offboarding

# Remove licenses

Set-MgUserLicense -UserId $user.Id -AddLicenses @() -RemoveLicenses $licenses

# Convert mailbox to shared (requires ExchangeOnlineManagement module)

Set-Mailbox -Identity $upn -Type Shared

# Remove from all groups

Get-MgUserMemberOf -UserId $user.Id | ForEach-Object {

    try { Remove-MgGroupMemberByRef -GroupId $_.Id -DirectoryObjectId $user.Id } catch {}

}

Write-Host "Offboarding complete for $upn"

Validation: Confirm in the M365 admin portal that the account shows "Blocked," has no active licenses, and the mailbox type is "Shared."

Best Practices

Tenant Setup

  • Enable MFA before adding users
  • Configure named locations for Conditional Access
  • Use separate admin accounts with PIM
  • Verify custom domains (and DNS propagation) before bulk user creation
  • Apply Microsoft Secure Score recommendations

Security Operations

  • Start Conditional Access policies in report-only mode
  • Review Sign-in logs for 48 h before enforcing a new policy
  • Never hardcode credentials in scripts — use Azure Key Vault or Get-Credential
  • Enable unified audit logging for all operations
  • Conduct quarterly security reviews and Secure Score check-ins

PowerShell Automation

  • Prefer Microsoft Graph (Microsoft.Graph module) over legacy MSOnline
  • Include try/catch blocks for error handling
  • Implement Write-Host/Write-Warning logging for audit trails
  • Use -WhatIf or dry-run output before bulk destructive operations
  • Test in a non-production tenant first

Reference Guides

references/powershell-templates.md

  • Ready-to-use script templates
  • Conditional Access policy examples
  • Bulk user provisioning scripts
  • Security audit scripts

references/security-policies.md

  • Conditional Access configuration
  • MFA enforcement strategies
  • DLP and retention policies
  • Security baseline settings

references/troubleshooting.md

  • Common error resolutions
  • PowerShell module issues
  • Permission troubleshooting
  • DNS propagation problems

Limitations

Constraint

Impact

Global Admin required

Full tenant setup needs highest privilege

API rate limits

Bulk operations may be throttled

License dependencies

E3/E5 required for advanced features

Hybrid scenarios

On-premises AD needs additional configuration

PowerShell prerequisites

Microsoft.Graph module required

Required PowerShell Modules

Install-Module Microsoft.Graph -Scope CurrentUser

Install-Module ExchangeOnlineManagement -Scope CurrentUser

Install-Module MicrosoftTeams -Scope CurrentUser

Required Permissions

  • Global Administrator — Full tenant setup
  • User Administrator — User management
  • Security Administrator — Security policies
  • Exchange Administrator — Mailbox management
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card