powershell - 将 SecureString 变量传递给只读域 Controller 的 DSC 配置

标签 powershell dsc

我正在尝试创建一个 DSC 脚本,该脚本可以在将成为只读域 Controller 的机器上本地运行。 xActiveDirectory DSC 资源不提供创建 RODC,因此我必须使用脚本资源并使用 Install-ADDSDomainController。

当我必须提供安全模式管理员密码时,我的问题就出现了。该参数将仅接受 SecureString,但是我无法将安全字符串传递给 DSC 配置。我可以为 Credential 参数传递一个 PSCredential 对象,但安全模式参数不接受它,所以我需要一个单独的变量。我正在使用自签名证书加密凭据,此时似乎可以正常工作。

我的 DSC 代码,底部有几行注释掉的行,我在其中测试了创建安全字符串的替代方法,这些方法都不起作用:

get-childitem cert:\localmachine\my | where-object {$_.Subject -like "*CN=DscEncryptionCert*"} | remove-item

$cert = New-SelfSignedCertificate -Type DocumentEncryptionCertLegacyCsp -DnsName 'DscEncryptionCert' -HashAlgorithm SHA256
$cert | Export-Certificate -FilePath "c:\RODC\DscPublicKey.cer" -Force

$thumbprint = (get-childitem cert:\localmachine\my | where-object {$_.Subject -like "*CN=DscEncryptionCert*"}).Thumbprint


$ConfigData= @{ 
    AllNodes = @(     
            @{   
                NodeName = "localhost" 

                CertificateFile = "C:\RODC\localhost.cer" 

                Thumbprint = $thumbprint 
            }; 
        );    
    }




configuration RODC

