1

I need to automate execution of scripts on target VMs as a domain administrator. The problem is, VMs don't have public. I also should not rewrite the script as it has been written by a team member and I'd rather provide my team with a solution that works for them and is automatable, instead of rewriting their scripts every time. The current process looks like thi

  1. VSTS initiates a build process with Azure PowerShell script command1.ps1
  2. Command1.ps1 installs Azure Custom Script Extension on the target VM
  3. Custom script extension downloads and executes command2.ps1 that runs command3.ps1 as a domain administrator

The problem I'm having is I'm unable to pass credentials from VSTS to command2.ps1 Please, recommend me how I should do that properly. The options I found:

  1. Not sure if it is possible with VSTS https://blogs.technet.microsoft.com/ashleymcglone/2016/08/30/powershell-remoting-kerberos-double-hop-solved-securely/

  2. Add IP public address to the target VM, configure WinRM, execute command2.ps1, delete public IP address

I'm sure there is a better way of doing this. command1.ps1:

    param
(
    [Parameter(Mandatory)]
    [String]$resourceGroupName,

    [Parameter(Mandatory)]
    [String]$targetVMname,

    [Parameter(Mandatory)]
    [String]$vmLocation,

    [Parameter(Mandatory)]
    [String]$FileUri,

    [Parameter(Mandatory)]
    [String]$nameOfTheScriptToRun,

    [Parameter(Mandatory)]
    [String]$customScriptExtensionName,

    [Parameter(Mandatory)]
    [String]$domainAdminName,

    [Parameter(Mandatory)]
    [String]$domainAdminPassword

)

$domainAdminPasswordSecureString = ConvertTo-SecureString -String $domainAdminPassword -AsPlainText -Force
$DomainCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domainAdminName, $domainAdminPasswordSecureString

Set-AzureRmVMCustomScriptExtension -Argument "-DomainCredentials $DomainCredentials" `
    -ResourceGroupName $resourceGroupName `
    -VMName $targetVMname `
    -Location $vmLocation `
    -FileUri $FileUri `
    -Run $nameOfTheScriptToRun `
    -Name $customScriptExtensionName

Remove-AzureRmVMCustomScriptExtension -Force `
    -ResourceGroupName $resourceGroupName `
    -VMName $targetVMname `
    -Name $customScriptExtensionName

command2.ps1:

    param
(
    [Parameter(Mandatory)]
    [System.Management.Automation.PSCredential]$DomainCredentials
)

$url = "https://raw.githubusercontent.com/x/command2.ps1"
$output = "C:\command2.ps1"

Invoke-WebRequest -Uri $url -OutFile $output
Start-Process -FilePath powershell.exe -ArgumentList $output -Credential $DomainCredentials
WinBoss
  • 879
  • 1
  • 17
  • 40

1 Answers1

3

You don't actually have the double hop problem, because you are not executing the command on the node, you are launching the extension, which downloads the script and executes it.

So what you need to do is this:

Set-AzureRMVMCustomScriptExtension ... -Argument "-domainAdminName admin -domainAdminPassword passw0rD" -VM $Vm
$vm | Update-AzureVM

and in your script (which is invoked INSIDE the machine, so command2.ps1) do:

$domainAdminPasswordSecureString = ConvertTo-SecureString -String $domainAdminPassword -AsPlainText -Force
$DomainCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domainAdminName, $domainAdminPasswordSecureString

and paste the appropriate params into the second script (so it accepts those)

Also, you don't need the intermediate script, you can just download "https://raw.githubusercontent.com/x/command2.ps1" and execute it with arguments

4c74356b41
  • 69,186
  • 6
  • 100
  • 141
  • Are you proposing to pass plain text password from VSTS through Azure Custom Extension? I don't think that's a good idea. The password will visible as plain text inside C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.9\RuntimeSettings\0.settings – WinBoss Sep 26 '17 at 13:38
  • you are removing the extension afterwards, so doesn't really matter. that place will be cleaned up. Or you can use protected settings and the command to execute will be encoded. https://learn.microsoft.com/en-us/azure/virtual-machines/windows/extensions-customscript – 4c74356b41 Sep 26 '17 at 13:40
  • Any way to pass protected settings with PowerShell? If not, what would you do? Would you feel safe passing password as simple string? – WinBoss Sep 26 '17 at 13:57
  • `-SecureExecution` https://learn.microsoft.com/en-us/powershell/module/azurerm.compute/set-azurermvmcustomscriptextension?view=azurermps-4.4.0 – 4c74356b41 Sep 26 '17 at 14:02
  • So, this should do the trick? `Set-AzureRMVMCustomScriptExtension ... -Argument "-domainAdminName admin" -SecureExecution "-domainAdminPassword passw0rD" -VM $Vm` ? – WinBoss Sep 26 '17 at 14:03
  • Although, thanks to this answer double hop issues is avoided, a new issue of Azure Custom Script Extension appeared. https://stackoverflow.com/questions/46433123/azure-custom-script-extension-execute-script-as-another-user – WinBoss Sep 26 '17 at 18:14
  • in this case you probably want to accept this answer ;) – 4c74356b41 Sep 26 '17 at 18:57