mirror of
https://github.com/microsoft/vcpkg.git
synced 2025-01-14 14:58:00 +08:00
[vcpkg] Use a crypto RNG to generate admin passwords (#11629)
* [vcpkg] Use a crypto RNG to generate admin passwords * Apply code review comments from Stephan and Casey. * Extract functions into create-vmss-helpers.psm1. * Put Wait-Shutdown back.
This commit is contained in:
parent
0fc90d9f15
commit
6d36e2a86b
165
scripts/azure-pipelines/create-vmss-helpers.psm1
Executable file
165
scripts/azure-pipelines/create-vmss-helpers.psm1
Executable file
@ -0,0 +1,165 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns whether there's a name collision in the resource group.
|
||||
|
||||
.DESCRIPTION
|
||||
Find-ResourceGroupNameCollision takes a list of resources, and checks if $Test
|
||||
collides names with any of the resources.
|
||||
|
||||
.PARAMETER Test
|
||||
The name to test.
|
||||
|
||||
.PARAMETER Resources
|
||||
The list of resources.
|
||||
#>
|
||||
function Find-ResourceGroupNameCollision {
|
||||
[CmdletBinding()]
|
||||
Param([string]$Test, $Resources)
|
||||
|
||||
foreach ($resource in $Resources) {
|
||||
if ($resource.ResourceGroupName -eq $Test) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Attempts to find a name that does not collide with any resources in the resource group.
|
||||
|
||||
.DESCRIPTION
|
||||
Find-ResourceGroupName takes a set of resources from Get-AzResourceGroup, and finds the
|
||||
first name in {$Prefix, $Prefix-1, $Prefix-2, ...} such that the name doesn't collide with
|
||||
any of the resources in the resource group.
|
||||
|
||||
.PARAMETER Prefix
|
||||
The prefix of the final name; the returned name will be of the form "$Prefix(-[1-9][0-9]*)?"
|
||||
#>
|
||||
function Find-ResourceGroupName {
|
||||
[CmdletBinding()]
|
||||
Param([string] $Prefix)
|
||||
|
||||
$resources = Get-AzResourceGroup
|
||||
$result = $Prefix
|
||||
$suffix = 0
|
||||
while (Find-ResourceGroupNameCollision -Test $result -Resources $resources) {
|
||||
$suffix++
|
||||
$result = "$Prefix-$suffix"
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generates a random password.
|
||||
|
||||
.DESCRIPTION
|
||||
New-Password generates a password, randomly, of length $Length, containing
|
||||
only alphanumeric characters, underscore, and dash.
|
||||
|
||||
.PARAMETER Length
|
||||
The length of the returned password.
|
||||
#>
|
||||
function New-Password {
|
||||
Param ([int] $Length = 32)
|
||||
|
||||
# This 64-character alphabet generates 6 bits of entropy per character.
|
||||
# The power-of-2 alphabet size allows us to select a character by masking a random Byte with bitwise-AND.
|
||||
$alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
|
||||
$mask = 63
|
||||
if ($alphabet.Length -ne 64) {
|
||||
throw 'Bad alphabet length'
|
||||
}
|
||||
|
||||
[Byte[]]$randomData = [Byte[]]::new($Length)
|
||||
$rng = $null
|
||||
try {
|
||||
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
|
||||
$rng.GetBytes($randomData)
|
||||
}
|
||||
finally {
|
||||
if ($null -ne $rng) {
|
||||
$rng.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
$result = ''
|
||||
for ($idx = 0; $idx -lt $Length; $idx++) {
|
||||
$result += $alphabet[$randomData[$idx] -band $mask]
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Waits for the shutdown of the specified resource.
|
||||
|
||||
.DESCRIPTION
|
||||
Wait-Shutdown takes a VM, and checks if there's a 'PowerState/stopped'
|
||||
code; if there is, it returns. If there isn't, it waits ten seconds and
|
||||
tries again.
|
||||
|
||||
.PARAMETER ResourceGroupName
|
||||
The name of the resource group to look up the VM in.
|
||||
|
||||
.PARAMETER Name
|
||||
The name of the virtual machine to wait on.
|
||||
#>
|
||||
function Wait-Shutdown {
|
||||
[CmdletBinding()]
|
||||
Param([string]$ResourceGroupName, [string]$Name)
|
||||
|
||||
Write-Host "Waiting for $Name to stop..."
|
||||
while ($true) {
|
||||
$Vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $Name -Status
|
||||
$highestStatus = $Vm.Statuses.Count
|
||||
for ($idx = 0; $idx -lt $highestStatus; $idx++) {
|
||||
if ($Vm.Statuses[$idx].Code -eq 'PowerState/stopped') {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "... not stopped yet, sleeping for 10 seconds"
|
||||
Start-Sleep -Seconds 10
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sanitizes a name to be used in a storage account.
|
||||
|
||||
.DESCRIPTION
|
||||
Sanitize-Name takes a string, and removes all of the '-'s and
|
||||
lowercases the string, since storage account names must have no
|
||||
'-'s and must be completely lowercase alphanumeric. It then makes
|
||||
certain that the length of the string is not greater than 24,
|
||||
since that is invalid.
|
||||
|
||||
.PARAMETER RawName
|
||||
The name to sanitize.
|
||||
#>
|
||||
function Sanitize-Name {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[string]$RawName
|
||||
)
|
||||
|
||||
$result = $RawName.Replace('-', '').ToLowerInvariant()
|
||||
if ($result.Length -gt 24) {
|
||||
Write-Error 'Sanitized name for storage account $result was too long.'
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Find-ResourceGroupName
|
||||
Export-ModuleMember -Function New-Password
|
||||
Export-ModuleMember -Function Wait-Shutdown
|
||||
Export-ModuleMember -Function Sanitize-Name
|
@ -27,111 +27,7 @@ $ProgressActivity = 'Creating Scale Set'
|
||||
$TotalProgress = 10
|
||||
$CurrentProgress = 1
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns whether there's a name collision in the resource group.
|
||||
|
||||
.DESCRIPTION
|
||||
Find-ResourceGroupNameCollision takes a list of resources, and checks if $Test
|
||||
collides names with any of the resources.
|
||||
|
||||
.PARAMETER Test
|
||||
The name to test.
|
||||
|
||||
.PARAMETER Resources
|
||||
The list of resources.
|
||||
#>
|
||||
function Find-ResourceGroupNameCollision {
|
||||
[CmdletBinding()]
|
||||
Param([string]$Test, $Resources)
|
||||
|
||||
foreach ($resource in $Resources) {
|
||||
if ($resource.ResourceGroupName -eq $Test) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Attempts to find a name that does not collide with any resources in the resource group.
|
||||
|
||||
.DESCRIPTION
|
||||
Find-ResourceGroupName takes a set of resources from Get-AzResourceGroup, and finds the
|
||||
first name in {$Prefix, $Prefix-1, $Prefix-2, ...} such that the name doesn't collide with
|
||||
any of the resources in the resource group.
|
||||
|
||||
.PARAMETER Prefix
|
||||
The prefix of the final name; the returned name will be of the form "$Prefix(-[1-9][0-9]*)?"
|
||||
#>
|
||||
function Find-ResourceGroupName {
|
||||
[CmdletBinding()]
|
||||
Param([string] $Prefix)
|
||||
|
||||
$resources = Get-AzResourceGroup
|
||||
$result = $Prefix
|
||||
$suffix = 0
|
||||
while (Find-ResourceGroupNameCollision -Test $result -Resources $resources) {
|
||||
$suffix++
|
||||
$result = "$Prefix-$suffix"
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a randomly generated password.
|
||||
|
||||
.DESCRIPTION
|
||||
New-Password generates a password, randomly, of length $Length, containing
|
||||
only alphanumeric characters (both uppercase and lowercase).
|
||||
|
||||
.PARAMETER Length
|
||||
The length of the returned password.
|
||||
#>
|
||||
function New-Password {
|
||||
Param ([int] $Length = 32)
|
||||
|
||||
$Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
$result = ''
|
||||
for ($idx = 0; $idx -lt $Length; $idx++) {
|
||||
# NOTE: this should probably use RNGCryptoServiceProvider
|
||||
$result += $Chars[(Get-Random -Minimum 0 -Maximum $Chars.Length)]
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sanitizes a name to be used in a storage account.
|
||||
|
||||
.DESCRIPTION
|
||||
Sanitize-Name takes a string, and removes all of the '-'s and
|
||||
lowercases the string, since storage account names must have no
|
||||
'-'s and must be completely lowercase alphanumeric. It then makes
|
||||
certain that the length of the string is not greater than 24,
|
||||
since that is invalid.
|
||||
|
||||
.PARAMETER RawName
|
||||
The name to sanitize.
|
||||
#>
|
||||
function Sanitize-Name {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[string]$RawName
|
||||
)
|
||||
|
||||
$result = $RawName.Replace('-', '').ToLowerInvariant()
|
||||
if ($result.Length -gt 24) {
|
||||
Write-Error 'Sanitized name for storage account $result was too long.'
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
Import-Module "$PSScriptRoot/../create-vmss-helpers.psm1" -DisableNameChecking
|
||||
|
||||
####################################################################################################
|
||||
Write-Progress `
|
||||
|
@ -29,145 +29,7 @@ $ProgressActivity = 'Creating Scale Set'
|
||||
$TotalProgress = 12
|
||||
$CurrentProgress = 1
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns whether there's a name collision in the resource group.
|
||||
|
||||
.DESCRIPTION
|
||||
Find-ResourceGroupNameCollision takes a list of resources, and checks if $Test
|
||||
collides names with any of the resources.
|
||||
|
||||
.PARAMETER Test
|
||||
The name to test.
|
||||
|
||||
.PARAMETER Resources
|
||||
The list of resources.
|
||||
#>
|
||||
function Find-ResourceGroupNameCollision {
|
||||
[CmdletBinding()]
|
||||
Param([string]$Test, $Resources)
|
||||
|
||||
foreach ($resource in $Resources) {
|
||||
if ($resource.ResourceGroupName -eq $Test) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Attempts to find a name that does not collide with any resources in the resource group.
|
||||
|
||||
.DESCRIPTION
|
||||
Find-ResourceGroupName takes a set of resources from Get-AzResourceGroup, and finds the
|
||||
first name in {$Prefix, $Prefix-1, $Prefix-2, ...} such that the name doesn't collide with
|
||||
any of the resources in the resource group.
|
||||
|
||||
.PARAMETER Prefix
|
||||
The prefix of the final name; the returned name will be of the form "$Prefix(-[1-9][0-9]*)?"
|
||||
#>
|
||||
function Find-ResourceGroupName {
|
||||
[CmdletBinding()]
|
||||
Param([string] $Prefix)
|
||||
|
||||
$resources = Get-AzResourceGroup
|
||||
$result = $Prefix
|
||||
$suffix = 0
|
||||
while (Find-ResourceGroupNameCollision -Test $result -Resources $resources) {
|
||||
$suffix++
|
||||
$result = "$Prefix-$suffix"
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a randomly generated password.
|
||||
|
||||
.DESCRIPTION
|
||||
New-Password generates a password, randomly, of length $Length, containing
|
||||
only alphanumeric characters (both uppercase and lowercase).
|
||||
|
||||
.PARAMETER Length
|
||||
The length of the returned password.
|
||||
#>
|
||||
function New-Password {
|
||||
Param ([int] $Length = 32)
|
||||
|
||||
$Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
$result = ''
|
||||
for ($idx = 0; $idx -lt $Length; $idx++) {
|
||||
# NOTE: this should probably use RNGCryptoServiceProvider
|
||||
$result += $Chars[(Get-Random -Minimum 0 -Maximum $Chars.Length)]
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Waits for the shutdown of the specified resource.
|
||||
|
||||
.DESCRIPTION
|
||||
Wait-Shutdown takes a VM, and checks if there's a 'PowerState/stopped'
|
||||
code; if there is, it returns. If there isn't, it waits ten seconds and
|
||||
tries again.
|
||||
|
||||
.PARAMETER ResourceGroupName
|
||||
The name of the resource group to look up the VM in.
|
||||
|
||||
.PARAMETER Name
|
||||
The name of the virtual machine to wait on.
|
||||
#>
|
||||
function Wait-Shutdown {
|
||||
[CmdletBinding()]
|
||||
Param([string]$ResourceGroupName, [string]$Name)
|
||||
|
||||
Write-Host "Waiting for $Name to stop..."
|
||||
while ($true) {
|
||||
$Vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $Name -Status
|
||||
$highestStatus = $Vm.Statuses.Count
|
||||
for ($idx = 0; $idx -lt $highestStatus; $idx++) {
|
||||
if ($Vm.Statuses[$idx].Code -eq 'PowerState/stopped') {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "... not stopped yet, sleeping for 10 seconds"
|
||||
Start-Sleep -Seconds 10
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sanitizes a name to be used in a storage account.
|
||||
|
||||
.DESCRIPTION
|
||||
Sanitize-Name takes a string, and removes all of the '-'s and
|
||||
lowercases the string, since storage account names must have no
|
||||
'-'s and must be completely lowercase alphanumeric. It then makes
|
||||
certain that the length of the string is not greater than 24,
|
||||
since that is invalid.
|
||||
|
||||
.PARAMETER RawName
|
||||
The name to sanitize.
|
||||
#>
|
||||
function Sanitize-Name {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[string]$RawName
|
||||
)
|
||||
|
||||
$result = $RawName.Replace('-', '').ToLowerInvariant()
|
||||
if ($result.Length -gt 24) {
|
||||
Write-Error 'Sanitized name for storage account $result was too long.'
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
Import-Module "$PSScriptRoot/../create-vmss-helpers.psm1" -DisableNameChecking
|
||||
|
||||
####################################################################################################
|
||||
Write-Progress `
|
||||
|
Loading…
x
Reference in New Issue
Block a user