xCertificatePrivateKeyAccess.psm1


class AccessList
{
    [DscProperty(Mandatory)]
    [string]$Identity

    [DscProperty(Mandatory)]
    [ValidateSet("Allow","Deny")]
    [System.String]$AccessControlType

    [DscProperty(Mandatory)]
    [ValidateSet("Synchronize","GenericRead","GenericAll")]
    [System.String[]]$Rights
}
[DscResource()]
class xCertificatePrivateKeyAccess
{
    [DscProperty(Mandatory)]
    [string]$Localtion

    [DscProperty(Key)]
    [string]$Thumbprint

    [DscProperty(Mandatory)]
    [AccessList[]]$Access

    [DscProperty(NotConfigurable)]
    [bool]$CertificateExist

    [AccessList[]]GetFormSys()
    {
        $x = @()
        #$cert= Get-Item (Join-Path $this.Localtion -ChildPath $this.Thumbprint)
        #$rsa = $cert.PrivateKey -as [System.Security.Cryptography.RSACryptoServiceProvider]
        #$cspParams = New-Object System.Security.Cryptography.CspParameters ($rsa.CspKeyContainerInfo.ProviderType, $rsa.CspKeyContainerInfo.ProviderName,$rsa.CspKeyContainerInfo.KeyContainerName)
        #$cspParams.Flags = [System.Security.Cryptography.CspProviderFlags]::UseExistingKey + [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore
        #$cspParams.CryptoKeySecurity = $rsa.CspKeyContainerInfo.CryptoKeySecurity

        $cspParams = $this.GetCspParams()

        foreach($item in $cspParams.CryptoKeySecurity.Access)
        {
            $t = [AccessList]::new()
            $t.Identity = $item.IdentityReference
            $t.AccessControlType = $item.AccessControlType
            $t.Rights = $item.CryptoKeyRights.ToString().replace(" ","").Split(",")
            $x+= $t
        }
        return $x
    }


    [System.Security.Cryptography.CspParameters]GetCspParams()
    {
        $cert=  Get-Item  (Join-Path $this.Localtion -ChildPath $this.Thumbprint)
        $rsa = $cert.PrivateKey -as [System.Security.Cryptography.RSACryptoServiceProvider]
        $cspParams = New-Object System.Security.Cryptography.CspParameters ($rsa.CspKeyContainerInfo.ProviderType, $rsa.CspKeyContainerInfo.ProviderName,$rsa.CspKeyContainerInfo.KeyContainerName)
        $cspParams.Flags = [System.Security.Cryptography.CspProviderFlags]::UseExistingKey + [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore
        $cspParams.CryptoKeySecurity = $rsa.CspKeyContainerInfo.CryptoKeySecurity
        return $cspParams
    }


    [void]Set()
    {
        $cspParams = $this.GetCspParams()
        foreach($item in $this.Access)
        {
            $x = $null
            $str_Identity = $item.Identity
            if(!($item.Identity.Contains("\")))
            {
                $str_Identity =  ( [System.Environment]::MachineName+"\"+$item.Identity)
            }
            $x = $cspParams.CryptoKeySecurity.Access.Where({$_.IdentityReference.Value -eq $str_Identity})
            foreach($ruleitem in $x)
            {
                $cspParams.CryptoKeySecurity.RemoveAccessRule($ruleitem)
            }
            $rule = New-Object System.Security.AccessControl.CryptoKeyAccessRule($item.Identity, [System.Security.AccessControl.CryptoKeyRights]($item.Rights), [System.Security.AccessControl.AccessControlType]($item.AccessControlType));
            $cspParams.CryptoKeySecurity.AddAccessRule($rule)
        }
        New-Object  System.Security.Cryptography.RSACryptoServiceProvider($cspParams)
    }
    [bool]Test()
    {
        $result = $true
        if((Test-Path (Join-Path $this.Localtion -ChildPath $this.Thumbprint)))
        {
            $cspParams = $this.GetCspParams()
            $x = $null
            foreach($item in $this.Access)
            {
                $str_Identity = $item.Identity
                if(!($item.Identity.Contains("\")))
                {
                    $str_Identity = ( [System.Environment]::MachineName+"\"+$item.Identity)
                }
                $x = $cspParams.CryptoKeySecurity.Access.Where({($_.IdentityReference.Value -eq $str_Identity) -and ($_.AccessControlType -eq  $item.AccessControlType) })
                if(!$x)
                {
                    Write-Verbose "can not found user $($str_Identity) acl with $($item.AccessControlType)"
                    $result = $false
                }
                else
                {
                    Write-Verbose "found user $($str_Identity) acl with $($item.AccessControlType)"
                    [int]$In_Mask = ([System.Security.AccessControl.CryptoKeyRights]$item.Rights).value__
                    [int]$SYS_Mask = ([System.Security.AccessControl.CryptoKeyRights]$x.CryptoKeyRights).value__
                    Write-Verbose "input mask id $($In_Mask) sys in $($SYS_Mask)"
                    if($In_Mask  -ne $SYS_Mask)
                    {
                        $result = $false
                        Write-Verbose "user $($str_Identity) test failed "
                    }
                }
            }
        }
        else
        {
            Write-Verbose "can not found Certificate"
            $result = $false
        }
        return $result
    }
    [xCertificatePrivateKeyAccess]Get()
    {
        $this.CertificateExist = Test-Path ((Join-Path $this.Localtion -ChildPath $this.Thumbprint))
        if(!$this.CertificateExist)
        {
            $this.Access = $null
        }
        else
        {
            $this.Access = $this.GetFormSys()
        }
        return $this
    }
}