programing

powershell을 사용하여 인증서 개인 키의 사용자에게 권한을 부여하는 방법은 무엇입니까?

powerit 2023. 9. 5. 20:51
반응형

powershell을 사용하여 인증서 개인 키의 사용자에게 권한을 부여하는 방법은 무엇입니까?

인증서가 컴퓨터에 이미 설치되어 있습니다.이제 응용 프로그램 사용자에게 인증서의 개인 키에 대한 읽기 권한을 부여합니다.

여기에 정답이 있다.

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

이제 배포의 일부로 실행합니다.파워셸 콘솔 창에서 위 스크립트를 실행하는 예입니다.

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

이 예제는 \LocalMachine\My에 설치되고 지문이 1fb7603985a8a11d3e85abee194697e9784a253인 인증서에 대해 사용자 testuser1에게 읽기 권한을 부여합니다.

ApplicationPoolIdentity를 사용하는 경우 사용자 이름은 '입니다.IIS AppPool\AppPoolName여기.

참고: IIS와 AppPool 사이에 공백이 있으므로 '를 사용해야 합니다.

승인된 답변은 저에게 효과가 없었습니다.$_.privatekeynull을 반환했습니다.다음과 같이 개인 키에 액세스하고 애플리케이션 풀에 대해 '읽기' 권한을 할당할 수 있었습니다.

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
}

몇 주 전에 무언가가 변경되었고(Windows 업데이트가 의심됨) 일부 인증서의 사용 기능이 손상되었다는 사실을 알게 되었습니다.CspKeyContainerInfo.UniqueKeyContainerName마이클 아미티지의 대본에 언급된 재산.일부 조사 결과 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;

물론 특정 요구사항을 충족하기 위해 이를 조정/강화할 수 있습니다.

Michael Armitage 스크립트를 추가하면 개인 키 값이 있는 경우와 비어 있는 경우 모두에 사용할 수 있습니다.

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

위 스크립트의 대안으로 사용됩니다.PowerShell 모듈을 사용할 수 있습니다.제가 직접 해보지는 않았지만 모듈은 좋아 보입니다.http://get-carbon.org/index.html

다음은 권한을 설정하는 명령입니다. http://get-carbon.org/Grant-Permission.html

인증서 구성 도구 링크: https://learn.microsoft.com/en-us/windows/desktop/winhttp/winhttpcertcfg-exe--a-certificate-configuration-tool 에서 WinHttpCertCfg.exe를 사용할 수 있습니다.

일부 코드 예:

Set privatekeyAcces to Svc-LocalAgent$@mydomain.local
*.\WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s *.d365.mydomain.com  -a "Svc-LocalAgent$@mydomain.com"*

언급URL : https://stackoverflow.com/questions/40046916/how-to-grant-permission-to-user-on-certificate-private-key-using-powershell

반응형