How to check if azure resource exists in PowerShell? - azure

I am trying to check if an azure key vault already exists in a resource group using PowerShell. If the vault with the same name already exists even in the deleted state I only want to receive a user friendly message saying Key Vault already exists or catch the exception if there is any. I don't want the terminal to blow up with errors. If the key vault does not exist I want to create a new keyvault.
I have the following code:
$KeyVaultName = "Key Vault Name"
$ResourceGroupName = "Resource group name"
$KeyVault = Get-AzKeyVault -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -ErrorAction SilentlyContinue
if($null -eq $KeyVault){
New-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $KeyVaultName -Location "Switzerland North"
}
else{
Write-Host "$KeyVaultName already exists"
}
After executing the code I am getting this error message on the terminal:
New-AzKeyVault : A vault with the same name already exists in deleted state. You need to either recover or purge existing key vault.
I also tried using the following code as well:
if (!(Test-AzureName -Service $KeyVaultName))
{
New-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $KeyVaultName -Location "Switzerland North"
}
It gives me the following error after execution:
Test-AzureName : No default subscription has been designated. Use Select-AzureSubscription -Default to set the default subscription.
Though I only have one subscription being used.
Can someone please tell me if I am doing something wrong here ? Can you please provide me with an efficient way to achieve this ?

You can try something like the following:
$KeyVaultName = "keyvaultname"
$ResourceGroupName = "resourcegroupname"
$KeyVaultLocation = "keyvaultlocation"
$KeyVault = Get-AzKeyVault -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -ErrorAction SilentlyContinue
if($null -eq $KeyVault){
$KeyVault = Get-AzKeyVault -VaultName $KeyVaultName -Location $KeyVaultLocation -InRemovedState -ErrorAction SilentlyContinue
if ($null -eq $KeyVault) {
New-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $KeyVaultName -Location $KeyVaultLocation
} else {
Write-Host "$KeyVaultName exists but is in soft-deleted state"
}
}
else{
Write-Host "$KeyVaultName already exists"
}
Essentially what we are doing here is first checking if the Key Vault exists and is in active state. If we do not find any Key Vault, then we are checking if the Key Vault is in soft deleted state. If no results are found, then we are proceeding with creation of new Key Vault.
However, please note that Key Vault name is globally unique so it is quite possible that your New-AzKeyVault Cmdlet fails.

Related

Why are write-host statements are not appearing when calling a script with an azure commandlet in it?

I have a very simplistic 2 scripts and I'm trying to call the powershell script from another powershell run script
run script (run.ps1)
.\NewRG.ps1 -rgName "singleVM12" -location "Canada Central" -tags #{dept="Marketing"}
called script (newRG.ps1)
[CmdletBinding()]
param (
[string]$rgName = "Test1-rg",
[string]$location = "Canada Central",
[Parameter(Mandatory)]
[hashtable]$tags)
$newRG = New-AzResourceGroup -name $rgName -location $location -tags #{dept="marketing"}
write-output "test"
I would expect that I should get test in the console but I get the properties of the Resource group
ResourceGroupName : singleVM12
Location : canadacentral
ProvisioningState : Succeeded
The issue is I have more complex scripts with multiple write-host entries that I want shown but none of it appears when I run the "run.ps1" file, it works fine if I just call the called script by itself. I tried using write-output and same thing happens. I noticed that hello world works, so I'm guessing something about the Azure commandlets are maybe causing this. Any way around this?
I am using Write-Output to print the values in prompt. I have followed the same way you did.
Follow the workaround:
testout.ps1
# I am getting resource information
[CmdletBinding()]
param (
[string]$rgName = "test")
#$newRG = New-AzResourceGroup -name $rgName -location $location -tags #{dept="marketing"}
$getResource = Get-AzResource -ResourceGroupName $rgName
write-output "azure resoure get successfully- " $rgName
$getResource = Get-AzResource -ResourceGroupName $rgName
write-output "test2- " $rgName
$getResource = Get-AzResource -ResourceGroupName $rgName
write-output "test3 - " $rgName
$getResource = Get-AzResource
write-output "test4- " $rgName
# you can use return to send the the required data to promt as well. But you can use end of your script otherwise it will skip after the return statement.
return $getResource.ResourceGroupName
test2.ps1
Calling testout.ps1 in test2.ps1 script.
# Connect Azure Account using specific Subscription Id if you are using more subscription in single account
Connect-AzAccount -SubscriptionId '<Your subscription Id>'
# calling test.ps1 script
.\testout.ps1 -rgName "<Your Resourcegroup Name>"
Result

Powershell script won't list expired key vault certificates

