将SecureString变量传递给只读域控制器的DSC配置

时间:2017-06-16 09:31:24

标签: powershell dsc

我正在尝试创建一个可以在作为只读域控制器的计算机上本地运行的DSC脚本。 xActiveDirectory DSC资源不提供创建RODC所以我必须使用脚本资源并使用Install-ADDSDomainController。

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

我的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资源MSFT_ScriptResource无法执行   Set-TargetResource功能,错误消息:无法绑定   参数'SafeModeAdministratorPassword'到目标。例外   设置“SafeModeAdministratorPassword”:   “SafeModeAdministratorPassword不能为空。”

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

如果我更改 -SafeModeAdministratorPassword:$ safemodepassword 以包含 $ using ,因为我有一些其他变量,我收到错误:

  

PowerShell DSC资源MSFT_ScriptResource无法执行   具有错误消息的Set-TargetResource功能:异常调用   用“1”参数“反序列化”:“系统无法找到路径   指定。

我不知道我可以从这里走到哪里。任何帮助,将不胜感激。感谢。

1 个答案:

答案 0 :(得分:0)

我认为在Script块中传递SecureString是不可能的。

它仅通过密钥加密,仅存在于本地PC上。

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
        }
}