证书已安装在机器上。现在我想授予应用程序用户对证书的私钥的读取权限。
这里是答案。
创建了一个名为AddUserToCertificate.ps1的PowerShell脚本文件。
以下是脚本文件的内容。
param(
[string]$userName,
[string]$permission,
[string]$certStoreLocation,
[string]$certThumbprint
);
# check if certificate is already installed
$certificateInstalled = Get-ChildItem cert:$certStoreLocation | Where thumbprint -eq $certThumbprint
# download & install only if certificate is not already installed on machine
if ($certificateInstalled -eq $null)
{
$message="Certificate with thumbprint:"+$certThumbprint+" does not exist at "+$certStoreLocation
Write-Host $message -ForegroundColor Red
exit 1;
}else
{
try
{
$rule = new-object security.accesscontrol.filesystemaccessrule $userName, $permission, allow
$root = "c:\programdata\microsoft\crypto\rsa\machinekeys"
$l = ls Cert:$certStoreLocation
$l = $l |? {$_.thumbprint -like $certThumbprint}
$l |%{
$keyname = $_.privatekey.cspkeycontainerinfo.uniquekeycontainername
$p = [io.path]::combine($root, $keyname)
if ([io.file]::exists($p))
{
$acl = get-acl -path $p
$acl.addaccessrule($rule)
echo $p
set-acl $p $acl
}
}
}
catch
{
Write-Host "Caught an exception:" -ForegroundColor Red
Write-Host "$($_.Exception)" -ForegroundColor Red
exit 1;
}
}
exit $LASTEXITCODE
现在将其作为部署的一部分运行。以下是在 PowerShell 控制台窗口中运行上述脚本的示例。
现在将其作为部署的一部分运行。在 PowerShell 控制台窗口中运行上述脚本的示例。
C:\>.\AddUserToCertificate.ps1 -userName testuser1 -permission read -certStoreLocation \LocalMachine\My -certThumbprint 1fb7603985a8a11d3e85abee194697e9784a253
此示例将读取权限授予在\LocalMachine\My中安装了指纹为1fb7603985a8a11d3e85abee194697e9784a253的证书的用户testuser1
如果您正在使用ApplicationPoolIdentity,则用户名将为'IIS AppPool\AppPoolNameHere'
注意:由于IIS和AppPool之间有一个空格,因此您需要使用' '
对我来说,被接受的答案并不起作用,因为$_.privatekey
返回null。我成功获取了私钥,并按以下方式为我的应用程序池分配了“读取”权限:
param (
[string]$certStorePath = "Cert:\LocalMachine\My",
[string]$AppPoolName,
[string]$certThumbprint
)
Import-Module WebAdministration
$certificate = Get-ChildItem $certStorePath | Where thumbprint -eq $certThumbprint
if ($certificate -eq $null)
{
$message="Certificate with thumbprint:"+$certThumbprint+" does not exist at "+$certStorePath
Write-Host $message -ForegroundColor Red
exit 1;
}else
{
$rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate)
$fileName = $rsaCert.key.UniqueName
$path = "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys\$fileName"
$permissions = Get-Acl -Path $path
$access_rule = New-Object System.Security.AccessControl.FileSystemAccessRule("IIS AppPool\$AppPoolName", 'Read', 'None', 'None', 'Allow')
$permissions.AddAccessRule($access_rule)
Set-Acl -Path $path -AclObject $permissions
}
CspKeyContainerInfo.UniqueKeyContainerName
属性的能力。调查发现Windows决定开始使用CNG而不是Crypto服务提供程序来保护密钥。以下脚本解决了我的问题,并应正确支持CNG与CSP使用情况:$serviceUser = "DOMAIN\Service User"
$certificate = Get-ChildItem Cert:\LocalMachine\My | Where-Object Thumbprint -eq "certificatethumbprint"
$privateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate)
$containerName = ""
if ($privateKey.GetType().Name -ieq "RSACng")
{
$containerName = $privateKey.Key.UniqueName
}
else
{
$containerName = $privateKey.CspKeyContainerInfo.UniqueKeyContainerName
}
$keyFullPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\" + $containerName;
if (-Not (Test-Path -Path $keyFullPath -PathType Leaf))
{
throw "Unable to get the private key container to set permissions."
}
# Get the current ACL of the private key
$acl = (Get-Item $keyFullPath).GetAccessControl()
# Add the new ACE to the ACL of the private key
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($serviceUser, "Read", "Allow")
$acl.AddAccessRule($accessRule);
# Write back the new ACL
Set-Acl -Path $keyFullPath -AclObject $acl;
当然,您肯定希望根据自己的具体需求进行适应和改进。
$keyFullPath = Get-ChildItem -Path $env:AllUsersProfile\Microsoft\Crypto -Recurse -Filter $containerName | Select -Expand FullName
这样的事情。 - TheMadTechnician$keyFullPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\" + $containerName;
行完全相同的结果。但是,在我的Win2k19服务器机器上使用PS 7.2.4时,没有可用的.GetAccessControl()
方法:InvalidOperation: Method invocation failed because [System.IO.FileInfo] does not contain a method named 'GetAccessControl'.
- 有什么帮助吗? - Yoda在Michael Armitage脚本的基础上,这将适用于PrivateKey值存在的情况,也适用于它为空的情况。
function setCertificatePermission {
param($accountName, $certificate)
if([string]::IsNullOrEmpty($certificate.PrivateKey))
{
$rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate)
$fileName = $rsaCert.key.UniqueName
$path = "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys\$fileName"
$permissions = Get-Acl -Path $path
$access_rule = New-Object System.Security.AccessControl.FileSystemAccessRule($accountName, 'FullControl', 'None', 'None', 'Allow')
$permissions.AddAccessRule($access_rule)
Set-Acl -Path $path -AclObject $permissions
} else{
$user = New-Object System.Security.Principal.NTAccount($accountName)
$accessRule = New-Object System.Security.AccessControl.CryptoKeyAccessRule($user, 'FullControl', 'Allow')
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine")
$store.Open("ReadWrite")
$rwCert = $store.Certificates | where {$_.Thumbprint -eq $certificate.Thumbprint}
$csp = New-Object System.Security.Cryptography.CspParameters($rwCert.PrivateKey.CspKeyContainerInfo.ProviderType, $rwCert.PrivateKey.CspKeyContainerInfo.ProviderName, $rwCert.PrivateKey.CspKeyContainerInfo.KeyContainerName)
$csp.Flags = "UseExistingKey","UseMachineKeyStore"
$csp.CryptoKeySecurity = $rwCert.PrivateKey.CspKeyContainerInfo.CryptoKeySecurity
$csp.KeyNumber = $rwCert.PrivateKey.CspKeyContainerInfo.KeyNumber
$csp.CryptoKeySecurity.AddAccessRule($AccessRule)
$rsa2 = New-Object System.Security.Cryptography.RSACryptoServiceProvider($csp)
$store.close()
}
}
Set privatekeyAcces to Svc-LocalAgent$@mydomain.local
*.\WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s *.d365.mydomain.com -a "Svc-LocalAgent$@mydomain.com"*
$_.privatekey
为空的情况下设置证书权限,这将抛出 访问被拒绝 的错误。 - Ankit Patel
$certificateInstalled = Get-ChildItem cert:$certStoreLocation | Where {$_.thumbprint -eq $certThumbprint}
。 - Tony