使用PowerShell将证书导入组策略存储

使用PowerShell将证书导入组策略存储,powershell,import,certificate,pfx,group-policy,Powershell,Import,Certificate,Pfx,Group Policy,我正在构建ARM模板以在Azure中设置测试环境。我正在使用DSC设置不同的机器。我想自动化的一件事是将证书导入组策略。您可以在域控制器(Active Directory服务器)上手动执行此操作: 组策略管理->林:mydomain.net->域->mydomain.net->组策略对象->默认域策略 右键单击->编辑 默认域策略->计算机配置->策略->Windows设置->安全设置->公钥策略->受信任的根证书颁发机构 右键单击->导入 为了完成这项任务,我已经尝试了导入PfxCerti

我正在构建ARM模板以在Azure中设置测试环境。我正在使用DSC设置不同的机器。我想自动化的一件事是将证书导入组策略。您可以在域控制器(Active Directory服务器)上手动执行此操作:

  • 组策略管理->林:mydomain.net->域->mydomain.net->组策略对象->默认域策略
  • 右键单击->编辑
  • 默认域策略->计算机配置->策略->Windows设置->安全设置->公钥策略->受信任的根证书颁发机构
  • 右键单击->导入
为了完成这项任务,我已经尝试了导入PfxCertificate、CertUtil.exe和.NET C#,但没有成功。我所测试的你可以在下面看到,我对我的想法发表了一些评论

有人能帮我吗?我该怎么做?

首先,我们创建一个证书并将其导出,最后删除它(我们保留导出的证书):

列出证书存储

