在PowerShell工作流

时间:2018-02-09 06:16:11

标签: powershell azure powershell-remoting azure-automation hybrid-runbook-worker

我有一个Azure自动化Powershell工作流程Runbook,我希望在Hybrid Runbook Worker服务器上运行,作为Azure Site Recovery故障转移后操作步骤的一部分。

在高级别,Runbook利用Azure Run AS连接来收集将要进行故障转移的其中一个VM的私有IP地址。存储此IP地址,然后将其写入环境中配置的Active Directory DNS中的STATIC A记录。

  

>   注意我向你保证,我们有充分的理由这样做。我意识到它在AD上出现的机器本身将刷新它的个人DNS名称条目,这是一个单独的A记录,我们想要指向故障转移服务器的IP地址。由于此服务器承载的应用程序存在已定义的问题,因此我们未使用CNAME。

所以我必须更新这个A记录。您将在下面找到执行此操作的脚本。当我使用适当的凭据(mydomain \ asrscripts)登录服务器时,我在Hybrid Runbook Server上运行它时,下面的脚本可以正常工作。

workflow VisionWebFailover-Test

{

inlineScript {

    $connectionName = 'AzureRunAsConnection'

    try
    {
        # Get the connection "AzureRunAsConnection "
        $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         

        "Logging in to Azure..."
        Add-AzureRmAccount `
    -ServicePrincipal `
    -TenantId $servicePrincipalConnection.TenantId `
    -ApplicationId $servicePrincipalConnection.ApplicationId `
    -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
    }
    catch {
        if (!$servicePrincipalConnection)
        {
            $ErrorMessage = "Connection $connectionName not found."
            throw $ErrorMessage
        } else{
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }

    $rg = "RG03ASR" #ResoureGroup where ASR Machines will come up
    $vmName = "ASRJUMP01" #VMname of the VM I need to get the IP from for updating in DNS



    Write-output "Getting IP"

    $ip = (Get-AzureRmNetworkInterface | Where-Object {($_.VirtualMachine.id).Split("/")[-1] -like $vmname}).IpConfigurations.PrivateIpAddress #find the primary nic and store it's IP address

    Write-Output "Returned VM IP"
    Write-Output $ip


        #PowerShell to be executed locally
        Import-Module dnsserver
        $hostname = 'customArecord'
        $zonname = 'mydomain.com'
        $DNSServer = 'MYDNSServer.mydomain.com'

        #Grab the existing DNS record and store it in the variable $oldobj
        $oldobj = Get-DnsServerResourceRecord -Name $hostname -ZoneName $zonname -RRType A -ComputerName $DNSServer
        Write-Output $oldobj

        #Copy the DNS record into $newobj
        $newobj = $oldobj.Clone()

        #Change the value of the IP address in $newobj to equal the IP address assigned to the visionwebdev server in Azure
        [System.Net.IPAddress]$NewIP = [System.Net.IPAddress]($ip)
        $newobj.RecordData.IPv4Address = $NewIp

        Write-Output $NewIP "this is the new IP that will be updated to DNS"

        write-output $newobj
        #Here is where we actually apply the change to the DNS record

        Set-DnsServerResourceRecord -ZoneName $zonname -OldInputObject $oldobj -NewInputObject $newobj -Computername $DNSServer -passthru

        Write-Output "DNS entry updated, replication may take 15 minutes"
    }

上述代码中的每一步都会成功进行,直到它到达Set-DNSServerResourceRecord语句,并失败并显示如下所示的Permission Denied Error。这是我从Azure自动化门户运行作业的时候。当我在用户登录的盒子上本地运行它时,它可以正常工作。

Set-DnsServerResourceRecord : Failed to update record customArecord.mydomain.com.
At VisionWebFailover-Test:27 char:27
+ 
   + CategoryInfo : PermissionDenied:(customArecord.mydomain.com:root/Microsoft/...rResourceRecord) 
[Set-DnsServerResourceRecord], CimException
    + FullyQualifiedErrorId : WIN32 5,Set-DnsServerResourceRecord
  

>   我想我需要在我的InlineScript块的末尾使用强制代码在我想要的定义的用户上下文中对DNS服务器执行。虽然我真正想要的是命令在定义的用户上下文中对混合Runbook worker执行。

about_inlinescript 文档说它接受了 https://docs.microsoft.com/en-us/powershell/module/psworkflow/about/about_inlinescript?view=powershell-5.1

并提供了一个像这样的例子

InlineScript {<script block>} <ActivityCommonParameters>

活动常用参数由此doc定义 https://docs.microsoft.com/en-us/powershell/module/psworkflow/about/about_activitycommonparameters?view=powershell-5.1

它引用了我希望使用的两个参数-PSComputerName-PSCredential

我构建了一个像这样的凭证对象

$secpasswd = ConvertTo-SecureString "MyAwesomePassword" -AsPlainText -Force $mycreds = New-Object System.Management.Automation.PSCredential ("MYDOMAIN\asrscripts", $secpasswd)

我甚至使用

从自动化中提取资产

$domainCred = Get-AutomationPSCredential -Name 'asrscripts'

当我运行我的代码并尝试模仿该示例时,通过在InlineScript的末尾添加-PSComputername或-PSCredential,我会收到错误。

At line:94 char:7 + -PSComputerName 'MYDNSServer' -PSCredential $domainCred + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Cannot find the '-PSComputerName' command. If this command is defined as a workflow, ensure it is defined before the workflow that calls it. If it is a command intended to run directly within Windows PowerShell (or is not available on this system), place it in an InlineScript: 'InlineScript { -PSComputerName }'

如果我按照上述错误的建议并将-PSComputerName和-PSCredential INSIDE放在InlineScript块中,我会收到一个错误,它无法找到-PSComputerName和-PSCredential的Set-DNSServerResourceRecord的参数

  

&GT;   我不知道我做错了什么

  • 在Runbook服务器上,我有所有合适的Powershell模块 安装。
  • 它已加入域名。
  • 它在DNSServer(也是域控制器)
  • 上添加为可信任主机
  • 我想在上下文中运行此用户的是MYDOMAIN \ asrscripts,它被添加为Azure自动化凭据工件
  • 如果我尝试将Hybrid Worker的RUNAS用户更改为CUSTOM并选择我的asrscripts工件,则作业将挂起,并且永远不会运行。它一直处于排队状态,直到它暂停。我在系统事件日志中收到用户无法进行身份验证的错误。
  • 我已经用尽了下面的远程故障排除文档

关于远程排除故障 - https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_troubleshooting?view=powershell-5.1

希望有人可以提供帮助。 谢谢!

1 个答案:

答案 0 :(得分:1)

&#34;无法找到&#39; -PSComputerName&#39;命令&#34;建议由错误的代码格式化导致语法错误。 PowerShell将此解释为参数时遇到麻烦,它认为这是一个单独的命令。您能否详细说明如何将此参数应用于InlineScript?例如,如果您执行此操作,则会出现此错误:

InlineScript {
    ...
}
-PSComputerName MyComputer

相反,你需要这样做:

InlineScript {
    ...
} -PSComputerName MyComputer

或:

InlineScript {
    ...
} `
-PSComputerName MyComputer