Store alias_primary_connection_string in keyvault under service bus queue SAS policy - azure

I want to store "alias_primary_connection_string" from each queue SAS policy of a defined service bus namespace in Keyvault secret using PowerShell in azure. Tried using Get-AzServiceBusNamespace & Get-AzServiceBusAuthorizationRule with for loop but not able to achieve it. I am getting name of all queues name but not alias_primary_connection_string. Need help on the code.
Tried below and got all the queue in namespace.
I want to store each queue's alias_primary_connection_string one by one in the keyvault secret with name like ("each queue name" append with string "alias_primary_string" ) and if entry already present in keyvault then override it or delete and recreate the secret.
#Code for getting queue names of namespace:
Get-AzServiceBusNamespace -ResourceGroupName mygroup -NamespaceName mybus |
ForEach-Object {
Get-AzServiceBusQueue -ResourceGroupName $_.ResourceGroup -Namespace $_.Name |
ForEach-Object {
[PsCustomObject\]#{
Queue = $\_.Name
}}}

I tried and got the script at last. This code will truncate entity path from alias connection string and send it to the keyvault.
$ResourceGroup = ******* define yours as per requirement
$rg = $ResourceGroup
$ns = ($ResourceGroup, "bus", "abc" -join '-').ToLower()
$kv = ("ABC", $EnvironmentName, $EnvironmentInstance, "key" -join '-').ToLower()
Get-AzServiceBusQueue -ResourceGroup $rg -NamespaceName $ns |
ForEach-Object {
Foreach ($i in $_.Name) {
Get-AzServiceBusAuthorizationRule -ResourceGroupName $rg -NamespaceName $ns -QueueName $_.Name |
ForEach-Object {
Get-AzServiceBusKey -ResourceGroupName $rg -NamespaceName $ns -QueueName $i -Name $_.name |
ForEach-Object {
$secretname = $_.KeyName + '-alias'
$secretvalue = $_.PrimaryConnectionString -replace ";EntityPath.*",""
Write-Host "adding latest secret value for $secretname"
$vaultsecret = ConvertTo-SecureString $secretvalue -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName $kv -Name $secretname -SecretValue $vaultsecret
Write-Host "$secretname added to keyvault $kv"
}
}
}
}

Related

Script for backing up keyvault

