AzurePasswordManager.psm1
Function New-Password { [OutputType([System.Security.SecureString])] [CmdletBinding()] PARAM ( [Parameter(Mandatory = $true)][int]$Length, [Parameter(Mandatory = $true)][int]$NumberOfSpecialCharacters ) Add-Type -AssemblyName System.Web $PwString = [Web.Security.Membership]::GeneratePassword($Length,$NumberOfSpecialCharacters) $secString = New-Object System.Security.SecureString For ($i = 0; $i -lt $PwString.length; $i++) { $char = $PwString.Substring($i, 1) $secString.AppendChar($char) } $secString } Function Get-ExistingCred { [OutputType([System.Collections.ArrayList])] [CmdletBinding()] PARAM ( [Parameter(Mandatory = $false)][string]$SearchString = $null ) #Get existing secrets from key vault If ($PSBoundParameters.ContainsKey('SearchString')) { $ExistingSecrets = Get-AzKeyVaultSecret -VaultName $Global:KeyVaultName| Where-Object -FilterScript { $_.Tags.ContainsKey('CredName') } | Where-Object -FilterScript { $_.Tags['CredName'] -imatch $SearchString } } else { $ExistingSecrets = Get-AzKeyVaultSecret -VaultName $Global:KeyVaultName } #Get credential names $ExistingCredNames = $ExistingSecrets | ForEach-Object -Process { $_.tags['CredName'] } | Get-Unique #Get credential user names $arrExistingCreds = New-Object -TypeName System.Collections.ArrayList FOreach ($item in $ExistingCredNames) { $UserNameSecret = $ExistingSecrets | Where-Object -FilterScript { $_.Tags['CredName'] -eq $item -and $_.Tags['Type'] -eq 'UserName' } $PasswordSecret = $ExistingSecrets | Where-Object -FilterScript { $_.Tags['CredName'] -eq $item -and $_.Tags['Type'] -eq 'Password' } $UserName = Get-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $UserNameSecret.Name -AsPlainText $objExistingCred = New-Object -TypeName psobject -Property @{ CredName = $item UserName = $UserName UserNameSecretName = $UserNameSecret.Name PasswordSecretName = $PasswordSecret.Name } [void]$arrExistingCreds.Add($objExistingCred) } ,$arrExistingCreds } Function New-KeyVaultCred { $NewCredName = $null $NewCredUserName = $null Do { $NewCredName = Read-Host -Prompt 'Give your new credential a name (only contain alphanumeric characters and dash)' } while ($NewCredName.Length -eq 0 -or $NewCredName -notmatch '^[0-9a-zA-Z-]+$') Do { $NewCredUserName = Read-Host -Prompt 'Enter user name' } while ($NewCredUserName.Length -eq 0) $NewCredPassword = Read-Host -Prompt "Enter new password or hit enter to generate a random password with $Global:RandomPasswordLength character in length with $Global:RandomPasswordSpecialCharactersCount special characters" -AsSecureString $UserNameSecretName = "$NewCredName`-UserName" $PasswordSecretName = "$NewCredName`-Password" #preparing for the tags $UTags = @{ CredName = "$NewCredName" Type = 'UserName' } $PTags = @{ CredName = "$NewCredName" Type = 'Password' } #Create secrets Write-Output -InputObject 'Creating Credential in key vault. please wait...' #user name $NewCredUserNameSecString = New-Object System.Security.SecureString For ($i = 0; $i -lt $NewCredUserName.length; $i++) { $char = $NewCredUserName.Substring($i, 1) $NewCredUserNameSecString.AppendChar($char) } $NewUserSecret = Set-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $UserNameSecretName -SecretValue $NewCredUserNameSecString -Tag $UTags -ErrorVariable errCreateNewUserName #password secret $bNewCopyPassworToClipboard = $false If ($NewCredPassword.length -eq 0) { Write-Output -InputObject 'Password not specified. Generating a new password...' $NewCredPassword = New-Password -Length $Global:RandomPasswordLength -NumberOfSpecialCharacters $Global:RandomPasswordSpecialCharactersCount $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewCredPassword) $NewCredPasswordClearText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) $bNewCopyPassworToClipboard = $true } $NewPasswordSecret = Set-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $PasswordSecretName -SecretValue $NewCredPassword -Tag $PTags -ErrorVariable errCreateNewPassword If ($errCreateNewUserName.Count -eq 0 -and $errCreateNewPassword.Count -eq 0) { Write-Host -Object 'Credential successfully created.' -ForegroundColor Green if ($bNewCopyPassworToClipboard -eq $true) { $NewCredPasswordClearText | clip.exe Write-Host -Object 'Password copied to clipboard.' -ForegroundColor Green Write-output "" } } Write-Output -InputObject '' } Function Get-KeyVaultCred # LIST / SEARCH CREDENTIALS { [CmdletBinding()] PARAM ( [Parameter(Mandatory = $false)][switch]$Search ) If ($Search) { Write-Host -Object 'Search credential' -ForegroundColor Yellow Do { $SearchString = Read-Host -Prompt 'Enter search string (only contain alphanumeric characters and dash)' } while ($SearchString.Length -eq 0 -or $SearchString -notmatch '^[0-9a-zA-Z-]+$') Write-Output -InputObject '' $ExistingCreds = Get-ExistingCred -SearchString $SearchString } else { $ExistingCreds = Get-ExistingCred } If ($ExistingCreds.count -gt 0) { Clear-Host Write-Host -Object $TopMenuTitleLine1 -ForegroundColor Cyan Write-Host -Object $TopMenuTitleLine2 -ForegroundColor Cyan Write-Host -Object $TopMenuTitleLine3 -ForegroundColor Cyan Write-Host -Object "Selected Key Vault: '$Global:KeyVaultName'" -ForegroundColor Cyan Write-Host -Object "" If ($Search) { Write-Host -Object "MAIN MENU > SEARCH CREDENTIALS" -ForegroundColor Cyan } else { Write-Host -Object "MAIN MENU > LIST CREDENTIALS" -ForegroundColor Cyan } Write-Output -InputObject "Number of existing credential(s) found in Azure Key Vault: $($ExistingCreds.count)" Write-Host -Object 'Select credential:' -ForegroundColor DarkGray $i = 0 Write-Host -Object " $i. Go Back" -ForegroundColor DarkGray Foreach ($item in $ExistingCreds) { $i++ Write-Host -Object " $i. $($item.CredName) `($($item.UserName)`)" -ForegroundColor Yellow } Do { [int]$ans = Read-Host -Prompt "Enter selection (0 - $i)" if ($ans -gt 0 -and $ans -le $i) { Write-Output -InputObject '' #retrieve the cred $SelectedCred = $ExistingCreds[$ans-1] Do { Write-Host -Object "Selected credential name: $($SelectedCred.CredName)" -ForegroundColor DarkGray Write-Host -Object ' 0. Go Back' -ForegroundColor DarkGray Write-Host -Object ' 1. Copy User Name to clipboard' -ForegroundColor Yellow Write-Host -Object ' 2. Copy Password to clipboard' -ForegroundColor Yellow Write-Host -Object ' 3. Update Credential' -ForegroundColor Yellow Write-Host -Object ' 4. Delete Credential' -ForegroundColor Yellow Do { [int]$GetCredOption = Read-Host -Prompt 'Enter selection (0 - 4)' } Until ($GetCredOption -ge 0 -and $GetCredOption -le 4) Write-Output -InputObject '' If ($GetCredOption -eq 1) #Copy username to clipboard { $ExistingCredUserName = Get-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $SelectedCred.UserNameSecretName -AsPlainText $ExistingCredUserName | clip.exe Write-Host -Object 'User Name copied to clipboard.' -ForegroundColor Green Write-output "" Write-Output -InputObject '' } elseif ($GetCredOption -eq 2) #Copy password to clipboard { $ExistingCredPassword = Get-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $SelectedCred.PasswordSecretName -AsPlainText $ExistingCredPassword | clip.exe Write-Host -Object 'Password copied to clipboard.' -ForegroundColor Green Write-output "" } elseif ($GetCredOption -eq 3) #Update { $UpdatedUserName = Read-Host -Prompt 'Enter new user name or hit enter to keep the existing user name' $UpdatedPassword = Read-Host -Prompt "Enter new password or hit enter to generate a random password with $Global:RandomPasswordLength character in length with $Global:RandomPasswordSpecialCharactersCount special characters" -AsSecureString $bEditCopyPassworToClipboard = $false If ($UpdatedPassword.length -eq 0) { Write-Output -InputObject 'Password not specified. Generating a new password...' $UpdatedPassword = New-Password -Length $Global:RandomPasswordLength -NumberOfSpecialCharacters $Global:RandomPasswordSpecialCharactersCount $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($UpdatedPassword) $UpdatedPasswordClearText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) $bEditCopyPassworToClipboard = $true } Write-Output -InputObject 'Updating Credential in key vault. please wait...' If ($UpdatedUserName.Length -gt 0) { #Upate the user name secret $UpdatedUserNameSecString = New-Object System.Security.SecureString For ($i = 0; $i -lt $UpdatedUserName.length; $i++) { $char = $UpdatedUserName.Substring($i, 1) $UpdatedUserNameSecString.AppendChar($char) } $ExistingUserNameSecret = Get-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $SelectedCred.UserNameSecretName $UpdateUserNameSecret = Set-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $ExistingUserNameSecret.Name -SecretValue $UpdatedUserNameSecString -Tag $($ExistingUserNameSecret.Attributes.Tags) -ErrorVariable errUpdateUserName } #Update the password secret $ExistingPasswordSecret = Get-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $SelectedCred.PasswordSecretName $UpdatePasswordSecret = Set-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $ExistingPasswordSecret.Name -SecretValue $UpdatedPassword -Tag $($ExistingPasswordSecret.Attributes.Tags) -ErrorVariable errUpdatePassword If ($errUpdateUserName.Count -eq 0 -and $errUpdatePassword.Count -eq 0) { Write-Host -Object 'Credential successfully updated.' -ForegroundColor Green if ($bEditCopyPassworToClipboard -eq $true) { $UpdatedPasswordClearText | clip.exe Write-Host -Object 'Password copied to clipboard.' -ForegroundColor Green Write-output "" } } Write-Output -InputObject '' } elseif ($GetCredOption -eq 4) #delete { #Confirm $DeleteConfirmationTitle = 'Confirming Credential Deletion' $DeleteConfirmationMessage = "Are you sure you want to delete credential '$($SelectedCred.CredName)'?" $yes = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes', 'Delete.' $no = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&No', 'Keep.' $DeleteConfirmOptions = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) $DeleteConfirmed = $host.ui.PromptForChoice($DeleteConfirmationTitle, $DeleteConfirmationMessage, $DeleteConfirmOptions, 0) If ($DeleteConfirmed -eq 0) { #Yes selected #Remove the user name secret $DeleteUserNameSecret = Remove-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $SelectedCred.UserNameSecretName -Force -Confirm:$false -ErrorVariable errDeleteUserName #Remove the password secret $DeletePasswordSecret = Remove-AzKeyVaultSecret -VaultName $Global:KeyVaultName -Name $SelectedCred.PasswordSecretName -Force -Confirm:$false -ErrorVariable errDeletePassword If ($errDeleteUserName.Count -eq 0 -and $errDeletePassword.Count -eq 0) { Write-Host -Object 'Credential successfully deleted.' -ForegroundColor Green $ExistingCreds.Remove($SelectedCred) #Go back to the parent menu $GetCredOption = 0 } Write-Output -InputObject '' } } } Until ($GetCredOption -eq 0) } } while ($ans -lt 0 -or $ans -gt $i) Write-Output -InputObject '' } else { Write-Host -Object 'No credentials are found in the Azure Key Vault.' -ForegroundColor Red } Write-Output -InputObject '' } Function Save-KeyVaultRepoProfile { #confirm Write-Output -InputObject 'By Saving the selected Azure subscription and Key Vault in registry, you will not need to select them again.' $SaveProfileConfirmationTitle = 'Save Profile' $SaveProfileConfirmationMessage = 'Are you sure you want to save selected Azure subscription Id and key vault name in your profile?' $yes = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes', 'Save.' $no = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&No', "Don't Save." $SaveProfileConfirmOptions = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) $SaveProfileConfirmed = $host.ui.PromptForChoice($SaveProfileConfirmationTitle, $SaveProfileConfirmationMessage, $SaveProfileConfirmOptions, 0) If ($SaveProfileConfirmed -eq 0) { #Yes selected $context = Get-AzContext #Create a new regkey $NewRegKey = New-Item -Path $Global:SettingRegPath -Name $context.account.id -Force $ProfilePath = Join-Path -Path $Global:SettingRegPath -ChildPath $context.account.id #Save Azure Subscription Id $AzureSubIdRegValue = New-ItemProperty -Path $ProfilePath -Name AzureSubscriptionId -Value $context.Subscription.SubscriptionId -PropertyType 'String' -Force $AzureKeyVaultNameRegValue = New-ItemProperty -Path $ProfilePath -Name AzureKeyVaultName -Value $Global:KeyVaultName -PropertyType 'String' -Force Write-Host -Object 'Profile saved.' -ForegroundColor Green Write-Output -InputObject '' } } Function Get-KeyVaultRepoProfile { $context = Get-AzContext $RegKeyPath = Join-Path -Path $Global:SettingRegPath -ChildPath $context.Account.Id If (Test-Path $RegKeyPath) { Try { $regvalues = Get-ItemProperty -Path $RegKeyPath -ErrorAction SilentlyContinue $AzureSubId = $regvalues.AzureSubscriptionId $KeyVaultName = $regvalues.AzureKeyVaultName } catch { $AzureSubId = $null $KeyVaultName = $null } } If ($AzureSubId.Length -gt 0 -and $KeyVaultName -gt 0) { $objProperty = @{ 'AzureSubId' = $AzureSubId 'KeyVaultName' = $KeyVaultName } $objProfile = New-Object -TypeName psobject -Property $objProperty $objProfile } else { $null } } Function Remove-KeyVaultRepoProfile { $context = Get-AzContext $RegKeyPath = Join-Path -Path $Global:SettingRegPath -ChildPath $context.Account.Id If (Test-Path $RegKeyPath) { #delete the registry #confirm Write-Output -InputObject 'By Deleting the Key Vault Password Manager Profile from registry, you will need to manually select Azure Subscription and key vault when you use it next time.' $DeleteProfileConfirmationTitle = 'Delete Profile' $DeleteProfileConfirmationMessage = 'Are you sure you want to delete your profile?' $yes = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes', 'Delete.' $no = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&No', "Don't Delete." $DeleteProfileConfirmOptions = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) $DeleteProfileConfirmed = $host.ui.PromptForChoice($DeleteProfileConfirmationTitle, $DeleteProfileConfirmationMessage, $DeleteProfileConfirmOptions, 0) If ($DeleteProfileConfirmed -eq 0) { #Yes selected $DeleteKey = Remove-Item -Path $RegKeyPath -Recurse -Force -ErrorVariable errDeleteProfile If ($errDeleteProfile.Count -eq 0) { Write-Host -Object 'Profile Deleted.' -ForegroundColor Green Write-Output -InputObject '' } else { Write-Error -Message 'Failed to delete the profile.' } } } else { Write-Host -Object "No profile exists for the current user Id '$($context.Account.Id)'." -ForegroundColor Red } } Function Add-KeyVaultFullAccessPolicy { Do { $AADSearchString = Read-Host -Prompt 'Enter a search string for the Azure AD user to search Azure Active Directory (i.e. name)' $AADUsers = Get-AzADUser -StartsWith $AADSearchString | Where UserPrincipalName -like '*@skyline.be' If ($AADUsers.count -eq 0) { Write-Host -Object 'No Azure AD users found that matches the search string. Please enter another search string' -ForegroundColor Red } } until ($AADUsers.count -gt 0) for ($i = 1;$i -le $AADUsers.count; $i++) { Write-Host -Object "$i. $($AADUsers[$i-1].DisplayName) `| UPN: $($AADUsers[$i-1].UserPrincipalName)" -ForegroundColor Yellow } Write-Host -Object "$i. Cancel" -ForegroundColor DarkGray Write-Host -Object 'Select the User Account' -ForegroundColor Yellow [int]$ans = Read-Host -Prompt 'Enter selection' $VaultAdmin = $AADUsers[$ans-1] $VaultAdminObjectId = $VaultAdmin.Id.ToString() Write-Output -InputObject "Configuring Key Vault Access Policy for '$($VaultAdmin.UserPrincipalName)'." Set-AzKeyVaultAccessPolicy -VaultName $Global:KeyVaultName -ObjectId $VaultAdminObjectId -PermissionsToKeys all -PermissionsToSecrets all -ErrorVariable errAddAccess -WarningAction SilentlyContinue If ($errAddAccess.Count -eq 0) { Write-Host -Object 'Key Vault access granted.' -ForegroundColor Green Write-Output -InputObject '' } else { Write-Error -Message 'Failed to grant access to the Key Vault.' Write-Output -InputObject '' } } Function Remove-KeyVaultFullAccessPolicy { #Get keyvault $KeyVault = Get-AzKeyVault -WarningAction SilentlyContinue -VaultName $Global:KeyVaultName #Get Access policies $AccessPolicies = $KeyVault.AccessPolicies Write-Host -Object 'Select Account to Remove:' -ForegroundColor DarkGray $i = 0 Write-Host -Object " $i. Go Back" -ForegroundColor DarkGray Foreach ($item in $AccessPolicies) { $i++ Write-Host -Object " $i. $($item.DisplayName) `(Object Id: $($item.ObjectId)`)" -ForegroundColor Yellow } Do { [int]$ans = Read-Host -Prompt "Enter selection (0 - $i)" if ($ans -gt 0 -and $ans -le $i) { $AccessPolicyToRemove = $AccessPolicies[$i-1] #Confirm Write-Output -InputObject 'By removing the access to Key Vault, the selected user will no longer have access to the credentials saved in this key vault.' $DeleteAccessConfirmationTitle = 'Remove Access' $DeleteAccessConfirmationMessage = "Are you sure you want to remove Key Vault access for '$($item.DisplayName)'?" $yes = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes', 'Remove.' $no = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&No', "Don't Remove." $DeleteAccessConfirmOptions = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) $DeleteAccessConfirmed = $host.ui.PromptForChoice($DeleteAccessConfirmationTitle, $DeleteAccessConfirmationMessage, $DeleteAccessConfirmOptions, 0) If ($DeleteAccessConfirmed -eq 0) { #Yes selected Write-Output "Removing Key Vault access for '$($AccessPolicyToRemove.DisplayName)'" $RemoveJob = Remove-AzKeyVaultAccessPolicy -VaultName $Global:KeyVaultName -ObjectId $AccessPolicyToRemove.ObjectId -ErrorVariable errRemoveAccess -WarningAction SilentlyContinue If ($errRemoveAccess.Count -eq 0) { Write-Host -Object 'Key Vault access removed.' -ForegroundColor Green Write-Output -InputObject '' } else { Write-Error -Message 'Failed to remove access to the Key Vault.' Write-Output -InputObject '' } } else { Write-Output "Key Vault access removal cancelled for '$($AccessPolicyToRemove.DisplayName)'." Write-Output -InputObject '' } } } while ($ans -lt 0 -or $ans -gt $i) } # .EXTERNALHELP AzurePasswordManager.psm1-Help.xml Function Start-AzurePasswordManager # MAIN MENU { Clear-Host #region variables $IdentifyingTagName = 'Purpose' $IdentifyingTagValue = 'AzurePasswordManager' $Global:RandomPasswordLength = 20 $Global:RandomPasswordSpecialCharactersCount = 3 $TopMenuTitleLine1 = '==========================' $TopMenuTitleLine2 = '= Azure Password Manager =' $TopMenuTitleLine3 = '==========================' $Global:SettingRegPath = 'HKCU:\Software\SkylineCommunications\AzurePasswordManager\Profiles' #endregion #region retrieve Azure resources #Logging in to Azure Write-Output -InputObject 'Starting Azure Password Manager.' Write-Output -InputObject 'Checking for existing Azure login session.' Do { Try { $context = Get-AzContext $CurrentAccount = $context.Account.Id If ($CurrentAccount -ne $null) { $AzureContextTitle = 'Existing Azure Credentials' $ExistingAccountMessage = "You are currently logged in to Azure using account $CurrentAccount. Do you want to keep using this account?" $yes = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes', 'Keep using this Id.' $no = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&No', 'Login to Azure using another Id.' $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) $UserSelected = $host.ui.PromptForChoice($AzureContextTitle, $ExistingAccountMessage, $options, 0) If ($UserSelected -eq 1) { Write-Output -InputObject 'Login to Auzre' $null = Connect-AzAccount $context = Get-AzContext $CurrentAccount = $context.Account.Id } } else { Write-Host -Object 'You are currently not logged in to Azure. Please login.' -ForegroundColor Red $null = Connect-AzAccount $context = Get-AzContext $CurrentAccount = $context.Account.Id } } Catch { Write-Host -Object 'You are currently not logged in to Azure. Please login.' -ForegroundColor Red $null = Connect-AzAccount $context = Get-AzContext $CurrentAccount = $context.Account.Id } } Until ($CurrentAccount -gt 0) $CurrentSubName = $context.Subscription.SubscriptionName $CurrentSubId = $context.Subscription.SubscriptionId #Check for existing profile Write-Output -InputObject 'Looking for existing profile' $ExistingProfile = Get-KeyVaultRepoProfile If ($ExistingProfile) { Write-Output -InputObject "Existing Profile is found for user '$($context.Account.Id)'. Loading profile..." if ($CurrentSubId -ine $ExistingProfile.AzureSubId) { Write-Output "Setting Azure Subscription '$($ExistingProfile.AzureSubId)' to the context." $null = Set-AzContext -Subscription $ExistingProfile.AzureSubId } Write-Output "Connecting to key vault '$($ExistingProfile.KeyVaultName)'" $KeyVault = Get-AzKeyVault -WarningAction SilentlyContinue -VaultName $ExistingProfile.KeyVaultName $Global:KeyVaultName = $KeyVault.VaultName } else { Write-Host -Object "No Profile is found for user '$($context.Account.Id)'" #Select Azure subscription If ($CurrentSubName -ne $null) { $SelectSubTitle = 'Select Azure Subscription' $SelectSubMessage = "Currently the Azure subscription '$CurrentSubName (Id: $CurrentSubId)' is selected. Do you want to use this subscription?" $yes = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes', 'Use the current subscription.' $no = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList '&No', 'Select another subscription.' $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) $UserSelected = $host.ui.PromptForChoice($SelectSubTitle, $SelectSubMessage, $options, 0) } If($UserSelected -eq 1) { Write-Output -InputObject 'Getting Azure subscriptions...' $subscriptions = Get-AzSubscription -WarningAction SilentlyContinue if ($subscriptions.count -gt 0) { Write-Host -Object 'Select Azure Subscription of which the Azure Key Vault is located' -ForegroundColor DarkGray $menu = @{} for ($i = 1;$i -le $subscriptions.count; $i++) { Write-Host -Object "$i. $($subscriptions[$i-1].SubscriptionName)" -ForegroundColor Yellow $menu.Add($i,($subscriptions[$i-1].SubscriptionId)) } Do { [int]$ans = Read-Host -Prompt "Enter selection (1 - $($i -1))" } while ($ans -le 0 -or $ans -gt $($i -1)) Write-Output -InputObject '' $subscriptionID = $menu.Item($ans) $null = Set-AzContext -Subscription $subscriptionID } else { Write-Error -Message 'No Azure Subscription found. Unable to continue!' Exit -1 } } $context = Get-AzContext $subscriptionID = $context.Subscription.SubscriptionId #Check for existing key vault configured for AaaS solutions $ExistingKeyVaults = Get-AzKeyVault -WarningAction SilentlyContinue | Where-Object -FilterScript { $_.Tags.ContainsKey($IdentifyingTagName) } | Where-Object -FilterScript { $_.Tags["$IdentifyingTagName"] -eq $IdentifyingTagValue } #Write-Host -Object 'DEBUG' -ForegroundColor Blue Write-Output -InputObject '' if ($ExistingKeyVaults.count -eq 0) { Write-Host -Object 'No existing key vaults found. select 0 to create a new key vault.' -ForegroundColor Red } else { Write-Host -Object 'Select a Key Vault' -ForegroundColor DarkGray } Write-Host -Object '0. [Create New Key Vault]' -ForegroundColor DarkGray $i = 0 Foreach ($KV in $ExistingKeyVaults) { $i++ Write-Host -Object "$i. $($KV.VaultName)" -ForegroundColor Yellow } Do { [int]$KVAnswer = Read-Host -Prompt "Enter selection (0 - $i)" } while ($KVAnswer -lt 0 -or $KVAnswer -gt $i) Write-Output -InputObject '' If ($KVAnswer -eq 0) { #Create new key vault $AzureLocations = Get-AzLocation $ExistingResourceGroups = @() #get resource groups Foreach ($item in Get-AzResourceGroup) { $RGLoc = $AzureLocations | Where-Object -FilterScript { $item.Location -eq $_.Location } if ($RGLoc.Providers -contains 'Microsoft.KeyVault') { $ExistingResourceGroups += $item } } Write-Host -Object 'Select a resource group' -ForegroundColor DarkGray Write-Host -Object '0. [Create New Resource Group]' -ForegroundColor DarkGray $i = 0 Foreach ($RG in $ExistingResourceGroups) { $i++ Write-Host -Object "$i. $($RG.ResourceGroupName)" -ForegroundColor Yellow } Do { [int]$RGAnswer = Read-Host -Prompt "Enter selection (1 - $i)" } while ($RGAnswer -lt 0 -or $RGAnswer -gt $i) Write-Output -InputObject '' if ($RGAnswer -eq 0) { #Create a new resource group #resource group name Do { $ResourceGroupName = Read-Host -Prompt 'Enter the name for the new Resource Group (only include alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.)' } while ($ResourceGroupName.Length -eq 0 -or $ResourceGroupName -notmatch '^[-\w\._\(\)]+$') #location $AvailableLocations = $AzureLocations | Where-Object -FilterScript { $_.Providers -contains 'Microsoft.Resources' -and $_.Providers -contains 'Microsoft.KeyVault' } | Sort-Object -Property DisplayName Write-Host -Object 'Select Azure Region:' -ForegroundColor DarkGray $i = 0 foreach ($loc in $AvailableLocations) { $i++ Write-Host -Object "$i. $($loc.DisplayName)" -ForegroundColor Yellow } Do { [int]$ans = Read-Host -Prompt "Enter selection (1 - $i)" } while ($ans -le 0 -or $ans -gt $i) Write-Output -InputObject '' $Location = $AvailableLocations[$ans-1] $strLocation = $Location.Location Write-Output -InputObject "Creating new Resource Group '$ResourceGroupName' in Azure region '$($Location.DisplayName)'." $NewRG = New-AzResourceGroup -Name $ResourceGroupName -Location $strLocation If ($NewRG.ProvisioningState -eq 'Succeeded') { Write-Host -Object "Resource group '$ResourceGroupName' successfully created." -ForegroundColor Green } else { Write-Host -Object "Resource Group creation failed. provisioning state: '$($NewRG.ProvisioningState)'." -ForegroundColor Red } Write-Output -InputObject '' } else { #choose existing Resource Group $ResourceGroupName = $ExistingResourceGroups[$RGAnswer -1].ResourceGroupName $strLocation = $ExistingResourceGroups[$RGAnswer -1].Location Write-Output -InputObject '' } #Create Key Vault #Key Vault name Do { $Global:KeyVaultName = Read-Host -Prompt 'Enter the name for the new Key Vault (only include alphanumeric characters and dashes and cannot start with a number.)' } while ($Global:KeyVaultName.Length -eq 0 -or $Global:KeyVaultName -notmatch '^[a-zA-Z0-9-]{3,24}$') Write-Output -InputObject 'Creating Azure Key Vault' $KeyVault = New-AzKeyVault -WarningAction SilentlyContinue -Name $Global:KeyVaultName -ResourceGroupName $ResourceGroupName -Location $strLocation -EnabledForDeployment -EnabledForTemplateDeployment -EnabledForDiskEncryption -Sku Standard -Tag @{ $IdentifyingTagName = $IdentifyingTagValue } -Confirm:$false $Global:KeyVaultName = $KeyVault.VaultName #Give someone access to the key vault Write-Output -InputObject 'Assigning Azure Key Vault permission to an Azure AD user. Searching Azure AD to get the AD user.' Add-KeyVaultFullAccessPolicy } else { $KeyVault = $ExistingKeyVaults[$KVAnswer-1] $Global:KeyVaultName = $KeyVault.VaultName } } #endregion #region manage key vault secrets Clear-Host Do { Clear-Host Write-Host -Object $TopMenuTitleLine1 -ForegroundColor Cyan Write-Host -Object $TopMenuTitleLine2 -ForegroundColor Cyan Write-Host -Object $TopMenuTitleLine3 -ForegroundColor Cyan Write-Host -Object "Selected Key Vault: '$Global:KeyVaultName'" -ForegroundColor Cyan Write-Host -Object "" Write-Host -Object "MAIN MENU" -ForegroundColor Cyan Write-Host -Object "Select what you'd like to do:" -ForegroundColor DarkGray Write-Host -Object '1. List credentials' -ForegroundColor Yellow Write-Host -Object '2. Search credentials' -ForegroundColor Yellow Write-Host -Object '3. Create new credential' -ForegroundColor Yellow Write-Host -Object '4. Save current Key Vault as my default' Write-Host -Object '5. Forget my default Key Vault' Write-Host -Object '6. Grant Key Vault Access' Write-Host -Object '7. Remove Key Vault Access' Write-Host -Object '8. Exit' -ForegroundColor DarkGray Do { [int]$option = Read-Host -Prompt 'Enter selection (1 - 8)' } while ($option -le 0 -or $option -gt 8) Write-Output -InputObject '' SWITCH ($option) { 1 { #list existing Get-KeyVaultCred } 2 { #search existing Get-KeyVaultCred -Search } 3 { #Create new New-KeyVaultCred Write-Output -InputObject '' } 4 { #Save profile Save-KeyVaultRepoProfile } 5 { #Delete profile Remove-KeyVaultRepoProfile } 6 { #Grant access Add-KeyVaultFullAccessPolicy } 7 { #Grant access Remove-KeyVaultFullAccessPolicy } 8 { Write-Output -InputObject 'See you next time!' } } } Until ($option -eq 8) } New-Alias -Name skypass -Value Start-AzurePasswordManager Export-ModuleMember -Alias * -Function * |