crypto: Fix known issues in modules (#52302)

* crypto: Fix known issues in modules

This fixes a few issues reported by 'validate-modules'.

* Fix whitespace
pull/52322/head
Dag Wieers 6 years ago committed by GitHub
parent 9c1033422b
commit cedd9d9926
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,8 +1,8 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# (c) 2016-2017, Yanis Guenane <yanis+ansible@guenane.org> # Copyright: (c) 2016-2017, Yanis Guenane <yanis+ansible@guenane.org>
# (c) 2017, Markus Teufelberger <mteufelberger+ansible@mgit.at> # Copyright: (c) 2017, Markus Teufelberger <mteufelberger+ansible@mgit.at>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
@ -14,268 +14,322 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = ''' DOCUMENTATION = r'''
--- ---
module: openssl_certificate module: openssl_certificate
author:
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
version_added: "2.4" version_added: "2.4"
short_description: Generate and/or check OpenSSL certificates short_description: Generate and/or check OpenSSL certificates
description: description:
- "This module allows one to (re)generate OpenSSL certificates. It implements a notion - This module allows one to (re)generate OpenSSL certificates.
of provider (ie. C(selfsigned), C(ownca), C(acme), C(assertonly)) for your certificate. - It implements a notion of provider (ie. C(selfsigned), C(ownca), C(acme), C(assertonly))
The 'assertonly' provider is intended for use cases where one is only interested in for your certificate.
- The C(assertonly) provider is intended for use cases where one is only interested in
checking properties of a supplied certificate. checking properties of a supplied certificate.
The 'ownca' provider is intended for generate OpenSSL certificate signed with your own - The C(ownca) provider is intended for generate OpenSSL certificate signed with your own
CA (Certificate Authority) certificate (self-signed certificate). CA (Certificate Authority) certificate (self-signed certificate).
Many properties that can be specified in this module are for validation of an - Many properties that can be specified in this module are for validation of an
existing or newly generated certificate. The proper place to specify them, if you existing or newly generated certificate. The proper place to specify them, if you
want to receive a certificate with these properties is a CSR (Certificate Signing Request). want to receive a certificate with these properties is a CSR (Certificate Signing Request).
It uses the pyOpenSSL python library to interact with OpenSSL." - It uses the pyOpenSSL python library to interact with OpenSSL.
requirements: requirements:
- python-pyOpenSSL >= 0.15 (if using C(selfsigned) or C(assertonly) provider) - python-pyOpenSSL >= 0.15 (if using C(selfsigned) or C(assertonly) provider)
- acme-tiny (if using the C(acme) provider) - acme-tiny (if using the C(acme) provider)
author:
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
options: options:
state: state:
default: "present"
choices: [ present, absent ]
description: description:
- Whether the certificate should exist or not, taking action if the state is different from what is stated. - Whether the certificate should exist or not, taking action if the state is different from what is stated.
type: str
choices: [ absent, present ]
default: present
path: path:
required: true
description: description:
- Remote absolute path where the generated certificate file should be created or is already located. - Remote absolute path where the generated certificate file should be created or is already located.
type: path
required: true
provider: provider:
required: true
choices: [ 'selfsigned', 'ownca', 'assertonly', 'acme' ]
description: description:
- Name of the provider to use to generate/retrieve the OpenSSL certificate. - Name of the provider to use to generate/retrieve the OpenSSL certificate.
The C(assertonly) provider will not generate files and fail if the certificate file is missing. - The C(assertonly) provider will not generate files and fail if the certificate file is missing.
required: true
type: str
choices: [ acme, assertonly, ownca, selfsigned ]
force: force:
default: False
type: bool
description: description:
- Generate the certificate, even if it already exists. - Generate the certificate, even if it already exists.
type: bool
default: no
csr_path: csr_path:
description: description:
- Path to the Certificate Signing Request (CSR) used to generate this certificate. This is not required in C(assertonly) mode. - Path to the Certificate Signing Request (CSR) used to generate this certificate.
- This is not required in C(assertonly) mode.
type: path
privatekey_path: privatekey_path:
description: description:
- Path to the private key to use when signing the certificate. - Path to the private key to use when signing the certificate.
type: path
privatekey_passphrase: privatekey_passphrase:
description: description:
- The passphrase for the I(privatekey_path). - The passphrase for the I(privatekey_path).
type: str
selfsigned_version: selfsigned_version:
default: 3
description: description:
- Version of the C(selfsigned) certificate. Nowadays it should almost always be C(3). - Version of the C(selfsigned) certificate.
- Nowadays it should almost always be C(3).
type: int
default: 3
version_added: "2.5" version_added: "2.5"
selfsigned_digest: selfsigned_digest:
default: "sha256"
description: description:
- Digest algorithm to be used when self-signing the certificate - Digest algorithm to be used when self-signing the certificate.
type: str
default: sha256
selfsigned_not_before: selfsigned_not_before:
default: +0s
description: description:
- "The point in time the certificate is valid from. Time can be specified either as relative time or as absolute timestamp. - The point in time the certificate is valid from.
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME) - Time can be specified either as relative time or as absolute timestamp.
where timespec can be an integer + C([w | d | h | m | s]) (e.g. C(+32w1d2h). - Time will always be interpreted as UTC.
Note that if using relative time this module is NOT idempotent. - Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
If this value is not specified, the certificate will start being valid from now." + C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- Note that if using relative time this module is NOT idempotent.
- If this value is not specified, the certificate will start being valid from now.
type: str
default: +0s
aliases: [ selfsigned_notBefore ] aliases: [ selfsigned_notBefore ]
selfsigned_not_after: selfsigned_not_after:
default: +3650d
description: description:
- "The point in time at which the certificate stops being valid. Time can be specified either as relative time or as absolute timestamp. - The point in time at which the certificate stops being valid.
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME) - Time can be specified either as relative time or as absolute timestamp.
where timespec can be an integer + C([w | d | h | m | s]) (e.g. C(+32w1d2h). - Time will always be interpreted as UTC.
Note that if using relative time this module is NOT idempotent. - Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
If this value is not specified, the certificate will stop being valid 10 years from now." + C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- Note that if using relative time this module is NOT idempotent.
- If this value is not specified, the certificate will stop being valid 10 years from now.
type: str
default: +3650d
aliases: [ selfsigned_notAfter ] aliases: [ selfsigned_notAfter ]
ownca_path: ownca_path:
description: description:
- Remote absolute path of the CA (Certificate Authority) certificate. - Remote absolute path of the CA (Certificate Authority) certificate.
type: path
version_added: "2.7" version_added: "2.7"
ownca_privatekey_path: ownca_privatekey_path:
description: description:
- Path to the CA (Certificate Authority) private key to use when signing the certificate. - Path to the CA (Certificate Authority) private key to use when signing the certificate.
type: path
version_added: "2.7" version_added: "2.7"
ownca_privatekey_passphrase: ownca_privatekey_passphrase:
description: description:
- The passphrase for the I(ownca_privatekey_path). - The passphrase for the I(ownca_privatekey_path).
type: str
version_added: "2.7" version_added: "2.7"
ownca_digest: ownca_digest:
default: "sha256"
description: description:
- Digest algorithm to be used for the C(ownca) certificate. - The digest algorithm to be used for the C(ownca) certificate.
type: str
default: sha256
version_added: "2.7" version_added: "2.7"
ownca_version: ownca_version:
default: 3
description: description:
- Version of the C(ownca) certificate. Nowadays it should almost always be C(3). - The version of the C(ownca) certificate.
- Nowadays it should almost always be C(3).
type: int
default: 3
version_added: "2.7" version_added: "2.7"
ownca_not_before: ownca_not_before:
default: +0s
description: description:
- "The point in time the certificate is valid from. Time can be specified either as relative time or as absolute timestamp. - The point in time the certificate is valid from.
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME) - Time can be specified either as relative time or as absolute timestamp.
where timespec can be an integer + C([w | d | h | m | s]) (e.g. C(+32w1d2h). - Time will always be interpreted as UTC.
Note that if using relative time this module is NOT idempotent. - Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
If this value is not specified, the certificate will start being valid from now." + C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- Note that if using relative time this module is NOT idempotent.
- If this value is not specified, the certificate will start being valid from now.
type: str
default: +0s
version_added: "2.7" version_added: "2.7"
ownca_not_after: ownca_not_after:
default: +3650d
description: description:
- "The point in time at which the certificate stops being valid. Time can be specified either as relative time or as absolute timestamp. - The point in time at which the certificate stops being valid.
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME) - Time can be specified either as relative time or as absolute timestamp.
where timespec can be an integer + C([w | d | h | m | s]) (e.g. C(+32w1d2h). - Time will always be interpreted as UTC.
Note that if using relative time this module is NOT idempotent. - Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
If this value is not specified, the certificate will stop being valid 10 years from now." + C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- Note that if using relative time this module is NOT idempotent.
- If this value is not specified, the certificate will stop being valid 10 years from now.
type: str
default: +3650d
version_added: "2.7" version_added: "2.7"
acme_accountkey_path: acme_accountkey_path:
description: description:
- Path to the accountkey for the C(acme) provider - The path to the accountkey for the C(acme) provider.
type: path
acme_challenge_path: acme_challenge_path:
description: description:
- Path to the ACME challenge directory that is served on U(http://<HOST>:80/.well-known/acme-challenge/) - The path to the ACME challenge directory that is served on U(http://<HOST>:80/.well-known/acme-challenge/)
type: path
acme_chain: acme_chain:
default: True
description: description:
- Include the intermediate certificate to the generated certificate - Include the intermediate certificate to the generated certificate
type: bool
default: yes
version_added: "2.5" version_added: "2.5"
signature_algorithms: signature_algorithms:
description: description:
- list of algorithms that you would accept the certificate to be signed with - A list of algorithms that you would accept the certificate to be signed with
(e.g. ['sha256WithRSAEncryption', 'sha512WithRSAEncryption']). (e.g. ['sha256WithRSAEncryption', 'sha512WithRSAEncryption']).
type: str
issuer: issuer:
description: description:
- Key/value pairs that must be present in the issuer name field of the certificate. - The key/value pairs that must be present in the issuer name field of the certificate.
If you need to specify more than one value with the same key, use a list as value. - If you need to specify more than one value with the same key, use a list as value.
type: str
issuer_strict: issuer_strict:
default: False
type: bool
description: description:
- If set to True, the I(issuer) field must contain only these values. - If set to C(yes), the I(issuer) field must contain only these values.
type: bool
default: no
version_added: "2.5" version_added: "2.5"
subject: subject:
description: description:
- Key/value pairs that must be present in the subject name field of the certificate. - The key/value pairs that must be present in the subject name field of the certificate.
If you need to specify more than one value with the same key, use a list as value. - If you need to specify more than one value with the same key, use a list as value.
type: str
subject_strict: subject_strict:
default: False
type: bool
description: description:
- If set to True, the I(subject) field must contain only these values. - If set to C(yes), the I(subject) field must contain only these values.
type: bool
default: no
version_added: "2.5" version_added: "2.5"
has_expired: has_expired:
default: False
type: bool
description: description:
- Checks if the certificate is expired/not expired at the time the module is executed. - Checks if the certificate is expired/not expired at the time the module is executed.
type: bool
default: no
version: version:
description: description:
- Version of the certificate. Nowadays it should almost always be 3. - The version of the certificate.
- Nowadays it should almost always be 3.
type: int
valid_at: valid_at:
description: description:
- The certificate must be valid at this point in time. The timestamp is formatted as an ASN.1 TIME. - The certificate must be valid at this point in time.
- The timestamp is formatted as an ASN.1 TIME.
type: str
invalid_at: invalid_at:
description: description:
- The certificate must be invalid at this point in time. The timestamp is formatted as an ASN.1 TIME. - The certificate must be invalid at this point in time.
- The timestamp is formatted as an ASN.1 TIME.
type: str
not_before: not_before:
description: description:
- The certificate must start to become valid at this point in time. The timestamp is formatted as an ASN.1 TIME. - The certificate must start to become valid at this point in time.
- The timestamp is formatted as an ASN.1 TIME.
type: str
aliases: [ notBefore ] aliases: [ notBefore ]
not_after: not_after:
description: description:
- The certificate must expire at this point in time. The timestamp is formatted as an ASN.1 TIME. - The certificate must expire at this point in time.
- The timestamp is formatted as an ASN.1 TIME.
type: str
aliases: [ notAfter ] aliases: [ notAfter ]
valid_in: valid_in:
description: description:
- "The certificate must still be valid at this relative time offset from now. - The certificate must still be valid at this relative time offset from now.
Valid formats are: C([+-]timespec | number_of_seconds) - Valid format is C([+-]timespec | number_of_seconds) where timespec can be an integer
where timespec can be an integer + C([w | d | h | m | s]) (e.g. C(+32w1d2h). + C([w | d | h | m | s]) (e.g. C(+32w1d2h).
Note that if using this parameter, this module is NOT idempotent." - Note that if using this parameter, this module is NOT idempotent.
type: str
key_usage: key_usage:
description: description:
- The I(key_usage) extension field must contain all these values. - The I(key_usage) extension field must contain all these values.
type: list
aliases: [ keyUsage ] aliases: [ keyUsage ]
key_usage_strict: key_usage_strict:
default: False
type: bool
description: description:
- If set to True, the I(key_usage) extension field must contain only these values. - If set to C(yes), the I(key_usage) extension field must contain only these values.
type: bool
default: no
aliases: [ keyUsage_strict ] aliases: [ keyUsage_strict ]
extended_key_usage: extended_key_usage:
description: description:
- The I(extended_key_usage) extension field must contain all these values. - The I(extended_key_usage) extension field must contain all these values.
type: list
aliases: [ extendedKeyUsage ] aliases: [ extendedKeyUsage ]
extended_key_usage_strict: extended_key_usage_strict:
default: False
type: bool
description: description:
- If set to True, the I(extended_key_usage) extension field must contain only these values. - If set to C(yes), the I(extended_key_usage) extension field must contain only these values.
type: bool
default: no
aliases: [ extendedKeyUsage_strict ] aliases: [ extendedKeyUsage_strict ]
subject_alt_name: subject_alt_name:
description: description:
- The I(subject_alt_name) extension field must contain these values. - The I(subject_alt_name) extension field must contain these values.
type: list
aliases: [ subjectAltName ] aliases: [ subjectAltName ]
subject_alt_name_strict: subject_alt_name_strict:
default: False
type: bool
description: description:
- If set to True, the I(subject_alt_name) extension field must contain only these values. - If set to C(yes), the I(subject_alt_name) extension field must contain only these values.
type: bool
default: no
aliases: [ subjectAltName_strict ] aliases: [ subjectAltName_strict ]
extends_documentation_fragment: files extends_documentation_fragment: files
notes: notes:
- All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern. - All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.
Date specified should be UTC. Minutes and seconds are mandatory. - Date specified should be UTC. Minutes and seconds are mandatory.
- For security reason, when you use C(ownca) provider, you should NOT run M(openssl_certificate) on - For security reason, when you use C(ownca) provider, you should NOT run M(openssl_certificate) on
a target machine, but on a dedicated CA machine. It is recommended not to store the CA private key a target machine, but on a dedicated CA machine. It is recommended not to store the CA private key
on the target machine. Once signed, the certificate can be moved to the target machine. on the target machine. Once signed, the certificate can be moved to the target machine.
seealso:
- module: openssl_csr
- module: openssl_dhparam
- module: openssl_pkcs12
- module: openssl_privatekey
- module: openssl_publickey
''' '''
EXAMPLES = r'''
EXAMPLES = '''
- name: Generate a Self Signed OpenSSL certificate - name: Generate a Self Signed OpenSSL certificate
openssl_certificate: openssl_certificate:
path: /etc/ssl/crt/ansible.com.crt path: /etc/ssl/crt/ansible.com.crt
@ -306,7 +360,7 @@ EXAMPLES = '''
provider: acme provider: acme
acme_accountkey_path: /etc/ssl/private/ansible.com.pem acme_accountkey_path: /etc/ssl/private/ansible.com.pem
acme_challenge_path: /etc/ssl/challenges/ansible.com/ acme_challenge_path: /etc/ssl/challenges/ansible.com/
force: True force: yes
# Examples for some checks one could use the assertonly provider for: # Examples for some checks one could use the assertonly provider for:
@ -315,8 +369,8 @@ EXAMPLES = '''
openssl_certificate: openssl_certificate:
path: /etc/ssl/crt/example.com.crt path: /etc/ssl/crt/example.com.crt
provider: assertonly provider: assertonly
has_expired: False has_expired: no
ignore_errors: True ignore_errors: yes
register: validity_check register: validity_check
- name: Run custom task(s) to get a new, valid certificate in case the initial check failed - name: Run custom task(s) to get a new, valid certificate in case the initial check failed
@ -327,7 +381,7 @@ EXAMPLES = '''
openssl_certificate: openssl_certificate:
path: /etc/ssl/crt/example.com.crt path: /etc/ssl/crt/example.com.crt
provider: assertonly provider: assertonly
has_expired: False has_expired: no
when: validity_check.failed when: validity_check.failed
# Some other checks that assertonly could be used for: # Some other checks that assertonly could be used for:
@ -337,7 +391,7 @@ EXAMPLES = '''
provider: assertonly provider: assertonly
issuer: issuer:
O: Let's Encrypt O: Let's Encrypt
has_expired: False has_expired: no
- name: Ensure that a certificate uses a modern signature algorithm (no SHA1, MD5 or DSA) - name: Ensure that a certificate uses a modern signature algorithm (no SHA1, MD5 or DSA)
openssl_certificate: openssl_certificate:
@ -405,8 +459,7 @@ EXAMPLES = '''
- test.example.com - test.example.com
''' '''
RETURN = r'''
RETURN = '''
filename: filename:
description: Path to the generated Certificate description: Path to the generated Certificate
returned: changed or success returned: changed or success
@ -710,14 +763,14 @@ class AssertOnlyCertificate(Certificate):
self.issuer_strict = module.params['issuer_strict'] self.issuer_strict = module.params['issuer_strict']
self.has_expired = module.params['has_expired'] self.has_expired = module.params['has_expired']
self.version = module.params['version'] self.version = module.params['version']
self.keyUsage = module.params['keyUsage'] self.keyUsage = module.params['key_usage']
self.keyUsage_strict = module.params['keyUsage_strict'] self.keyUsage_strict = module.params['key_usage_strict']
self.extendedKeyUsage = module.params['extendedKeyUsage'] self.extendedKeyUsage = module.params['extended_key_usage']
self.extendedKeyUsage_strict = module.params['extendedKeyUsage_strict'] self.extendedKeyUsage_strict = module.params['extended_key_usage_strict']
self.subjectAltName = module.params['subjectAltName'] self.subjectAltName = module.params['subject_alt_name']
self.subjectAltName_strict = module.params['subjectAltName_strict'] self.subjectAltName_strict = module.params['subject_alt_name_strict']
self.notBefore = module.params['notBefore'] self.notBefore = module.params['not_before']
self.notAfter = module.params['notAfter'] self.notAfter = module.params['not_after']
self.valid_at = module.params['valid_at'] self.valid_at = module.params['valid_at']
self.invalid_at = module.params['invalid_at'] self.invalid_at = module.params['invalid_at']
self.valid_in = module.params['valid_in'] self.valid_in = module.params['valid_in']
@ -1002,7 +1055,7 @@ def main():
argument_spec=dict( argument_spec=dict(
state=dict(type='str', choices=['present', 'absent'], default='present'), state=dict(type='str', choices=['present', 'absent'], default='present'),
path=dict(type='path', required=True), path=dict(type='path', required=True),
provider=dict(type='str', choices=['selfsigned', 'ownca', 'assertonly', 'acme']), provider=dict(type='str', choices=['acme', 'assertonly', 'ownca', 'selfsigned']),
force=dict(type='bool', default=False,), force=dict(type='bool', default=False,),
csr_path=dict(type='path'), csr_path=dict(type='path'),
@ -1016,20 +1069,20 @@ def main():
issuer_strict=dict(type='bool', default=False), issuer_strict=dict(type='bool', default=False),
has_expired=dict(type='bool', default=False), has_expired=dict(type='bool', default=False),
version=dict(type='int'), version=dict(type='int'),
keyUsage=dict(type='list', aliases=['key_usage'], elements='str'), key_usage=dict(type='list', elements='str', aliases=['keyUsage']),
keyUsage_strict=dict(type='bool', default=False, aliases=['key_usage_strict']), key_usage_strict=dict(type='bool', default=False, aliases=['keyUsage_strict']),
extendedKeyUsage=dict(type='list', aliases=['extended_key_usage'], elements='str'), extended_key_usage=dict(type='list', elements='str', aliases=['extendedKeyUsage']),
extendedKeyUsage_strict=dict(type='bool', default=False, aliases=['extended_key_usage_strict']), extended_key_usage_strict=dict(type='bool', default=False, aliases=['extendedKeyUsage_strict']),
subjectAltName=dict(type='list', aliases=['subject_alt_name'], elements='str'), subject_alt_name=dict(type='list', elements='str', aliases=['subjectAltName']),
subjectAltName_strict=dict(type='bool', default=False, aliases=['subject_alt_name_strict']), subject_alt_name_strict=dict(type='bool', default=False, aliases=['subjectAltName_strict']),
notBefore=dict(type='str', aliases=['not_before']), not_before=dict(type='str', aliases=['notBefore']),
notAfter=dict(type='str', aliases=['not_after']), not_after=dict(type='str', aliases=['notAfter']),
valid_at=dict(type='str'), valid_at=dict(type='str'),
invalid_at=dict(type='str'), invalid_at=dict(type='str'),
valid_in=dict(type='str'), valid_in=dict(type='str'),
# provider: selfsigned # provider: selfsigned
selfsigned_version=dict(type='int', default='3'), selfsigned_version=dict(type='int', default=3),
selfsigned_digest=dict(type='str', default='sha256'), selfsigned_digest=dict(type='str', default='sha256'),
selfsigned_not_before=dict( selfsigned_not_before=dict(
type='str', default='+0s', aliases=['selfsigned_notBefore']), type='str', default='+0s', aliases=['selfsigned_notBefore']),
@ -1041,7 +1094,7 @@ def main():
ownca_privatekey_path=dict(type='path'), ownca_privatekey_path=dict(type='path'),
ownca_privatekey_passphrase=dict(type='path', no_log=True), ownca_privatekey_passphrase=dict(type='path', no_log=True),
ownca_digest=dict(type='str', default='sha256'), ownca_digest=dict(type='str', default='sha256'),
ownca_version=dict(type='int', default='3'), ownca_version=dict(type='int', default=3),
ownca_not_before=dict(type='str', default='+0s'), ownca_not_before=dict(type='str', default='+0s'),
ownca_not_after=dict(type='str', default='+3650d'), ownca_not_after=dict(type='str', default='+3650d'),

@ -1,228 +1,225 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# (c) 2017, Yanis Guenane <yanis+ansible@guenane.org> # Copyrigt: (c) 2017, Yanis Guenane <yanis+ansible@guenane.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'], 'status': ['preview'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = r'''
DOCUMENTATION = '''
--- ---
module: openssl_csr module: openssl_csr
author: "Yanis Guenane (@Spredzy)" version_added: '2.4'
version_added: "2.4"
short_description: Generate OpenSSL Certificate Signing Request (CSR) short_description: Generate OpenSSL Certificate Signing Request (CSR)
description: description:
- "This module allows one to (re)generate OpenSSL certificate signing requests. - This module allows one to (re)generate OpenSSL certificate signing requests.
It uses the pyOpenSSL python library to interact with openssl. This module supports - It uses the pyOpenSSL python library to interact with openssl. This module supports
the subjectAltName, keyUsage, extendedKeyUsage, basicConstraints and OCSP Must Staple the subjectAltName, keyUsage, extendedKeyUsage, basicConstraints and OCSP Must Staple
extensions." extensions.
requirements: requirements:
- "One of the following Python libraries:" - Either cryptography >= 1.3
- "cryptography >= 1.3" - Or pyOpenSSL >= 0.15
- "pyOpenSSL >= 0.15" author:
- Yanis Guenane (@Spredzy)
options: options:
state: state:
required: false
default: "present"
choices: [ present, absent ]
description: description:
- Whether the certificate signing request should exist or not, taking action if the state is different from what is stated. - Whether the certificate signing request should exist or not, taking action if the state is different from what is stated.
digest: type: str
required: false required: false
default: "sha256" choices: [ absent, present ]
default: present
digest:
description: description:
- Digest used when signing the certificate signing request with the private key - The digest used when signing the certificate signing request with the private key.
type: str
default: sha256
privatekey_path: privatekey_path:
required: true
description: description:
- Path to the privatekey to use when signing the certificate signing request - The path to the privatekey to use when signing the certificate signing request.
type: path
required: true
privatekey_passphrase: privatekey_passphrase:
required: false
description: description:
- The passphrase for the privatekey. - The passphrase for the privatekey.
type: str
version: version:
required: false
default: 1
description: description:
- Version of the certificate signing request - The version of the certificate signing request.
type: int
default: 1
force: force:
required: false
default: False
type: bool
description: description:
- Should the certificate signing request be forced regenerated by this ansible module - Should the certificate signing request be forced regenerated by this ansible module.
type: bool
default: no
path: path:
required: true
description: description:
- Name of the file into which the generated OpenSSL certificate signing request will be written - The name of the file into which the generated OpenSSL certificate signing request will be written.
type: path
required: true
subject: subject:
required: false
description: description:
- Key/value pairs that will be present in the subject name field of the certificate signing request. - Key/value pairs that will be present in the subject name field of the certificate signing request.
- If you need to specify more than one value with the same key, use a list as value. - If you need to specify more than one value with the same key, use a list as value.
type: str
version_added: '2.5' version_added: '2.5'
country_name: country_name:
required: false
aliases: [ 'C', 'countryName' ]
description: description:
- countryName field of the certificate signing request subject - The countryName field of the certificate signing request subject.
type: str
aliases: [ C, countryName ]
state_or_province_name: state_or_province_name:
required: false
aliases: [ 'ST', 'stateOrProvinceName' ]
description: description:
- stateOrProvinceName field of the certificate signing request subject - The stateOrProvinceName field of the certificate signing request subject.
type: str
aliases: [ ST, stateOrProvinceName ]
locality_name: locality_name:
required: false
aliases: [ 'L', 'localityName' ]
description: description:
- localityName field of the certificate signing request subject - The localityName field of the certificate signing request subject.
type: str
aliases: [ L, localityName ]
organization_name: organization_name:
required: false
aliases: [ 'O', 'organizationName' ]
description: description:
- organizationName field of the certificate signing request subject - The organizationName field of the certificate signing request subject.
type: str
aliases: [ O, organizationName ]
organizational_unit_name: organizational_unit_name:
required: false
aliases: [ 'OU', 'organizationalUnitName' ]
description: description:
- organizationalUnitName field of the certificate signing request subject - The organizationalUnitName field of the certificate signing request subject.
type: str
aliases: [ OU, organizationalUnitName ]
common_name: common_name:
required: false
aliases: [ 'CN', 'commonName' ]
description: description:
- commonName field of the certificate signing request subject - The commonName field of the certificate signing request subject.
type: str
aliases: [ CN, commonName ]
email_address: email_address:
required: false
aliases: [ 'E', 'emailAddress' ]
description: description:
- emailAddress field of the certificate signing request subject - The emailAddress field of the certificate signing request subject.
type: str
aliases: [ E, emailAddress ]
subject_alt_name: subject_alt_name:
required: false
aliases: [ 'subjectAltName' ]
description: description:
- SAN extension to attach to the certificate signing request - SAN extension to attach to the certificate signing request.
- This can either be a 'comma separated string' or a YAML list. - This can either be a 'comma separated string' or a YAML list.
- Values should be prefixed by their options. (i.e., C(email), C(URI), C(DNS), C(RID), C(IP), C(dirName), - Values should be prefixed by their options. (i.e., C(email), C(URI), C(DNS), C(RID), C(IP), C(dirName),
C(otherName) and the ones specific to your CA) C(otherName) and the ones specific to your CA)
- Note that if no SAN is specified, but a common name, the common - Note that if no SAN is specified, but a common name, the common
name will be added as a SAN except if C(useCommonNameForSAN) is name will be added as a SAN except if C(useCommonNameForSAN) is
set to I(false). set to I(false).
- More at U(https://tools.ietf.org/html/rfc5280#section-4.2.1.6) - More at U(https://tools.ietf.org/html/rfc5280#section-4.2.1.6).
type: list
aliases: [ subjectAltName ]
subject_alt_name_critical: subject_alt_name_critical:
required: false
aliases: [ 'subjectAltName_critical' ]
description: description:
- Should the subjectAltName extension be considered as critical - Should the subjectAltName extension be considered as critical.
useCommonNameForSAN:
type: bool type: bool
default: true aliases: [ subjectAltName_critical ]
use_common_name_for_san:
description: description:
- If set to I(true), the module will fill the common name in for - If set to C(yes), the module will fill the common name in for
C(subject_alt_name) with C(DNS:) prefix if no SAN is specified. C(subject_alt_name) with C(DNS:) prefix if no SAN is specified.
type: bool
default: yes
aliases: [ useCommonNameForSAN ]
version_added: '2.8' version_added: '2.8'
key_usage: key_usage:
required: false
aliases: [ 'keyUsage' ]
description: description:
- This defines the purpose (e.g. encipherment, signature, certificate signing) - This defines the purpose (e.g. encipherment, signature, certificate signing)
of the key contained in the certificate. of the key contained in the certificate.
- This can either be a 'comma separated string' or a YAML list. type: list
aliases: [ keyUsage ]
key_usage_critical: key_usage_critical:
required: false
aliases: [ 'keyUsage_critical' ]
description: description:
- Should the keyUsage extension be considered as critical - Should the keyUsage extension be considered as critical.
type: bool
aliases: [ keyUsage_critical ]
extended_key_usage: extended_key_usage:
required: false
aliases: [ 'extKeyUsage', 'extendedKeyUsage' ]
description: description:
- Additional restrictions (e.g. client authentication, server authentication) - Additional restrictions (e.g. client authentication, server authentication)
on the allowed purposes for which the public key may be used. on the allowed purposes for which the public key may be used.
- This can either be a 'comma separated string' or a YAML list. type: list
aliases: [ extKeyUsage, extendedKeyUsage ]
extended_key_usage_critical: extended_key_usage_critical:
required: false
aliases: [ 'extKeyUsage_critical', 'extendedKeyUsage_critical' ]
description: description:
- Should the extkeyUsage extension be considered as critical - Should the extkeyUsage extension be considered as critical.
type: bool
aliases: [ extKeyUsage_critical, extendedKeyUsage_critical ]
basic_constraints: basic_constraints:
required: false
aliases: ['basicConstraints']
description: description:
- Indicates basic constraints, such as if the certificate is a CA. - Indicates basic constraints, such as if the certificate is a CA.
version_added: 2.5 type: list
aliases: [ basicConstraints ]
version_added: '2.5'
basic_constraints_critical: basic_constraints_critical:
required: false
aliases: [ 'basicConstraints_critical' ]
description: description:
- Should the basicConstraints extension be considered as critical - Should the basicConstraints extension be considered as critical.
version_added: 2.5 type: bool
aliases: [ basicConstraints_critical ]
version_added: '2.5'
ocsp_must_staple: ocsp_must_staple:
required: false
aliases: ['ocspMustStaple']
description: description:
- Indicates that the certificate should contain the OCSP Must Staple - Indicates that the certificate should contain the OCSP Must Staple
extension (U(https://tools.ietf.org/html/rfc7633)). extension (U(https://tools.ietf.org/html/rfc7633)).
version_added: 2.5 type: bool
aliases: [ ocspMustStaple ]
version_added: '2.5'
ocsp_must_staple_critical: ocsp_must_staple_critical:
required: false
aliases: [ 'ocspMustStaple_critical' ]
description: description:
- Should the OCSP Must Staple extension be considered as critical - Should the OCSP Must Staple extension be considered as critical
- "Warning: according to the RFC, this extension should not be marked - Note that according to the RFC, this extension should not be marked
as critical, as old clients not knowing about OCSP Must Staple as critical, as old clients not knowing about OCSP Must Staple
are required to reject such certificates are required to reject such certificates
(see U(https://tools.ietf.org/html/rfc7633#section-4))." (see U(https://tools.ietf.org/html/rfc7633#section-4)).
version_added: 2.5 type: bool
aliases: [ ocspMustStaple_critical ]
version_added: '2.5'
select_crypto_backend: select_crypto_backend:
description: description:
- "Determines which crypto backend to use. The default choice is C(auto), - Determines which crypto backend to use.
which tries to use C(cryptography) if available, and falls back to - The default choice is C(auto), which tries to use C(cryptography) if available, and falls back to C(pyopenssl).
C(pyopenssl)." - If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) library.
- "If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) - If set to C(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
library."
- "If set to C(cryptography), will try to use the
L(cryptography,https://cryptography.io/) library."
type: str type: str
default: 'auto' choices: [ auto, cryptography, pyopenssl ]
choices: default: auto
- auto version_added: '2.8'
- cryptography extends_documentation_fragment:
- pyopenssl - files
version_added: "2.8"
extends_documentation_fragment: files
notes: notes:
- "If the certificate signing request already exists it will be checked whether subjectAltName, - If the certificate signing request already exists it will be checked whether subjectAltName,
keyUsage, extendedKeyUsage and basicConstraints only contain the requested values, whether keyUsage, extendedKeyUsage and basicConstraints only contain the requested values, whether
OCSP Must Staple is as requested, and if the request was signed by the given private key." OCSP Must Staple is as requested, and if the request was signed by the given private key.
seealso:
- module: openssl_certificate
- module: openssl_dhparam
- module: openssl_pkcs12
- module: openssl_privatekey
- module: openssl_publickey
''' '''
EXAMPLES = r'''
EXAMPLES = ''' - name: Generate an OpenSSL Certificate Signing Request
# Generate an OpenSSL Certificate Signing Request openssl_csr:
- openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
common_name: www.ansible.com common_name: www.ansible.com
# Generate an OpenSSL Certificate Signing Request with a - name: Generate an OpenSSL Certificate Signing Request with a passphrase protected private key
# passphrase protected private key openssl_csr:
- openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
privatekey_passphrase: ansible privatekey_passphrase: ansible
common_name: www.ansible.com common_name: www.ansible.com
# Generate an OpenSSL Certificate Signing Request with Subject information - name: Generate an OpenSSL Certificate Signing Request with Subject information
- openssl_csr: openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
country_name: FR country_name: FR
@ -230,14 +227,14 @@ EXAMPLES = '''
email_address: jdoe@ansible.com email_address: jdoe@ansible.com
common_name: www.ansible.com common_name: www.ansible.com
# Generate an OpenSSL Certificate Signing Request with subjectAltName extension - name: Generate an OpenSSL Certificate Signing Request with subjectAltName extension
- openssl_csr: openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
subject_alt_name: 'DNS:www.ansible.com,DNS:m.ansible.com' subject_alt_name: 'DNS:www.ansible.com,DNS:m.ansible.com'
# Generate an OpenSSL CSR with subjectAltName extension with dynamic list - name: Generate an OpenSSL CSR with subjectAltName extension with dynamic list
- openssl_csr: openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
subject_alt_name: "{{ item.value | map('regex_replace', '^', 'DNS:') | list }}" subject_alt_name: "{{ item.value | map('regex_replace', '^', 'DNS:') | list }}"
@ -246,15 +243,15 @@ EXAMPLES = '''
- www.ansible.com - www.ansible.com
- m.ansible.com - m.ansible.com
# Force re-generate an OpenSSL Certificate Signing Request - name: Force re-generate an OpenSSL Certificate Signing Request
- openssl_csr: openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
force: True force: yes
common_name: www.ansible.com common_name: www.ansible.com
# Generate an OpenSSL Certificate Signing Request with special key usages - name: Generate an OpenSSL Certificate Signing Request with special key usages
- openssl_csr: openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
common_name: www.ansible.com common_name: www.ansible.com
@ -264,16 +261,15 @@ EXAMPLES = '''
extended_key_usage: extended_key_usage:
- clientAuth - clientAuth
# Generate an OpenSSL Certificate Signing Request with OCSP Must Staple - name: Generate an OpenSSL Certificate Signing Request with OCSP Must Staple
- openssl_csr: openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
common_name: www.ansible.com common_name: www.ansible.com
ocsp_must_staple: true ocsp_must_staple: yes
''' '''
RETURN = r'''
RETURN = '''
privatekey: privatekey:
description: Path to the TLS/SSL private key the CSR was generated for description: Path to the TLS/SSL private key the CSR was generated for
returned: changed or success returned: changed or success
@ -384,34 +380,34 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
self.privatekey_path = module.params['privatekey_path'] self.privatekey_path = module.params['privatekey_path']
self.privatekey_passphrase = module.params['privatekey_passphrase'] self.privatekey_passphrase = module.params['privatekey_passphrase']
self.version = module.params['version'] self.version = module.params['version']
self.subjectAltName = module.params['subjectAltName'] self.subjectAltName = module.params['subject_alt_name']
self.subjectAltName_critical = module.params['subjectAltName_critical'] self.subjectAltName_critical = module.params['subject_alt_name_critical']
self.keyUsage = module.params['keyUsage'] self.keyUsage = module.params['key_usage']
self.keyUsage_critical = module.params['keyUsage_critical'] self.keyUsage_critical = module.params['key_usage_critical']
self.extendedKeyUsage = module.params['extendedKeyUsage'] self.extendedKeyUsage = module.params['extended_key_usage']
self.extendedKeyUsage_critical = module.params['extendedKeyUsage_critical'] self.extendedKeyUsage_critical = module.params['extended_key_usage_critical']
self.basicConstraints = module.params['basicConstraints'] self.basicConstraints = module.params['basic_constraints']
self.basicConstraints_critical = module.params['basicConstraints_critical'] self.basicConstraints_critical = module.params['basic_constraints_critical']
self.ocspMustStaple = module.params['ocspMustStaple'] self.ocspMustStaple = module.params['ocsp_must_staple']
self.ocspMustStaple_critical = module.params['ocspMustStaple_critical'] self.ocspMustStaple_critical = module.params['ocsp_must_staple_critical']
self.request = None self.request = None
self.privatekey = None self.privatekey = None
self.subject = [ self.subject = [
('C', module.params['countryName']), ('C', module.params['country_name']),
('ST', module.params['stateOrProvinceName']), ('ST', module.params['state_or_province_name']),
('L', module.params['localityName']), ('L', module.params['locality_name']),
('O', module.params['organizationName']), ('O', module.params['organization_name']),
('OU', module.params['organizationalUnitName']), ('OU', module.params['organizational_unit_name']),
('CN', module.params['commonName']), ('CN', module.params['common_name']),
('emailAddress', module.params['emailAddress']), ('emailAddress', module.params['email_address']),
] ]
if module.params['subject']: if module.params['subject']:
self.subject = self.subject + crypto_utils.parse_name_field(module.params['subject']) self.subject = self.subject + crypto_utils.parse_name_field(module.params['subject'])
self.subject = [(entry[0], entry[1]) for entry in self.subject if entry[1]] self.subject = [(entry[0], entry[1]) for entry in self.subject if entry[1]]
if not self.subjectAltName and module.params['useCommonNameForSAN']: if not self.subjectAltName and module.params['use_common_name_for_san']:
for sub in self.subject: for sub in self.subject:
if sub[0] in ('commonName', 'CN'): if sub[0] in ('commonName', 'CN'):
self.subjectAltName = ['DNS:%s' % sub[1]] self.subjectAltName = ['DNS:%s' % sub[1]]
@ -944,33 +940,33 @@ class CertificateSigningRequestCryptography(CertificateSigningRequestBase):
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'], type='str'), state=dict(type='str', default='present', choices=['absent', 'present']),
digest=dict(default='sha256', type='str'), digest=dict(type='str', default='sha256'),
privatekey_path=dict(require=True, type='path'), privatekey_path=dict(type='path', require=True),
privatekey_passphrase=dict(type='str', no_log=True), privatekey_passphrase=dict(type='str', no_log=True),
version=dict(default='1', type='int'), version=dict(type='int', default=1),
force=dict(default=False, type='bool'), force=dict(type='bool', default=False),
path=dict(required=True, type='path'), path=dict(type='path', required=True),
subject=dict(type='dict'), subject=dict(type='dict'),
countryName=dict(aliases=['C', 'country_name'], type='str'), country_name=dict(type='str', aliases=['C', 'countryName']),
stateOrProvinceName=dict(aliases=['ST', 'state_or_province_name'], type='str'), state_or_province_name=dict(type='str', aliases=['ST', 'stateOrProvinceName']),
localityName=dict(aliases=['L', 'locality_name'], type='str'), locality_name=dict(type='str', aliases=['L', 'localityName']),
organizationName=dict(aliases=['O', 'organization_name'], type='str'), organization_name=dict(type='str', aliases=['O', 'organizationName']),
organizationalUnitName=dict(aliases=['OU', 'organizational_unit_name'], type='str'), organizational_unit_name=dict(type='str', aliases=['OU', 'organizationalUnitName']),
commonName=dict(aliases=['CN', 'common_name'], type='str'), common_name=dict(type='str', aliases=['CN', 'commonName']),
emailAddress=dict(aliases=['E', 'email_address'], type='str'), email_address=dict(type='str', aliases=['E', 'emailAddress']),
subjectAltName=dict(aliases=['subject_alt_name'], type='list', elements='str'), subject_alt_name=dict(type='list', elements='str', aliases=['subjectAltName']),
subjectAltName_critical=dict(aliases=['subject_alt_name_critical'], default=False, type='bool'), subject_alt_name_critical=dict(type='bool', default=False, aliases=['subjectAltName_critical']),
useCommonNameForSAN=dict(type='bool', default=True), use_common_name_for_san=dict(type='bool', default=True, aliases=['useCommonNameForSAN']),
keyUsage=dict(aliases=['key_usage'], type='list', elements='str'), key_usage=dict(type='list', elements='str', aliases=['keyUsage']),
keyUsage_critical=dict(aliases=['key_usage_critical'], default=False, type='bool'), key_usage_critical=dict(type='bool', default=False, aliases=['keyUsage_critical']),
extendedKeyUsage=dict(aliases=['extKeyUsage', 'extended_key_usage'], type='list', elements='str'), extended_key_usage=dict(type='list', elements='str', aliases=['extKeyUsage', 'extendedKeyUsage']),
extendedKeyUsage_critical=dict(aliases=['extKeyUsage_critical', 'extended_key_usage_critical'], default=False, type='bool'), extended_key_usage_critical=dict(type='bool', default=False, aliases=['extKeyUsage_critical', 'extendedKeyUsage_critical']),
basicConstraints=dict(aliases=['basic_constraints'], type='list', elements='str'), basic_constraints=dict(type='list', elements='str', aliases=['basicConstraints']),
basicConstraints_critical=dict(aliases=['basic_constraints_critical'], default=False, type='bool'), basic_constraints_critical=dict(type='bool', default=False, aliases=['basicConstraints_critical']),
ocspMustStaple=dict(aliases=['ocsp_must_staple'], default=False, type='bool'), ocsp_must_staple=dict(type='bool', default=False, aliases=['ocspMustStaple']),
ocspMustStaple_critical=dict(aliases=['ocsp_must_staple_critical'], default=False, type='bool'), ocsp_must_staple_critical=dict(type='bool', default=False, aliases=['ocspMustStaple_critical']),
select_crypto_backend=dict(required=False, choices=['auto', 'pyopenssl', 'cryptography'], default='auto', type='str'), select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']),
), ),
add_file_common_args=True, add_file_common_args=True,
supports_check_mode=True, supports_check_mode=True,

@ -1,80 +1,85 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# (c) 2017, Thom Wiggers <ansible@thomwiggers.nl> # Copyright: (c) 2017, Thom Wiggers <ansible@thomwiggers.nl>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'], 'status': ['preview'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = r'''
DOCUMENTATION = '''
--- ---
module: openssl_dhparam module: openssl_dhparam
author: "Thom Wiggers (@thomwiggers)"
version_added: "2.5" version_added: "2.5"
short_description: Generate OpenSSL Diffie-Hellman Parameters short_description: Generate OpenSSL Diffie-Hellman Parameters
description: description:
- "This module allows one to (re)generate OpenSSL DH-params. - This module allows one to (re)generate OpenSSL DH-params.
This module uses file common arguments to specify generated file permissions." - This module uses file common arguments to specify generated file permissions.
requirements: requirements:
- OpenSSL - OpenSSL
author:
- Thom Wiggers (@thomwiggers)
options: options:
state: state:
required: false
default: "present"
choices: [ present, absent ]
description: description:
- Whether the parameters should exist or not, - Whether the parameters should exist or not,
taking action if the state is different from what is stated. taking action if the state is different from what is stated.
type: str
choices: [ absent, present ]
default: present
size: size:
required: false
default: 4096
description: description:
- Size (in bits) of the generated DH-params - Size (in bits) of the generated DH-params.
type: int
default: 4096
force: force:
required: false
default: False
type: bool
description: description:
- Should the parameters be regenerated even it it already exists - Should the parameters be regenerated even it it already exists.
type: bool
default: no
path: path:
required: true
description: description:
- Name of the file in which the generated parameters will be saved. - Name of the file in which the generated parameters will be saved.
extends_documentation_fragment: files type: path
required: true
extends_documentation_fragment:
- files
seealso:
- module: openssl_certificate
- module: openssl_csr
- module: openssl_pkcs12
- module: openssl_privatekey
- module: openssl_publickey
''' '''
EXAMPLES = ''' EXAMPLES = r'''
# Generate Diffie-Hellman parameters with the default size (4096 bits) - name: Generate Diffie-Hellman parameters with the default size (4096 bits)
- openssl_dhparam: openssl_dhparam:
path: /etc/ssl/dhparams.pem path: /etc/ssl/dhparams.pem
# Generate DH Parameters with a different size (2048 bits) - name: Generate DH Parameters with a different size (2048 bits)
- openssl_dhparam: openssl_dhparam:
path: /etc/ssl/dhparams.pem path: /etc/ssl/dhparams.pem
size: 2048 size: 2048
# Force regenerate an DH parameters if they already exist - name: Force regenerate an DH parameters if they already exist
- openssl_dhparam: openssl_dhparam:
path: /etc/ssl/dhparams.pem path: /etc/ssl/dhparams.pem
force: True force: yes
''' '''
RETURN = ''' RETURN = r'''
size: size:
description: Size (in bits) of the Diffie-Hellman parameters description: Size (in bits) of the Diffie-Hellman parameters.
returned: changed or success returned: changed or success
type: int type: int
sample: 4096 sample: 4096
filename: filename:
description: Path to the generated Diffie-Hellman parameters description: Path to the generated Diffie-Hellman parameters.
returned: changed or success returned: changed or success
type: str type: str
sample: /etc/ssl/dhparams.pem sample: /etc/ssl/dhparams.pem
@ -97,7 +102,7 @@ class DHParameter(object):
def __init__(self, module): def __init__(self, module):
self.state = module.params['state'] self.state = module.params['state']
self.path = module.params['path'] self.path = module.params['path']
self.size = int(module.params['size']) self.size = module.params['size']
self.force = module.params['force'] self.force = module.params['force']
self.changed = False self.changed = False
self.openssl_bin = module.get_bin_path('openssl', True) self.openssl_bin = module.get_bin_path('openssl', True)
@ -150,7 +155,7 @@ class DHParameter(object):
match = re.search(r"Parameters:\s+\((\d+) bit\).*", result) match = re.search(r"Parameters:\s+\((\d+) bit\).*", result)
if not match: if not match:
return False # No "xxxx bit" in output return False # No "xxxx bit" in output
else:
bits = int(match.group(1)) bits = int(match.group(1))
# if output contains "WARNING" we've got a problem # if output contains "WARNING" we've got a problem
@ -182,10 +187,10 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'], type='str'), state=dict(type='str', default='present', choices=['absent', 'present']),
size=dict(default=4096, type='int'), size=dict(type='int', default=4096),
force=dict(default=False, type='bool'), force=dict(type='bool', default=False),
path=dict(required=True, type='path'), path=dict(type='path', required=True),
), ),
supports_check_mode=True, supports_check_mode=True,
add_file_common_args=True, add_file_common_args=True,
@ -195,7 +200,7 @@ def main():
if not os.path.isdir(base_dir): if not os.path.isdir(base_dir):
module.fail_json( module.fail_json(
name=base_dir, name=base_dir,
msg='The directory %s does not exist or the file is not a directory' % base_dir msg="The directory '%s' does not exist or the file is not a directory" % base_dir
) )
dhparam = DHParameter(module) dhparam = DHParameter(module)

@ -1,8 +1,8 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# Copyright: (c) 2017, Guillaume Delpierre <gde@llew.me>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Copyright (c) 2017 Guillaume Delpierre <gde@llew.me>
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
@ -11,128 +11,145 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'], 'status': ['preview'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = ''' DOCUMENTATION = r'''
--- ---
module: openssl_pkcs12 module: openssl_pkcs12
author: "Guillaume Delpierre (@gdelpierre)" author:
- Guillaume Delpierre (@gdelpierre)
version_added: "2.7" version_added: "2.7"
short_description: Generate OpenSSL PKCS#12 archive. short_description: Generate OpenSSL PKCS#12 archive
description: description:
- This module allows one to (re-)generate PKCS#12. - This module allows one to (re-)generate PKCS#12.
requirements: requirements:
- python-pyOpenSSL - python-pyOpenSSL
options: options:
action: action:
default: export
choices: ['parse', 'export']
description: description:
- C(export) or C(parse) a PKCS#12. - C(export) or C(parse) a PKCS#12.
choices: [ export, parse ]
default: export
ca_certificates: ca_certificates:
description: description:
- List of CA certificate to include. - List of CA certificate to include.
type: list
certificate_path: certificate_path:
description: description:
- The path to read certificates and private keys from. Must be in PEM format. - The path to read certificates and private keys from.
- Must be in PEM format.
type: path
force: force:
default: False
type: bool
description: description:
- Should the file be regenerated even if it already exists. - Should the file be regenerated even if it already exists.
type: bool
default: no
friendly_name: friendly_name:
aliases: ['name']
description: description:
- Specifies the friendly name for the certificate and private key. - Specifies the friendly name for the certificate and private key.
type: str
aliases: [ name ]
iter_size: iter_size:
default: 2048
description: description:
- Number of times to repeat the encryption step. - Number of times to repeat the encryption step.
type: int
default: 2048
maciter_size: maciter_size:
default: 1
description: description:
- Number of times to repeat the MAC step. - Number of times to repeat the MAC step.
type: int
default: 1
passphrase: passphrase:
description: description:
- The PKCS#12 password. - The PKCS#12 password.
type: str
path: path:
required: True
description: description:
- Filename to write the PKCS#12 file to. - Filename to write the PKCS#12 file to.
type: path
required: True
privatekey_passphrase: privatekey_passphrase:
description: description:
- Passphrase source to decrypt any input private keys with. - Passphrase source to decrypt any input private keys with.
type: str
privatekey_path: privatekey_path:
description: description:
- File to read private key from. - File to read private key from.
type: path
state: state:
default: 'present'
choices: ['present', 'absent']
description: description:
- Whether the file should exist or not. - Whether the file should exist or not.
All parameters except C(path) are ignored when state is C(absent). All parameters except C(path) are ignored when state is C(absent).
choices: [ absent, present ]
default: present
src: src:
description: description:
- PKCS#12 file path to parse. - PKCS#12 file path to parse.
type: path
extends_documentation_fragment: extends_documentation_fragment:
- files - files
seealso:
- module: openssl_certificate
- module: openssl_csr
- module: openssl_dhparam
- module: openssl_privatekey
- module: openssl_publickey
''' '''
EXAMPLES = ''' EXAMPLES = r'''
- name: 'Generate PKCS#12 file' - name: Generate PKCS#12 file
openssl_pkcs12: openssl_pkcs12:
action: export action: export
path: '/opt/certs/ansible.p12' path: /opt/certs/ansible.p12
friendly_name: 'raclette' friendly_name: raclette
privatekey_path: '/opt/certs/keys/key.pem' privatekey_path: /opt/certs/keys/key.pem
certificate_path: '/opt/certs/cert.pem' certificate_path: /opt/certs/cert.pem
ca_certificates: '/opt/certs/ca.pem' ca_certificates: /opt/certs/ca.pem
state: present state: present
- name: 'Change PKCS#12 file permission' - name: Change PKCS#12 file permission
openssl_pkcs12: openssl_pkcs12:
action: export action: export
path: '/opt/certs/ansible.p12' path: /opt/certs/ansible.p12
friendly_name: 'raclette' friendly_name: raclette
privatekey_path: '/opt/certs/keys/key.pem' privatekey_path: /opt/certs/keys/key.pem
certificate_path: '/opt/certs/cert.pem' certificate_path: /opt/certs/cert.pem
ca_certificates: '/opt/certs/ca.pem' ca_certificates: /opt/certs/ca.pem
state: present state: present
mode: 0600 mode: '0600'
- name: 'Regen PKCS#12 file' - name: Regen PKCS#12 file
openssl_pkcs12: openssl_pkcs12:
action: export action: export
src: '/opt/certs/ansible.p12' src: /opt/certs/ansible.p12
path: '/opt/certs/ansible.p12' path: /opt/certs/ansible.p12
friendly_name: 'raclette' friendly_name: raclette
privatekey_path: '/opt/certs/keys/key.pem' privatekey_path: /opt/certs/keys/key.pem
certificate_path: '/opt/certs/cert.pem' certificate_path: /opt/certs/cert.pem
ca_certificates: '/opt/certs/ca.pem' ca_certificates: /opt/certs/ca.pem
state: present state: present
mode: 0600 mode: '0600'
force: True force: yes
- name: 'Dump/Parse PKCS#12 file' - name: Dump/Parse PKCS#12 file
openssl_pkcs12: openssl_pkcs12:
action: parse action: parse
src: '/opt/certs/ansible.p12' src: /opt/certs/ansible.p12
path: '/opt/certs/ansible.pem' path: /opt/certs/ansible.pem
state: present state: present
- name: 'Remove PKCS#12 file' - name: Remove PKCS#12 file
openssl_pkcs12: openssl_pkcs12:
path: '/opt/certs/ansible.p12' path: /opt/certs/ansible.p12
state: absent state: absent
''' '''
RETURN = ''' RETURN = r'''
filename: filename:
description: Path to the generate PKCS#12 file. description: Path to the generate PKCS#12 file.
returned: changed or success returned: changed or success
type: str type: str
sample: /opt/certs/ansible.p12 sample: /opt/certs/ansible.p12
privatekey: privatekey:
description: Path to the TLS/SSL private key the public key was generated from description: Path to the TLS/SSL private key the public key was generated from.
returned: changed or success returned: changed or success
type: str type: str
sample: /etc/ssl/private/ansible.com.pem sample: /etc/ssl/private/ansible.com.pem
@ -280,8 +297,7 @@ class Pkcs(crypto_utils.OpenSSLObject):
def main(): def main():
argument_spec = dict( argument_spec = dict(
action=dict(type='str', default='export', action=dict(type='str', default='export', choices=['export', 'parse']),
choices=['parse', 'export']),
ca_certificates=dict(type='list', elements='path'), ca_certificates=dict(type='list', elements='path'),
certificate_path=dict(type='path'), certificate_path=dict(type='path'),
force=dict(type='bool', default=False), force=dict(type='bool', default=False),
@ -292,8 +308,7 @@ def main():
path=dict(type='path', required=True), path=dict(type='path', required=True),
privatekey_passphrase=dict(type='str', no_log=True), privatekey_passphrase=dict(type='str', no_log=True),
privatekey_path=dict(type='path'), privatekey_path=dict(type='path'),
state=dict(type='str', default='present', state=dict(type='str', default='present', choices=['absent', 'present']),
choices=['present', 'absent']),
src=dict(type='path'), src=dict(type='path'),
) )
@ -320,8 +335,7 @@ def main():
if not os.path.isdir(base_dir): if not os.path.isdir(base_dir):
module.fail_json( module.fail_json(
name=base_dir, name=base_dir,
msg='The directory %s does not exist or ' msg="The directory '%s' does not exist or the path is not a directory" % base_dir
'the path is not a directory' % base_dir
) )
pkcs12 = Pkcs(module) pkcs12 = Pkcs(module)

@ -1,66 +1,65 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# (c) 2016, Yanis Guenane <yanis+ansible@guenane.org> # Copyright: (c) 2016, Yanis Guenane <yanis+ansible@guenane.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'], 'status': ['preview'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = r'''
DOCUMENTATION = '''
--- ---
module: openssl_privatekey module: openssl_privatekey
author:
- "Yanis Guenane (@Spredzy)"
- "Felix Fontein (@felixfontein)"
version_added: "2.3" version_added: "2.3"
short_description: Generate OpenSSL private keys. short_description: Generate OpenSSL private keys
description: description:
- "This module allows one to (re)generate OpenSSL private keys. One can - This module allows one to (re)generate OpenSSL private keys.
generate L(RSA,https://en.wikipedia.org/wiki/RSA_(cryptosystem)), - One can generate L(RSA,https://en.wikipedia.org/wiki/RSA_(cryptosystem)),
L(DSA,https://en.wikipedia.org/wiki/Digital_Signature_Algorithm) or L(DSA,https://en.wikipedia.org/wiki/Digital_Signature_Algorithm) or
L(ECC,https://en.wikipedia.org/wiki/Elliptic-curve_cryptography) L(ECC,https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)
private keys. Keys are generated in PEM format." private keys.
- "The module can use the cryptography Python library, or the pyOpenSSL Python - Keys are generated in PEM format.
- The module can use the cryptography Python library, or the pyOpenSSL Python
library. By default, it tries to detect which one is available. This can be library. By default, it tries to detect which one is available. This can be
overridden with the I(select_crypto_backend) option." overridden with the I(select_crypto_backend) option."
requirements: requirements:
- "One of the following Python libraries:" - Either cryptography >= 1.2.3 (older versions might work as well)
- "cryptography >= 1.2.3 (older versions might work as well)" - Or pyOpenSSL
- "pyOpenSSL" author:
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
options: options:
state: state:
required: false
default: "present"
choices: [ present, absent ]
description: description:
- Whether the private key should exist or not, taking action if the state is different from what is stated. - Whether the private key should exist or not, taking action if the state is different from what is stated.
type: str
choices: [ absent, present ]
default: present
size: size:
required: false
default: 4096
description: description:
- Size (in bits) of the TLS/SSL key to generate - Size (in bits) of the TLS/SSL key to generate.
type: int
default: 4096
type: type:
required: false
default: "RSA"
choices:
- RSA
- DSA
- ECC
# - X448
# - X25519
description: description:
- The algorithm used to generate the TLS/SSL private key - The algorithm used to generate the TLS/SSL private key.
- "Note that C(ECC) requires the C(cryptography) backend. Depending on the curve, you need a newer - Note that C(ECC) requires the C(cryptography) backend.
version of the cryptography backend." - Depending on the curve, you need a newer version of the cryptography backend.
type: str
#choices: [ DSA, ECC, RSA, X448, X25519 ]
choices: [ DSA, ECC, RSA ]
default: RSA
curve: curve:
required: false description:
- Note that not all curves are supported by all versions of C(cryptography).
- For maximal interoperability, C(secp384r1) or C(secp256k1) should be used.
- We use the curve names as defined in the
L(IANA registry for TLS,https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
type: str
choices: choices:
- secp384r1 - secp384r1
- secp521r1 - secp521r1
@ -80,105 +79,100 @@ options:
- sect283r1 - sect283r1
- sect233r1 - sect233r1
- sect163r2 - sect163r2
description:
- Note that not all curves are supported by all versions of C(cryptography).
- For maximal interoperability, C(secp384r1) or C(secp256k1) should be used.
- We use the curve names as defined in the
L(IANA registry for TLS,https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
version_added: "2.8" version_added: "2.8"
force: force:
required: false
default: False
type: bool
description: description:
- Should the key be regenerated even if it already exists - Should the key be regenerated even if it already exists.
type: bool
default: no
path: path:
required: true
description: description:
- Name of the file in which the generated TLS/SSL private key will be written. It will have 0600 mode. - Name of the file in which the generated TLS/SSL private key will be written. It will have 0600 mode.
type: path
required: true
passphrase: passphrase:
required: false
description: description:
- The passphrase for the private key. - The passphrase for the private key.
type: str
version_added: "2.4" version_added: "2.4"
cipher: cipher:
required: false
description: description:
- The cipher to encrypt the private key. (cipher can be found by running `openssl list-cipher-algorithms`) - The cipher to encrypt the private key. (cipher can be found by running `openssl list-cipher-algorithms`)
- When using the C(cryptography) backend, use C(auto). - When using the C(cryptography) backend, use C(auto).
type: str
version_added: "2.4" version_added: "2.4"
select_crypto_backend: select_crypto_backend:
description: description:
- "Determines which crypto backend to use. The default choice is C(auto), - Determines which crypto backend to use.
which tries to use C(cryptography) if available, and falls back to - The default choice is C(auto), which tries to use C(cryptography) if available, and falls back to C(pyopenssl).
C(pyopenssl)." - If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) library.
- "If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) - If set to C(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
library."
- "If set to C(cryptography), will try to use the
L(cryptography,https://cryptography.io/) library."
type: str type: str
default: 'auto' choices: [ auto, cryptography, pyopenssl ]
choices: default: auto
- auto
- cryptography
- pyopenssl
version_added: "2.8" version_added: "2.8"
extends_documentation_fragment: files extends_documentation_fragment:
- files
seealso:
- module: openssl_certificate
- module: openssl_csr
- module: openssl_dhparam
- module: openssl_pkcs12
- module: openssl_publickey
''' '''
EXAMPLES = ''' EXAMPLES = r'''
# Generate an OpenSSL private key with the default values (4096 bits, RSA) - name: Generate an OpenSSL private key with the default values (4096 bits, RSA)
- openssl_privatekey: openssl_privatekey:
path: /etc/ssl/private/ansible.com.pem path: /etc/ssl/private/ansible.com.pem
# Generate an OpenSSL private key with the default values (4096 bits, RSA) - name: Generate an OpenSSL private key with the default values (4096 bits, RSA) and a passphrase
# and a passphrase openssl_privatekey:
- openssl_privatekey:
path: /etc/ssl/private/ansible.com.pem path: /etc/ssl/private/ansible.com.pem
passphrase: ansible passphrase: ansible
cipher: aes256 cipher: aes256
# Generate an OpenSSL private key with a different size (2048 bits) - name: Generate an OpenSSL private key with a different size (2048 bits)
- openssl_privatekey: openssl_privatekey:
path: /etc/ssl/private/ansible.com.pem path: /etc/ssl/private/ansible.com.pem
size: 2048 size: 2048
# Force regenerate an OpenSSL private key if it already exists - name: Force regenerate an OpenSSL private key if it already exists
- openssl_privatekey: openssl_privatekey:
path: /etc/ssl/private/ansible.com.pem path: /etc/ssl/private/ansible.com.pem
force: True force: yes
# Generate an OpenSSL private key with a different algorithm (DSA) - name: Generate an OpenSSL private key with a different algorithm (DSA)
- openssl_privatekey: openssl_privatekey:
path: /etc/ssl/private/ansible.com.pem path: /etc/ssl/private/ansible.com.pem
type: DSA type: DSA
''' '''
RETURN = ''' RETURN = r'''
size: size:
description: Size (in bits) of the TLS/SSL private key description: Size (in bits) of the TLS/SSL private key.
returned: changed or success returned: changed or success
type: int type: int
sample: 4096 sample: 4096
type: type:
description: Algorithm used to generate the TLS/SSL private key description: Algorithm used to generate the TLS/SSL private key.
returned: changed or success returned: changed or success
type: str type: str
sample: RSA sample: RSA
curve: curve:
description: Elliptic curve used to generate the TLS/SSL private key description: Elliptic curve used to generate the TLS/SSL private key.
returned: changed or success, and I(type) is C(ECC) returned: changed or success, and I(type) is C(ECC)
type: str type: str
sample: secp256k1 sample: secp256k1
filename: filename:
description: Path to the generated TLS/SSL private key file description: Path to the generated TLS/SSL private key file.
returned: changed or success returned: changed or success
type: str type: str
sample: /etc/ssl/private/ansible.com.pem sample: /etc/ssl/private/ansible.com.pem
fingerprint: fingerprint:
description: The fingerprint of the public key. Fingerprint will be generated for description:
each C(hashlib.algorithms) available. - The fingerprint of the public key. Fingerprint will be generated for each C(hashlib.algorithms) available.
The PyOpenSSL backend requires PyOpenSSL >= 16.0 for meaningful output. - The PyOpenSSL backend requires PyOpenSSL >= 16.0 for meaningful output.
returned: changed or success returned: changed or success
type: dict type: dict
sample: sample:

@ -1,117 +1,125 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# (c) 2016, Yanis Guenane <yanis+ansible@guenane.org> # Copyright: (c) 2016, Yanis Guenane <yanis+ansible@guenane.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'], 'status': ['preview'],
'supported_by': 'community'} 'supported_by': 'community'}
DOCUMENTATION = r'''
DOCUMENTATION = '''
--- ---
module: openssl_publickey module: openssl_publickey
author: "Yanis Guenane (@Spredzy)"
version_added: "2.3" version_added: "2.3"
short_description: Generate an OpenSSL public key from its private key. short_description: Generate an OpenSSL public key from its private key.
description: description:
- "This module allows one to (re)generate OpenSSL public keys from their private keys. - This module allows one to (re)generate OpenSSL public keys from their private keys.
It uses the pyOpenSSL python library to interact with openssl. Keys are generated - It uses the pyOpenSSL python library to interact with openssl.
in PEM format. This module works only if the version of PyOpenSSL is recent enough (> 16.0.0)." - Keys are generated in PEM format.
- This module works only if the version of PyOpenSSL is recent enough (> 16.0.0).
requirements: requirements:
- "python-pyOpenSSL" - python-pyOpenSSL
author:
- Yanis Guenane (@Spredzy)
options: options:
state: state:
required: false
default: "present"
choices: [ present, absent ]
description: description:
- Whether the public key should exist or not, taking action if the state is different from what is stated. - Whether the public key should exist or not, taking action if the state is different from what is stated.
type: str
choices: [ absent, present ]
default: present
force: force:
required: false
default: False
type: bool
description: description:
- Should the key be regenerated even it it already exists - Should the key be regenerated even it it already exists.
type: bool
default: no
format: format:
required: false
default: PEM
choices: [ PEM, OpenSSH ]
description: description:
- The format of the public key. - The format of the public key.
type: str
choices: [ OpenSSH, PEM ]
default: PEM
version_added: "2.4" version_added: "2.4"
path: path:
required: true
description: description:
- Name of the file in which the generated TLS/SSL public key will be written. - Name of the file in which the generated TLS/SSL public key will be written.
privatekey_path: type: path
required: true required: true
privatekey_path:
description: description:
- Path to the TLS/SSL private key from which to generate the public key. - Path to the TLS/SSL private key from which to generate the public key.
type: path
required: true
privatekey_passphrase: privatekey_passphrase:
required: false
description: description:
- The passphrase for the privatekey. - The passphrase for the privatekey.
type: str
version_added: "2.4" version_added: "2.4"
extends_documentation_fragment: files extends_documentation_fragment:
- files
seealso:
- module: openssl_certificate
- module: openssl_csr
- module: openssl_dhparam
- module: openssl_pkcs12
- module: openssl_privatekey
''' '''
EXAMPLES = ''' EXAMPLES = r'''
# Generate an OpenSSL public key in PEM format. - name: Generate an OpenSSL public key in PEM format
- openssl_publickey: openssl_publickey:
path: /etc/ssl/public/ansible.com.pem path: /etc/ssl/public/ansible.com.pem
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
# Generate an OpenSSL public key in OpenSSH v2 format. - name: Generate an OpenSSL public key in OpenSSH v2 format
- openssl_publickey: openssl_publickey:
path: /etc/ssl/public/ansible.com.pem path: /etc/ssl/public/ansible.com.pem
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
format: OpenSSH format: OpenSSH
# Generate an OpenSSL public key with a passphrase protected - name: Generate an OpenSSL public key with a passphrase protected private key
# private key openssl_publickey:
- openssl_publickey:
path: /etc/ssl/public/ansible.com.pem path: /etc/ssl/public/ansible.com.pem
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
privatekey_passphrase: ansible privatekey_passphrase: ansible
# Force regenerate an OpenSSL public key if it already exists - name: Force regenerate an OpenSSL public key if it already exists
- openssl_publickey: openssl_publickey:
path: /etc/ssl/public/ansible.com.pem path: /etc/ssl/public/ansible.com.pem
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
force: True force: yes
# Remove an OpenSSL public key - name: Remove an OpenSSL public key
- openssl_publickey: openssl_publickey:
path: /etc/ssl/public/ansible.com.pem path: /etc/ssl/public/ansible.com.pem
privatekey_path: /etc/ssl/private/ansible.com.pem privatekey_path: /etc/ssl/private/ansible.com.pem
state: absent state: absent
''' '''
RETURN = ''' RETURN = r'''
privatekey: privatekey:
description: Path to the TLS/SSL private key the public key was generated from description: Path to the TLS/SSL private key the public key was generated from.
returned: changed or success returned: changed or success
type: str type: str
sample: /etc/ssl/private/ansible.com.pem sample: /etc/ssl/private/ansible.com.pem
format: format:
description: The format of the public key (PEM, OpenSSH, ...) description: The format of the public key (PEM, OpenSSH, ...).
returned: changed or success returned: changed or success
type: str type: str
sample: PEM sample: PEM
filename: filename:
description: Path to the generated TLS/SSL public key file description: Path to the generated TLS/SSL public key file.
returned: changed or success returned: changed or success
type: str type: str
sample: /etc/ssl/public/ansible.com.pem sample: /etc/ssl/public/ansible.com.pem
fingerprint: fingerprint:
description: The fingerprint of the public key. Fingerprint will be generated for each hashlib.algorithms available. description:
Requires PyOpenSSL >= 16.0 for meaningful output. - The fingerprint of the public key. Fingerprint will be generated for each hashlib.algorithms available.
- Requires PyOpenSSL >= 16.0 for meaningful output.
returned: changed or success returned: changed or success
type: dict type: dict
sample: sample:
@ -259,16 +267,16 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'], type='str'), state=dict(type='str', default='present', choices=['present', 'absent']),
force=dict(default=False, type='bool'), force=dict(type='bool', default=False),
path=dict(required=True, type='path'), path=dict(type='path', required=True),
privatekey_path=dict(type='path'), privatekey_path=dict(type='path'),
format=dict(type='str', choices=['PEM', 'OpenSSH'], default='PEM'), format=dict(type='str', default='PEM', choices=['OpenSSH', 'PEM']),
privatekey_passphrase=dict(type='str', no_log=True), privatekey_passphrase=dict(type='str', no_log=True),
), ),
supports_check_mode=True, supports_check_mode=True,
add_file_common_args=True, add_file_common_args=True,
required_if=[('state', 'present', ['privatekey_path'])] required_if=[('state', 'present', ['privatekey_path'])],
) )
if not pyopenssl_found: if not pyopenssl_found:
@ -278,7 +286,7 @@ def main():
if not os.path.isdir(base_dir): if not os.path.isdir(base_dir):
module.fail_json( module.fail_json(
name=base_dir, name=base_dir,
msg='The directory %s does not exist or the file is not a directory' % base_dir msg="The directory '%s' does not exist or the file is not a directory" % base_dir
) )
public_key = PublicKey(module) public_key = PublicKey(module)

@ -360,8 +360,6 @@ lib/ansible/modules/clustering/znode.py E326
lib/ansible/modules/commands/command.py E322 lib/ansible/modules/commands/command.py E322
lib/ansible/modules/commands/command.py E323 lib/ansible/modules/commands/command.py E323
lib/ansible/modules/commands/command.py E325 lib/ansible/modules/commands/command.py E325
lib/ansible/modules/crypto/openssl_certificate.py E325
lib/ansible/modules/crypto/openssl_csr.py E325
lib/ansible/modules/database/influxdb/influxdb_database.py E324 lib/ansible/modules/database/influxdb/influxdb_database.py E324
lib/ansible/modules/database/influxdb/influxdb_query.py E324 lib/ansible/modules/database/influxdb/influxdb_query.py E324
lib/ansible/modules/database/influxdb/influxdb_retention_policy.py E324 lib/ansible/modules/database/influxdb/influxdb_retention_policy.py E324

Loading…
Cancel
Save