现在,我正在执行以下操作以从 CEP 服务器请求证书:
- 打开 gpedit.msc
- 在计算机配置 > Windows 设置 > 安全设置 > 公钥策略下,双击“证书服务客户端 - 证书注册策略”
- 使能够
- 输入 CEP URI
- 切换到用户名/密码验证
- 验证(提供凭证)
- 打开 MMC,然后导入证书管理单元
- 转至证书 > 个人
- 右键单击 > 请求新证书
- 输入“更多信息”(CN、DNS名称等)
- 提供信用
此后,我获得了 CEP 颁发的证书;但是,手动执行此过程非常痛苦。有没有办法在 Server 2008(和 2012)中自动执行此操作?我能找到的所有信息都告诉您如何安装 CEP 服务以使服务器成为注册策略服务器(没有关于实际请求新证书或在客户端启用它的信息)。是否可以自动执行此操作?
看起来此过程在 HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Cryptography 下添加了大量数据。我可以手动添加这些数据(并伪造 GUID/ServiceID)吗?
答案1
这是我在 Windows 2012 R2 及更高版本上使用的过程。所有 PowerShell 代码都是从提升的 PowerShell 提示符运行的。完全自动化留给用户作为练习。
先决条件
确保您的证书服务器上有一个模板,该模板在“主题”选项卡中选中了“在请求中提供”单选按钮。由于这不是 AD 计算机,因此证书服务器无法充分查询 Active Directory 以获取信息。
导出根
导出证书服务器上的受信任的根证书颁发机构证书,然后将该证书文件复制到目标服务器
certutil --% -ca.cert <name of certificate file>
信任根
将该证书导入到目标服务器上的受信任的根证书颁发机构
$PathToCertificate=<name of certificate file>
$RootCertificate=Get-PfxCertificate -FilePath $PathToCertificate
$AlreadyExists=Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object { $_.Thumbprint -eq $RootCertificate.Thumbprint }
if ($AlreadyExists -eq $null) { Import-Certificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath $PathToCertificate }
else { Write-Warning "Root certificate already installed" }
Active Directory 策略提供程序
确定 Active Directory 策略提供程序的 URL
# Get AD Configuration Context
$RootDSE=[System.DirectoryServices.DirectoryEntry]::new("LDAP://RootDSE")
$ConfigContext="CN=Enrollment Services,CN=Public Key Services,CN=Services,"+$RootDSE.configurationNamingContext
# Get name of Enterprise Root Certificate Autority server
$Server=Get-ADObject -SearchBase $ConfigContext -Filter "*"
if ($Server.Count -eq 1) { throw "No Enterprise Root Certificate Autority server exists" }
else { $Server=$Server[1].Name }
# Get Enrollment URL
$ConfigContext="CN=$Server,"+$ConfigContext
$EnrollmentURL=(Get-ADObject -SearchBase $ConfigContext -Filter "*" -Properties "msPKI-Enrollment-Servers" | Select-Object -ExpandProperty "msPKI-Enrollment-Servers").Split("`n") | Where-Object { $_ -like "http*" }
if ($EnrollmentURL -eq $null) { $EnrollmentURL="" }
# Get AD Enrollment Policy URL
$Server=$Server+$RootDSE.configurationNamingContext.Value.Replace("CN=Configuration","").Replace(",DC=",".")
$WMI=Get-WmiObject -ComputerName $Server -Namespace "root\WebAdministration" -Class Application | Where-Object { $_.Path -eq "/ADPolicyProvider_CEP_UsernamePassword" }
if ($WMI -ne $null) { $PolicyURL="https://"+$Server+$WMI.Path+"/service.svc/CEP" }
else { $PolicyURL="" }
Write-Output "Enrollment URL = $EnrollmentURL"
Write-Output "Policy URL = $PolicyURL"
招生政策
将注册策略添加到目标服务器(这仅适用于 Windows 2012 及更高版本。有关 GUI 说明,请参阅下文)。确保在创建非域模板后添加策略,否则它将不会出现,因为策略不会刷新。
$User="<your domain name>\<your domain user name>"
$Pass="<Your domain password>"
$SecPass=ConvertTo-SecureString -String $Pass -AsPlainText -Force
$Cred=[System.Management.Automation.PSCredential]::new($User,$SecPass)
Add-CertificateEnrollmentPolicyServer -Url $PolicyURL -context Machine -NoClobber -AutoEnrollmentEnabled -Credential $Cred
获取证书
您现在应该能够使用所需的模板注册证书
$DNS="<FQDN of your server>"
$URL=Get-CertificateEnrollmentPolicyServer -Scope All -Context Machine | Select-Object -ExpandProperty Url | Select-Object -ExpandProperty AbsoluteUri
$Enrollment=Get-Certificate -Url $URL -Template "<Template name (not display name)>" -SubjectName "CN=$DNS" -DnsName $DNS -Credential $Cred -CertStoreLocation cert:\LocalMachine\My
$Enrollment.Certificate.FriendlyName=$DNS
Windows 2012 R2 之前的注册政策
- 打开证书 MMC
- 深入到个人证书存储
- 右键单击“证书”,然后选择所有任务/高级操作/管理
- 上下文菜单中的注册政策
- 点击“添加”按钮
- 粘贴注册政策的 URL
- 选择用户名/密码作为身份验证类型
- 单击“验证服务器”按钮并输入您的域凭据,包括域
- 假设您已成功验证,请点击“添加”按钮
- 选择注册策略并点击“属性”按钮
- 确保选中“启用自动注册和续订”框
- 我从来没有检查过“注册时需要强验证”,所以我不知道它有什么作用
答案2
我假设您的证书请求是使用模板进行的。如果是这种情况,则使用 GPOPublic Key Policies/Certificate Services Client - Auto-Enrollment Settings
强制自动注册。您还需要确保模板 ACL 已Enroll
标记AutoEnroll
为域计算机或域用户(或任何 acl 对象,取决于目标受众)有一个用户配置和计算机配置策略可以利用,具体取决于您要推送的是机器证书还是用户证书。在链接和执行 GPO 后,一旦推送策略(通常约 15 分钟),注册就会开始。
答案3
我没有完整的解决方案,但是我可以提出一些建议。我的PowerShell PKI 模块从 Windows 7/Windows Server 2008 R2 开始,可以注册注册服务端点(请注意,Windows Server 2008 不支持注册服务)。以下是如何注册策略的示例:http://en-us.sysadmins.lv/Lists/Posts/Post.aspx?ID=101
关于入学。这博客文章系列可能会让您了解如何利用 CertEnroll COM 接口在 PowerShell 中执行证书注册。不幸的是,没有关于注册 Web 服务的内容,但技术是相同的。您需要从此界面开始:IX509证书请求Pkcs10V2
高血压
答案4
PowershellGet-Certificate
有一些限制。就我而言,它不支持使用计算机凭据进行注册。COMCertEnroll
库但是,确实如此。这是一个 Powershell 示例。模板名称是硬编码的;有CertEnroll
用于动态 CA/模板发现的 API(通过 Active Directory 和 LDAP),但我没有费心。我们拥有的模板需要用户提供主题和 SAN 扩展,因此此代码片段就是这样的。
# Parameters
$ServerName = "myserver.example.com"
$TemplateName = "MyTemplate"
$ce = New-Object -COM X509Enrollment.CX509Enrollment
$ce.InitializeFromTemplateName(3 <#ContextAdministratorForceMachine#>, $TemplateName)
$ce.Silent = $true
# Quirk: the real PKCS10 cert request is embedded inside a CMC one
$req = $ce.Request.GetInnerRequest(0 <#LevelInnermost#>)
# Set Subject to the server's name
# Feel free to use a more involved DN
$subj = New-Object -COM X509Enrollment.CX500DistinguishedName
$subj.Encode("CN="+$ServerName, 0 <#XCN_CERT_NAME_STR_NONE#>)
$req.Subject = $subj
# Set Alt Name to the server's name - feel free to provide more names
# In our template, that extension is absent. We don't check for existence.
$altname = New-Object -COM X509Enrollment.CAlternativeName
$altname.InitializeFromString(3 <#XCN_CERT_ALT_NAME_DNS_NAME#>, $ServerName)
$altnames = New-Object -COM X509Enrollment.CAlternativeNames
$altnames.Add($altname)
$ext = New-Object -COM X509Enrollment.CX509ExtensionAlternativeNames
$ext.InitializeEncode($altnames)
$req.X509Extensions.Add($ext)
$ce.Enroll() # It may exception or it may report an error via Status
$st = $ce.Status.Status
# 1 means success
就我们的 IT 商店而言,我无法控制模板和相关 CA。发行方的其他设置可能需要不同的请求详细信息。
库文档没有提到这一点,但那里的几乎每个接口都有相应的 coclass。ProgID 约定是 - 取接口名称,将开头的“I”替换为“C”,并以“X509Enrollment”作为前缀。因此,对于名为 的 CertEnroll 接口IFoo
,ProgID 将是X509Enrollment.CFoo
。