This article is contributed. See the original author and article here.

Hello Folks,


 


I’ve been working with some colleagues on a shared demo environment, and one issue came up during a session with customers that highlighted a problem.  If any of us change the local admin password of the servers or redeploys the environment with a password of their own.  We no longer can access it without contacting the group and request the new password.


I started to look a way to regularly update the password from a location that is built specifically for storing passwords and other secrets. Namely, Azure Key Vault.


 


And, I had just read the PowerShell’s Team blog announcing the general availability of their SecretManagement and SecretStore modules.  That seemed like the best candidates to help.  The SecretManagement module helps users manage secrets by providing a common set of cmdlets to interface with secrets across vaults. IT utilizes an extensible model where local and remote vaults (including Azure Key Vaults) can be registered and unregistered for use in accessing and retrieving secrets.


 


The module provides the following cmdlets for accessing secrets and managing SecretVaults:



  • Get-Secret

  • Get-SecretInfo

  • Get-SecretVault

  • Register-SecretVault

  • Remove-Secret

  • Set-Secret

  • Set-SecretInfo

  • Set-SecretVaultDefault

  • Test-SecretVault

  • Unregister-SecretVault


The solution


To address our issue, we took the following steps.
1- Created a key vault and created/stored a secret with a complex password. (because it’s in the demo resource group, we can all retrieve the secret when needed)


 

pshl-1.png


 


 


2- Deployed Azure Automation in our environment and created a Run as account to provide authentication for managing resources in Azure with the Azure cmdlets.



3- Created a new Runbook that would get the secret from Key vault using PowerShell Microsoft.PowerShell.SecretManagement module and using the Azure VMAccess extension would update the local admin password to the one retrieved from Key vault. (The sample code available below). Of course, this is proof of concept at this point and needs to be worked on. However, it does open the door to other usage. This could be re-used and modified to run on a schedule to generate a new complex password and store it in Key Vault, then update all the servers in your environment with the new password on a regular basis.


 


pshl-2.png


 


4- Here is the sample code.


 


 


 

param(

    [string]$ResourceGroupName = "Secret-Demo",
    [string]$vaultname = "SecretDemoVault"

)
Disable-AzContextAutosave -Scope Process

$VERSION = "1.0"
$currentTime = (Get-Date).ToUniversalTime()

Write-Output "Runbook started. Version: $VERSION at $currentTime"
Write-Output "---------------------------------------------------"

# Authenticate with your Automation Account
	$connection = Get-AutomationConnection -Name AzureRunAsConnection
    # Wrap authentication in retry logic for transient network failures
    $logonAttempt = 0
    while(!($connectionResult) -and ($logonAttempt -le 10))
    {
        $LogonAttempt++
        # Logging in to Azure...
        $connectionResult = Connect-AzAccount `
                                -ServicePrincipal `
                                -Tenant $connection.TenantID `
                                -ApplicationId $connection.ApplicationID `
                                -CertificateThumbprint $connection.CertificateThumbprint

        Start-Sleep -Seconds 30
    }

    $AzureContext = Get-AzSubscription -SubscriptionId $connection.SubscriptionID
    $SubID = $AzureContext.id
    Write-Output "Subscription ID: $SubID"
    Write-Output "Resource Group: $ResourceGroupName"
    Write-Output "VaultName: $vaultname"

# Get Secret from KeyVault
    Register-SecretVault -Name AzKeyVault -ModuleName Az.KeyVault -VaultParameters @{ AZKVaultName = $vaultname; SubscriptionId = $SubID }
    $secret = Get-Secret -Vault AzKeyVault -Name sysadmin
    Write-Output "SecretValue :  $secret"
    $Credential = New-Object -TypeName PSCredential -ArgumentList "sysadmin", $secret

# Get a list of all virtual machines in subscription
    $VMList = Get-AzVM -ResourceGroupName $ResourceGroupName
    foreach ($vm in $VMList)
    {
        Write-Output "Reseting password on $vm.name" 
        Set-AzVMAccessExtension -ResourceGroupName $ResourceGroupName -VMName $Vm.Name -Credential $Credential -typeHandlerVersion "2.0" -Name VMAccessAgent
    }

 


 


 


The code above required me to import some PowerShell Modules into our Automation environment.  The modules I imported from the gallery


 


pshl-4.png


 


The added modules were the following:


 



  • Az.Accounts

  • Az.Compute

  • AZ.KeyVault

  • Microsoft.PowerShell.SecretManagement

  • Microsoft.PowerShell.SecretStore


 


pshl-6.png


 


 


 


5- Once created and published I linked the Runbook to a schedule that will execute the script nightly.


 


pshl-3.png


 


 


That’s it!  a simple solution based on a new PowerShell module that provides us with loads of value.  Maybe it will be of value for you too.


 


Cheers!


 


Pierre


 

 

 

 

Brought to you by Dr. Ware, Microsoft Office 365 Silver Partner, Charleston SC.