From 07a2d03e5f4c9b21fcdbbf77354ee3a6c27ec310 Mon Sep 17 00:00:00 2001 From: Jordan Pitlor Date: Wed, 6 Sep 2023 23:47:04 -0400 Subject: [PATCH] win_acl/Certificates: Add tests for Crypto API --- plugins/module_utils/_CertACLHelper.cs | 15 +++-- .../targets/win_acl/tasks/main.yml | 25 +++++++-- .../targets/win_acl/tasks/tests.yml | 56 ++++++++++++++----- 3 files changed, 70 insertions(+), 26 deletions(-) diff --git a/plugins/module_utils/_CertACLHelper.cs b/plugins/module_utils/_CertACLHelper.cs index d8c6a05b..a7cb52d3 100644 --- a/plugins/module_utils/_CertACLHelper.cs +++ b/plugins/module_utils/_CertACLHelper.cs @@ -123,14 +123,13 @@ private enum CryptProvParam : uint [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CryptSetProvParam(SafeCryptHandle safeProvHandle, CryptProvParam dwParam, [MarshalAs(UnmanagedType.LPArray)] byte[] pbData, SecurityInformationFlags dwFlags); - SafeCryptHandle handle; - bool ncrypt = false; + private SafeCryptHandle handle; + private bool ncrypt = false; public CertAclHelper(X509Certificate2 certificate) { SafeCryptHandle certPkeyHandle; KeySpec keySpec; - bool ownHandle; if (CryptAcquireCertificatePrivateKey( certificate.Handle, @@ -166,7 +165,7 @@ public FileSecurity Acl uint securityDescriptorSize = 0; if (ncrypt) { - int securityDescriptorResult = NCryptGetProperty( + var securityDescriptorResult = NCryptGetProperty( handle, "Security Descr", new SafeSecurityDescriptorPtr(), @@ -216,9 +215,9 @@ public FileSecurity Acl } } - byte[] buffer = new byte[securityDescriptorSize]; + var buffer = new byte[securityDescriptorSize]; Marshal.Copy(securityDescriptorBuffer.DangerousGetHandle(), buffer, 0, buffer.Length); - FileSecurity acl = new FileSecurity(); + var acl = new FileSecurity(); acl.SetSecurityDescriptorBinaryForm(buffer); return acl; @@ -227,8 +226,8 @@ public FileSecurity Acl { if (ncrypt) { - byte[] sd = value.GetSecurityDescriptorBinaryForm(); - int setPropertyResult = NCryptSetProperty( + var sd = value.GetSecurityDescriptorBinaryForm(); + var setPropertyResult = NCryptSetProperty( handle, "Security Descr", sd, diff --git a/tests/integration/targets/win_acl/tasks/main.yml b/tests/integration/targets/win_acl/tasks/main.yml index 4fec9b66..957e7375 100644 --- a/tests/integration/targets/win_acl/tasks/main.yml +++ b/tests/integration/targets/win_acl/tasks/main.yml @@ -16,9 +16,21 @@ - absent - present -- name: create certificate for testing - win_shell: '(New-SelfSignedCertificate -Subject "ACL Test" -KeyExportPolicy Exportable).Thumbprint' - register: test_acl_certificate_thumbprint +- name: create certificates for testing + win_shell: | + $certParams = @{ + KeyAlgorithm = 'RSA' + KeyExportPolicy = 'Exportable' + KeyLength = 2048 + } + (New-SelfSignedCertificate @certParams -Subject "ACL Test CNG" -Provider "Microsoft Software Key Storage Provider").Thumbprint + (New-SelfSignedCertificate @certParams -Subject "ACL Test CryptoAPI" -Provider "Microsoft Base Cryptographic Provider v1.0" -KeySpec Signature).Thumbprint + register: test_acl_cert_info + +- name: set variables of certificate thumbprints + set_fact: + test_acl_certificiate_cng_thumbprint: '{{ test_acl_cert_info.stdout_lines[0] }}' + test_acl_certificiate_cryptoapi_thumbprint: '{{ test_acl_cert_info.stdout_lines[1] }}' - block: - name: create test dir for link target @@ -53,9 +65,12 @@ delete_key: yes state: absent - - name: uninstall testing certificate + - name: uninstall testing certificates win_certificate_store: - thumbprint: '{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + thumbprint: '{{ item }}' state: absent store_location: LocalMachine store_name: My + with_items: + - test_acl_certificiate_cng_thumbprint + - test_acl_certificiate_cryptoapi_thumbprint diff --git a/tests/integration/targets/win_acl/tasks/tests.yml b/tests/integration/targets/win_acl/tasks/tests.yml index 9815789b..f04d6aac 100644 --- a/tests/integration/targets/win_acl/tasks/tests.yml +++ b/tests/integration/targets/win_acl/tasks/tests.yml @@ -12,6 +12,16 @@ } $keyFullPath = $env:ProgramData + "\Microsoft\Crypto\Keys\" + $containerName; ConvertTo-Json -InputObject @((Get-Acl $keyFullPath).Access) + test_crypto_cert_ace_cmd: | + $certificate = Get-ChildItem Cert:\LocalMachine\My | Where-Object Thumbprint -eq $thumbprint + $privateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate) + $containerName = if ($privateKey.GetType().Name -ieq "RSACng") { + $privateKey.Key.UniqueName + } else { + $privateKey.CspKeyContainerInfo.UniqueKeyContainerName + } + $keyFullPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\" + $containerName; + ConvertTo-Json -InputObject @((Get-Acl $keyFullPath).Access) test_ace_cmd: | # Overcome bug in Set-Acl/Get-Acl for registry paths and -LiteralPath New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS > $null @@ -446,7 +456,7 @@ # have very different access masks than private keys in the crypt API - name: add FullControl rights on certificate - check mode win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: present @@ -461,7 +471,7 @@ - name: add FullControl rights on certificate win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: present @@ -469,7 +479,7 @@ register: add_fullcontrol_rights_on_certificate - name: get result of add FullControl rights on certificate - win_shell: '$thumbprint = ''{{ test_acl_certificate_thumbprint.stdout_lines[0] }}''; {{ test_cert_ace_cmd }}' + win_shell: '$thumbprint = ''{{ test_acl_certificiate_cng_thumbprint }}''; {{ test_cert_ace_cmd }}' register: add_fullcontrol_rights_on_certificate_actual - name: assert add FullControl rights on certificate @@ -481,7 +491,7 @@ - name: add FullControl rights on certificate again win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: present @@ -495,7 +505,7 @@ - name: remove FullControl rights on certificate - check mode win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: absent @@ -510,7 +520,7 @@ - name: remove FullControl rights on certificate win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: absent @@ -518,7 +528,7 @@ register: remove_fullcontrol_rights_on_certificate - name: get result of remove FullControl rights on certificate - win_shell: '$thumbprint = ''{{ test_acl_certificate_thumbprint.stdout_lines[0] }}''; {{ test_cert_ace_cmd }}' + win_shell: '$thumbprint = ''{{ test_acl_certificiate_cng_thumbprint }}''; {{ test_cert_ace_cmd }}' register: remove_fullcontrol_rights_on_certificate_actual - name: assert remove FullControl rights on certificate @@ -530,7 +540,7 @@ - name: remove FullControl rights on certificate again win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: absent @@ -547,7 +557,7 @@ - name: add Read rights on certificate win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: present @@ -555,7 +565,7 @@ register: add_read_rights_on_certificate - name: get result of add Read rights on certificate - win_shell: '$thumbprint = ''{{ test_acl_certificate_thumbprint.stdout_lines[0] }}''; {{ test_cert_ace_cmd }}' + win_shell: '$thumbprint = ''{{ test_acl_certificiate_cng_thumbprint }}''; {{ test_cert_ace_cmd }}' register: add_read_rights_on_certificate_actual - name: assert add Read rights on certificate @@ -567,7 +577,7 @@ - name: remove Read rights on certificate win_acl: - path: 'Cert:\LocalMachine\My\{{ test_acl_certificate_thumbprint.stdout_lines[0] }}' + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cng_thumbprint }}' user: Guests type: allow state: absent @@ -575,7 +585,7 @@ register: remove_read_rights_on_certificate - name: get result of remove Read rights on certificate - win_shell: '$thumbprint = ''{{ test_acl_certificate_thumbprint.stdout_lines[0] }}''; {{ test_cert_ace_cmd }}' + win_shell: '$thumbprint = ''{{ test_acl_certificiate_cng_thumbprint }}''; {{ test_cert_ace_cmd }}' register: remove_read_rights_on_certificate_actual - name: assert remove Read rights on certificate @@ -583,4 +593,24 @@ that: - remove_read_rights_on_certificate is changed - item.IdentityReference.Value != 'BUILTIN\Guests' or item.FileSystemRights != 1179785 - with_items: '{{ remove_read_rights_on_certificate_actual.stdout|from_json }}' \ No newline at end of file + with_items: '{{ remove_read_rights_on_certificate_actual.stdout|from_json }}' + +- name: add FullControl rights on Crypto certificate + win_acl: + path: 'Cert:\LocalMachine\My\{{ test_acl_certificiate_cryptoapi_thumbprint }}' + user: Guests + type: allow + state: present + rights: FullControl + register: add_fullcontrol_rights_on_crypto_certificate + +- name: get result of add FullControl rights on Crypto certificate + win_shell: '$thumbprint = ''{{ test_acl_certificiate_cryptoapi_thumbprint }}''; {{ test_crypto_cert_ace_cmd }}' + register: add_fullcontrol_rights_on_crypto_certificate_actual + +- name: assert add FullControl rights on Crypto certificate + assert: + that: + - add_fullcontrol_rights_on_crypto_certificate is changed + - (add_fullcontrol_rights_on_crypto_certificate_actual.stdout|from_json|last).IdentityReference.Value == 'BUILTIN\Guests' + - (add_fullcontrol_rights_on_crypto_certificate_actual.stdout|from_json|last).FileSystemRights == 2032127 \ No newline at end of file