【问题标题】:How to Grant permission to user on Certificate private key using powershell?如何使用 powershell 授予用户对证书私钥的权限?
【发布时间】:2017-02-24 02:34:39
【问题描述】:

证书已安装在机器上。现在我想将证书的 PrivateKey 的读取权限授予应用程序用户。

【问题讨论】:

    标签: powershell permissions certificate private-key applicationpoolidentity


    【解决方案1】:

    这就是答案。

    创建了一个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 之间有一个空格。

    【讨论】:

    • 非常感谢,很棒的脚本。如果有人需要给予完全控制权限,那真的是 - fullcontrol
    • 我有一台装有 PowerShell V2 的旧 Win2008 机器。我不得不在第 8 行(第一条语句)中使用 $certificateInstalled = Get-ChildItem cert:$certStoreLocation | Where {$_.thumbprint -eq $certThumbprint}
    • 这不再有效。 $_.privatekey 现在返回 null。
    • 感谢这真的节省了我的一周,我将这个答案与stackoverflow.com/questions/7334216/… 结合起来,并且能够设置应用程序池来读取证书。
    【解决方案2】:

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

    【讨论】:

    • 是的。接受的答案对我有用,但我运行它已经有一段时间了。有同样的问题,$_.privatekey 返回 null。谢谢你。这似乎已经解决了。
    • 这似乎也不能正常工作了。 $rsaCert 和 $fileName 变量似乎不包含正确的信息,提取了一个 UniqueName 值,该值根本不以 $path 变量可以使用的方式存在。
    【解决方案3】:

    作为上述脚本的替代。您可以使用 PowerShell 模块。我自己没有尝试过,但模块看起来不错。 http://get-carbon.org/index.html

    这里是设置权限的命令 http://get-carbon.org/Grant-Permission.html

    【讨论】:

      【解决方案4】:

      您可以使用证书配置工具 WinHttpCertCfg.exe 链接:https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttpcertcfg-exe--a-certificate-configuration-tool

      一些代码示例:

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

      【讨论】:

      • 花时间向 Michael Armitage 学习 Powershell 版本。
      • @DonaldAirey 为什么?如果您拥有该工具并且它支持您的方案,这会简单得多。
      • 1.因为 Powershell 是一种通用语言。 2. Powershell 将在 WinHttpCertCfg.exe 退役后很久。 3. 您的解决方案涉及设置路径以包含 WinHttpCertCfg.exe 所在的目录,并可能下载它。我不知道这个工具在我的机器上的什么位置,也没有时间去找。
      • $_.privatekey为空的证书上设置权限,这将抛出访问被拒绝的错误
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 2020-06-17
        • 2013-06-15
        • 2013-03-07
        • 2011-06-24
        • 2010-09-27
        • 1970-01-01
        • 1970-01-01
        • 2018-10-05
        • 1970-01-01
        相关资源
        最近更新 更多