I have a powershell script that is attempting to list all the expired secrets of my Azure Key Vault. Unfortunately I'm struggling to do this.
This is how I retrieve sercrets. But what do I need to add to get the expiration of all secrets? Then delete those that are expired? I'm guessing I'll need to set an access policy.
Select-AzSubscription -Subscription "My subscriptsion"
Set-AzKeyVaultAccessPolicy -VaultName "testKeyVaultPwsh" -UserPrincipalName "mystuff#domain.com" -PermissionsToSecrets get,set,delete
#Retrieve secret
$secret = Get-AzKeyVaultSecret -VaultName "testKeyVaultPwsh" -Name "ExamplePassword" -AsPlainText
You can delete the expired secrets using below commands .(Make sure
you have get,set,delete access policies set and given proper
permissions )
I have tried in my environment and able to delete expired secrets sussessfully.
After checking expiry using
$exp =Get-AzKeyVaultSecret -VaultName $vaultname -Name $secretname | Select-Object Name,Expires
$exp
I created secrets and have secrets expired.
Commands:
$vaultname= “<keyvaultname>”
$secrets= Get-AzKeyVaultSecret -VaultName $vaultname
$secretnames =$secrets.Name
$current_date=Get-Date
Foreach($secretname in $secretnames)
{
$exp =Get-AzKeyVaultSecret -VaultName $vaultname -Name $secretname | Select-Object Expires
$keyvaultsecretvexpirydate =[datetime]($exp.Expires)
$timediff=NEW-TIMESPAN -Start $current_date -End $keyvaultsecretvexpirydate
$days_until_expiration=$timediff.Days
Write-Output “days_until_expiration of secret named $secretname is :$days_until_expiration”
Write-Output “ ”
if ($days_until_expiration -eq 0)
{
Write-Output "Secret named $secretname got expired “
Write-Output “removing expired secret : $secretname”
Write-Output “ ”
Remove-AzKeyVaultSecret -VaultName $vaultname -Name $secretname
}
}
Confirm to delete by typing Y and refresh the secrets page to see the expired secret being removed/deleted.
References:
KeyVaultSecretExpirationAlerts |github
remove-azkeyvaultsecret | microsoftdocs

ARM Template deployment returing a value that I dont expect

