-
Notifications
You must be signed in to change notification settings - Fork 173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate win_certificate_info module to ansible.windows repo from ansible.community repo #687
Merged
jborean93
merged 1 commit into
ansible-collections:main
from
ronger4:migrate_win_certificate_info
Nov 7, 2024
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
#!powershell | ||
|
||
# Copyright: (c) 2019, Micah Hunsberger | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
#AnsibleRequires -CSharpUtil Ansible.Basic | ||
|
||
function ConvertTo-Timestamp($start_date, $end_date) { | ||
if ($start_date -and $end_date) { | ||
return (New-TimeSpan -Start $start_date -End $end_date).TotalSeconds | ||
} | ||
} | ||
|
||
function Format-Date([DateTime]$date) { | ||
return $date.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssK') | ||
} | ||
|
||
function Get-CertificateInfo ($cert) { | ||
$epoch_date = Get-Date -Date "01/01/1970" | ||
|
||
$cert_info = @{ extensions = @() } | ||
$cert_info.friendly_name = $cert.FriendlyName | ||
$cert_info.thumbprint = $cert.Thumbprint | ||
$cert_info.subject = $cert.Subject | ||
$cert_info.issuer = $cert.Issuer | ||
$cert_info.valid_from = (ConvertTo-Timestamp -start_date $epoch_date -end_date $cert.NotBefore.ToUniversalTime()) | ||
$cert_info.valid_from_iso8601 = Format-Date -date $cert.NotBefore | ||
$cert_info.valid_to = (ConvertTo-Timestamp -start_date $epoch_date -end_date $cert.NotAfter.ToUniversalTime()) | ||
$cert_info.valid_to_iso8601 = Format-Date -date $cert.NotAfter | ||
$cert_info.serial_number = $cert.SerialNumber | ||
$cert_info.archived = $cert.Archived | ||
$cert_info.version = $cert.Version | ||
$cert_info.has_private_key = $cert.HasPrivateKey | ||
$cert_info.issued_by = $cert.GetNameInfo('SimpleName', $true) | ||
$cert_info.issued_to = $cert.GetNameInfo('SimpleName', $false) | ||
$cert_info.signature_algorithm = $cert.SignatureAlgorithm.FriendlyName | ||
$cert_info.dns_names = [System.Collections.Generic.List`1[String]]@($cert_info.issued_to) | ||
$cert_info.raw = [System.Convert]::ToBase64String($cert.GetRawCertData()) | ||
$cert_info.public_key = [System.Convert]::ToBase64String($cert.GetPublicKey()) | ||
if ($cert.Extensions.Count -gt 0) { | ||
[array]$cert_info.extensions = foreach ($extension in $cert.Extensions) { | ||
$extension_info = @{ | ||
critical = $extension.Critical | ||
field = $extension.Oid.FriendlyName | ||
value = $extension.Format($false) | ||
} | ||
if ($extension -is [System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension]) { | ||
$cert_info.is_ca = $extension.CertificateAuthority | ||
$cert_info.path_length_constraint = $extension.PathLengthConstraint | ||
} | ||
elseif ($extension -is [System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]) { | ||
$cert_info.intended_purposes = $extension.EnhancedKeyUsages.FriendlyName -as [string[]] | ||
} | ||
elseif ($extension -is [System.Security.Cryptography.X509Certificates.X509KeyUsageExtension]) { | ||
$cert_info.key_usages = $extension.KeyUsages.ToString().Split(',').Trim() -as [string[]] | ||
} | ||
elseif ($extension -is [System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension]) { | ||
$cert_info.ski = $extension.SubjectKeyIdentifier | ||
} | ||
elseif ($extension.Oid.value -eq '2.5.29.17') { | ||
$sans = $extension.Format($true).Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) | ||
foreach ($san in $sans) { | ||
$san_parts = $san.Split("=") | ||
if ($san_parts.Length -ge 2 -and $san_parts[0].Trim() -eq 'DNS Name') { | ||
$cert_info.dns_names.Add($san_parts[1].Trim()) | ||
} | ||
} | ||
} | ||
$extension_info | ||
} | ||
} | ||
return $cert_info | ||
} | ||
|
||
$store_location_values = ([System.Security.Cryptography.X509Certificates.StoreLocation]).GetEnumValues() | ForEach-Object { $_.ToString() } | ||
|
||
$spec = @{ | ||
options = @{ | ||
thumbprint = @{ type = "str"; required = $false } | ||
store_name = @{ type = "str"; default = "My"; } | ||
store_location = @{ type = "str"; default = "LocalMachine"; choices = $store_location_values; } | ||
} | ||
supports_check_mode = $true | ||
} | ||
|
||
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) | ||
|
||
$thumbprint = $module.Params.thumbprint | ||
$store_name = $module.Params.store_name | ||
$store_location = [System.Security.Cryptography.X509Certificates.Storelocation]"$($module.Params.store_location)" | ||
|
||
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location | ||
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly) | ||
|
||
$module.Result.exists = $false | ||
$module.Result.certificates = @() | ||
|
||
try { | ||
if ($null -ne $thumbprint) { | ||
$found_certs = $store.Certificates.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint, $thumbprint, $false) | ||
} | ||
else { | ||
$found_certs = $store.Certificates | ||
} | ||
|
||
if ($found_certs.Count -gt 0) { | ||
$module.Result.exists = $true | ||
[array]$module.Result.certificates = $found_certs | ForEach-Object { Get-CertificateInfo -cert $_ } | Sort-Object -Property { $_.thumbprint } | ||
} | ||
} | ||
finally { | ||
$store.Close() | ||
} | ||
|
||
$module.ExitJson() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright: (c) 2016, Ansible, inc | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
DOCUMENTATION = r''' | ||
--- | ||
module: win_certificate_info | ||
short_description: Get information on certificates from a Windows Certificate Store | ||
description: | ||
- Returns information about certificates in a Windows Certificate Store. | ||
version_added: 2.6.0 | ||
options: | ||
thumbprint: | ||
description: | ||
- The thumbprint as a hex string of a certificate to find. | ||
- When specified, filters the I(certificates) return value to a single certificate | ||
- See the examples for how to format the thumbprint. | ||
type: str | ||
required: no | ||
store_name: | ||
description: | ||
- The name of the store to search. | ||
- See U(https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.storename) | ||
for a list of built-in store names. | ||
type: str | ||
default: My | ||
store_location: | ||
description: | ||
- The location of the store to search. | ||
type: str | ||
choices: [ CurrentUser, LocalMachine ] | ||
default: LocalMachine | ||
seealso: | ||
- module: ansible.windows.win_certificate_store | ||
author: | ||
- Micah Hunsberger (@mhunsber) | ||
''' | ||
|
||
EXAMPLES = r''' | ||
ronger4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- name: Obtain information about a particular certificate in the computer's personal store | ||
ansible.windows.win_certificate_info: | ||
thumbprint: BD7AF104CF1872BDB518D95C9534EA941665FD27 | ||
register: mycert | ||
|
||
# thumbprint can also be lower case | ||
- name: Obtain information about a particular certificate in the computer's personal store | ||
ansible.windows.win_certificate_info: | ||
thumbprint: bd7af104cf1872bdb518d95c9534ea941665fd27 | ||
register: mycert | ||
|
||
- name: Obtain information about all certificates in the root store | ||
ansible.windows.win_certificate_info: | ||
store_name: Root | ||
register: ca | ||
|
||
# Import a pfx and then get information on the certificates | ||
- name: Import pfx certificate that is password protected | ||
ansible.windows.win_certificate_store: | ||
path: C:\Temp\cert.pfx | ||
state: present | ||
password: VeryStrongPasswordHere! | ||
become: true | ||
become_method: runas | ||
register: mycert | ||
|
||
- name: Obtain information on each certificate that was touched | ||
ansible.windows.win_certificate_info: | ||
thumbprint: "{{ item }}" | ||
register: mycert_stats | ||
loop: "{{ mycert.thumbprints }}" | ||
''' | ||
|
||
RETURN = r''' | ||
exists: | ||
description: | ||
- Whether any certificates were found in the store. | ||
- When I(thumbprint) is specified, returns true only if the certificate mathing the thumbprint exists. | ||
returned: success | ||
type: bool | ||
sample: true | ||
certificates: | ||
description: | ||
- A list of information about certificates found in the store, sorted by thumbprint. | ||
returned: success | ||
type: list | ||
elements: dict | ||
contains: | ||
archived: | ||
description: Indicates that the certificate is archived. | ||
type: bool | ||
sample: false | ||
dns_names: | ||
description: Lists the registered dns names for the certificate. | ||
type: list | ||
elements: str | ||
sample: [ '*.m.wikiquote.org', '*.wikipedia.org' ] | ||
extensions: | ||
description: The collection of the certificates extensions. | ||
type: list | ||
elements: dict | ||
sample: [ | ||
{ | ||
"critical": false, | ||
"field": "Subject Key Identifier", | ||
"value": "88 27 17 09 a9 b6 18 60 8b ec eb ba f6 47 59 c5 52 54 a3 b7" | ||
}, | ||
{ | ||
"critical": true, | ||
"field": "Basic Constraints", | ||
"value": "Subject Type=CA, Path Length Constraint=None" | ||
}, | ||
{ | ||
"critical": false, | ||
"field": "Authority Key Identifier", | ||
"value": "KeyID=2b d0 69 47 94 76 09 fe f4 6b 8d 2e 40 a6 f7 47 4d 7f 08 5e" | ||
}, | ||
{ | ||
"critical": false, | ||
"field": "CRL Distribution Points", | ||
"value": "[1]CRL Distribution Point: Distribution Point Name:Full Name:URL=http://crl.apple.com/root.crl" | ||
}, | ||
{ | ||
"critical": true, | ||
"field": "Key Usage", | ||
"value": "Digital Signature, Certificate Signing, Off-line CRL Signing, CRL Signing (86)" | ||
}, | ||
{ | ||
"critical": false, | ||
"field": null, | ||
"value": "05 00" | ||
} | ||
] | ||
friendly_name: | ||
description: The associated alias for the certificate. | ||
type: str | ||
sample: Microsoft Root Authority | ||
has_private_key: | ||
description: Indicates that the certificate contains a private key. | ||
type: bool | ||
sample: false | ||
intended_purposes: | ||
description: lists the intended applications for the certificate. | ||
returned: enhanced key usages extension exists. | ||
type: list | ||
sample: [ "Server Authentication" ] | ||
is_ca: | ||
description: Indicates that the certificate is a certificate authority (CA) certificate. | ||
returned: basic constraints extension exists. | ||
type: bool | ||
sample: true | ||
issued_by: | ||
description: The certificate issuer's common name. | ||
type: str | ||
sample: Apple Root CA | ||
issued_to: | ||
description: The certificate's common name. | ||
type: str | ||
sample: Apple Worldwide Developer Relations Certification Authority | ||
issuer: | ||
description: The certificate issuer's distinguished name. | ||
type: str | ||
sample: 'CN=Apple Root CA, OU=Apple Certification Authority, O=Apple Inc., C=US' | ||
key_usages: | ||
description: | ||
- Defines how the certificate key can be used. | ||
- If this value is not defined, the key can be used for any purpose. | ||
returned: key usages extension exists. | ||
type: list | ||
elements: str | ||
sample: [ "CrlSign", "KeyCertSign", "DigitalSignature" ] | ||
path_length_constraint: | ||
description: | ||
- The number of levels allowed in a certificates path. | ||
- If this value is 0, the certificate does not have a restriction. | ||
returned: basic constraints extension exists | ||
type: int | ||
sample: 0 | ||
public_key: | ||
description: The base64 encoded public key of the certificate. | ||
type: str | ||
cert_data: | ||
description: The base64 encoded data of the entire certificate. | ||
type: str | ||
serial_number: | ||
description: The serial number of the certificate represented as a hexadecimal string | ||
type: str | ||
sample: 01DEBCC4396DA010 | ||
signature_algorithm: | ||
description: The algorithm used to create the certificate's signature | ||
type: str | ||
sample: sha1RSA | ||
ski: | ||
description: The certificate's subject key identifier | ||
returned: subject key identifier extension exists. | ||
type: str | ||
sample: 88271709A9B618608BECEBBAF64759C55254A3B7 | ||
subject: | ||
description: The certificate's distinguished name. | ||
type: str | ||
sample: 'CN=Apple Worldwide Developer Relations Certification Authority, OU=Apple Worldwide Developer Relations, O=Apple Inc., C=US' | ||
thumbprint: | ||
description: | ||
- The thumbprint as a hex string of the certificate. | ||
- The return format will always be upper case. | ||
type: str | ||
sample: FF6797793A3CD798DC5B2ABEF56F73EDC9F83A64 | ||
valid_from: | ||
description: The start date of the certificate represented in seconds since epoch. | ||
type: float | ||
sample: 1360255727 | ||
valid_from_iso8601: | ||
description: The start date of the certificate represented as an iso8601 formatted date. | ||
type: str | ||
sample: '2017-12-15T08:39:32Z' | ||
valid_to: | ||
description: The expiry date of the certificate represented in seconds since epoch. | ||
type: float | ||
sample: 1675788527 | ||
valid_to_iso8601: | ||
description: The expiry date of the certificate represented as an iso8601 formatted date. | ||
type: str | ||
sample: '2086-01-02T08:39:32Z' | ||
version: | ||
description: The x509 format version of the certificate | ||
type: int | ||
sample: 3 | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
shippable/windows/group3 |
3 changes: 3 additions & 0 deletions
3
tests/integration/targets/win_certificate_info/defaults/main.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
win_cert_dir: '{{ remote_tmp_dir }}\win_certificate .ÅÑŚÌβŁÈ [$!@^&test(;)]' | ||
subj_thumbprint: 'BD7AF104CF1872BDB518D95C9534EA941665FD27' | ||
root_thumbprint: 'BC05633694E675449136679A658281F17A191087' |
20 changes: 20 additions & 0 deletions
20
tests/integration/targets/win_certificate_info/files/root-cert.pem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIDKDCCAhCgAwIBAgIJAP1vIdGgMJv/MA0GCSqGSIb3DQEBCwUAMCgxGTAXBgNV | ||
BAMMEHJvb3QuYW5zaWJsZS5jb20xCzAJBgNVBAYTAlVTMCAXDTE3MTIxNTA4Mzkz | ||
MloYDzIwODYwMTAyMDgzOTMyWjAoMRkwFwYDVQQDDBByb290LmFuc2libGUuY29t | ||
MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmq | ||
YT8eZY6rFQKnmScUGnnUH1tLQ+3WQpfKiWygCUSb1CNqO3J1u3pGMEqYM58LK4Kr | ||
Mpskv7K1tCV/EMZqGTqXAIfSLy9umlb/9C3AhL9thBPn5I9dam/EmrIZktI9/w5Y | ||
wBXn4toe+OopA3QkMQh9BUjUCPb9fdOI+ir7OGFZMmxXmiM64+BEeywM2oSGsdZ9 | ||
5hU378UBu2IX4+OAV8Fbr2l6VW+Fxg/tKIOo6Bs46Pa4EZgtemOqs3kxYBOltBTb | ||
vFcLsLa4KYVu5Ge5YfB0Axfaem7PoP8IlMs8gxyojZ/r0o5hzxUcYlL/h8GeeoLW | ||
PFFdiAS+UgxWINOqNXMCAwEAAaNTMFEwHQYDVR0OBBYEFLp9k4LmOnAR4ROrqhb+ | ||
CFdbk2+oMB8GA1UdIwQYMBaAFLp9k4LmOnAR4ROrqhb+CFdbk2+oMA8GA1UdEwEB | ||
/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGksycHsjGbXfWfuhQh+CvXk/A2v | ||
MoNgiHtNMTGliVNgoVp1B1rj4x9xyZ8YrO8GAmv8jaCwCShd0B5Ul4aZVk1wglVv | ||
lFAwb4IAZN9jv9+fw5BRzQ2tLhkVWIEwx6pZkhGhhjBvMaplLN5JwBtsdZorFbm7 | ||
wuKiUKcFAM28acoOhCmOhgyNNBZpZn5wXaQDY43AthJOhitAV7vph4MPUkwIJnOh | ||
MA5GJXEqS58TE9z9pkhQnn9598G8tmOXyA2erAoM9JAXM3EYHxVpoHBb9QRj6WAw | ||
XVBo6qRXkwjNEM5CbnD4hVIBsdkOGsDrgd4Q5izQZ3x+jFNkdL/zPsXjJFw= | ||
-----END CERTIFICATE----- | ||
|
19 changes: 19 additions & 0 deletions
19
tests/integration/targets/win_certificate_info/files/subj-cert.pem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIC0TCCAbkCCQC/MtOBa1UDpzANBgkqhkiG9w0BAQsFADAoMRkwFwYDVQQDDBBy | ||
b290LmFuc2libGUuY29tMQswCQYDVQQGEwJVUzAgFw0xNzEyMTUwODU2MzBaGA8y | ||
MDg2MDEwMjA4NTYzMFowKzEcMBoGA1UEAwwTc3ViamVjdC5hbnNpYmxlLmNvbTEL | ||
MAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDszqdF | ||
So3GlVP1xUnN4bSPrFRFiOl/Mqup0Zn5UJJUR9wLnRD+OLcq7kKin6hYqozSu7cC | ||
+BnWQoq7vGSSNVqv7BqFMwzGJt9IBUQv0UqIQkA/duUdKdAiMn2PQRsNDnkWEbTj | ||
4xsitItVNv84cDG0lkZBYyTgfyZlZLZWplkpUQkrZhoFCekZRJ+ODrqNW3W560rr | ||
OUIh+HiQeBqocat6OdxgICBqpUh8EVo1iha3DXjGN08q5utg6gmbIl2VBaVJjfyd | ||
wnUSqHylJwh6WCIEh+HXsn4ndfNWSN/fDqvi5I10V1j6Zos7yqQf8qAezUAm6eSq | ||
hLgZz0odq9DsO4HHAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFK5mVIJ2D+kI0kk | ||
sxnW4ibWFjzlYFYPYrZg+2JFIVTbKBg1YzyhuIKm0uztqRxQq5iLn/C/uponHoqF | ||
7KDQI37KAJIQdgSva+mEuO9bZAXg/eegail2hN6np7HjOKlPu23s40dAbFrbcOWP | ||
VbsBEPDP0HLv6OgbQWzNlE9HO1b7pX6ozk3q4ULO7IR85P6OHYsBBThL+qsOTzg/ | ||
gVknuB9+n9hgNqZcAcXBLDetOM9aEmYJCGk0enYP5UGLYpseE+rTXFbRuHTPr1o6 | ||
e8BetiSWS/wcrV4ZF5qr9NiYt5eD6JzTB5Rn5awxxj0FwMtrBu003lLQUWxsuTzz | ||
35/RLY4= | ||
-----END CERTIFICATE----- | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
dependencies: | ||
- setup_remote_tmp_dir |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to set the version when this module was added to the collection through the
version_added
key.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason you put 2.6.0 because it will be the upcoming version release, right?
Is there a place where we can follow the planned release dates if there is such
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version is in the galaxy.yml file and while sometimes it may have already been bumped it may still track the older release. I just compare it with the tagged releases and see if I need to increment it or not. In this case
2.5.0
is the latest release and thegalaxy.yml
has not been updated yet. A minor version bump is needed for new features so the next release will be2.6.0
.As for a release schedule there hasn't been a hard rule of when to release. I usually aim for a release every 1-2 months but that is also dependent on whether there are changes to be made in a release.