I've been trying to tweak and make a basic simple script just a bit more clean and overall to improve it.
Basically the initial script was iterating and doing a backup for each secret,certificate and key from each keyvault in a subscription.
I am trying to make it better by creating a function and trying to use it as such, unfortunately I'm still missing some thigns and I would like someone to help me sort this out:
function Get-Backup{
[CmdletBinding()]
param (
[Parameter()]
$Item,
[Parameter()]
$VaultName
)
$Items = az keyvault $Item list --vault-name $VaultName | ConvertFrom-Json
foreach ($Item in $Items) {
az keyvault $Item backup --vault-name $VaultName --name $Item.Name --file $Item/$Name.txt
}
}
$Vaults = az keyvault list | ConvertFrom-Json
foreach ($VaultName in $Vaults) {
Get-Backup("secret",$VaultName)
Get-Backup("certificate",$VaultName)
Get-Backup("key",$VaultName)
}
This doesn't work, and I don't understand really what I'm missing or doing wrong. the whole point of this would be to do a script that would automatically pick all the secrets all the keys and all the certificates in a vault, and do this for each vault.
I am trying to compile a function so I could reduce the main code and rely more on functions.
Unfortunatetly I can not post the error as it contains lots of identifiable information of my subscription name resource group etc. Starts with " ERROR: '' is misspelled or not recognized by the system. "
I am looking to do this myself but being stuck for a couple of days, I'd really appreaciate some hints and help.
Could you try solution given here. But please note that here you have
risk of having in-memory variables
Param(
[parameter(mandatory)] [string] $originVault,
[parameter(mandatory)] [string] $originSubscriptionId,
[parameter(mandatory)] [string] $destinationVault,
[parameter(mandatory)] [string] $destinationSubscriptionId,
[string] $disableDestinationSecrets = $true
)
# 1. Set the source subscription id.
Write-Host "Setting origin subscription to: $($originSubscriptionId)..."
az account set -s $originSubscriptionId
# 1.1 Get all secrets
Write-Host "Listing all origin secrets from vault: $($originVault)"
$originSecretKeys = az keyvault secret list --vault-name $originVault -o json --query "[].name" | ConvertFrom-Json
# 1.3 Loop secrets into PSCustomObjects, making it easy to work with later.
$secretObjects = $originSecretKeys | ForEach-Object {
Write-Host " - Getting secret value for '$($_)'"
$secret = az keyvault secret show --name $_ --vault-name $originVault -o json | ConvertFrom-Json
[PSCustomObject]#{
secretName = $_;
secretValue = $secret.value;
}#endcustomobject.
}#endforeach.
Write-Host "Done fetching secrets..."
# 2. Set the destination subscription id.
Write-Host "Setting destination subscription to: $($destinationSubscriptionId)..."
az account set -s $destinationSubscriptionId
# 2.2 Loop secrets objects, and set secrets in destination vault
Write-Host "Writing all destination secrets to vault: $($destinationVault)"
$secretObjects | ForEach-Object {
Write-Host " - Setting secret value for '$($_.secretName)'"
az keyvault secret set --vault-name $destinationVault --name "$($_.secretName)" --value "$($_.secretValue)" --disabled $disableDestinationSecrets -o none
}
# 3. Clean up
Write-Host "Cleaning up and exiting."
Remove-Variable secretObjects
Remove-Variable originSecretKeys
Write-Host "Finished."
or this one which uses powershell instead of azure cli.
$storageAccountTemplateFile = "https://raw.githubusercontent.com/srozemuller/Azure/main/AzureStorageAccount/azuredeploy.json"
$storageAccountTemplateParameters = "https://raw.githubusercontent.com/srozemuller/Azure/main/AzureStorageAccount/azuredeploy.parameters.json"
$backupFolder = "$env:Temp\KeyVaultBackup"
$location = "West Europe"
$backupLocationTag = "BackupLocation"
$backupContainerTag = "BackupContainer"
$global:parameters = #{
resourceGroupName = "RG-PRD-Backups-001"
location = $location
}
function backup-keyVaultItems($keyvaultName) {
#######Parameters
#######Setup backup directory
If ((test-path $backupFolder)) {
Remove-Item $backupFolder -Recurse -Force
}
####### Backup items
New-Item -ItemType Directory -Force -Path "$($backupFolder)\$($keyvaultName)" | Out-Null
Write-Output "Starting backup of KeyVault to a local directory."
###Certificates
$certificates = Get-AzKeyVaultCertificate -VaultName $keyvaultName
foreach ($cert in $certificates) {
Backup-AzKeyVaultCertificate -Name $cert.name -VaultName $keyvaultName -OutputFile "$backupFolder\$keyvaultName\certificate-$($cert.name)" | Out-Null
}
###Secrets
$secrets = Get-AzKeyVaultSecret -VaultName $keyvaultName
foreach ($secret in $secrets) {
#Exclude any secrets automatically generated when creating a cert, as these cannot be backed up
if (! ($certificates.Name -contains $secret.name)) {
Backup-AzKeyVaultSecret -Name $secret.name -VaultName $keyvaultName -OutputFile "$backupFolder\$keyvaultName\secret-$($secret.name)" | Out-Null
}
}
#keys
$keys = Get-AzKeyVaultKey -VaultName $keyvaultName
foreach ($kvkey in $keys) {
#Exclude any keys automatically generated when creating a cert, as these cannot be backed up
if (! ($certificates.Name -contains $kvkey.name)) {
Backup-AzKeyVaultKey -Name $kvkey.name -VaultName $keyvaultName -OutputFile "$backupFolder\$keyvaultName\key-$($kvkey.name)" | Out-Null
}
}
}
$keyvaults = Get-AzKeyVault
if ($keyvaults) {
if ($null -eq (get-AzResourceGroup $global:parameters.resourceGroupName -ErrorAction SilentlyContinue)) {
New-AzResourceGroup #global:parameters
}
if ($null -eq ($keyvaults | ? { $_.Tags.Keys -match $BackupLocationTag })) {
# if no backuplocation tags is available at any of the keyVaults we will create one first
$deployment = New-AzResourceGroupDeployment -ResourceGroupName $global:parameters.resourceGroupName -TemplateUri $storageAccountTemplateFile -TemplateParameterUri $storageAccountTemplateParameters
$backupLocation = $deployment.outputs.Get_Item("storageAccount").value
if ($deployment.ProvisioningState -eq "Succeeded") {
foreach ($keyvault in $keyvaults) {
$containerName = $keyvault.VaultName.Replace("-", $null).ToLower()
if (!(Get-aztag -ResourceId $keyvault.ResourceId | ? { $_.Tags.Keys -match $BackupLocationTag } )) {
Update-AzTag $keyvault.ResourceId -operation Merge -Tag #{BackupLocation = $backupLocation; BackupContainer = $containerName }
}
}
}
}
else {
foreach ($keyvault in $keyvaults) {
$backupLocation = (get-azkeyvault -VaultName $keyvault.vaultname | ? { $_.Tags.Keys -match $BackupLocationTag}).tags.Get_Item($BackupLocationTag)
$storageAccount = get-AzStorageAccount | ? { $_.StorageAccountName -eq $backupLocation }
if ($null -eq (Get-aztag -ResourceId $keyvault.ResourceId | ? { $_.Tags.Keys -match $BackupContainerTag } )) {
$containerName = $keyvault.VaultName.Replace("-", $null).ToLower()
Update-AzTag $keyvault.ResourceId -operation Merge -Tag #{BackupContainer = $containerName }
}
$containerName = (get-azkeyvault -VaultName $keyvault.vaultname | ? { $_.Tags.Keys -match $backupContainerTag }).tags.Get_Item($backupContainerTag)
if ($null -eq (Get-AzStorageContainer -Name $containerName -Context $storageAccount.context)) {
New-AzStorageContainer -Name $containerName -Context $storageAccount.context
}
backup-keyVaultItems -keyvaultName $keyvault.VaultName
foreach ($file in (get-childitem "$($backupFolder)\$($keyvault.VaultName)")) {
Set-AzStorageBlobContent -File $file.FullName -Container $containerName -Blob $file.name -Context $storageAccount.context -Force
}
}
}
}

