更新以解释我的根本问题:如果 Azure 在配置VM 时具有扩展,以加入域和运行脚本,我如何以域用户身份运行脚本?
该脚本需要以域用户身份运行才能访问文件共享以检索安装文件和其他脚本,这些脚本既不是 VM 模板映像的一部分,也不能(合理地)上传到 Azure Blob 存储并作为预配的一部分下载.
我把这个问题一分为二,因为第二部分(在这里表示)没有得到解决。
我正在工作的是一个 Powershell 脚本,它需要一个 JSON 文件来创建一个新的 VM;JSON 文件包含 VM 加入域和运行自定义脚本的说明。这两件事都发生了,但脚本以用户身份运行workgroup\system
,因此无权访问网络驱动器。
- 我怎样才能最好地为这样的脚本提供特定用户的凭据?
我试图让脚本使用不同用户的凭据生成一个新的 Powershell 会话,但我很难弄清楚语法——我什至无法让它在我的开发工作站上工作。自然,安全性是一个问题,但如果我可以使用加密的存储凭据使其工作,这可能是可以接受的。
...但不要限制你的答案——也许有一种完全不同的方法可以解决这个问题并达到相同的效果?
Param(
[switch]$sudo, # Indicates we've already tried to elevate to admin
[switch]$su # Indicates we've already tried to switch to domain user
)
try {
# Pseudo-constants
$DevOrProd=(Get-Item $MyInvocation.MyCommand.Definition).Directory.Parent.Name
$PsScriptPath = Split-Path -parent $MyInvocation.MyCommand.Definition
$pathOnPDrive = "\\dkfile01\P\SoftwareTestData\Azure\automation\$DevOrProd\run-once"
$fileScriptLocal = $MyInvocation.MyCommand.Source
$fileScriptRemote = "$pathOnPDrive\run-once-from-netdrive.ps1"
# $filePw = "$pathOnPDrive\cred.txt"
$fileLog="$PsScriptPath\switch-user.log"
$Myuser="mohican"
$Myuserpass="alhambra"
$Mydomainuser="mydomain\$Myuser"
$Mydomain="mydomain.com"
# Check variables
write-output("SUDO=[$SUDO]")
write-output("SU=[$SU]")
# Functions
function Test-Admin {
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
return ($currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator))
}
# Main
write-output("Run-once script starting ...")
# Check admin privilege
write-output("Checking admin privilege ...")
if (Test-Admin) {
write-output("- Is admin.")
} else {
write-output("- Not an admin.")
if ($sudo) {
write-output(" - Already tried elevating, didn't work.")
write-output("Run-once script on local VM finished.")
write-output("")
exit(0) # Don't return failure exit code because Azure will report it as if the deployment broke...
} else {
write-output(" - Attempting to elevate ...")
$arguments = "-noprofile -file $fileScriptLocal"
$arguments = $arguments +" -sudo"
try {
Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments
write-output(" - New process started.")
} catch {
write-output(" - New process failed to start.")
}
write-output("Run-once script on local VM finished.")
write-output("")
exit(0) # The action will continue in the spawned process
}
}
write-output("Checked admin privilege ... [OK]")
# Check current user
write-output("Checking user account ...")
$hostname = $([Environment]::MachineName).tolower()
$domainname = $([Environment]::UserDomainName).tolower()
$thisuser = $([Environment]::UserName).tolower()
write-output("- Current user is ""$domainname\$thisuser"" on ""$hostname"".")
write-output("- Want to be user ""$Myuser"".")
if ($Myuser -eq $thisuser) {
write-output(" - Correct user.")
} else {
write-output(" - Incorrect user.")
if ($su) {
write-output(" - Already tried switching user, didn't work.")
write-output("Run-once script on local VM finished.")
write-output("")
exit(0) # Don't return failure exit code because Azure will report it as if the deployment broke...
} else {
write-output(" - Attempting to switch to user ""$Mydomainuser"" with passwond ""$Myuserpass"" ...")
# FIXME -- This does not work... :-(
$MyuserpassSecure = ConvertTo-SecureString $Myuserpass -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $Mydomainuser, $MyuserpassSecure
$arguments = "-noprofile -file $fileScriptLocal"
$arguments = $arguments +" -sudo -su -Credential $credential -computername $hostname"
try {
Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments
write-output(" - New process started.")
} catch {
write-output(" - New process failed to start.")
}
write-output("Run-once script on local VM finished.")
write-output("")
exit(0) # The action will continue in the spawned process
}
}
write-output("Checked user account ... [OK]")
# Run script from P: drive (finally!)
write-output("Attempting to run script from P: drive ...")
write-output("- Script file: ""$fileScriptRemote""")
if (test-path $fileScriptRemote) {
write-output("Running script from P: drive ...")
$arguments = "-noprofile -file $fileScriptRemote"
try {
Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments
write-output(" - New process started.")
} catch {
write-output(" - New process failed to start.")
}
write-output("Run-once script on local VM finished.")
write-output("")
exit(0) # The action will continue in the spawned process
} else {
write-output("- Could not locate/access script file!")
write-output("Ran script from P: drive ... [ERROR]")
}
write-output("Run-once script on local VM finished.")
write-output("")
} catch {
write-warning("Unhandled error in line $($_.InvocationInfo.ScriptLineNumber): $($error[0])")
write-output("ABEND")
write-output("")
}