This collection demonstrates PowerShell's capabilities for Azure resource management, automation, and cloud operations. These examples use the Azure PowerShell module and follow Azure best practices for security and resource management.
Azure Resource Management
Virtual Machine Management
<#
.SYNOPSIS
Comprehensive Azure Virtual Machine management functions
.DESCRIPTION
Provides functions for creating, managing, and monitoring Azure VMs
with proper error handling and security configurations
.EXAMPLE
New-AzureVM -ResourceGroupName "MyRG" -VMName "WebServer01" -Location "East US"
#>
function New-AzureVM
{
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$ResourceGroupName,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$VMName,
[Parameter(Mandatory = $true)]
[ValidateSet("East US", "West US", "Central US", "North Europe", "West Europe")]
[string]$Location,
[Parameter()]
[ValidateSet("Standard_B2s", "Standard_D2s_v3", "Standard_D4s_v3", "Standard_E2s_v3")]
[string]$VMSize = "Standard_B2s",
[Parameter()]
[ValidateSet("Windows Server 2019", "Windows Server 2022", "Ubuntu 20.04", "Ubuntu 22.04")]
[string]$OperatingSystem = "Windows Server 2022",
[Parameter()]
[string]$AdminUsername = "azureuser",
[Parameter()]
[securestring]$AdminPassword,
[Parameter()]
[string]$VNetName,
[Parameter()]
[string]$SubnetName = "default",
[Parameter()]
[hashtable]$Tags = @{}
)
try
{
Write-Verbose "Starting Azure VM deployment: $VMName"
# Ensure Azure PowerShell module is loaded
if (-not (Get-Module -Name Az.Compute -ListAvailable))
{
throw "Azure PowerShell module (Az.Compute) is not installed. Install with: Install-Module -Name Az"
}
# Check if already connected to Azure
$Context = Get-AzContext
if (-not $Context)
{
Write-Host "Connecting to Azure..." -ForegroundColor Yellow
Connect-AzAccount
}
# Verify resource group exists
$ResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue
if (-not $ResourceGroup)
{
Write-Host "Creating resource group: $ResourceGroupName" -ForegroundColor Green
$ResourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Location -Tag $Tags
}
# Generate secure password if not provided
if (-not $AdminPassword)
{
$PasswordString = -join ((1..16) | ForEach-Object { Get-Random -Input @('abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789', '!@#$%^&*')[Get-Random -Minimum 0 -Maximum 4] })
$AdminPassword = ConvertTo-SecureString -String $PasswordString -AsPlainText -Force
Write-Host "Generated secure password for VM. Please save securely." -ForegroundColor Yellow
}
# Create credential object
$Credential = New-Object System.Management.Automation.PSCredential($AdminUsername, $AdminPassword)
# Configure VM based on operating system
$VMConfig = switch ($OperatingSystem)
{
"Windows Server 2019" {
@{
PublisherName = "MicrosoftWindowsServer"
Offer = "WindowsServer"
Skus = "2019-Datacenter"
Version = "latest"
}
}
"Windows Server 2022" {
@{
PublisherName = "MicrosoftWindowsServer"
Offer = "WindowsServer"
Skus = "2022-Datacenter"
Version = "latest"
}
}
"Ubuntu 20.04" {
@{
PublisherName = "Canonical"
Offer = "0001-com-ubuntu-server-focal"
Skus = "20_04-lts-gen2"
Version = "latest"
}
}
"Ubuntu 22.04" {
@{
PublisherName = "Canonical"
Offer = "0001-com-ubuntu-server-jammy"
Skus = "22_04-lts-gen2"
Version = "latest"
}
}
}
# Create or get virtual network
if ($VNetName)
{
$VNet = Get-AzVirtualNetwork -Name $VNetName -ResourceGroupName $ResourceGroupName -ErrorAction SilentlyContinue
if (-not $VNet)
{
Write-Host "Creating virtual network: $VNetName" -ForegroundColor Green
$SubnetConfig = New-AzVirtualNetworkSubnetConfig -Name $SubnetName -AddressPrefix "10.0.1.0/24"
$VNet = New-AzVirtualNetwork -Name $VNetName -ResourceGroupName $ResourceGroupName -Location $Location -AddressPrefix "10.0.0.0/16" -Subnet $SubnetConfig
}
}
else
{
$VNetName = "$VMName-vnet"
Write-Host "Creating virtual network: $VNetName" -ForegroundColor Green
$SubnetConfig = New-AzVirtualNetworkSubnetConfig -Name $SubnetName -AddressPrefix "10.0.1.0/24"
$VNet = New-AzVirtualNetwork -Name $VNetName -ResourceGroupName $ResourceGroupName -Location $Location -AddressPrefix "10.0.0.0/16" -Subnet $SubnetConfig
}
# Create Network Security Group with basic rules
$NSGName = "$VMName-nsg"
Write-Host "Creating network security group: $NSGName" -ForegroundColor Green
$NSGRules = @()
if ($OperatingSystem -like "*Windows*")
{
$NSGRules += New-AzNetworkSecurityRuleConfig -Name "RDP" -Protocol "TCP" -Direction "Inbound" -Priority 1000 -SourceAddressPrefix "*" -SourcePortRange "*" -DestinationAddressPrefix "*" -DestinationPortRange "3389" -Access "Allow"
}
else
{
$NSGRules += New-AzNetworkSecurityRuleConfig -Name "SSH" -Protocol "TCP" -Direction "Inbound" -Priority 1000 -SourceAddressPrefix "*" -SourcePortRange "*" -DestinationAddressPrefix "*" -DestinationPortRange "22" -Access "Allow"
}
$NSG = New-AzNetworkSecurityGroup -Name $NSGName -ResourceGroupName $ResourceGroupName -Location $Location -SecurityRules $NSGRules
# Create public IP
$PublicIPName = "$VMName-pip"
Write-Host "Creating public IP: $PublicIPName" -ForegroundColor Green
$PublicIP = New-AzPublicIpAddress -Name $PublicIPName -ResourceGroupName $ResourceGroupName -Location $Location -AllocationMethod "Static" -Sku "Standard"
# Create network interface
$NICName = "$VMName-nic"
Write-Host "Creating network interface: $NICName" -ForegroundColor Green
$Subnet = Get-AzVirtualNetworkSubnetConfig -Name $SubnetName -VirtualNetwork $VNet
$NIC = New-AzNetworkInterface -Name $NICName -ResourceGroupName $ResourceGroupName -Location $Location -SubnetId $Subnet.Id -PublicIpAddressId $PublicIP.Id -NetworkSecurityGroupId $NSG.Id
# Create VM configuration
Write-Host "Creating VM configuration..." -ForegroundColor Green
$VM = New-AzVMConfig -VMName $VMName -VMSize $VMSize
if ($OperatingSystem -like "*Windows*")
{
$VM = Set-AzVMOperatingSystem -VM $VM -Windows -ComputerName $VMName -Credential $Credential -ProvisionVMAgent -EnableAutoUpdate
}
else
{
$VM = Set-AzVMOperatingSystem -VM $VM -Linux -ComputerName $VMName -Credential $Credential
}
$VM = Set-AzVMSourceImage -VM $VM -PublisherName $VMConfig.PublisherName -Offer $VMConfig.Offer -Skus $VMConfig.Skus -Version $VMConfig.Version
$VM = Add-AzVMNetworkInterface -VM $VM -Id $NIC.Id
# Set OS disk configuration
$VM = Set-AzVMOSDisk -VM $VM -CreateOption "FromImage" -StorageAccountType "Premium_LRS"
# Add tags
$DefaultTags = @{
"CreatedBy" = "PowerShell"
"CreatedDate" = (Get-Date -Format "yyyy-MM-dd")
"Environment" = "Development"
}
$AllTags = $DefaultTags + $Tags
# Create the virtual machine
Write-Host "Creating virtual machine: $VMName" -ForegroundColor Green
Write-Host "This may take several minutes..." -ForegroundColor Yellow
$VMResult = New-AzVM -ResourceGroupName $ResourceGroupName -Location $Location -VM $VM -Tag $AllTags
if ($VMResult.IsSuccessStatusCode)
{
Write-Host "VM created successfully!" -ForegroundColor Green
# Get VM details
$CreatedVM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName
$VMPublicIP = Get-AzPublicIpAddress -Name $PublicIPName -ResourceGroupName $ResourceGroupName
# Return VM information
$VMInfo = [PSCustomObject]@{
VMName = $VMName
ResourceGroup = $ResourceGroupName
Location = $Location
Size = $VMSize
OperatingSystem = $OperatingSystem
PublicIPAddress = $VMPublicIP.IpAddress
AdminUsername = $AdminUsername
Status = "Created"
CreatedDate = Get-Date
Tags = $AllTags
}
Write-Host "VM Details:" -ForegroundColor Cyan
Write-Host "Name: $($VMInfo.VMName)" -ForegroundColor White
Write-Host "Public IP: $($VMInfo.PublicIPAddress)" -ForegroundColor White
Write-Host "Username: $($VMInfo.AdminUsername)" -ForegroundColor White
if ($OperatingSystem -like "*Windows*")
{
Write-Host "RDP Connection: mstsc /v:$($VMInfo.PublicIPAddress)" -ForegroundColor Yellow
}
else
{
Write-Host "SSH Connection: ssh $($VMInfo.AdminUsername)@$($VMInfo.PublicIPAddress)" -ForegroundColor Yellow
}
return $VMInfo
}
else
{
throw "VM creation failed"
}
}
catch
{
Write-Error "VM creation failed: $($_.Exception.Message)"
throw
}
}
function Get-AzureVMStatus
{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true)]
[string[]]$ResourceGroupName,
[Parameter()]
[string[]]$VMName,
[Parameter()]
[switch]$IncludeMetrics
)
begin
{
$VMStatusList = [System.Collections.Generic.List[object]]@()
}
process
{
foreach ($RGName in $ResourceGroupName)
{
try
{
if ($VMName)
{
$VMs = $VMName | ForEach-Object { Get-AzVM -ResourceGroupName $RGName -Name $_ -Status }
}
else
{
$VMs = Get-AzVM -ResourceGroupName $RGName -Status
}
foreach ($VM in $VMs)
{
$PowerState = ($VM.Statuses | Where-Object Code -like "PowerState/*").DisplayStatus
$ProvisioningState = ($VM.Statuses | Where-Object Code -like "ProvisioningState/*").DisplayStatus
$VMStatus = [PSCustomObject]@{
VMName = $VM.Name
ResourceGroup = $VM.ResourceGroupName
Location = $VM.Location
Size = $VM.HardwareProfile.VmSize
PowerState = $PowerState
ProvisioningState = $ProvisioningState
OSType = $VM.StorageProfile.OsDisk.OsType
LastModified = $VM.TimeCreated
}
if ($IncludeMetrics)
{
try
{
# Get basic metrics for the VM
$EndTime = Get-Date
$StartTime = $EndTime.AddHours(-1)
$CPUMetric = Get-AzMetric -ResourceId $VM.Id -MetricName "Percentage CPU" -StartTime $StartTime -EndTime $EndTime -TimeGrain "00:05:00" -ErrorAction SilentlyContinue
$NetworkInMetric = Get-AzMetric -ResourceId $VM.Id -MetricName "Network In Total" -StartTime $StartTime -EndTime $EndTime -TimeGrain "00:05:00" -ErrorAction SilentlyContinue
$VMStatus | Add-Member -NotePropertyName "AvgCPUPercent" -NotePropertyValue (($CPUMetric.Data | Measure-Object Average -Average).Average)
$VMStatus | Add-Member -NotePropertyName "NetworkInBytes" -NotePropertyValue (($NetworkInMetric.Data | Measure-Object Total -Sum).Sum)
}
catch
{
$VMStatus | Add-Member -NotePropertyName "MetricsError" -NotePropertyValue $_.Exception.Message
}
}
$VMStatusList.Add($VMStatus)
}
}
catch
{
Write-Error "Failed to get VM status for resource group $RGName`: $($_.Exception.Message)"
}
}
}
end
{
return $VMStatusList
}
}
Azure Storage Management
Storage Account Operations
function New-AzureStorageAccountSecure
{
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^[a-z0-9]{3,24}$')]
[string]$StorageAccountName,
[Parameter(Mandatory = $true)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $true)]
[string]$Location,
[Parameter()]
[ValidateSet("Standard_LRS", "Standard_GRS", "Standard_RAGRS", "Premium_LRS")]
[string]$SkuName = "Standard_LRS",
[Parameter()]
[ValidateSet("BlobStorage", "Storage", "StorageV2")]
[string]$Kind = "StorageV2",
[Parameter()]
[switch]$EnableHttpsTrafficOnly = $true,
[Parameter()]
[hashtable]$Tags = @{}
)
try
{
Write-Verbose "Creating secure storage account: $StorageAccountName"
# Check if storage account name is available
$NameAvailability = Get-AzStorageAccountNameAvailability -Name $StorageAccountName
if (-not $NameAvailability.NameAvailable)
{
throw "Storage account name '$StorageAccountName' is not available: $($NameAvailability.Reason)"
}
# Create storage account with security best practices
$StorageAccount = New-AzStorageAccount `
-ResourceGroupName $ResourceGroupName `
-Name $StorageAccountName `
-Location $Location `
-SkuName $SkuName `
-Kind $Kind `
-EnableHttpsTrafficOnly:$EnableHttpsTrafficOnly `
-Tag $Tags
# Configure additional security settings
Write-Host "Configuring security settings..." -ForegroundColor Green
# Disable blob public access
Set-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName -AllowBlobPublicAccess $false
# Enable secure transfer
Set-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName -EnableHttpsTrafficOnly $true
# Set minimum TLS version
Set-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName -MinimumTlsVersion TLS1_2
# Get storage account keys
$StorageKeys = Get-AzStorageAccountKey -ResourceGroupName $ResourceGroupName -Name $StorageAccountName
$Context = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageKeys[0].Value
# Create default containers with private access
$DefaultContainers = @("logs", "backups", "uploads")
foreach ($ContainerName in $DefaultContainers)
{
try
{
New-AzStorageContainer -Name $ContainerName -Context $Context -Permission Off
Write-Host "Created container: $ContainerName" -ForegroundColor Green
}
catch
{
Write-Warning "Failed to create container $ContainerName`: $($_.Exception.Message)"
}
}
# Return storage account information
$StorageInfo = [PSCustomObject]@{
StorageAccountName = $StorageAccountName
ResourceGroup = $ResourceGroupName
Location = $Location
Sku = $SkuName
Kind = $Kind
PrimaryEndpoint = $StorageAccount.PrimaryEndpoints.Blob
HttpsOnly = $EnableHttpsTrafficOnly
CreatedContainers = $DefaultContainers
ConnectionString = "DefaultEndpointsProtocol=https;AccountName=$StorageAccountName;AccountKey=$($StorageKeys[0].Value);EndpointSuffix=core.windows.net"
}
Write-Host "Storage account created successfully!" -ForegroundColor Green
Write-Host "Primary endpoint: $($StorageInfo.PrimaryEndpoint)" -ForegroundColor Cyan
return $StorageInfo
}
catch
{
Write-Error "Storage account creation failed: $($_.Exception.Message)"
throw
}
}
function Backup-AzureVMToBlobStorage
{
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$VMResourceGroupName,
[Parameter(Mandatory = $true)]
[string]$VMName,
[Parameter(Mandatory = $true)]
[string]$StorageAccountName,
[Parameter(Mandatory = $true)]
[string]$StorageResourceGroupName,
[Parameter()]
[string]$ContainerName = "vm-backups",
[Parameter()]
[int]$RetentionDays = 30
)
try
{
Write-Host "Starting VM backup process..." -ForegroundColor Green
# Get VM information
$VM = Get-AzVM -ResourceGroupName $VMResourceGroupName -Name $VMName
if (-not $VM)
{
throw "VM '$VMName' not found in resource group '$VMResourceGroupName'"
}
# Get storage context
$StorageAccount = Get-AzStorageAccount -ResourceGroupName $StorageResourceGroupName -Name $StorageAccountName
$StorageKeys = Get-AzStorageAccountKey -ResourceGroupName $StorageResourceGroupName -Name $StorageAccountName
$Context = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageKeys[0].Value
# Ensure backup container exists
$Container = Get-AzStorageContainer -Name $ContainerName -Context $Context -ErrorAction SilentlyContinue
if (-not $Container)
{
New-AzStorageContainer -Name $ContainerName -Context $Context -Permission Off
Write-Host "Created backup container: $ContainerName" -ForegroundColor Green
}
# Create snapshot of OS disk
$OSDisk = Get-AzDisk -ResourceGroupName $VM.ResourceGroupName -DiskName $VM.StorageProfile.OsDisk.Name
$SnapshotName = "$($VM.Name)-os-snapshot-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
Write-Host "Creating OS disk snapshot: $SnapshotName" -ForegroundColor Yellow
$SnapshotConfig = New-AzSnapshotConfig -SourceUri $OSDisk.Id -CreateOption Copy -Location $VM.Location
$Snapshot = New-AzSnapshot -ResourceGroupName $VM.ResourceGroupName -SnapshotName $SnapshotName -Snapshot $SnapshotConfig
# Export snapshot to storage account
$BlobName = "$($VM.Name)/$SnapshotName.vhd"
$SASUri = Grant-AzSnapshotAccess -ResourceGroupName $VM.ResourceGroupName -SnapshotName $SnapshotName -Access Read -DurationInSecond 3600
Write-Host "Copying snapshot to blob storage..." -ForegroundColor Yellow
# Start async copy operation
$CopyBlob = Start-AzStorageBlobCopy -AbsoluteUri $SASUri.AccessSAS -DestContainer $ContainerName -DestBlob $BlobName -Context $Context
# Monitor copy progress
do
{
Start-Sleep -Seconds 30
$CopyStatus = $CopyBlob | Get-AzStorageBlobCopyState
$PercentComplete = if ($CopyStatus.TotalBytes -gt 0) { [math]::Round(($CopyStatus.BytesCopied / $CopyStatus.TotalBytes) * 100, 2) } else { 0 }
Write-Host "Copy progress: $PercentComplete%" -ForegroundColor Cyan
}
while ($CopyStatus.Status -eq "Pending")
if ($CopyStatus.Status -eq "Success")
{
Write-Host "Backup completed successfully!" -ForegroundColor Green
# Clean up snapshot
Remove-AzSnapshot -ResourceGroupName $VM.ResourceGroupName -SnapshotName $SnapshotName -Force
Revoke-AzSnapshotAccess -ResourceGroupName $VM.ResourceGroupName -SnapshotName $SnapshotName
# Set metadata on blob
$Blob = Get-AzStorageBlob -Container $ContainerName -Blob $BlobName -Context $Context
$Metadata = @{
"VMName" = $VM.Name
"ResourceGroup" = $VM.ResourceGroupName
"BackupDate" = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
"OSType" = $VM.StorageProfile.OsDisk.OsType
"VMSize" = $VM.HardwareProfile.VmSize
}
$Blob.ICloudBlob.SetMetadata($Metadata)
# Clean up old backups
Write-Host "Cleaning up old backups..." -ForegroundColor Yellow
$OldBlobs = Get-AzStorageBlob -Container $ContainerName -Context $Context -Prefix "$($VM.Name)/" |
Where-Object { $_.LastModified -lt (Get-Date).AddDays(-$RetentionDays) }
foreach ($OldBlob in $OldBlobs)
{
Remove-AzStorageBlob -Container $ContainerName -Blob $OldBlob.Name -Context $Context -Force
Write-Host "Removed old backup: $($OldBlob.Name)" -ForegroundColor Gray
}
$BackupInfo = [PSCustomObject]@{
VMName = $VM.Name
BackupDate = Get-Date
SnapshotName = $SnapshotName
BlobName = $BlobName
StorageAccount = $StorageAccountName
Container = $ContainerName
SizeGB = [math]::Round($CopyStatus.TotalBytes / 1GB, 2)
Status = "Success"
}
return $BackupInfo
}
else
{
throw "Backup copy failed: $($CopyStatus.Status)"
}
}
catch
{
Write-Error "VM backup failed: $($_.Exception.Message)"
throw
}
}
Azure Monitoring and Automation
Resource Health Monitoring
function Get-AzureResourceHealth
{
[CmdletBinding()]
param(
[Parameter()]
[string[]]$ResourceGroupName,
[Parameter()]
[string[]]$ResourceType,
[Parameter()]
[switch]$IncludeMetrics,
[Parameter()]
[string]$OutputPath
)
try
{
Write-Host "Gathering Azure resource health information..." -ForegroundColor Green
$HealthResults = [System.Collections.Generic.List[object]]@()
# Get all resources or filter by resource group
if ($ResourceGroupName)
{
$Resources = $ResourceGroupName | ForEach-Object { Get-AzResource -ResourceGroupName $_ }
}
else
{
$Resources = Get-AzResource
}
# Filter by resource type if specified
if ($ResourceType)
{
$Resources = $Resources | Where-Object ResourceType -in $ResourceType
}
foreach ($Resource in $Resources)
{
try
{
Write-Progress -Activity "Checking Resource Health" -Status "Processing $($Resource.Name)" -PercentComplete (($Resources.IndexOf($Resource) / $Resources.Count) * 100)
$HealthInfo = [PSCustomObject]@{
ResourceName = $Resource.Name
ResourceType = $Resource.ResourceType
ResourceGroup = $Resource.ResourceGroupName
Location = $Resource.Location
Status = "Unknown"
LastChecked = Get-Date
Issues = @()
Metrics = @{}
}
# Check specific resource types
switch ($Resource.ResourceType)
{
"Microsoft.Compute/virtualMachines"
{
$VM = Get-AzVM -ResourceGroupName $Resource.ResourceGroupName -Name $Resource.Name -Status
$PowerState = ($VM.Statuses | Where-Object Code -like "PowerState/*").DisplayStatus
$ProvisioningState = ($VM.Statuses | Where-Object Code -like "ProvisioningState/*").DisplayStatus
$HealthInfo.Status = if ($PowerState -eq "VM running" -and $ProvisioningState -eq "Provisioning succeeded") { "Healthy" } else { "Unhealthy" }
if ($PowerState -ne "VM running")
{
$HealthInfo.Issues += "VM not running: $PowerState"
}
if ($IncludeMetrics)
{
try
{
$EndTime = Get-Date
$StartTime = $EndTime.AddHours(-1)
$CPUMetric = Get-AzMetric -ResourceId $Resource.ResourceId -MetricName "Percentage CPU" -StartTime $StartTime -EndTime $EndTime -TimeGrain "00:15:00"
$HealthInfo.Metrics["AvgCPU"] = [math]::Round(($CPUMetric.Data | Measure-Object Average -Average).Average, 2)
}
catch
{
$HealthInfo.Issues += "Unable to retrieve metrics"
}
}
}
"Microsoft.Storage/storageAccounts"
{
$StorageAccount = Get-AzStorageAccount -ResourceGroupName $Resource.ResourceGroupName -Name $Resource.Name
$HealthInfo.Status = if ($StorageAccount.ProvisioningState -eq "Succeeded") { "Healthy" } else { "Unhealthy" }
if ($StorageAccount.ProvisioningState -ne "Succeeded")
{
$HealthInfo.Issues += "Storage account provisioning state: $($StorageAccount.ProvisioningState)"
}
# Check if HTTPS is enforced
if (-not $StorageAccount.EnableHttpsTrafficOnly)
{
$HealthInfo.Issues += "HTTPS traffic not enforced"
}
}
"Microsoft.Web/sites"
{
$WebApp = Get-AzWebApp -ResourceGroupName $Resource.ResourceGroupName -Name $Resource.Name
$HealthInfo.Status = if ($WebApp.State -eq "Running") { "Healthy" } else { "Unhealthy" }
if ($WebApp.State -ne "Running")
{
$HealthInfo.Issues += "Web app not running: $($WebApp.State)"
}
# Check if HTTPS is enforced
if (-not $WebApp.HttpsOnly)
{
$HealthInfo.Issues += "HTTPS not enforced"
}
if ($IncludeMetrics)
{
try
{
$EndTime = Get-Date
$StartTime = $EndTime.AddHours(-1)
$RequestMetric = Get-AzMetric -ResourceId $Resource.ResourceId -MetricName "Requests" -StartTime $StartTime -EndTime $EndTime -TimeGrain "00:15:00"
$HealthInfo.Metrics["TotalRequests"] = ($RequestMetric.Data | Measure-Object Total -Sum).Sum
}
catch
{
$HealthInfo.Issues += "Unable to retrieve metrics"
}
}
}
default
{
# Generic resource check
try
{
$GenericResource = Get-AzResource -ResourceId $Resource.ResourceId
$HealthInfo.Status = if ($GenericResource.Properties.provisioningState -eq "Succeeded") { "Healthy" } else { "Unknown" }
}
catch
{
$HealthInfo.Status = "Error"
$HealthInfo.Issues += "Unable to retrieve resource details"
}
}
}
$HealthResults.Add($HealthInfo)
}
catch
{
Write-Warning "Failed to check health for resource $($Resource.Name): $($_.Exception.Message)"
}
}
Write-Progress -Activity "Checking Resource Health" -Completed
# Generate summary
$Summary = @{
TotalResources = $HealthResults.Count
HealthyResources = ($HealthResults | Where-Object Status -eq "Healthy").Count
UnhealthyResources = ($HealthResults | Where-Object Status -eq "Unhealthy").Count
UnknownResources = ($HealthResults | Where-Object Status -eq "Unknown").Count
ResourcesWithIssues = ($HealthResults | Where-Object { $_.Issues.Count -gt 0 }).Count
}
Write-Host "`nResource Health Summary:" -ForegroundColor Cyan
Write-Host "Total Resources: $($Summary.TotalResources)" -ForegroundColor White
Write-Host "Healthy: $($Summary.HealthyResources)" -ForegroundColor Green
Write-Host "Unhealthy: $($Summary.UnhealthyResources)" -ForegroundColor Red
Write-Host "Unknown: $($Summary.UnknownResources)" -ForegroundColor Yellow
Write-Host "With Issues: $($Summary.ResourcesWithIssues)" -ForegroundColor Orange
# Export results if path specified
if ($OutputPath)
{
$ReportDate = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$ReportFile = Join-Path $OutputPath "AzureResourceHealth_$ReportDate.csv"
$HealthResults | Export-Csv -Path $ReportFile -NoTypeInformation
Write-Host "Report saved to: $ReportFile" -ForegroundColor Cyan
}
return $HealthResults
}
catch
{
Write-Error "Resource health check failed: $($_.Exception.Message)"
throw
}
}
# Usage Examples
Write-Host @"
AZURE POWERSHELL EXAMPLES
1. Create Secure VM:
New-AzureVM -ResourceGroupName "MyRG" -VMName "WebServer01" -Location "East US"
2. Get VM Status:
Get-AzureVMStatus -ResourceGroupName "MyRG" -IncludeMetrics
3. Create Secure Storage:
New-AzureStorageAccountSecure -StorageAccountName "mystorageacct123" -ResourceGroupName "MyRG" -Location "East US"
4. Backup VM:
Backup-AzureVMToBlobStorage -VMResourceGroupName "MyRG" -VMName "WebServer01" -StorageAccountName "backupstorageacct" -StorageResourceGroupName "BackupRG"
5. Check Resource Health:
Get-AzureResourceHealth -ResourceGroupName "MyRG" -IncludeMetrics -OutputPath "C:\Reports"
These examples demonstrate Azure PowerShell capabilities for:
- Virtual machine management with security best practices
- Storage account creation with security configurations
- Automated VM backup to blob storage
- Comprehensive resource health monitoring
- Metrics collection and reporting
All functions include proper error handling, progress reporting,
and security best practices for Azure resource management.
"@ -ForegroundColor Green