Setup and deploy Azure function using PowerShell

I try to setup and deploy Azure Function by using PowerShell script based on this topic: Setup Azure Function from PowerShell
My script looks like this:
#=============Defining All Variables=========
$location = 'Central US'
$resourceGroupName = 'MyResourceGroup'
$subscriptionId = 'MysubscriptionId'
$functionAppName = 'MyfunctionAppName'
$appServicePlanName = 'ASP-test-8b50'
$tier = 'Dynamic'
$archivePath = 'd:\TestAzureFunc.zip'
Connect-AzAccount
#========Creating Azure Resource Group========
$resourceGroup = Get-AzResourceGroup | Where-Object { $_.ResourceGroupName -eq $resourceGroupName }
if ($resourceGroup -eq $null)
{
New-AzResourceGroup -Name $resourceGroupName -Location $location -force
}
#selecting default azure subscription by name
Select-AzSubscription -SubscriptionID $subscriptionId
Set-AzContext $subscriptionId
#========Creating App Service Plan============
New-AzAppServicePlan -ResourceGroupName $resourceGroupName -Name $appServicePlanName -Location $location -Tier $tier
$functionAppSettings = #{
ServerFarmId="/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.Web/serverfarms/$appServicePlanName";
alwaysOn=$True;
}
#========Creating Azure Function========
$functionAppResource = Get-AzResource | Where-Object { $_.ResourceName -eq $functionAppName -And $_.ResourceType -eq "Microsoft.Web/Sites" }
if ($functionAppResource -eq $null)
{
New-AzResource -ResourceType 'Microsoft.Web/Sites' -ResourceName $functionAppName -kind 'functionapp' -Location $location -ResourceGroupName $resourceGroupName -Properties $functionAppSettings -force
}
#========Defining Azure Function Settings========
$AppSettings =#{}
$AppSettings =#{'FUNCTIONS_EXTENSION_VERSION' = '~2';
'FUNCTIONS_WORKER_RUNTIME' = 'dotnet';}
Set-AzWebApp -Name $functionAppName -ResourceGroupName $resourceGroupName -AppSettings $AppSettings
#========Deploy Azure Function from zip========
Publish-AzWebapp -ResourceGroupName $resourceGroupName -Name $functionAppName -ArchivePath $archivePath
The script works without errors. Resource group and Function App created as needed. But the list of functions of the Function App is empty.
Function details here:
My intuition tells me that I've forgotten something. But I don't know what.
Could you advise me on how to deploy my Azure function properly?
One of the workaround you can follow ,
Looking at your script we need to ensure that we are providing function app configuration as below cmdlts the link you followed:-
$AzFunctionAppSettings = #{
APPINSIGHTS_INSTRUMENTATIONKEY = $AppInsightsKey;
AzureWebJobsDashboard = $AzFunctionAppStorageAccountConnectionString;
AzureWebJobsStorage = $AzFunctionAppStorageAccountConnectionString;
FUNCTIONS_EXTENSION_VERSION = "~4";
FUNCTIONS_WORKER_RUNTIME = "dotnet";
}
And also make sure that the storage account connection string you provided in the function is same as here providing.
And then you can navigate to Kudu API to check the wwwroot folder is exist or not.
For more information please refer the below links:-
SO THREAD|Powershell command Publish-AzWebApp not publishing apllication
BLOG|How to Deploy Azure Function Apps With Powershell.

