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

dfddblmv  于 12个月前  发布在  Shell
关注(0)|答案(7)|浏览(135)

证书已经安装在计算机上。现在我想给予对应用程序用户证书私钥的读取权限。

ttisahbt

ttisahbt1#

这就是答案。
已创建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

字符串
现在将其作为部署的一部分运行。在powershell控制台窗口中运行上述脚本的示例。

C:\>.\AddUserToCertificate.ps1 -userName testuser1 -permission read -certStoreLocation \LocalMachine\My -certThumbprint 1fb7603985a8a11d3e85abee194697e9784a253


此示例给予testuser1授予对安装在**\LocalMachine\My中且具有指纹证书的读取权限1fb7603985a8a11d3e85abee194697e9784a253**
如果您使用的是ApplicationPoolIdentity,则您的用户名将为**'IIS应用池\此处的应用池名称'**

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

2ic8powd

2ic8powd2#

接受的答案对我不起作用,因为$_.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
}

字符串

7lrncoxx

7lrncoxx3#

几周前,我注意到 * 某些 * 发生了变化(我怀疑是Windows更新),并破坏了某些证书使用Michael Armitage脚本中引用的CspKeyContainerInfo.UniqueKeyContainerName属性的能力。一些侦查发现,Windows决定开始使用CNG而不是Crypto Service Provider来保护密钥。以下脚本修复了我的问题,应该正确支持CNG vs 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;

字符串
当然,你会想调整/增强它以满足你的特定需求。

t5fffqht

t5fffqht4#

添加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()
        }
}

字符串

a5g8bdjr

a5g8bdjr5#

作为上述脚本的替代方案。您可以使用PowerShell模块。我自己没有尝试过,但模块看起来不错。http://get-carbon.org/index.html
下面是设置权限http://get-carbon.org/Grant-Permission.html的命令

xwmevbvl

xwmevbvl6#

您可以使用WinHttpCertCfg.exe,一个证书配置工具链接:https://learn.microsoft.com/en-us/windows/desktop/winhttp/winhttpcertcfg-exe--a-certificate-configuration-tool
代码示例:

Set privatekeyAcces to [email protected]
*.\WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s *.d365.mydomain.com  -a "[email protected]"*

字符串

b5buobof

b5buobof7#

最近来到这篇文章,想扔在一个简化的代码,我使用。
它是从上面的脚本中经过一些简化后得到的(在我看来)。
我用它来设置我的Let's Encrypt证书的权限,当一个新的证书每45天左右生成一次时。因此,在主题中使用相同的名称并选择最新的证书。
它接受证书的部分或全部主题,然后是要添加的用户名和可选的FullControl。默认情况下,如果没有指定任何内容,则只读取密钥。它还支持在运行前使用-WhatIf。
PS.使用ChatGPT作为初始代码,并通过FleshCPU测试🧠

function Set-CertificatePrivateKeyPermission {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
    [string]$certSubjectPart,
    [string]$adUsername,
    [ValidateSet('Read','FullControl')]
    [string]$permissionType = 'Read'
)

try {
    # Find the newest certificate that matches the subject part
    $newestCert = Get-ChildItem -Path Cert:\LocalMachine\My | 
                  Where-Object { $_.Subject -like "*$certSubjectPart*" } | 
                  Sort-Object NotBefore -Descending | 
                  Select-Object -First 1

    if ($newestCert -eq $null) {
        Write-Error "No certificate found with subject part '$certSubjectPart'"
        return
    }

    # Define the private key path
    $root = "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys"
    $keyname = $newestCert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
    $path = [IO.Path]::Combine($root, $keyname)

    if ([IO.File]::Exists($path)) {
        if ($PSCmdlet.ShouldProcess($path, "Add $permissionType permission for $adUsername")) {
            # Creating the access rule for the user
            $rule = new-object Security.AccessControl.FileSystemAccessRule $adUsername, $permissionType, 'Allow'
            $acl = Get-Acl -Path $path
            $acl.AddAccessRule($rule)
            Set-Acl -Path $path -AclObject $acl
            Write-Host "Permissions would be updated for certificate with thumbprint: $($newestCert.Thumbprint)"
        }
    } else {
        Write-Error "Private key file not found."
    }
} catch {
    Write-Host "Caught an exception:" -ForegroundColor Red
    Write-Host "$($_.Exception)" -ForegroundColor Red
    exit 1;
}

字符串
}

相关问题