0

更新解释我的根本问题:如果天青对虚拟机的,扩展,因为他们正在供应,加入域,并且运行脚本,我怎么能运行脚本作为域用户?如何以域用户身份运行Azure VM CustomScriptExtension? (部分2)

该脚本需要作为域用户运行才能访问文件共享以检索既不是VM模板映像的一部分也不能(合理)上载到Azure blob存储的安装文件和其他脚本,以及作为供应的一部分下载。

我将this question分为两部分,因为下半部分(代表此处)没有得到解决。

我工作的是一个采用JSON文件创建新VM的Powershell脚本; JSON文件包含虚拟机加入域并运行自定义脚本的说明。两种情况都会发生,但脚本以用户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("") 
} 

回答

0

有这个问题了几个零件,以及!

首先在那里获取凭证,在某些时候,您将需要将凭证传递给机器,即使它是凭证以获取凭证。

我个人的解决方案是创建一个证书来加密PSCredential对象,将该对象存储在HTTP服务器上,然后在脚本中传递证书和pfx密码。当然,如果你正在建立服务器,你可以预先安装这个证书。 (有一个code review question与此代码)

或者,您可能能够使用类似Azure密钥保管库来存储pfx密码。

对于runas部分。有几个选项

我还没有推出Powershell作为一个不同的用户,因为大约v1!所以我希望别人谈论那个。

您可以运行以不同用户身份登录的计划任务,这应该有效。

如果您在不同的环境下运行,您可以设置自动登录属性,重启机器让其脚本运行,然后删除自动登录项并重新启动。这带来了额外的好处,即您可以拥有一个特定的严格限制的域帐户,该帐户只能访问您所需的共享资源,并且每次创建后都会从每台计算机上剥离其管理员/登录权限。这样,您还可以将所有构建脚本保留在Active Directory中,并让该用户自动将其拉下并运行。

+0

1)我以为我可以在脚本本身存储一个(hashed/encrypted/rot13'd)密码_来生成凭证。你是否在说,_无论如何,用户必须按Enter键进入UAC提示?如果是这样,这种方法在水中死亡。 – KlaymenDK

+0

2)'帐户是敏感的......' - 恐怕我不知道这是什么意思。 :-( – KlaymenDK

+0

3)我确实需要“成为域用户”才能连接到文件共享。默认用户'workgroup \ system'(为什么不是至少我在JSON中指定的管理员?)没有权限。 – KlaymenDK

相关问题