foreach($item in Get-ChildItem "CERT:\")
{
    Write-Host " - CERT:\$($item.Location)\";

    foreach($store in $item.StoreNames.GetEnumerator())
    {
        Write-Host "   - CERT:\$($item.Location)\$($store.Name)";
    }
}
PowerShell–导入PfxCertificate

$certificateStoreLocation = "CERT:\LocalMachine\Root";
$password = ConvertTo-SecureString -String "P@ssword12" -Force -AsPlainText;

Import-PfxCertificate -CertStoreLocation $certificateStoreLocation -FilePath "C:\Data\Certificates\Test-Certificate.pfx" -Password $password;

Get-ChildItem $certificateStoreLocation;

# Now you can find the certificate in the MMC Certificate Snapin:
# [Console Root\Certificates (Local Computer)\Trusted Root Certification Authorities\Certificates]

# Now you can find the certificate in the registry.
# Get-ChildItem "REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\";

# I want to put the certificate here:
# Get-ChildItem "REGISTRY::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\SystemCertificates\Root\Certificates\";
PowerShell–CertUtil

CertUtil -p "P@ssword12" -ImportPfx "Root" "C:\Data\Certificates\Test-Certificate.pfx";

Get-ChildItem "CERT:\LocalMachine\Root";

CertUtil -p "P@ssword12" -ImportPfx -GroupPolicy "Root" "C:\Data\Certificates\Test-Certificate.pfx"; # No error but the same result as CertUtil -p "P@ssword12" -ImportPfx "Root" "C:\Data\Certificates\Test-Certificate.pfx".
.NET C#

我想象的解决方案

我认为这是一个可能的解决方案:

  • 将证书导入“CERT:\LocalMachine\Root”
  • 将注册表项“HKLM:\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\THUMBPRINT”移动到“HKLM:\SOFTWARE\Policys\Microsoft\SystemCertificates\Root\Certificates\THUMBPRINT”
  • 重新启动机器
  • 注册表项正确,但localmachine根证书仍在证书mmc管理单元中,并且在组策略管理控制台中找不到根证书

    $certificateRegistryKeyPathPrefix = "HKLM:\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\";
    $certificateStoreLocation = "CERT:\LocalMachine\Root";
    $password = ConvertTo-SecureString -String "P@ssword12" -Force -AsPlainText;
    $pfxCertificatePath = "C:\Data\Certificates\Test-Certificate.pfx";
    $policyCertificateRegistryKeyPathPrefix = "HKLM:\Software\Policies\Microsoft\SystemCertificates\Root\Certificates\";
    
    # Get the thumbprint from the pfx-file so we can check if it's already in the registry.
    $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2;
    $certificate.Import($pfxCertificatePath, $password, "DefaultKeySet");
    
    $policyCertificateRegistryKeyPath = "$($policyCertificateRegistryKeyPathPrefix)$($certificate.Thumbprint)";
    
    $policyCertificateRegistryKey = Get-Item -ErrorAction SilentlyContinue -Path $policyCertificateRegistryKeyPath;
    
    if(!$policyCertificateRegistryKey)
    {
        $certificateRegistryKeyPath = "$($certificateRegistryKeyPathPrefix)$($certificate.Thumbprint)";
    
        $certificateRegistryKey = Get-Item -ErrorAction SilentlyContinue -Path $certificateRegistryKeyPath;
    
        if(!$certificateRegistryKey)
        {
            $certificate = Import-PfxCertificate -CertStoreLocation $certificateStoreLocation -FilePath $pfxCertificatePath -Password $password;
    
            $certificateRegistryKey = Get-Item -Path $certificateRegistryKeyPath;
        }
    
        Move-Item -Destination $policyCertificateRegistryKeyPath -Path $certificateRegistryKeyPath;
    
        # And then we need to reboot the machine.
    }
    

    不要试图直接修改“策略”路径下的注册表,而是创建或修改“registry.pol”文件来填充它

    您可以使用PowerShell Gallery中的“PolicyFileEditor”模块来执行此操作,但最简单的方法是使用本机GroupPolicy模块创建并设置Registry.pol文件作为域GPO的一部分,这也会将证书推出到成员服务器

    在域控制器上,导入/创建证书,使其具有存储在注册表中的blob值,创建GPO,然后运行以下操作来配置GPO(此处名为“DistributerOtCerts”):


    然后你只需要用“New GPLink”将GPO链接到生产环境中。

    这将有助于显示你尝试运行以及收到了哪些错误。BenH:所以,我编辑了我的帖子。现在我再解释一下我的测试。@HansKindberg你解决了这个问题吗?@Brooke不,我没有。非常感谢你,Brian。我稍后会试试这个。我会回来的。
    using(var certificate = new X509Certificate2(@"C:\Data\Certificates\Test-Certificate.pfx", "P@ssword12"))
    {
        // We only have StoreLocation.CurrentUser and StoreLocation.LocalMachine.
        // Can I use System.Management.Automation.Security.NativeMethods+CertStoreFlags.CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
        // somehow to create/open a store by calling new X509Store(IntPtr storeHandle).
    
        using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
        {
            store.Open(OpenFlags.ReadWrite);
            store.Add(certificate);
        }
    }
    
    $certificateRegistryKeyPathPrefix = "HKLM:\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\";
    $certificateStoreLocation = "CERT:\LocalMachine\Root";
    $password = ConvertTo-SecureString -String "P@ssword12" -Force -AsPlainText;
    $pfxCertificatePath = "C:\Data\Certificates\Test-Certificate.pfx";
    $policyCertificateRegistryKeyPathPrefix = "HKLM:\Software\Policies\Microsoft\SystemCertificates\Root\Certificates\";
    
    # Get the thumbprint from the pfx-file so we can check if it's already in the registry.
    $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2;
    $certificate.Import($pfxCertificatePath, $password, "DefaultKeySet");
    
    $policyCertificateRegistryKeyPath = "$($policyCertificateRegistryKeyPathPrefix)$($certificate.Thumbprint)";
    
    $policyCertificateRegistryKey = Get-Item -ErrorAction SilentlyContinue -Path $policyCertificateRegistryKeyPath;
    
    if(!$policyCertificateRegistryKey)
    {
        $certificateRegistryKeyPath = "$($certificateRegistryKeyPathPrefix)$($certificate.Thumbprint)";
    
        $certificateRegistryKey = Get-Item -ErrorAction SilentlyContinue -Path $certificateRegistryKeyPath;
    
        if(!$certificateRegistryKey)
        {
            $certificate = Import-PfxCertificate -CertStoreLocation $certificateStoreLocation -FilePath $pfxCertificatePath -Password $password;
    
            $certificateRegistryKey = Get-Item -Path $certificateRegistryKeyPath;
        }
    
        Move-Item -Destination $policyCertificateRegistryKeyPath -Path $certificateRegistryKeyPath;
    
        # And then we need to reboot the machine.
    }
    
    $certsGpoName = 'DistributeRootCerts'
    
    $certThumbprint = '3A8E60952E2CDB7A31713258468A8F0C7FB3C6F6'
    
    $certRegistryKeyPath = 'HKLM:\SOFTWARE\Microsoft\SystemCertificates\MY\Certificates\{0}' -f $certThumbprint
    
    $certBlob = Get-ItemProperty -Path $certRegistryKeyPath -Name 'Blob' | Select -Expand 'Blob'
    
    $certPoliciesRegistryKey = 'HKLM\SOFTWARE\Policies\Microsoft\SystemCertificates\Root\Certificates\{0}' -f $certThumbprint
    
    $null = Set-GPRegistryValue -Name $certsGpoName -Key $certPoliciesRegistryKey -ValueName 'Blob' -Type Binary -Value $certBlob