Lock azure resource with PowerShell

I've been trying to run a script to create a lock on azure resource to prevent resources being deleted inadvertently.
I get an error message and I can't figure out why it's showing me this error message.
Script:
#Sign in to Azure account
Login-AzAccount
#Select the subscription you want to work on
Select-AzSubscription -Subscription "test.subscription"
#Get All Resources in a resource group
$Resources = Get-AzResource -ResourceGroupName dummy_rg | Format-Table
# Create lock "delete" on each Resource if it doesn't exist
foreach($Resource in $Resources) {
$ResourceName = $Resource.Name
$lck = Get-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType
if ($null -eq $lck)
{
Write-Host "$ResourceName has no lock"
New-AzResourceLock -resourceGroupName $rg -ResourceName $ResourceName -ResourceType $Resource.ResourceType -LockName "$ResourceName-lck" -LockLevel CanNotDelete -Force
Write-Host "$ResourceName has been locked"
}
else
{
Write-host "$ResourceName already locked"
}
}
Error message:
Gaurav request result:
#Start logging
Start-Transcript -Path "C:\Windows\Logs\Lock - $(((get-date).ToUniversalTime()).ToString("yyyy-MM-dd_hh-mm-ss")).log" -Force
#Connect to Azure account
Login-AzAccount
#Select Azure subscription
Set-AzContext -Subscription "subscription_id_numbers"
#Deny rule on Azure Data Factory and Azure Machine Learning
$Resources = Get-AzResource | Where-Object {$_.Name -NotLike '*adf*' -and $_.Name -NotLike '*aml*'}
# Create lock "delete" on each Resource if it doesn't exist
foreach($Resource in $Resources) {
$ResourceName = $Resource.Name
$lck = Get-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType
if ($lck -eq $null)
{
Write-Host "$ResourceName has no lock"
Set-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType -LockName "$ResourceName-lck" -LockLevel CanNotDelete -Force
Write-Host "$ResourceName has been locked"
}
else
{
Write-host "$ResourceName already locked"
}
}
#Stop Logging
Stop-Transcript
This will loop on every ressources except azure data factory in the tenant and create a "delete" type lock to make sure resources aren't deleted inadvertently.
Read comments in each section to understand the code.

How to get the list of azure servers having Auto-Shutdown disabled using PowerShell?

