如何使用PowerShell为证书私钥授予用户权限?

Bal*_*til 20 permissions powershell certificate applicationpoolidentity private-key

证书已安装在计算机上.现在我想给应用程序用户提供有关证书PrivateKey的读取权限.

Bal*_*til 27

这是答案.

创建了一个powershell脚本文件AddUserToCertificate.ps1

这是脚本文件的内容.

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
Run Code Online (Sandbox Code Playgroud)

现在将其作为部署的一部分运行.在powershell控制台窗口中运行上面脚本的示例.

C:\>.\AddUserToCertificate.ps1 -userName testuser1 -permission read -certStoreLocation \LocalMachine\My -certThumbprint 1fb7603985a8a11d3e85abee194697e9784a253
Run Code Online (Sandbox Code Playgroud)

此示例为安装在\ LocalMachine\My中的用户testuser1提供读取权限,并且有拇指打印1fb7603985a8a11d3e85abee194697e9784a253

如果您使用的是ApplicationPoolIdentity,那么您的用户名将是'IIS AppPool\AppPoolNameHere'

注意:您需要使用'',因为IIS和AppPool之间有空格.

  • 这不再有效。$_.privatekey 现在返回 null。 (3认同)
  • 非常感谢,很棒的剧本。如果有人需要给予完全控制权限,那就真的 - _fullcontrol_ (2认同)

Mic*_*age 17

上面的回答对我来说不起作为$_.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
}
Run Code Online (Sandbox Code Playgroud)


小智 7

几周前,我注意到有些事情CspKeyContainerInfo.UniqueKeyContainerName发生了变化(我怀疑是 Windows 更新),并且破坏了某些证书使用 Michael Armitage 脚本中引用的属性的能力。一些调查发现,Windows 决定开始使用 CNG 而不是加密服务提供商来保护密钥。以下脚本解决了我的问题,并且应该正确支持 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;
Run Code Online (Sandbox Code Playgroud)

当然,您会希望调整/增强它以满足您的特定需求。

  • 干得好,请记住存储在 RSA\MachineKeys 文件夹中的证书越来越少,因此您最好执行类似 `$keyFullPath = Get-ChildItem -Path $env:AllUsersProfile\Microsoft\Crypto -Recurse -Filter 的操作$containerName | $containerName | 选择-展开全名` (2认同)