I am working on writing some Powershell that I am going to use in Azure DevOPS pipelines. This is to create an AppServiceplan. I have included the code below. I have used this same basic template to deploy a few other things and I have not run into this problem before.
This piece of the code $appSP = Get-AzAppServicePlan -Name $appServicePlanName -ResourceGroupName $rgname does not return a value, which is expected because this is the first time running it, yet its triggering this piece of code Write-verbose "AppService Plan '$appServicePlanName' already exists."
So it seems that even though the Get-AzAppServicePlan appears to be blank, maybe its returning some sort of object that I cant see?
Any ideas?
function Assert-AppServicePlan {
<#
.SYNOPSIS
This function will ensure that specified AppServicePlan exists.
.DESCRIPTION
Function will check if specified Azure AppServicePlan exists, and if not - it will be created.
Will return AppServicePLan object or, in case of error, $null.
.PARAMETER appServicePlanName
App Service Plan to be checked or created.
.PARAMETER rgName
Resource Group.
.PARAMETER SKU
SKU for App Service Plan. Default is P2V2.
.EXAMPLE
Assert-AppServicePlan -appServicePlansName "BARF" -rgName "MyResourceGroup" -SKU "F1" -verbose
#>
param(
[Parameter(Mandatory = $true)][ValidateNotNullorEmpty()][string]$appServicePlanName,
[Parameter(Mandatory = $true)][ValidateNotNullorEmpty()][string]$rgName,
[Parameter(Mandatory = $true)][ValidateNotNullorEmpty()][string]$SKU
);
$appSP = Get-AzAppServicePlan -Name $appServicePlanName -ResourceGroupName $rgname
if ($notPresent)
{
Write-Verbose "App Service Plan '$appServicePlanName' doesn't exist. Creating it."
try
{
$appSP = New-AzResourceGroupDeployment -ResourceGroupName `
$rgname -TemplateFile .\templates\appserviceplan.json `
-TemplateParameterFile .\templates\appserviceplan.parameters.json `
-ErrorAction Stop
}
catch
{
Write-verbose "Error while creating App Service Plan."
Write-Error $_
}
}
else
{
Write-verbose "AppService Plan '$appServicePlanName' already exists."
}
return $appSP
}
The Get-AzAppServicePlan cmdlet returns the App Service Plan object if found in the specified resource group, else nothing. So, it would be sufficient to check on this result in your if condition.
Another case where the result might mislead returning null is when you query under an incorrect PS context or a different Subscription (locally). However, since you intend to run this as part of Azure DevOps pipelines, the Service connection used by the task would ensure it.
Just another suggestion, you can use ErrorVariable
Get-AzAppServicePlan -Name $appServicePlanName -ResourceGroupName $rgname -ErrorAction Silentlycontinue -ErrorVariable notPresent
if ($notPresent)
{
#create something
}
else {
#exits
}

Get-AzKeyVaultSecret can't read secret value in Powershell

I'm not able to read the value of one of my secrets in Key Vault. I'm logged in with my Azure account and I have full permission to the selected Key Vault.
I'm able to retrieve a list of available secrets using the following command:
$keyVaultValue = (Get-AzKeyVaultSecret -VaultName 'name-of-key-vault')
And then see the content when I write:
Write-Output $keyVaultValue
But when I ask for a specific key it just returns null:
$keyVaultValue = (Get-AzKeyVaultSecret -VaultName 'name-of-key-vault' -Name 'my-secret-name').SecretValueText
I've checked the name and subscription ID and everything is correct. I can easily read the value from the portal, but no from powershell on my Windows PC.
Any suggestions?
SecretValueText is deprecated, You can use the following syntax the retrieve the value as plain text:
$keyVaultValue = Get-AzKeyVaultSecret -VaultName 'name-of-key-vault' -Name 'my-secret-name'
$keyVaultValue.SecretValue | ConvertFrom-SecureString -AsPlainText
More information and examples can be found here.
If you want to show all key-vault secrets name and their key values then you can use this in powershell
$secrets=Get-AzKeyVaultSecret -VaultName 'key-vault-name'
$secrets | % {Write-Output "$($_.name) $($(Get-AzKeyVaultSecret -VaultName $_.VaultName -Name $_.Name).SecretValue | ConvertFrom-SecureString -AsPlainText)" }
Try using this function:
function GetSecretValue
{
param(
[String]$keyvaultName,
[String]$secretName
)
Write-Host "Retrieving secret $secretName from $keyvaultName... " -NoNewline
if ((Get-Command Get-AzKeyVaultSecret).ParameterSets.Parameters.Name -contains "AsPlainText")
{
# Newer Get-AzKeyVaultSecret version requires -AsPlainText parameter
$secretValue = Get-AzKeyVaultSecret -VaultName $keyvaultName -Name $secretName -AsPlainText
}
else
{
$secretValue = (Get-AzKeyVaultSecret -VaultName $keyvaultName -Name $secretName).SecretValueText
}
Write-Host "ok"
return $secretValue
}
Usage example:
$keyVaultValue = GetSecretValue "name-of-key-vault" "my-secret-name"

VM has reported a failure when processing extension AzureDiskEncryption

I am running the following script:
$keyVault = Get-AzKeyVault -VaultName $keyVaultName -ResourceGroupName $rgName;
$diskEncryptionKeyVaultUrl = $keyVault.VaultUri;
$keyVaultResourceId = $keyVault.ResourceId;
$keyEncryptionKeyUrl = (Get-AzureKeyVaultKey -VaultName $keyVaultName -Name myKey).Key.kid;
Set-AzVMDiskEncryptionExtension -ResourceGroupName $rgName `
-VMName "myVM" `
-DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl `
-DiskEncryptionKeyVaultId $keyVaultResourceId `
-KeyEncryptionKeyUrl $keyEncryptionKeyUrl `
-KeyEncryptionKeyVaultId $keyVaultResourceId
which is returning the following around 1 minutes of processing:
Set-AzureRmVmDiskEncryptionExtension : Long running operation failed
with status 'Failed'. Additional Info:'VM has reported a failure when
processing extension 'AzureDiskEncryption'. Error message: "Failed to
send DiskEncryptionData, Check KeyVault inputs, ResourceIds and retry
encryption operation".' ErrorCode: VMExtensionProvisioningError
ErrorMessage: VM has reported a failure when processing extension
'AzureDiskEncryption'. Error message: "Failed to send
DiskEncryptionData, Check KeyVault inputs, ResourceIds and retry
encryption operation". ErrorTarget: StartTime: 3/2/19 2:10:59 PM
EndTime: 3/2/19 2:10:59 PM
i have verified the values are all correctly passed to the set command and no nulls are being passed.
in this case OP needed to enable Key Vault for disk encryption, under advanced access policies.
I had this issue but banging my head for days the below steps fixed my issue.
Check the values of the $KeyVault, $DiskEncryptionKeyVaultUrl, and $KeyVaultResourceId
variables and make sure they are not null or empty.
If step 1 is completed, check the Key Vault creation process thoroughly, and
check if it is in the same region as the VM and that it has been enabled
for disk encryption:Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -
EnabledForDiskEncryption
If you are still facing the issue, you can try this:
Go to the disk of a VM that needs to be encrypted.
Click Identity
Turn Status to "ON" for a system or user assigned.
Then execute below commands.
It is available with explanation on https://learn.microsoft.com/en-us/azure/virtual-machines/windows/encrypt-disks
$keyVault = Get-AzKeyVault -VaultName $keyVaultName -ResourceGroupName $rgName;
$diskEncryptionKeyVaultUrl = $keyVault.VaultUri;
$keyVaultResourceId = $keyVault.ResourceId;
$keyEncryptionKeyUrl = (Get-AzKeyVaultKey -VaultName $keyVaultName -Name myKey).Key.kid;
Set-AzVMDiskEncryptionExtension -ResourceGroupName $rgName `
-VMName "myVM"
-DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl `
-DiskEncryptionKeyVaultId $keyVaultResourceId `
-KeyEncryptionKeyUrl $keyEncryptionKeyUrl `
-KeyEncryptionKeyVaultId $keyVaultResourceId$

Resources