Как предоставить разрешение пользователю на закрытый ключ сертификата с помощью powershell?

Сертификат уже установлен на машине. Теперь я хочу дать разрешение на чтение PrivateKey сертификата пользователю приложения.


person Balpreet Patil    schedule 14.10.2016    source источник


Ответы (5)


Вот ответ.

Создан файл сценария 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 AppPool\AppPoolNameHere'.

Примечание. Вам нужно будет использовать ' ', так как между IIS и AppPool есть пробел.

person Balpreet Patil    schedule 14.10.2016
comment
большое спасибо, отличный сценарий. если кому-то нужно дать разрешение на полный доступ, то это действительно - полный контроль - person iBobb; 22.11.2017
comment
У меня есть старая машина Win2008 с PowerShell V2. Мне пришлось использовать $certificateInstalled = Get-ChildItem cert:$certStoreLocation | Where {$_.thumbprint -eq $certThumbprint} в строке 8 (первый оператор) - person Tony; 09.05.2018
comment
Это больше не работает. $_.privatekey теперь возвращает null. - person Quarkly; 02.04.2019
comment
Спасибо, это действительно спасло мою неделю, я объединил это с этим ответом /questions/7334216/ и смог настроить пул приложений для чтения сертификата. - person Juan; 18.05.2020

Приведенный выше ответ не сработал для меня, так как $_.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
}
person Michael Armitage    schedule 17.09.2018
comment
да. Принятый ответ работал у меня, но прошло некоторое время с тех пор, как я его запустил. Была та же проблема, $_.privatekey возвращал значение null. Спасибо. Кажется, это исправлено. - person Quarkly; 02.04.2019

В качестве альтернативы приведенному выше сценарию. Вы можете использовать модуль PowerShell. Сам не пробовал, но модуль выглядит хорошо. http://get-carbon.org/index.html

Вот команда для установки разрешений http://get-carbon.org/Grant-Permission.html

person Balpreet Patil    schedule 14.10.2016

Вы можете использовать WinHttpCertCfg.exe, средство настройки сертификата. Ссылка: https://docs.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]"*
person Barreto    schedule 26.09.2018
comment
Потратьте время, чтобы изучить версию Powershell от Майкла Армитиджа. - person Quarkly; 02.04.2019
comment
@DonaldAirey, почему? Это намного проще, если у вас есть инструмент, и он поддерживает ваш сценарий. - person Ohad Schneider; 16.04.2019
comment
1. Потому что Powershell — это язык общего назначения. 2. Powershell будет существовать еще долго после того, как WinHttpCertCfg.exe будет упразднен. 3. Ваше решение включает в себя установку пути для включения каталога, в котором находится WinHttpCertCfg.exe, и, возможно, его загрузку. Я не знаю, где этот инструмент находится на моей машине, и у меня нет времени его искать. - person Quarkly; 16.04.2019
comment
установка разрешения на сертификат, где $_.privatekey равно нулю, это вызовет ошибку отказано в доступе - person Ankit Patel; 23.06.2020

Добавление сценария Майкла Армитиджа. Это будет работать как для случаев, когда значение 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()
        }
}
person Ankit Patel    schedule 23.06.2020