This post is exactly what I need, but I would like to add NSG and Route table information:
$subs = Get-AzSubscription
foreach ($Sub in $Subs) {
Write-Host "***************************"
Write-Host " "
$Sub.Name
$SelectSub = Select-AzSubscription -SubscriptionName $Sub.Name
$VNETs = Get-AzVirtualNetwork
foreach ($VNET in $VNETs) {
Write-Host "--------------------------"
Write-Host " "
Write-Host " vNet: " $VNET.Name
Write-Host " AddressPrefixes: " ($VNET).AddressSpace.AddressPrefixes
$vNetExpanded = Get-AzVirtualNetwork -Name $VNET.Name -ResourceGroupName $VNET.ResourceGroupName -ExpandResource 'subnets/ipConfigurations'
foreach($subnet in $vNetExpanded.Subnets)
{
Write-Host " Subnet: " $subnet.Name
Write-Host " Connected devices " $subnet.IpConfigurations.Count
foreach($ipConfig in $subnet.IpConfigurations)
{
Write-Host " " $ipConfig.PrivateIpAddress
}
}
Write-Host " "
}
}
I tried adding the variables to reflect it, but I guess I cant get it to work.
Add below script snippet to get NetworkSecurityGroup(NSG) and Route table information:
$nsgs = Get-AzNetworkSecurityGroup
foreach ($nsg in $nsgs) {
Write-Host " nsg: " $nsg.Name
$networksecuritygroup = Get-AzNetworkSecurityGroup -Name $nsg -ResourceGroupName $nsg.ResourceGroupName
}
$rts = Get-Azroutetable
foreach ($rt in $rts) {
Write-Host " rt: " $rt.Name
$routetableinfo = Get-Azroutetable -Name $rt -ResourceGroupName $rt.ResourceGroupName
}
Output:
Related
I am Trying to pull All the Tags resource level in azure
$subscripionList = Get-AzSubscription
foreach ($subscriptionId in $subscripionList) {
Write-Host 'Getting details about SubscriptionId :' $subscriptionId
Set-AzContext -Subscription $subscriptionId
#Select-AzureRmSubscription -SubscriptionName $subscriptionId
$resourcesgroups = Get-AzResourceGroup
foreach($resourcesgroup in $resourcesgroups){
Write-Host 'resourcegroup :' $resourcesgroup
$resources = Get-AzResource -ResourceGroupName $resourcesgroup.ResourceGroupName
#$azure_resources = Get-AzResource
foreach($resource in $resources){
Write-Host $resource
{
#Fetching Tags
$Tags = $resource.Tags
#Checkign if tags is null or have value
if($Tags -ne $null)
{
foreach($Tag in $Tags)
{
$TagsAsString += $Tag.Name + ":" + $Tag.Value + ";"
}
}
else
{
$TagsAsString = "NULL"
}
}
}
}
I am Trying to get all the subscription then
I am Trying to get all the resource groups then
I am Trying to get all the resource present in resource group
Trying to get all the tags
But i am unable to get Tags and can anyone guide me how to export all tags into csv file.
As there is no $tag.Name and $Tag.Value , Your code doesn't store any values. The output you are looking are stored as $tags.keys and $tags.values. So, to collect them you will have to use for loop again . I tested the same by replacing the for each loop for the resources with the below script:
$TagsAsString=#()
$tagkeys =#()
$TagValues =#()
$resources = Get-AzResource -ResourceGroupName <resourcegroupname>
foreach($resource in $resources){
Write-host ("ResourceName :")$resource.Name
if($resource.Tags -ne $null){
foreach($Tag in $resource.Tags){
foreach($key in $Tag.keys){
$tagkeys += $key
}
foreach($value in $Tag.values){
$TagValues += $value
}
}
}
else{
Write-Host ("No Tags")
}
}
for($i = 0; $i -lt $tagkeys.Length; $i++) {
$TagsAsString=( '{0} : {1}' -f $tagkeys[$i], $tagvalues[$i] )
Write-Host $TagsAsString
}
Output:
Context : I am automating starting of 3 Azure VM through a PowerShell script, and each VM is taking 4-5min to start. I want to run the start command parallel and after 5-6min verify them whether they are started.
function restartLoadAgents ($AzuresecretValue,$AzureApplicationID,$AzureObjectID,$AzureDirectoryID,$AzureUserName,$AzureSubscriptionID) {
$password = ConvertTo-SecureString $AzuresecretValue -AsPlainText -Force;
$LoadAgentResourceGroup = "test-performance-rg01";
#Connecting to the Azure VM using the Service Principle
$pscredential = New-Object -TypeName System.Management.Automation.PSCredential($AzureApplicationID, $password);
Connect-AzAccount -ServicePrincipal -Tenant $AzureDirectoryID -Credential $pscredential | Out-null;
#List all the Load Agents
$VMList = Get-AzVm -ResourceGroupName $LoadAgentResourceGroup -Status;
ForEach($VM in $VMList) {
#Skipping the Master Machine and DB machine
if ($VM.Name -eq "test-load-appmachine01" -or $VM.Name -eq "test-load-appmachine02") {
continue;
}
$VMLoadAgentStatus = (Get-AzVm -ResourceGroupName $LoadAgentResourceGroup -Name $VM.Name -status).Statuses
$CurrentLoadAgentRunningStatus = $VMLoadAgentStatus[1].DisplayStatus;
if($CurrentLoadAgentRunningStatus -match "deallocated" -or $CurrentLoadAgentRunningStatus -match "VM deallocated"){
Start-AzVM -ResourceGroupName $LoadAgentResourceGroup -Name $VM.Name | Out-null
commandVerifier;
checkVMStatus($VM.Name);
}
else {
Write-Host $VM.Name " Current State is "$CurrentLoadAgentRunningStatus;
}
}
}
function commandVerifier() {
if ($?){
Write-Host "Successfully Started "$VM.Name;
}
else {
Write-Host "Start Unsuccessful "$VM.Name;
}
}
function checkVMStatus($VM_NAME) {
$VMLoadAgentStatus = (Get-AzVm -ResourceGroupName $LoadAgentResourceGroup -Name $$VM_NAME -status).Statuses
$VMRunningStatusAfterTriggered = $VMLoadAgentStatus[1].DisplayStatus;
if($VMRunningStatusAfterTriggered -eq "running" -or $VMRunningStatusAfterTriggered -eq "VM running"){
Write-Host "Successfully Started VM"
}
else{
Write-Host "Something went with starting VM and current status is"$VMRunningStatusAfterTriggered
}
}
function getServicePrincipleDetails () {
$AzuresecretValue = "<secretValue>";
$AzureApplicationID = "<app_id>";
$AzureObjectID = "<obj_id>";
$AzureDirectoryID = "<dir_id>";
$AzureUserName = "SVCUSER";
$AzureSubscriptionID = "<sub_id>";
restartLoadAgents $AzuresecretValue $AzureApplicationID $AzureObjectID $AzureDirectoryID $AzureUserName $AzureSubscriptionID
}
getServicePrincipleDetails
There are 5 VM in total and first two need not to be stopped or started. test-load-appmachine03,test-load-appmachine04 & test-load-appmachine05 are the target VM and I want to start them parallelly and check after.
<#
NAME
AzureSubscriptionRBACAudit.ps1
SYNOPSIS
Gathers Azure Role Based Access Control Data for Audit Purposes.
DESCRIPTION
Gathers Azure Role Based Access Control Data for Audit Purposes. The script will prompt the user to
select a subscription to run the audit against. The user is only presented the scriptions currently
available to the users credentials.
OUTPUTS
Outputs a CSV file in the same directory that the script is located in. The CSV file will have the
name of the subscription in its title followed by "Azure RBAC Audit.csv"
#>
Functions
Function Login {
<#
.SYNOPSIS
Runs the Azure Login Command
#>
$needLogin = $true
Try {
$content = Get-AzContext
if ($content) {
$needLogin = ([string]::IsNullOrEmpty($content.Account))
}
}
Catch {
if ($_ -like "*Login-AzAccount to login*") {
$needLogin = $true
}
else {
throw
}
}
if ($needLogin) {
#Login-AzAccount
Select-Azure
}
}
Function Select-Azure{
<#
.SYNOPSIS
Provides a list of Azure Environments for the user to select from.
AzureGov, AzureCloud, etc.
#>
Clear-Host
$ErrorActionPreference = 'SilentlyContinue'
$Menu = 0
$AzEnvironment = #(Get-AzEnvironment |select-object Name)
Write-Host "Please select the Azure Environment you want to use:" -ForegroundColor Green;
ForEach-Object {Write-Host ""}
$AzEnvironment | ForEach-Object {Write-Host "[$($Menu)]" -ForegroundColor Cyan -NoNewline ; Write-host ". $($_.Name)"; $Menu++; }
ForEach-Object {Write-Host ""}
ForEach-Object {Write-Host "[Q]" -ForegroundColor Red -NoNewline ; Write-host ". To quit."}
ForEach-Object {Write-Host ""}
$selection = Read-Host "Please select the Azure Environment Number - Valid numbers are 0 - $($AzEnvironment.count -1) or Q to quit"
If ($selection -eq 'Q') {
Clear-Host
Exit
}
If ($AzEnvironment.item($selection) -ne $null)
{ Connect-AzAccount -EnvironmentName $AzEnvironment.item($selection).Name -ErrorAction Stop}
}
Function Select-Subs {
<#
.SYNOPSIS
Provides a list of subscriptions for the user to select from.
#>
Clear-Host
$ErrorActionPreference = 'SilentlyContinue'
$Menu = 0
$Subs = #(Get-AzSubscription | Select-Object Name, ID, TenantId)
Write-Host "Please select the subscription you want to use:" -ForegroundColor Green;
ForEach-Object {Write-Host ""}
$Subs | ForEach-Object {Write-Host "[$($Menu)]" -ForegroundColor Cyan -NoNewline ; Write-host ". $($_.Name)"; $Menu++; }
ForEach-Object {Write-Host ""}
ForEach-Object {Write-Host "[S]" -ForegroundColor Yellow -NoNewline ; Write-host ". To switch Azure Account."}
ForEach-Object {Write-Host ""}
ForEach-Object {Write-Host "[Q]" -ForegroundColor Red -NoNewline ; Write-host ". To quit."}
ForEach-Object {Write-Host ""}
$selection = Read-Host "Please select the Subscription Number - Valid numbers are 0 - $($Subs.count -1), S to switch Azure Account or Q to quit"
If ($selection -eq 'S') {
Get-AzContext | ForEach-Object {Clear-AzContext -Scope CurrentUser -Force}
Select-Azure
Select-Subs
}
If ($selection -eq 'Q') {
Clear-Host
Exit
}
If ($Subs.item($selection) -ne $null)
{ Return #{name = $subs[$selection].Name; ID = $subs[$selection].ID}
}
}
Function Resolve-AzAdGroupMembers {
<#
.SYNOPSIS
Gets list of Azure Active Directory groups and its members
#>
param(
[guid]
$GroupObjectId,
$GroupList
)
$VerbosePreference = 'continue'
Write-Verbose -Message ('Resolving {0}' -f $GroupObjectId)
$group = $GroupList | Where-Object -Property Id -EQ -Value $GroupObjectId
$groupMembers = Get-AzADGroupMember -GroupObjectId $GroupObjectId
Write-Verbose -Message ('Found members {0}' -f ($groupMembers.DisplayName -join ', '))
$parentGroup = #{
Id = $group.Id
DisplayName = $group.DisplayName
}
$groupMembers |
Where-Object -Property Type -NE -Value Group |
Select-Object -Property Id, DisplayName, #{
Name = 'ParentGroup'
Expression = { $parentGroup }
}
$groupMembers |
Where-Object -Property type -EQ -Value Group |
ForEach-Object -Process {
Resolve-AzAdGroupMembers -GroupObjectId $_.Id -GroupList $GroupList
}
}
Main Part of Script
Write-Output "Running login script"
Login # Login to Azure
$SubscriptionSelection = Select-Subs # Runs function to get Azure subscriptions available to user and sets the subscription to the users choice.
Select-AzSubscription -SubscriptionName $SubscriptionSelection.Name -ErrorAction Stop
## Get current Azure Subscription Name to be used in reporting output
$Azuresub = $SubscriptionSelection.Name -replace , '/'
ForEach-Object {Write-Host "Getting Azure AD Groups" -ForegroundColor Yellow -NoNewline}
ForEach-Object {Write-Host "`r`n========================================" -ForegroundColor Yellow -NoNewline}
ForEach-Object {Write-Host "`nThis process can take a while to run since it is checking every Azure Role and its corresponding assignments." -ForegroundColor Yellow -NoNewline }
$GroupList = (Get-AzADGroup)
ForEach-Object {Write-Host "Getting Role Assignments" -ForegroundColor Yellow -NoNewline}
ForEach-Object {Write-Host "`r`n========================================" -ForegroundColor Yellow -NoNewline}
$roleAssignments = Get-AzRoleAssignment -IncludeClassicAdministrators
## Loop through each role assignment to determine the user assigned to that role.
$members = $roleAssignments | ForEach-Object -Process {
Write-Verbose -Message ('Processing Assignment {0}' -f $_.RoleDefinitionName)
$roleAssignment = $_
if($roleAssignment.ObjectType -eq 'Group')
{
Resolve-AzAdGroupMembers -GroupObjectId $roleAssignment.ObjectId -GroupList $GroupList `
| Select-Object -Property Id,
DisplayName,
ParentGroup, #{
Name = 'RoleDefinitionName'
Expression = { $roleAssignment.RoleDefinitionName }
}, #{
Name = 'Scope'
Expression = { $roleAssignment.Scope }
}, #{
Name = 'CanDelegate'
Expression = { $roleAssignment.CanDelegate }
}
}
else
{
$roleAssignment | Select-Object -Property #{
Name = 'Id'
Expression = { $_.ObjectId }
},
DisplayName,
#{
Name = 'RoleDefinitionName'
Expression = { $roleAssignment.RoleDefinitionName }
},
Scope,
CanDelegate
}
}
Generating CSV Output for reporting
$outtbl = #()
$members | ForEach-Object {
$x = New-Object PSObject -Property #{
Subscription = $Azuresub -join ','
ActiveDirID = $_.Id -join ','
DisplayName = $_.DisplayName -join ','
ParentGroupID = $_.ParentGroup.Id -join ','
ParentGroupDisplayName = $_.ParentGroup.DisplayName -join ','
RoleDefinitionName = $_.RoleDefinitionName -join ','
Scope = $_.Scope
}
$outtbl += $x
}
$outtbl | Select-Object Subscription,ActiveDirID,DisplayName,ParentGroupID,ParentGroupDisplayName,RoleDefinitionName, Scope |Export-CSV -path $($PSScriptRoot + "\" + "$Azuresub" + " Azure RBAC Audit.csv") -NoTypeInformation
ForEach-Object {Write-Host " `r`nRBAC Audit has completed. Your CSV file is located: $($PSScriptRoot + "\" + "$Azuresub" + " Azure RBAC Audit.csv")" -ForegroundColor Green -NoNewline }
Above code is working fine for complete subscription but we need to filter the output only for resoucegroup. so how to add one more function to get output only based on reouce group.
https://github.com/arnoldna/RBACReporting/blob/master/AzureSubscriptionRBACAudit.ps1
For your requirement, just use the -ResourceGroupName parameter in the command Get-AzRoleAssignment to specify the resource group you want in Main Part of Script.
$roleAssignments = Get-AzRoleAssignment -IncludeClassicAdministrators -ResourceGroupName <ResourceGroupName>
Note: The RBAC role permissions are inherited, e.g. if a user/service principal/AAD group has an RBAC role at the subscription/management group scope, it will also have the permission at all the resource groups located in the subscription/management group, so the command above will also get the role assignments that assigned at the subscription/management group scope, the management group is a higher scope than subscription, refer to this link.
So if you just want to get the role assignment that directly assigned to the resource group/single resource in the resource group, modify the command as below, it depends on your reqirement.
$roleAssignments = Get-AzRoleAssignment -IncludeClassicAdministrators -ResourceGroupName <ResourceGroupName> | Where-Object {$_.Scope -like '/subscriptions/*/resourceGroups/*'}
I'm trying to write a PowerShell script that lists me all connected devices with there ips in my subnets in all VNets in all subscriptions.
UPDATE the below script works, scroll down for original problem.
$subs = Get-AzSubscription
foreach ($Sub in $Subs) {
Write-Host "***************************"
Write-Host " "
$Sub.Name
$SelectSub = Select-AzSubscription -SubscriptionName $Sub.Name
$VNETs = Get-AzVirtualNetwork
foreach ($VNET in $VNETs) {
Write-Host "--------------------------"
Write-Host " "
Write-Host " vNet: " $VNET.Name
Write-Host " AddressPrefixes: " ($VNET).AddressSpace.AddressPrefixes
$vNetExpanded = Get-AzVirtualNetwork -Name $VNET.Name -ResourceGroupName $VNET.ResourceGroupName -ExpandResource 'subnets/ipConfigurations'
foreach($subnet in $vNetExpanded.Subnets)
{
Write-Host " Subnet: " $subnet.Name
Write-Host " Connected devices " $subnet.IpConfigurations.Count
foreach($ipConfig in $subnet.IpConfigurations)
{
Write-Host " " $ipConfig.PrivateIpAddress
}
}
Write-Host " "
}
}
My original problem:
The problem however is that I cannot get the $subnet.IpConfigurations property to be filled. By that I mean that I do get a list but the child items only contain an Id, the rest of the properties like name, privateip, etc are null.
According to my research, if we want to get detailed information about subnet IpConfigurations, we need to specify the parameter ExpandResource with powershell command Get-AzVirtualNetwork.
For example
$result=Get-AzVirtualNetwork -Name '<vnet name>' -ResourceGroupName '<group nmae>' -ExpandResource 'subnets/ipConfigurations'
$result.Subnets[0].IpConfigurations
I have a script to start VMs/Stop them at a specific time. The issue is, I want the script to only exit when all the VMs are started/running or when they are deallocated/stopped. My current problem is when a VM is starting, it waits until it has started before moving to the next one.
eg: vm1 is starting..
vm2 is starting..
vm3 is starting..
vm1 is now running..
vm2 is still starting
vm3 is still starting
vm1 is now running..
vm2 is now running..
vm3 is now running..
Then script exits.
Full script here
$ACTION="start"
Write-Output "Number of Virtual Machines: $($GetVMS.Name.Count)" `n
$GetVMS | Format-Table
$startstopvm = {
$ResourceGroupName = $args[0]
$Name = $args[1]
$ACTION = $args[2]
# Get VM status
try {
$VMs = Get-AzureRmVM -Name $Name -ResourceGroupName $ResourceGroupName -Status -WarningAction SilentlyContinue
} catch {
Write-Output ("Cloud not get vm $Name in $ResourceGroupName")
$Error[0]
Exit 1
}
if ($ACTION -eq "start")
{
foreach ($VM in $VMs)
{
if ($VM.Statuses[1].Code -eq "PowerState/running")
{
Write-Output ($VM.Name + " in " + $VM.ResourceGroupName + " is already running")
}
else
{
# The VM needs to be started
Write-Output ("Starting VM " + $VM.Name)
$startVM += Start-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -AsJob -ErrorAction Continue
$startTime = Get-Date
$timeElapsed = $((Get-Date) - $startTime).TotalMinutes
while ($timeElapsed -lt 2)
{
$startVM = Get-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -Status -WarningAction SilentlyContinue
if ($startVM.Statuses[1].Code -match "PowerState/(running|starting)")
{
# The VM started, so send notice
Write-Output ($VM.Name + " in " + $VM.ResourceGroupName + " has been started`n")
break
}
Start-Sleep -s 30
}
if ($getStat.Statuses[1].Code -ne "PowerState/(running|starting)")
{
# The VM failed to start, so send notice
Write-Output ($VM.Name + " failed to start`n")
}
}
}
}
NOTE: I am reading the VM name & RG from a file
try {
$VMList = Get-Content C:\Users\local\Desktop\VMs.csv | ConvertFrom-Csv
} catch {
Write-Output ("Cannot open file...")
exit -1
}
$Result = #()
foreach ($vm in $VMList) {
Invoke-Command -ArgumentList $vm.ResourceGroupName, $vm.Name, $ACTION -Verbose -ScriptBlock $startstopvm
}
The simplest way I have done this in the past is to use the -Wait parameter on a Start-Process cmdlet.
You should be able to implement this with small changes.
Saving your current code block into a seperate .ps1 i.e. startstopvm.ps1
You could then change the Invoke-Commmand line to read something like:
Invoke-Command -ArgumentList $vm.ResourceGroupName, $vm.Name, $ACTION -Verbose -ScriptBlock {Start-Process powershell.exe -Argument "C:\Scripts\Backup.ps1 TestBackup" -Wait}
Definitely some other ways to do it but an approach like this has always worked for me