{
    param(
        [Parameter()]$DomainName,
        [Parameter()]$ReplicationSourceDC,
        [Parameter()]$SiteName,
        [Parameter()]$Thumbprint,
        [PSCredential]$PSCredential = $PSCredential,
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [System.Security.SecureString]$safemodepassword = $safemodepassword
        )

    Import-DscResource -module 'PSDesiredStateConfiguration'

    Node localhost

    {

        LocalConfigurationManager 
            { 
            CertificateId = $Thumbprint 
            } 

        WindowsFeature ADDSInstall
            {
            Ensure = 'Present'
            Name = 'AD-Domain-Services'
            IncludeAllSubFeature = $true
            }

        script installRODC
            {
            DependsOn = '[WindowsFeature]ADDSInstall'
            SetScript =
                {
                Import-Module ADDSDeployment
                Install-ADDSDomainController `
                -AllowPasswordReplicationAccountName @("test\Allowed RODC Password Replication Group") `
                -NoGlobalCatalog:$false `
                -Credential:$PSCredential `
                -CriticalReplicationOnly:$false `
                -DenyPasswordReplicationAccountName @("BUILTIN\Administrators", "BUILTIN\Server Operators", "BUILTIN\Backup Operators", "BUILTIN\Account Operators", "test\Denied RODC Password Replication Group") `
                -DomainName:$using:DomainName `
                -InstallDns:$true `
                -NoRebootOnCompletion:$false `
                -ReadOnlyReplica:$true `
                -ReplicationSourceDC:$using:ReplicationSourceDC `
                -SiteName $using:SiteName `
                -Force:$true `
                -SafeModeAdministratorPassword:$safemodepassword
                }
            TestScript =
                {
                if((get-wmiobject win32_computersystem).domainrole -eq 4){$true}else{$false}
                }
            GetScript =
                {
                Return @{result = (get-wmiobject win32_computersystem).domainrole}
                }
            }

    }

}

$PSCredential = Get-Credential
$safemodepassword = Read-Host -assecurestring "Please enter the Safe Mode Administrator password"
#$safemodepassword = ConvertTo-SecureString "P@55word" -AsPlainText -Force
#$safemodepassword = New-Object System.Management.Automation.PSCredential ("Administrator", $password)

RODC -DomainName test.local -ReplicationSourceDC DC1.test.local -Sitename Site11 -PSCredential $PSCredential -safemodepassword $safemodepassword

Set-DscLocalConfigurationManager -path .\RODC -Verbose -Force

Start-DscConfiguration -path .\RODC -Verbose -force

我写了一个简单的测试来检查脚本代码本身是否正常工作,它是:
$PSCredential = Get-Credential
$safemodepassword = Read-Host -assecurestring "Please enter the Safe Mode Administrator password"

$DomainName = "test.local"
$ReplicationSourceDC = "DC1.test.local"
$Sitename = "Site11"


Install-ADDSDomainController `
-AllowPasswordReplicationAccountName @("test\Allowed RODC Password Replication Group") `
-NoGlobalCatalog:$false `
-Credential:$PSCredential `
-CriticalReplicationOnly:$false `
-DenyPasswordReplicationAccountName @("BUILTIN\Administrators", "BUILTIN\Server Operators", "BUILTIN\Backup Operators", "BUILTIN\Account Operators", "test\Denied RODC Password Replication Group") `
-DomainName:$DomainName `
-InstallDns:$true `
-NoRebootOnCompletion:$false `
-ReadOnlyReplica:$true `
-ReplicationSourceDC:$ReplicationSourceDC `
-SiteName $SiteName `
-Force:$true `
-SafeModeAdministratorPassword:$safemodepassword

我得到的主要错误是:

PowerShell DSC resource MSFT_ScriptResource failed to execute Set-TargetResource functionality with error message: Cannot bind parameter 'SafeModeAdministratorPassword' to the target. Exception setting "SafeModeAdministratorPassword": "SafeModeAdministratorPassword cannot be null."



它是 NULL 是因为它没有被正确传递吗?如果我打印出变量的值,它会告诉我存在一个安全字符串,但在实际的 DSC 配置本身中似乎并非如此。

如果我将 -SafeModeAdministratorPassword:$safemodepassword 更改为包含 $using ,就像我对其他一些变量所做的那样,我会收到错误消息:

PowerShell DSC resource MSFT_ScriptResource failed to execute Set-TargetResource functionality with error message: Exception calling "Deserialize" with "1" argument(s): "The system cannot find the path specified.



我不确定我可以从这里去哪里。任何帮助,将不胜感激。谢谢。

最佳答案

我认为不可能在 Script block 中传递 SecureString 。

它由仅存在于本地 PC 上的 key 加密。

PS C:\> [System.Management.Automation.PSSerializer]::Deserialize('<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
>>   <Obj RefId="0">
>>     <TN RefId="0">
>>       <T>System.Management.Automation.PSCredential</T>
>>       <T>System.Object</T>
>>     </TN>
>>     <ToString>System.Management.Automation.PSCredential</ToString>
>>     <Props>
>>       <S N="UserName">Hey</S>
>>       <SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb0100000034646a6e6b53d244b223386a302a6fe700000000020000000000106600000001000020000000db75ebc7ae7b02d84ef6cb1161559006bdd81a84ccd5d152f3a6fdfdcf102165000000000e8000000002000020000000f0c4f2676ae5a65d2823ec8d73c352c79a97d7fd3971fd64c084d90c6c94ff7c20000000476fd1bd7f1842fdfb2e2f2fc4fd17ee0d7b41fefb39cda407bd2a6176e7b40e40000000575dac900276dcc550f09fe48b341885431dd8d287a6073ccbbfbc89e2ff8ee9e3158a8d75a52332ab2a60126cbc69232c6d9109d1db17e28535726b5e1ec2b3</SS>
>>     </Props>
>>   </Obj>
>> </Objs>')

UserName                     Password
--------                     --------
Hey      System.Security.SecureString
[WIN-U42BH7N5O4B]: PS C:\> [System.Management.Automation.PSSerializer]::Deserialize('<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
>>   <Obj RefId="0">
>>     <TN RefId="0">
>>       <T>System.Management.Automation.PSCredential</T>
>>       <T>System.Object</T>
>>     </TN>
>>     <ToString>System.Management.Automation.PSCredential</ToString>
>>     <Props>
>>       <S N="UserName">Hey</S>
>>       <SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb0100000034646a6e6b53d244b223386a302a6fe700000000020000000000106600000001000020000000db75ebc7ae7b02d84ef6cb1161559006bdd81a84ccd5d152f3a6fdfdcf102165000000000e8000000002000020000000f0c4f2676ae5a65d2823ec8d73c352c79a97d7fd3971fd64c084d90c6c94ff7c20000000476fd1bd7f1842fdfb2e2f2fc4fd17ee0d7b41fefb39cda407bd2a6176e7b40e40000000575dac900276dcc550f09fe48b341885431dd8d287a6073ccbbfbc89e2ff8ee9e3158a8d75a52332ab2a60126cbc69232c6d9109d1db17e28535726b5e1ec2b3</SS>
>>     </Props>
>>   </Obj>
>> </Objs>')
Exception calling "Deserialize" with "1" argument(s): "Key not valid for use in specified state.
"
At line:1 char:1
+ [System.Management.Automation.PSSerializer]::Deserialize('<Objs Versi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CryptographicException

使用Cryptographic Message Syntax加密字符串。
Configuration WebSitePublishConfig
{
    param
    (
        [Parameter(Mandatory=$true)]
        [PSCredential] $Credential,
        [Parameter(Mandatory=$true)]
        [string] $CertificateFile
    )

    Import-DscResource -ModuleName PSDesiredStateConfiguration

    $UserName = $Credential.UserName
    $EncryptedPassword = $Credential.GetNetworkCredential().Password | Protect-CmsMessage -To $CertificateFile

    Script MyScript
    {
        SetScript = `
            {
                # $using:UserName
                $password = Unprotect-CmsMessage -Content $using:EncryptedPassword
            }
    }
}

如果您不关心安全性,请以纯文本形式传递密码:
$UserName = $Credential.UserName
$PasswordPlain = $Credential.GetNetworkCredential().Password

Script MyScript
{
    SetScript = `
        {
            # $using.UserName
            # $using:PasswordPlain
        }
}

关于powershell - 将 SecureString 变量传递给只读域 Controller 的 DSC 配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44585764/

相关文章:

Powershell DSC - 不支持缓冲区。检查缓冲区的编码和长度

encoding - Powershell:设置获取内容管道的编码

sql-server-2008 - SQL Server SMO连接超时不起作用

syntax - 在powershell中括号还有其他用途吗?

powershell - 如何忽略警告错误?

azure - 为什么我的 powershell DSC 失败并显示消息 "An item with the same key has already been added"

powershell - 适用于 Azure Arm 模板的 Bootstrap DSC 扩展

powershell - 如何应用多个DSC配置?

powershell - 如何强制函数返回单个元素数组而不是包含的对象?

windows - 如何使用 Azure 中的所需状态配置 (DSC) 进行 Windows VM 的代理设置?