I want to get the list of azure servers having auto-shutdown disabled on them, I have the below script but the issue with the script is that it gets the list of RG's under the Subscription GUID but repeats the output after every loop.
Import-AzureRmContext -Path "$PSScriptRoot\AzureProfile.json"
Select-AzureRmSubscription -SubscriptionId {subscriptionId}
[array]$ResourceGroupArray = Get-AzureRMVm | Select-Object -Property ResourceGroupName, Name, VmId
foreach ($resourceGroup in $ResourceGroupArray){
$targetResourceId = (Get-AzureRmVM -ResourceGroupName $resourcegroup.ResourceGroupName -Name $resourceGroup.Name).Id
$shutdownInformation = (Get-AzureRmResource -ResourceGroupName $resourcegroup.ResourceGroupName -ResourceType Microsoft.DevTestLab/schedules -Expandproperties).Properties
Write-Host "ID: " $targetResourceId
$shutdownInformation
The output for each VM is displayed in the following format,
What I want is simple, I want the VM name and its status of Auto-shutdown to be displayed on the screen so that its easy for me to find out which all VM have auto-shutdown currently disabled on them.
Any help related to this would be helpful.
You just need to get the microsoft.devtestlab/schedules resource ID using:
/subscriptions/{subscriptionId}/resourceGroups/{rgName}/providers/microsoft.devtestlab/schedules/shutdown-computevm-{vmName}
Then iterate over all your VMs using Get-AzVM, Get the microsoft.devtestlab/schedules resource using Get-AzResource, then output VM name and status into a table using Format-Table.
$subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Set-AzContext -SubscriptionId $subscriptionId
& {
foreach ($vm in Get-AzVM) {
try {
$shutdownResource = Get-AzResource `
-ResourceId "/subscriptions/$subscriptionId/resourceGroups/$($vm.ResourceGroupName)/providers/microsoft.devtestlab/schedules/shutdown-computevm-$($vm.Name)" `
-ErrorAction Stop
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $shutdownResource.Properties.status
}
}
catch {
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $_.Exception.Message
}
}
}
} | Format-Table -AutoSize
To set the context to the correct subscription, we can use Set-AzContext.
The above however is using the latest Az modules. You can do the same using the equivalent AzureRm modules.
$subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Set-AzureRmContext -SubscriptionId $subscriptionId
& {
foreach ($vm in Get-AzureRmVM) {
try {
$shutdownResource = Get-AzureRmResource `
-ResourceId "/subscriptions/$subscriptionId/resourceGroups/$($vm.ResourceGroupName)/providers/microsoft.devtestlab/schedules/shutdown-computevm-$($vm.Name)" `
-ErrorAction Stop
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $shutdownResource.Properties.status
}
}
catch {
[PSCustomObject]#{
VMName = $vm.Name
ShutdownStatus = $_.Exception.Message
}
}
}
} | Format-Table -AutoSize
Although I do recommend moving to the Az module since support for AzureRm is ending December 2020. You can read the documentation for more information about this.
The above code should give you an output similar to the following
VMName ShutdownStatus
------ --------------
vm1 Enabled
vm2 Disabled
Update
The Call operator & is used here to run the for loop as a script block. You can read more about this in about_Script_Blocks.
Try something like this to get the auto-shutdown status of all VMs. Instead of trying to get the schedules inside the loop, get all the ones in the subscription and match them based on the VM's full resource Id.
[array]$VMArray = Get-AzureRMVm | Select-Object -Property ResourceGroupName, Name, VmId, Id
$ShutdownInformation = (Get-AzureRmResource -ResourceType Microsoft.DevTestLab/schedules -Expandproperties).Properties
foreach($vm in $VMArray) {
$ShutdownStatus = "Not Configured"
$Schedule = $ShutdownInformation | Where-Object { $_.targetResourceId -eq $vm.Id } | Select -First 1
if($Schedule -ne $null) {
$ShutdownStatus = $Schedule.status
}
Write-Host $vm.VmId $ShutdownStatus
}

Azure Automation Runbook missing mandatory parameters

I'm trying to set a Tag on all virtual machines in my subscription but I keep getting errors when running the Runbook.
The error is the following:
Get-AzureRmVM : Cannot process command because of one or more missing mandatory parameters: ResourceGroupName. At line:30
Here is my Runbook:
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Add-AzureRmAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzureRmVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzureRmVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzureRmResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzureRmResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"
I tried importing the right modules but this doesn't seem to affect the outcome.
Running the same commands in Cloud Shell does work correctly.
I can reproduce your issue, the error was caused by this part Get-AzureRmVM -Name $azurevm, when running this command, the -ResourceGroupName is needed.
You need to use the Az command Get-AzVM -Name $azurevm, it will work.
Running the same commands in Cloud Shell does work correctly.
In Cloud shell, azure essentially uses the new Az module to run your command, you can understand it runs the Enable-AzureRmAlias before the command, you could check that via debug mode.
Get-AzureRmVM -Name joyWindowsVM -debug
To solve your issue completely, I recommend you to use the new Az module, because the AzureRM module was deprecated and will not be updated.
Please follow the steps below.
1.Navigate to your automation account in the portal -> Modules, check if you have imported the modules Az.Accounts, Az.Compute, Az.Resources, if not, go to Browse Gallery -> search and import them.
2.After import successfully, change your script to the one like below, then it should work fine.
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Connect-AzAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"

Resources