Advertisement
Guest User

Untitled

a guest
May 18th, 2018
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ## Helper Functions
  2. <#
  3.     Helper function for merging hashtables
  4.     <https://stackoverflow.com/questions/8800375/merging-hashtables-in-powershell-how>
  5. #>
  6.  
  7. function Merge-HashTable {
  8.     param(
  9.         [hashtable] $OriginTable, # your original set
  10.         [hashtable] $Append # the set you want to update/Append to the original set
  11.     )
  12.  
  13.     # clone for idempotence
  14.     $OriginTable1 = $OriginTable.Clone() ;
  15.  
  16.     # we need to remove any key-value pairs in $OriginTable1 that we will
  17.     # be replacing with key-value pairs from $uppend
  18.     foreach ($key in $Append.Keys) {
  19.         if ($OriginTable1.ContainsKey($key)) {
  20.             $OriginTable1.Remove($key) ;
  21.         }
  22.     }
  23.  
  24.     # union both sets
  25.     return $OriginTable1 + $Append ;
  26. }
  27.  
  28. ## Runbook Variables
  29. # Resource types that are untaggable
  30. $exAzureResources = @(
  31.     "Microsoft.ClassicNetwork/virtualNetworks"
  32.     "Microsoft.ClassicStorage/storageAccounts"
  33.     "Microsoft.ClassicCompute/domainNames"
  34.     "Microsoft.ClassicCompute/virtualMachines"
  35.     "Microsoft.OperationsManagement/solutions"
  36.     "Microsoft.DomainRegistration/domains"
  37.     "microsoft.insights/alertrules"
  38.     "microsoft.insights/webtests"
  39.     "TrendMicro.DeepSecurity/accounts"
  40.     "Microsoft.Automation/automationAccounts/configurations"
  41. )
  42.  
  43. # Counters for results
  44. $tagCounterSuccess      = 0
  45. $tagCounterFail         = 0
  46. $tagCounterSkip         = 0
  47. $tagCounterNull         = 0
  48. $tagCounterUntaggable   = 0
  49. $tagCounterError        = 0
  50.  
  51. ## Connect to Azure with Run As account
  52. $Conn = Get-AutomationConnection -Name AzureRunAsConnection
  53. $azRMAccountParams = @{
  54.     ServicePrincipal        = $true
  55.     Tenant                  = $Conn.TenantID
  56.     ApplicationId           = $Conn.ApplicationID
  57.     CertificateThumbprint   = $Conn.CertificateThumbprint
  58. }
  59. Add-AzureRMAccount @azRMAccountParams | Out-Null
  60.  
  61. ## Script main
  62. try {
  63.     /write-host
  64.     # Capture Tags from Resource Group
  65.     $azResourceGroups = Get-AzureRmResourceGroup
  66.  
  67.     # Iterate through groups and set tags
  68.     foreach ($azResourceGroup in $azResourceGroups) {
  69.         # Get Resources in the Resource Group
  70.         $azResources = Get-AzureRmResource | Where-Object {$_.ResourceGroupName -like $azResourceGroup.ResourceGroupName}
  71.         # Standard TFL tags
  72.         $tflTags = @{
  73.             "SvcName"       = $null
  74.             "SvcOwner"      = $null
  75.             "CrgCostCode"   = $null
  76.             "Environment"   = $null
  77.         }
  78.         # Temp var to store RG tags before merge
  79.         $tempTable = @{}
  80.         # Test for Tags property
  81.         switch ($azResourceGroup.PSObject.Properties['Tags']) {
  82.             # If Tags property is present
  83.             ({$PSItem.Value})
  84.             {
  85.                 # Iterate through Resource Group Tags
  86.                 foreach ($kvpRG in $azResourceGroup.Tags.GetEnumerator()) {
  87.                     # Iterate through TFL Tags
  88.                     foreach ($kvpTag in $tflTags.GetEnumerator()) {
  89.                         # If match is found add Resource Group Tag/Value to $tempTable
  90.                         if ($kvpTag.Key -like $kvpRG.Key) {
  91.                             $tempTable.Add($kvpRG.Key,$kvpRG.Value)
  92.                         }
  93.                     }
  94.                 }
  95.             }
  96.             # If Tags property is not present
  97.             ({!($PSItem.Value)})
  98.             {
  99.                 $tagCounterNull++
  100.                 # Log this for informational purposes
  101.                 Write-Output "No Tags set on $($azResourceGroup.ResourceGroupName)"
  102.             }
  103.         }
  104.  
  105.         # Merge TFL Tags with the Resource Group Tags
  106.         # We do it this way so that even if it's blank the key is added
  107.         $mergeTableRG = Merge-HashTable -OriginTable $tflTags -Append $tempTable
  108.  
  109.         # Iterate through the Resources
  110.         foreach ($azResource in $azResources) {
  111.             # Test if resourceType is classic
  112.             switch ($azResource.ResourceType) {
  113.                 # If in the exclude list ignore
  114.                 ({$PSItem -in $exAzureResources})
  115.                 {
  116.                     $tagCounterUntaggable++
  117.                     # Uncomment for debugging purposes
  118.                     #Write-Output "$($azResource.ResourceName) is not a taggable resource"
  119.                 }
  120.                 # If not in the exclude list
  121.                 ({!($PSItem -in $exAzureResources)})
  122.                 {
  123.                     # Test each Resource for Tags property
  124.                     switch ($azResource.PSObject.Properties['Tags']) {
  125.                         # If Tags property is present
  126.                         ({$PSItem})
  127.                         {
  128.                             # Capture Tags hashtable to var
  129.                             $azResourceTags = $azResource.Tags
  130.                         }
  131.                         # If Tags property is not present
  132.                         ({!($PSItem)})
  133.                         {
  134.                             # Create blank/dummy hashtable for the merge
  135.                             $azResourceTags = @{}
  136.                         }
  137.                     }
  138.  
  139.                     # Final merge with all tags for resource
  140.                     $mergeTable = Merge-HashTable -OriginTable $mergeTableRG -Append $azResourceTags
  141.  
  142.                     # Test if tags are up to date
  143.                     # Convert hastables to PSCustomObject so that we can use Compare-Object
  144.                     $currentTags = [PSCustomObject]$azResourceTags
  145.                     $newTags = [PSCustomObject]$mergeTable
  146.                     switch (!(Compare-Object $currentTags.PSObject.Properties $newTags.PSObject.Properties)) {
  147.                         # If tags match skip
  148.                         ({$PSItem})
  149.                         {
  150.                             $tagCounterSkip
  151.                             # Commented out to avoid noise
  152.                             # Uncomment for debugging purposes
  153.                             #Write-Output "Skip $($azResource.ResourceName)"
  154.                         }
  155.                         # If mismatch then tag
  156.                         ({!($PSItem)})
  157.                         {
  158.                             try {
  159.                                 # Get-AzureRmResource Paramaters
  160.                                 $GetAzureRmResourceParams = @{
  161.                                     ResourceName        = $azResource.ResourceName
  162.                                     ResourceGroupName   = $azResourceGroup.ResourceGroupName
  163.                                 }
  164.                                 # Set-AzureRmResource Parameters
  165.                                 $SetAzureRmResourceParams = @{
  166.                                     Tag     = $mergeTable
  167.                                     Force   = $true
  168.                                 }
  169.                                 # Run tagging command
  170.                                 Write-Output "Tagging $($azResource.ResourceName)..."
  171.                                 Get-AzureRmResource @GetAzureRmResourceParams | Set-AzureRmResource @SetAzureRmResourceParams | Out-Null
  172.                                 # Verify Tagging was successful
  173.                                 # Grab new Tags
  174.                                 $verifyTagsTest = [PSCustomObject](Get-AzureRmResource @GetAzureRmResourceParams).Tags
  175.                                 # Compare current tags to what *SHOULD* have been applied
  176.                                 switch (!(Compare-Object $verifyTagsTest.PSObject.Properties $newTags.PSObject.Properties)) {
  177.                                     # If match, log successfull
  178.                                     ({$PSItem})
  179.                                     {
  180.                                         $tagCounterFail++
  181.                                         Write-Warning -Message "$($azResource.ResourceName) failed tagging"
  182.                                         Write-Warning -Message "Error message: $($Error[0])"
  183.                                     }
  184.                                     # If they don't match log and log last error for debugging
  185.                                     ({!($PSItem)})
  186.                                     {
  187.                                         $tagCounterSuccess++
  188.                                         Write-Output "$($azResource.ResourceName) was tagged successfully"
  189.                                     }
  190.                                 }
  191.                             }
  192.                             catch {
  193.                                 $tagCounterError++
  194.                                 Write-Warning -Message "Unable to set tag"
  195.                                 Write-Warning -Message "Error message: $($Error[0])"
  196.                             }
  197.                         } # End mismatch
  198.                     } # End Tagging switch
  199.                 } # End not Classic Resource
  200.             } # End Classic Resource test
  201.         } # End Resource loop
  202.     } # End Resource Group loop
  203.     ## Final Script Output
  204.     $outputTable = @{
  205.         "Resources Tagged"          = $tagCounterSuccess
  206.         "Resources Failed Tagging"  = $tagCounterFail
  207.         "Resources Skipped Tagging" = $tagCounterSkip
  208.         "Resource Groups w/o Tags"  = $tagCounterNull
  209.         "Resources Untaggable"      = $tagCounterUntaggable
  210.         "Errors"                    = $tagCounterError
  211.     }
  212.     $Output = [PSCustomObject]$outputTable
  213.     return $Output
  214. }
  215. catch {
  216.     # Capture all errors
  217.     $errorMessage = "Error in Runbook: Unhandled exception :: " +
  218.                     "Line: $($_.InvocationInfo.ScriptLineNumber) " +
  219.                     "Line: $($_.InvocationInfo.Line) " +
  220.                     "Error message: $($_.exception.message)"
  221.     # Output errors for debugging and halt runbook
  222.     Write-Error -Message $errorMessage -ErrorAction Stop
  223. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement