crypto: Fix known issues in modules (#52302)
* crypto: Fix known issues in modules This fixes a few issues reported by 'validate-modules'. * Fix whitespace
This commit is contained in:
parent
9c1033422b
commit
cedd9d9926
7 changed files with 590 additions and 522 deletions
|
@ -1,8 +1,8 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2016-2017, Yanis Guenane <yanis+ansible@guenane.org>
|
||||
# (c) 2017, Markus Teufelberger <mteufelberger+ansible@mgit.at>
|
||||
# Copyright: (c) 2016-2017, Yanis Guenane <yanis+ansible@guenane.org>
|
||||
# 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)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
@ -14,268 +14,322 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
|
|||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: openssl_certificate
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
version_added: "2.4"
|
||||
short_description: Generate and/or check OpenSSL certificates
|
||||
description:
|
||||
- "This module allows one to (re)generate OpenSSL certificates. It implements a notion
|
||||
of provider (ie. C(selfsigned), C(ownca), C(acme), C(assertonly)) for your certificate.
|
||||
The 'assertonly' provider is intended for use cases where one is only interested in
|
||||
checking properties of a supplied certificate.
|
||||
The 'ownca' provider is intended for generate OpenSSL certificate signed with your own
|
||||
CA (Certificate Authority) certificate (self-signed certificate).
|
||||
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
|
||||
want to receive a certificate with these properties is a CSR (Certificate Signing Request).
|
||||
It uses the pyOpenSSL python library to interact with OpenSSL."
|
||||
- This module allows one to (re)generate OpenSSL certificates.
|
||||
- It implements a notion of provider (ie. C(selfsigned), C(ownca), C(acme), C(assertonly))
|
||||
for your certificate.
|
||||
- The C(assertonly) provider is intended for use cases where one is only interested in
|
||||
checking properties of a supplied certificate.
|
||||
- The C(ownca) provider is intended for generate OpenSSL certificate signed with your own
|
||||
CA (Certificate Authority) certificate (self-signed certificate).
|
||||
- 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
|
||||
want to receive a certificate with these properties is a CSR (Certificate Signing Request).
|
||||
- It uses the pyOpenSSL python library to interact with OpenSSL.
|
||||
requirements:
|
||||
- python-pyOpenSSL >= 0.15 (if using C(selfsigned) or C(assertonly) provider)
|
||||
- acme-tiny (if using the C(acme) provider)
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
options:
|
||||
state:
|
||||
default: "present"
|
||||
choices: [ present, absent ]
|
||||
description:
|
||||
- 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:
|
||||
required: true
|
||||
description:
|
||||
- Remote absolute path where the generated certificate file should be created or is already located.
|
||||
type: path
|
||||
required: true
|
||||
|
||||
provider:
|
||||
required: true
|
||||
choices: [ 'selfsigned', 'ownca', 'assertonly', 'acme' ]
|
||||
description:
|
||||
- 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:
|
||||
default: False
|
||||
type: bool
|
||||
description:
|
||||
- Generate the certificate, even if it already exists.
|
||||
type: bool
|
||||
default: no
|
||||
|
||||
csr_path:
|
||||
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:
|
||||
description:
|
||||
- Path to the private key to use when signing the certificate.
|
||||
type: path
|
||||
|
||||
privatekey_passphrase:
|
||||
description:
|
||||
- The passphrase for the I(privatekey_path).
|
||||
type: str
|
||||
|
||||
selfsigned_version:
|
||||
default: 3
|
||||
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"
|
||||
|
||||
selfsigned_digest:
|
||||
default: "sha256"
|
||||
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:
|
||||
default: +0s
|
||||
description:
|
||||
- "The point in time the certificate is valid from. Time can be specified either as relative time or as absolute timestamp.
|
||||
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME)
|
||||
where timespec can be an integer + 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."
|
||||
- The point in time the certificate is valid from.
|
||||
- Time can be specified either as relative time or as absolute timestamp.
|
||||
- Time will always be interpreted as UTC.
|
||||
- Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
|
||||
+ 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 ]
|
||||
|
||||
selfsigned_not_after:
|
||||
default: +3650d
|
||||
description:
|
||||
- "The point in time at which the certificate stops being valid. Time can be specified either as relative time or as absolute timestamp.
|
||||
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME)
|
||||
where timespec can be an integer + 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."
|
||||
- The point in time at which the certificate stops being valid.
|
||||
- Time can be specified either as relative time or as absolute timestamp.
|
||||
- Time will always be interpreted as UTC.
|
||||
- Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
|
||||
+ 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 ]
|
||||
|
||||
ownca_path:
|
||||
description:
|
||||
- Remote absolute path of the CA (Certificate Authority) certificate.
|
||||
type: path
|
||||
version_added: "2.7"
|
||||
|
||||
ownca_privatekey_path:
|
||||
description:
|
||||
- Path to the CA (Certificate Authority) private key to use when signing the certificate.
|
||||
type: path
|
||||
version_added: "2.7"
|
||||
|
||||
ownca_privatekey_passphrase:
|
||||
description:
|
||||
- The passphrase for the I(ownca_privatekey_path).
|
||||
type: str
|
||||
version_added: "2.7"
|
||||
|
||||
ownca_digest:
|
||||
default: "sha256"
|
||||
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"
|
||||
|
||||
ownca_version:
|
||||
default: 3
|
||||
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"
|
||||
|
||||
ownca_not_before:
|
||||
default: +0s
|
||||
description:
|
||||
- "The point in time the certificate is valid from. Time can be specified either as relative time or as absolute timestamp.
|
||||
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME)
|
||||
where timespec can be an integer + 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."
|
||||
- The point in time the certificate is valid from.
|
||||
- Time can be specified either as relative time or as absolute timestamp.
|
||||
- Time will always be interpreted as UTC.
|
||||
- Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
|
||||
+ 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"
|
||||
|
||||
ownca_not_after:
|
||||
default: +3650d
|
||||
description:
|
||||
- "The point in time at which the certificate stops being valid. Time can be specified either as relative time or as absolute timestamp.
|
||||
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | ASN.1 TIME)
|
||||
where timespec can be an integer + 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."
|
||||
- The point in time at which the certificate stops being valid.
|
||||
- Time can be specified either as relative time or as absolute timestamp.
|
||||
- Time will always be interpreted as UTC.
|
||||
- Valid format is C([+-]timespec | ASN.1 TIME) where timespec can be an integer
|
||||
+ 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"
|
||||
|
||||
acme_accountkey_path:
|
||||
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:
|
||||
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:
|
||||
default: True
|
||||
description:
|
||||
- Include the intermediate certificate to the generated certificate
|
||||
type: bool
|
||||
default: yes
|
||||
version_added: "2.5"
|
||||
|
||||
signature_algorithms:
|
||||
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']).
|
||||
type: str
|
||||
|
||||
issuer:
|
||||
description:
|
||||
- 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.
|
||||
- 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.
|
||||
type: str
|
||||
|
||||
issuer_strict:
|
||||
default: False
|
||||
type: bool
|
||||
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"
|
||||
|
||||
subject:
|
||||
description:
|
||||
- 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.
|
||||
- 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.
|
||||
type: str
|
||||
|
||||
subject_strict:
|
||||
default: False
|
||||
type: bool
|
||||
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"
|
||||
|
||||
has_expired:
|
||||
default: False
|
||||
type: bool
|
||||
description:
|
||||
- Checks if the certificate is expired/not expired at the time the module is executed.
|
||||
type: bool
|
||||
default: no
|
||||
|
||||
version:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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 ]
|
||||
|
||||
not_after:
|
||||
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 ]
|
||||
|
||||
|
||||
valid_in:
|
||||
description:
|
||||
- "The certificate must still be valid at this relative time offset from now.
|
||||
Valid formats are: C([+-]timespec | number_of_seconds)
|
||||
where timespec can be an integer + C([w | d | h | m | s]) (e.g. C(+32w1d2h).
|
||||
Note that if using this parameter, this module is NOT idempotent."
|
||||
- The certificate must still be valid at this relative time offset from now.
|
||||
- Valid format is C([+-]timespec | number_of_seconds) where timespec can be an integer
|
||||
+ C([w | d | h | m | s]) (e.g. C(+32w1d2h).
|
||||
- Note that if using this parameter, this module is NOT idempotent.
|
||||
type: str
|
||||
|
||||
key_usage:
|
||||
description:
|
||||
- The I(key_usage) extension field must contain all these values.
|
||||
type: list
|
||||
aliases: [ keyUsage ]
|
||||
|
||||
key_usage_strict:
|
||||
default: False
|
||||
type: bool
|
||||
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 ]
|
||||
|
||||
extended_key_usage:
|
||||
description:
|
||||
- The I(extended_key_usage) extension field must contain all these values.
|
||||
type: list
|
||||
aliases: [ extendedKeyUsage ]
|
||||
|
||||
extended_key_usage_strict:
|
||||
default: False
|
||||
type: bool
|
||||
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 ]
|
||||
|
||||
subject_alt_name:
|
||||
description:
|
||||
- The I(subject_alt_name) extension field must contain these values.
|
||||
type: list
|
||||
aliases: [ subjectAltName ]
|
||||
|
||||
subject_alt_name_strict:
|
||||
default: False
|
||||
type: bool
|
||||
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 ]
|
||||
extends_documentation_fragment: files
|
||||
notes:
|
||||
- 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
|
||||
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.
|
||||
seealso:
|
||||
- module: openssl_csr
|
||||
- module: openssl_dhparam
|
||||
- module: openssl_pkcs12
|
||||
- module: openssl_privatekey
|
||||
- module: openssl_publickey
|
||||
'''
|
||||
|
||||
|
||||
EXAMPLES = '''
|
||||
EXAMPLES = r'''
|
||||
- name: Generate a Self Signed OpenSSL certificate
|
||||
openssl_certificate:
|
||||
path: /etc/ssl/crt/ansible.com.crt
|
||||
|
@ -306,7 +360,7 @@ EXAMPLES = '''
|
|||
provider: acme
|
||||
acme_accountkey_path: /etc/ssl/private/ansible.com.pem
|
||||
acme_challenge_path: /etc/ssl/challenges/ansible.com/
|
||||
force: True
|
||||
force: yes
|
||||
|
||||
# Examples for some checks one could use the assertonly provider for:
|
||||
|
||||
|
@ -315,8 +369,8 @@ EXAMPLES = '''
|
|||
openssl_certificate:
|
||||
path: /etc/ssl/crt/example.com.crt
|
||||
provider: assertonly
|
||||
has_expired: False
|
||||
ignore_errors: True
|
||||
has_expired: no
|
||||
ignore_errors: yes
|
||||
register: validity_check
|
||||
|
||||
- name: Run custom task(s) to get a new, valid certificate in case the initial check failed
|
||||
|
@ -327,7 +381,7 @@ EXAMPLES = '''
|
|||
openssl_certificate:
|
||||
path: /etc/ssl/crt/example.com.crt
|
||||
provider: assertonly
|
||||
has_expired: False
|
||||
has_expired: no
|
||||
when: validity_check.failed
|
||||
|
||||
# Some other checks that assertonly could be used for:
|
||||
|
@ -337,7 +391,7 @@ EXAMPLES = '''
|
|||
provider: assertonly
|
||||
issuer:
|
||||
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)
|
||||
openssl_certificate:
|
||||
|
@ -405,8 +459,7 @@ EXAMPLES = '''
|
|||
- test.example.com
|
||||
'''
|
||||
|
||||
|
||||
RETURN = '''
|
||||
RETURN = r'''
|
||||
filename:
|
||||
description: Path to the generated Certificate
|
||||
returned: changed or success
|
||||
|
@ -710,14 +763,14 @@ class AssertOnlyCertificate(Certificate):
|
|||
self.issuer_strict = module.params['issuer_strict']
|
||||
self.has_expired = module.params['has_expired']
|
||||
self.version = module.params['version']
|
||||
self.keyUsage = module.params['keyUsage']
|
||||
self.keyUsage_strict = module.params['keyUsage_strict']
|
||||
self.extendedKeyUsage = module.params['extendedKeyUsage']
|
||||
self.extendedKeyUsage_strict = module.params['extendedKeyUsage_strict']
|
||||
self.subjectAltName = module.params['subjectAltName']
|
||||
self.subjectAltName_strict = module.params['subjectAltName_strict']
|
||||
self.notBefore = module.params['notBefore']
|
||||
self.notAfter = module.params['notAfter']
|
||||
self.keyUsage = module.params['key_usage']
|
||||
self.keyUsage_strict = module.params['key_usage_strict']
|
||||
self.extendedKeyUsage = module.params['extended_key_usage']
|
||||
self.extendedKeyUsage_strict = module.params['extended_key_usage_strict']
|
||||
self.subjectAltName = module.params['subject_alt_name']
|
||||
self.subjectAltName_strict = module.params['subject_alt_name_strict']
|
||||
self.notBefore = module.params['not_before']
|
||||
self.notAfter = module.params['not_after']
|
||||
self.valid_at = module.params['valid_at']
|
||||
self.invalid_at = module.params['invalid_at']
|
||||
self.valid_in = module.params['valid_in']
|
||||
|
@ -1002,7 +1055,7 @@ def main():
|
|||
argument_spec=dict(
|
||||
state=dict(type='str', choices=['present', 'absent'], default='present'),
|
||||
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,),
|
||||
csr_path=dict(type='path'),
|
||||
|
||||
|
@ -1016,20 +1069,20 @@ def main():
|
|||
issuer_strict=dict(type='bool', default=False),
|
||||
has_expired=dict(type='bool', default=False),
|
||||
version=dict(type='int'),
|
||||
keyUsage=dict(type='list', aliases=['key_usage'], elements='str'),
|
||||
keyUsage_strict=dict(type='bool', default=False, aliases=['key_usage_strict']),
|
||||
extendedKeyUsage=dict(type='list', aliases=['extended_key_usage'], elements='str'),
|
||||
extendedKeyUsage_strict=dict(type='bool', default=False, aliases=['extended_key_usage_strict']),
|
||||
subjectAltName=dict(type='list', aliases=['subject_alt_name'], elements='str'),
|
||||
subjectAltName_strict=dict(type='bool', default=False, aliases=['subject_alt_name_strict']),
|
||||
notBefore=dict(type='str', aliases=['not_before']),
|
||||
notAfter=dict(type='str', aliases=['not_after']),
|
||||
key_usage=dict(type='list', elements='str', aliases=['keyUsage']),
|
||||
key_usage_strict=dict(type='bool', default=False, aliases=['keyUsage_strict']),
|
||||
extended_key_usage=dict(type='list', elements='str', aliases=['extendedKeyUsage']),
|
||||
extended_key_usage_strict=dict(type='bool', default=False, aliases=['extendedKeyUsage_strict']),
|
||||
subject_alt_name=dict(type='list', elements='str', aliases=['subjectAltName']),
|
||||
subject_alt_name_strict=dict(type='bool', default=False, aliases=['subjectAltName_strict']),
|
||||
not_before=dict(type='str', aliases=['notBefore']),
|
||||
not_after=dict(type='str', aliases=['notAfter']),
|
||||
valid_at=dict(type='str'),
|
||||
invalid_at=dict(type='str'),
|
||||
valid_in=dict(type='str'),
|
||||
|
||||
# provider: selfsigned
|
||||
selfsigned_version=dict(type='int', default='3'),
|
||||
selfsigned_version=dict(type='int', default=3),
|
||||
selfsigned_digest=dict(type='str', default='sha256'),
|
||||
selfsigned_not_before=dict(
|
||||
type='str', default='+0s', aliases=['selfsigned_notBefore']),
|
||||
|
@ -1041,7 +1094,7 @@ def main():
|
|||
ownca_privatekey_path=dict(type='path'),
|
||||
ownca_privatekey_passphrase=dict(type='path', no_log=True),
|
||||
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_after=dict(type='str', default='+3650d'),
|
||||
|
||||
|
|
|
@ -1,228 +1,225 @@
|
|||
#!/usr/bin/python
|
||||
# -*- 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)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: openssl_csr
|
||||
author: "Yanis Guenane (@Spredzy)"
|
||||
version_added: "2.4"
|
||||
version_added: '2.4'
|
||||
short_description: Generate OpenSSL Certificate Signing Request (CSR)
|
||||
description:
|
||||
- "This module allows one to (re)generate OpenSSL certificate signing requests.
|
||||
It uses the pyOpenSSL python library to interact with openssl. This module supports
|
||||
the subjectAltName, keyUsage, extendedKeyUsage, basicConstraints and OCSP Must Staple
|
||||
extensions."
|
||||
- This module allows one to (re)generate OpenSSL certificate signing requests.
|
||||
- It uses the pyOpenSSL python library to interact with openssl. This module supports
|
||||
the subjectAltName, keyUsage, extendedKeyUsage, basicConstraints and OCSP Must Staple
|
||||
extensions.
|
||||
requirements:
|
||||
- "One of the following Python libraries:"
|
||||
- "cryptography >= 1.3"
|
||||
- "pyOpenSSL >= 0.15"
|
||||
- Either cryptography >= 1.3
|
||||
- Or pyOpenSSL >= 0.15
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
options:
|
||||
state:
|
||||
required: false
|
||||
default: "present"
|
||||
choices: [ present, absent ]
|
||||
description:
|
||||
- Whether the certificate signing request should exist or not, taking action if the state is different from what is stated.
|
||||
type: str
|
||||
required: false
|
||||
choices: [ absent, present ]
|
||||
default: present
|
||||
digest:
|
||||
required: false
|
||||
default: "sha256"
|
||||
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:
|
||||
required: true
|
||||
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:
|
||||
required: false
|
||||
description:
|
||||
- The passphrase for the privatekey.
|
||||
type: str
|
||||
version:
|
||||
required: false
|
||||
description:
|
||||
- The version of the certificate signing request.
|
||||
type: int
|
||||
default: 1
|
||||
description:
|
||||
- Version of the certificate signing request
|
||||
force:
|
||||
required: false
|
||||
default: False
|
||||
description:
|
||||
- Should the certificate signing request be forced regenerated by this ansible module.
|
||||
type: bool
|
||||
description:
|
||||
- Should the certificate signing request be forced regenerated by this ansible module
|
||||
default: no
|
||||
path:
|
||||
required: true
|
||||
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:
|
||||
required: false
|
||||
description:
|
||||
- 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.
|
||||
type: str
|
||||
version_added: '2.5'
|
||||
country_name:
|
||||
required: false
|
||||
aliases: [ 'C', 'countryName' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'ST', 'stateOrProvinceName' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'L', 'localityName' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'O', 'organizationName' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'OU', 'organizationalUnitName' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'CN', 'commonName' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'E', 'emailAddress' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'subjectAltName' ]
|
||||
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.
|
||||
- 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)
|
||||
- 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
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'subjectAltName_critical' ]
|
||||
description:
|
||||
- Should the subjectAltName extension be considered as critical
|
||||
useCommonNameForSAN:
|
||||
- Should the subjectAltName extension be considered as critical.
|
||||
type: bool
|
||||
default: true
|
||||
aliases: [ subjectAltName_critical ]
|
||||
use_common_name_for_san:
|
||||
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.
|
||||
type: bool
|
||||
default: yes
|
||||
aliases: [ useCommonNameForSAN ]
|
||||
version_added: '2.8'
|
||||
key_usage:
|
||||
required: false
|
||||
aliases: [ 'keyUsage' ]
|
||||
description:
|
||||
- This defines the purpose (e.g. encipherment, signature, certificate signing)
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'keyUsage_critical' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'extKeyUsage', 'extendedKeyUsage' ]
|
||||
description:
|
||||
- Additional restrictions (e.g. client authentication, server authentication)
|
||||
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:
|
||||
required: false
|
||||
aliases: [ 'extKeyUsage_critical', 'extendedKeyUsage_critical' ]
|
||||
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:
|
||||
required: false
|
||||
aliases: ['basicConstraints']
|
||||
description:
|
||||
- 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:
|
||||
required: false
|
||||
aliases: [ 'basicConstraints_critical' ]
|
||||
description:
|
||||
- Should the basicConstraints extension be considered as critical
|
||||
version_added: 2.5
|
||||
- Should the basicConstraints extension be considered as critical.
|
||||
type: bool
|
||||
aliases: [ basicConstraints_critical ]
|
||||
version_added: '2.5'
|
||||
ocsp_must_staple:
|
||||
required: false
|
||||
aliases: ['ocspMustStaple']
|
||||
description:
|
||||
- Indicates that the certificate should contain the OCSP Must Staple
|
||||
extension (U(https://tools.ietf.org/html/rfc7633)).
|
||||
version_added: 2.5
|
||||
type: bool
|
||||
aliases: [ ocspMustStaple ]
|
||||
version_added: '2.5'
|
||||
ocsp_must_staple_critical:
|
||||
required: false
|
||||
aliases: [ 'ocspMustStaple_critical' ]
|
||||
description:
|
||||
- Should the OCSP Must Staple extension be considered as critical
|
||||
- "Warning: according to the RFC, this extension should not be marked
|
||||
as critical, as old clients not knowing about OCSP Must Staple
|
||||
are required to reject such certificates
|
||||
(see U(https://tools.ietf.org/html/rfc7633#section-4))."
|
||||
version_added: 2.5
|
||||
- Note that according to the RFC, this extension should not be marked
|
||||
as critical, as old clients not knowing about OCSP Must Staple
|
||||
are required to reject such certificates
|
||||
(see U(https://tools.ietf.org/html/rfc7633#section-4)).
|
||||
type: bool
|
||||
aliases: [ ocspMustStaple_critical ]
|
||||
version_added: '2.5'
|
||||
select_crypto_backend:
|
||||
description:
|
||||
- "Determines which crypto backend to use. The default choice is C(auto),
|
||||
which tries to use C(cryptography) if available, and falls back to
|
||||
C(pyopenssl)."
|
||||
- "If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/)
|
||||
library."
|
||||
- "If set to C(cryptography), will try to use the
|
||||
L(cryptography,https://cryptography.io/) library."
|
||||
- Determines which crypto backend to use.
|
||||
- The default choice is C(auto), which tries to use C(cryptography) if available, and falls back to C(pyopenssl).
|
||||
- If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) library.
|
||||
- If set to C(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
|
||||
type: str
|
||||
default: 'auto'
|
||||
choices:
|
||||
- auto
|
||||
- cryptography
|
||||
- pyopenssl
|
||||
version_added: "2.8"
|
||||
extends_documentation_fragment: files
|
||||
|
||||
choices: [ auto, cryptography, pyopenssl ]
|
||||
default: auto
|
||||
version_added: '2.8'
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
notes:
|
||||
- "If the certificate signing request already exists it will be checked whether subjectAltName,
|
||||
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."
|
||||
- If the certificate signing request already exists it will be checked whether subjectAltName,
|
||||
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.
|
||||
seealso:
|
||||
- module: openssl_certificate
|
||||
- module: openssl_dhparam
|
||||
- module: openssl_pkcs12
|
||||
- module: openssl_privatekey
|
||||
- module: openssl_publickey
|
||||
'''
|
||||
|
||||
|
||||
EXAMPLES = '''
|
||||
# Generate an OpenSSL Certificate Signing Request
|
||||
- openssl_csr:
|
||||
EXAMPLES = r'''
|
||||
- name: Generate an OpenSSL Certificate Signing Request
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
common_name: www.ansible.com
|
||||
|
||||
# Generate an OpenSSL Certificate Signing Request with a
|
||||
# passphrase protected private key
|
||||
- openssl_csr:
|
||||
- name: Generate an OpenSSL Certificate Signing Request with a passphrase protected private key
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
privatekey_passphrase: ansible
|
||||
common_name: www.ansible.com
|
||||
|
||||
# Generate an OpenSSL Certificate Signing Request with Subject information
|
||||
- openssl_csr:
|
||||
- name: Generate an OpenSSL Certificate Signing Request with Subject information
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
country_name: FR
|
||||
|
@ -230,14 +227,14 @@ EXAMPLES = '''
|
|||
email_address: jdoe@ansible.com
|
||||
common_name: www.ansible.com
|
||||
|
||||
# Generate an OpenSSL Certificate Signing Request with subjectAltName extension
|
||||
- openssl_csr:
|
||||
- name: Generate an OpenSSL Certificate Signing Request with subjectAltName extension
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
subject_alt_name: 'DNS:www.ansible.com,DNS:m.ansible.com'
|
||||
|
||||
# Generate an OpenSSL CSR with subjectAltName extension with dynamic list
|
||||
- openssl_csr:
|
||||
- name: Generate an OpenSSL CSR with subjectAltName extension with dynamic list
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
subject_alt_name: "{{ item.value | map('regex_replace', '^', 'DNS:') | list }}"
|
||||
|
@ -246,15 +243,15 @@ EXAMPLES = '''
|
|||
- www.ansible.com
|
||||
- m.ansible.com
|
||||
|
||||
# Force re-generate an OpenSSL Certificate Signing Request
|
||||
- openssl_csr:
|
||||
- name: Force re-generate an OpenSSL Certificate Signing Request
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
force: True
|
||||
force: yes
|
||||
common_name: www.ansible.com
|
||||
|
||||
# Generate an OpenSSL Certificate Signing Request with special key usages
|
||||
- openssl_csr:
|
||||
- name: Generate an OpenSSL Certificate Signing Request with special key usages
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
common_name: www.ansible.com
|
||||
|
@ -264,16 +261,15 @@ EXAMPLES = '''
|
|||
extended_key_usage:
|
||||
- clientAuth
|
||||
|
||||
# Generate an OpenSSL Certificate Signing Request with OCSP Must Staple
|
||||
- openssl_csr:
|
||||
- name: Generate an OpenSSL Certificate Signing Request with OCSP Must Staple
|
||||
openssl_csr:
|
||||
path: /etc/ssl/csr/www.ansible.com.csr
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
common_name: www.ansible.com
|
||||
ocsp_must_staple: true
|
||||
ocsp_must_staple: yes
|
||||
'''
|
||||
|
||||
|
||||
RETURN = '''
|
||||
RETURN = r'''
|
||||
privatekey:
|
||||
description: Path to the TLS/SSL private key the CSR was generated for
|
||||
returned: changed or success
|
||||
|
@ -384,34 +380,34 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
|
|||
self.privatekey_path = module.params['privatekey_path']
|
||||
self.privatekey_passphrase = module.params['privatekey_passphrase']
|
||||
self.version = module.params['version']
|
||||
self.subjectAltName = module.params['subjectAltName']
|
||||
self.subjectAltName_critical = module.params['subjectAltName_critical']
|
||||
self.keyUsage = module.params['keyUsage']
|
||||
self.keyUsage_critical = module.params['keyUsage_critical']
|
||||
self.extendedKeyUsage = module.params['extendedKeyUsage']
|
||||
self.extendedKeyUsage_critical = module.params['extendedKeyUsage_critical']
|
||||
self.basicConstraints = module.params['basicConstraints']
|
||||
self.basicConstraints_critical = module.params['basicConstraints_critical']
|
||||
self.ocspMustStaple = module.params['ocspMustStaple']
|
||||
self.ocspMustStaple_critical = module.params['ocspMustStaple_critical']
|
||||
self.subjectAltName = module.params['subject_alt_name']
|
||||
self.subjectAltName_critical = module.params['subject_alt_name_critical']
|
||||
self.keyUsage = module.params['key_usage']
|
||||
self.keyUsage_critical = module.params['key_usage_critical']
|
||||
self.extendedKeyUsage = module.params['extended_key_usage']
|
||||
self.extendedKeyUsage_critical = module.params['extended_key_usage_critical']
|
||||
self.basicConstraints = module.params['basic_constraints']
|
||||
self.basicConstraints_critical = module.params['basic_constraints_critical']
|
||||
self.ocspMustStaple = module.params['ocsp_must_staple']
|
||||
self.ocspMustStaple_critical = module.params['ocsp_must_staple_critical']
|
||||
self.request = None
|
||||
self.privatekey = None
|
||||
|
||||
self.subject = [
|
||||
('C', module.params['countryName']),
|
||||
('ST', module.params['stateOrProvinceName']),
|
||||
('L', module.params['localityName']),
|
||||
('O', module.params['organizationName']),
|
||||
('OU', module.params['organizationalUnitName']),
|
||||
('CN', module.params['commonName']),
|
||||
('emailAddress', module.params['emailAddress']),
|
||||
('C', module.params['country_name']),
|
||||
('ST', module.params['state_or_province_name']),
|
||||
('L', module.params['locality_name']),
|
||||
('O', module.params['organization_name']),
|
||||
('OU', module.params['organizational_unit_name']),
|
||||
('CN', module.params['common_name']),
|
||||
('emailAddress', module.params['email_address']),
|
||||
]
|
||||
|
||||
if 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]]
|
||||
|
||||
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:
|
||||
if sub[0] in ('commonName', 'CN'):
|
||||
self.subjectAltName = ['DNS:%s' % sub[1]]
|
||||
|
@ -944,33 +940,33 @@ class CertificateSigningRequestCryptography(CertificateSigningRequestBase):
|
|||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(default='present', choices=['present', 'absent'], type='str'),
|
||||
digest=dict(default='sha256', type='str'),
|
||||
privatekey_path=dict(require=True, type='path'),
|
||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||
digest=dict(type='str', default='sha256'),
|
||||
privatekey_path=dict(type='path', require=True),
|
||||
privatekey_passphrase=dict(type='str', no_log=True),
|
||||
version=dict(default='1', type='int'),
|
||||
force=dict(default=False, type='bool'),
|
||||
path=dict(required=True, type='path'),
|
||||
version=dict(type='int', default=1),
|
||||
force=dict(type='bool', default=False),
|
||||
path=dict(type='path', required=True),
|
||||
subject=dict(type='dict'),
|
||||
countryName=dict(aliases=['C', 'country_name'], type='str'),
|
||||
stateOrProvinceName=dict(aliases=['ST', 'state_or_province_name'], type='str'),
|
||||
localityName=dict(aliases=['L', 'locality_name'], type='str'),
|
||||
organizationName=dict(aliases=['O', 'organization_name'], type='str'),
|
||||
organizationalUnitName=dict(aliases=['OU', 'organizational_unit_name'], type='str'),
|
||||
commonName=dict(aliases=['CN', 'common_name'], type='str'),
|
||||
emailAddress=dict(aliases=['E', 'email_address'], type='str'),
|
||||
subjectAltName=dict(aliases=['subject_alt_name'], type='list', elements='str'),
|
||||
subjectAltName_critical=dict(aliases=['subject_alt_name_critical'], default=False, type='bool'),
|
||||
useCommonNameForSAN=dict(type='bool', default=True),
|
||||
keyUsage=dict(aliases=['key_usage'], type='list', elements='str'),
|
||||
keyUsage_critical=dict(aliases=['key_usage_critical'], default=False, type='bool'),
|
||||
extendedKeyUsage=dict(aliases=['extKeyUsage', 'extended_key_usage'], type='list', elements='str'),
|
||||
extendedKeyUsage_critical=dict(aliases=['extKeyUsage_critical', 'extended_key_usage_critical'], default=False, type='bool'),
|
||||
basicConstraints=dict(aliases=['basic_constraints'], type='list', elements='str'),
|
||||
basicConstraints_critical=dict(aliases=['basic_constraints_critical'], default=False, type='bool'),
|
||||
ocspMustStaple=dict(aliases=['ocsp_must_staple'], default=False, type='bool'),
|
||||
ocspMustStaple_critical=dict(aliases=['ocsp_must_staple_critical'], default=False, type='bool'),
|
||||
select_crypto_backend=dict(required=False, choices=['auto', 'pyopenssl', 'cryptography'], default='auto', type='str'),
|
||||
country_name=dict(type='str', aliases=['C', 'countryName']),
|
||||
state_or_province_name=dict(type='str', aliases=['ST', 'stateOrProvinceName']),
|
||||
locality_name=dict(type='str', aliases=['L', 'localityName']),
|
||||
organization_name=dict(type='str', aliases=['O', 'organizationName']),
|
||||
organizational_unit_name=dict(type='str', aliases=['OU', 'organizationalUnitName']),
|
||||
common_name=dict(type='str', aliases=['CN', 'commonName']),
|
||||
email_address=dict(type='str', aliases=['E', 'emailAddress']),
|
||||
subject_alt_name=dict(type='list', elements='str', aliases=['subjectAltName']),
|
||||
subject_alt_name_critical=dict(type='bool', default=False, aliases=['subjectAltName_critical']),
|
||||
use_common_name_for_san=dict(type='bool', default=True, aliases=['useCommonNameForSAN']),
|
||||
key_usage=dict(type='list', elements='str', aliases=['keyUsage']),
|
||||
key_usage_critical=dict(type='bool', default=False, aliases=['keyUsage_critical']),
|
||||
extended_key_usage=dict(type='list', elements='str', aliases=['extKeyUsage', 'extendedKeyUsage']),
|
||||
extended_key_usage_critical=dict(type='bool', default=False, aliases=['extKeyUsage_critical', 'extendedKeyUsage_critical']),
|
||||
basic_constraints=dict(type='list', elements='str', aliases=['basicConstraints']),
|
||||
basic_constraints_critical=dict(type='bool', default=False, aliases=['basicConstraints_critical']),
|
||||
ocsp_must_staple=dict(type='bool', default=False, aliases=['ocspMustStaple']),
|
||||
ocsp_must_staple_critical=dict(type='bool', default=False, aliases=['ocspMustStaple_critical']),
|
||||
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']),
|
||||
),
|
||||
add_file_common_args=True,
|
||||
supports_check_mode=True,
|
||||
|
|
|
@ -1,80 +1,85 @@
|
|||
#!/usr/bin/python
|
||||
# -*- 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)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: openssl_dhparam
|
||||
author: "Thom Wiggers (@thomwiggers)"
|
||||
version_added: "2.5"
|
||||
short_description: Generate OpenSSL Diffie-Hellman Parameters
|
||||
description:
|
||||
- "This module allows one to (re)generate OpenSSL DH-params.
|
||||
This module uses file common arguments to specify generated file permissions."
|
||||
- This module allows one to (re)generate OpenSSL DH-params.
|
||||
- This module uses file common arguments to specify generated file permissions.
|
||||
requirements:
|
||||
- OpenSSL
|
||||
author:
|
||||
- Thom Wiggers (@thomwiggers)
|
||||
options:
|
||||
state:
|
||||
required: false
|
||||
default: "present"
|
||||
choices: [ present, absent ]
|
||||
description:
|
||||
- Whether the parameters should exist or not,
|
||||
taking action if the state is different from what is stated.
|
||||
type: str
|
||||
choices: [ absent, present ]
|
||||
default: present
|
||||
size:
|
||||
required: false
|
||||
description:
|
||||
- Size (in bits) of the generated DH-params.
|
||||
type: int
|
||||
default: 4096
|
||||
description:
|
||||
- Size (in bits) of the generated DH-params
|
||||
force:
|
||||
required: false
|
||||
default: False
|
||||
type: bool
|
||||
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:
|
||||
required: true
|
||||
description:
|
||||
- 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 = '''
|
||||
# Generate Diffie-Hellman parameters with the default size (4096 bits)
|
||||
- openssl_dhparam:
|
||||
EXAMPLES = r'''
|
||||
- name: Generate Diffie-Hellman parameters with the default size (4096 bits)
|
||||
openssl_dhparam:
|
||||
path: /etc/ssl/dhparams.pem
|
||||
|
||||
# Generate DH Parameters with a different size (2048 bits)
|
||||
- openssl_dhparam:
|
||||
- name: Generate DH Parameters with a different size (2048 bits)
|
||||
openssl_dhparam:
|
||||
path: /etc/ssl/dhparams.pem
|
||||
size: 2048
|
||||
|
||||
# Force regenerate an DH parameters if they already exist
|
||||
- openssl_dhparam:
|
||||
- name: Force regenerate an DH parameters if they already exist
|
||||
openssl_dhparam:
|
||||
path: /etc/ssl/dhparams.pem
|
||||
force: True
|
||||
|
||||
force: yes
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
RETURN = r'''
|
||||
size:
|
||||
description: Size (in bits) of the Diffie-Hellman parameters
|
||||
description: Size (in bits) of the Diffie-Hellman parameters.
|
||||
returned: changed or success
|
||||
type: int
|
||||
sample: 4096
|
||||
filename:
|
||||
description: Path to the generated Diffie-Hellman parameters
|
||||
description: Path to the generated Diffie-Hellman parameters.
|
||||
returned: changed or success
|
||||
type: str
|
||||
sample: /etc/ssl/dhparams.pem
|
||||
|
@ -97,7 +102,7 @@ class DHParameter(object):
|
|||
def __init__(self, module):
|
||||
self.state = module.params['state']
|
||||
self.path = module.params['path']
|
||||
self.size = int(module.params['size'])
|
||||
self.size = module.params['size']
|
||||
self.force = module.params['force']
|
||||
self.changed = False
|
||||
self.openssl_bin = module.get_bin_path('openssl', True)
|
||||
|
@ -150,8 +155,8 @@ class DHParameter(object):
|
|||
match = re.search(r"Parameters:\s+\((\d+) bit\).*", result)
|
||||
if not match:
|
||||
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 "WARNING" in result or "WARNING" in to_native(err):
|
||||
|
@ -182,10 +187,10 @@ def main():
|
|||
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(default='present', choices=['present', 'absent'], type='str'),
|
||||
size=dict(default=4096, type='int'),
|
||||
force=dict(default=False, type='bool'),
|
||||
path=dict(required=True, type='path'),
|
||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||
size=dict(type='int', default=4096),
|
||||
force=dict(type='bool', default=False),
|
||||
path=dict(type='path', required=True),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
|
@ -195,7 +200,7 @@ def main():
|
|||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
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)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#!/usr/bin/python
|
||||
# -*- 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)
|
||||
# Copyright (c) 2017 Guillaume Delpierre <gde@llew.me>
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
@ -11,128 +11,145 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
|
|||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: openssl_pkcs12
|
||||
author: "Guillaume Delpierre (@gdelpierre)"
|
||||
author:
|
||||
- Guillaume Delpierre (@gdelpierre)
|
||||
version_added: "2.7"
|
||||
short_description: Generate OpenSSL PKCS#12 archive.
|
||||
short_description: Generate OpenSSL PKCS#12 archive
|
||||
description:
|
||||
- This module allows one to (re-)generate PKCS#12.
|
||||
requirements:
|
||||
- python-pyOpenSSL
|
||||
options:
|
||||
action:
|
||||
default: export
|
||||
choices: ['parse', 'export']
|
||||
description:
|
||||
- C(export) or C(parse) a PKCS#12.
|
||||
choices: [ export, parse ]
|
||||
default: export
|
||||
ca_certificates:
|
||||
description:
|
||||
- List of CA certificate to include.
|
||||
type: list
|
||||
certificate_path:
|
||||
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:
|
||||
default: False
|
||||
type: bool
|
||||
description:
|
||||
- Should the file be regenerated even if it already exists.
|
||||
type: bool
|
||||
default: no
|
||||
friendly_name:
|
||||
aliases: ['name']
|
||||
description:
|
||||
- Specifies the friendly name for the certificate and private key.
|
||||
type: str
|
||||
aliases: [ name ]
|
||||
iter_size:
|
||||
default: 2048
|
||||
description:
|
||||
- Number of times to repeat the encryption step.
|
||||
type: int
|
||||
default: 2048
|
||||
maciter_size:
|
||||
default: 1
|
||||
description:
|
||||
- Number of times to repeat the MAC step.
|
||||
type: int
|
||||
default: 1
|
||||
passphrase:
|
||||
description:
|
||||
- The PKCS#12 password.
|
||||
type: str
|
||||
path:
|
||||
required: True
|
||||
description:
|
||||
- Filename to write the PKCS#12 file to.
|
||||
type: path
|
||||
required: True
|
||||
privatekey_passphrase:
|
||||
description:
|
||||
- Passphrase source to decrypt any input private keys with.
|
||||
type: str
|
||||
privatekey_path:
|
||||
description:
|
||||
- File to read private key from.
|
||||
type: path
|
||||
state:
|
||||
default: 'present'
|
||||
choices: ['present', 'absent']
|
||||
description:
|
||||
- Whether the file should exist or not.
|
||||
All parameters except C(path) are ignored when state is C(absent).
|
||||
choices: [ absent, present ]
|
||||
default: present
|
||||
src:
|
||||
description:
|
||||
- PKCS#12 file path to parse.
|
||||
|
||||
type: path
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
seealso:
|
||||
- module: openssl_certificate
|
||||
- module: openssl_csr
|
||||
- module: openssl_dhparam
|
||||
- module: openssl_privatekey
|
||||
- module: openssl_publickey
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: 'Generate PKCS#12 file'
|
||||
EXAMPLES = r'''
|
||||
- name: Generate PKCS#12 file
|
||||
openssl_pkcs12:
|
||||
action: export
|
||||
path: '/opt/certs/ansible.p12'
|
||||
friendly_name: 'raclette'
|
||||
privatekey_path: '/opt/certs/keys/key.pem'
|
||||
certificate_path: '/opt/certs/cert.pem'
|
||||
ca_certificates: '/opt/certs/ca.pem'
|
||||
path: /opt/certs/ansible.p12
|
||||
friendly_name: raclette
|
||||
privatekey_path: /opt/certs/keys/key.pem
|
||||
certificate_path: /opt/certs/cert.pem
|
||||
ca_certificates: /opt/certs/ca.pem
|
||||
state: present
|
||||
|
||||
- name: 'Change PKCS#12 file permission'
|
||||
- name: Change PKCS#12 file permission
|
||||
openssl_pkcs12:
|
||||
action: export
|
||||
path: '/opt/certs/ansible.p12'
|
||||
friendly_name: 'raclette'
|
||||
privatekey_path: '/opt/certs/keys/key.pem'
|
||||
certificate_path: '/opt/certs/cert.pem'
|
||||
ca_certificates: '/opt/certs/ca.pem'
|
||||
path: /opt/certs/ansible.p12
|
||||
friendly_name: raclette
|
||||
privatekey_path: /opt/certs/keys/key.pem
|
||||
certificate_path: /opt/certs/cert.pem
|
||||
ca_certificates: /opt/certs/ca.pem
|
||||
state: present
|
||||
mode: 0600
|
||||
mode: '0600'
|
||||
|
||||
- name: 'Regen PKCS#12 file'
|
||||
- name: Regen PKCS#12 file
|
||||
openssl_pkcs12:
|
||||
action: export
|
||||
src: '/opt/certs/ansible.p12'
|
||||
path: '/opt/certs/ansible.p12'
|
||||
friendly_name: 'raclette'
|
||||
privatekey_path: '/opt/certs/keys/key.pem'
|
||||
certificate_path: '/opt/certs/cert.pem'
|
||||
ca_certificates: '/opt/certs/ca.pem'
|
||||
src: /opt/certs/ansible.p12
|
||||
path: /opt/certs/ansible.p12
|
||||
friendly_name: raclette
|
||||
privatekey_path: /opt/certs/keys/key.pem
|
||||
certificate_path: /opt/certs/cert.pem
|
||||
ca_certificates: /opt/certs/ca.pem
|
||||
state: present
|
||||
mode: 0600
|
||||
force: True
|
||||
mode: '0600'
|
||||
force: yes
|
||||
|
||||
- name: 'Dump/Parse PKCS#12 file'
|
||||
- name: Dump/Parse PKCS#12 file
|
||||
openssl_pkcs12:
|
||||
action: parse
|
||||
src: '/opt/certs/ansible.p12'
|
||||
path: '/opt/certs/ansible.pem'
|
||||
src: /opt/certs/ansible.p12
|
||||
path: /opt/certs/ansible.pem
|
||||
state: present
|
||||
|
||||
- name: 'Remove PKCS#12 file'
|
||||
- name: Remove PKCS#12 file
|
||||
openssl_pkcs12:
|
||||
path: '/opt/certs/ansible.p12'
|
||||
path: /opt/certs/ansible.p12
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
RETURN = r'''
|
||||
filename:
|
||||
description: Path to the generate PKCS#12 file.
|
||||
returned: changed or success
|
||||
type: str
|
||||
sample: /opt/certs/ansible.p12
|
||||
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
|
||||
type: str
|
||||
sample: /etc/ssl/private/ansible.com.pem
|
||||
|
@ -280,8 +297,7 @@ class Pkcs(crypto_utils.OpenSSLObject):
|
|||
|
||||
def main():
|
||||
argument_spec = dict(
|
||||
action=dict(type='str', default='export',
|
||||
choices=['parse', 'export']),
|
||||
action=dict(type='str', default='export', choices=['export', 'parse']),
|
||||
ca_certificates=dict(type='list', elements='path'),
|
||||
certificate_path=dict(type='path'),
|
||||
force=dict(type='bool', default=False),
|
||||
|
@ -292,8 +308,7 @@ def main():
|
|||
path=dict(type='path', required=True),
|
||||
privatekey_passphrase=dict(type='str', no_log=True),
|
||||
privatekey_path=dict(type='path'),
|
||||
state=dict(type='str', default='present',
|
||||
choices=['present', 'absent']),
|
||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||
src=dict(type='path'),
|
||||
)
|
||||
|
||||
|
@ -320,8 +335,7 @@ def main():
|
|||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
name=base_dir,
|
||||
msg='The directory %s does not exist or '
|
||||
'the path is not a directory' % base_dir
|
||||
msg="The directory '%s' does not exist or the path is not a directory" % base_dir
|
||||
)
|
||||
|
||||
pkcs12 = Pkcs(module)
|
||||
|
|
|
@ -1,66 +1,65 @@
|
|||
#!/usr/bin/python
|
||||
# -*- 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)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: openssl_privatekey
|
||||
author:
|
||||
- "Yanis Guenane (@Spredzy)"
|
||||
- "Felix Fontein (@felixfontein)"
|
||||
version_added: "2.3"
|
||||
short_description: Generate OpenSSL private keys.
|
||||
short_description: Generate OpenSSL private keys
|
||||
description:
|
||||
- "This module allows one to (re)generate OpenSSL private keys. One can
|
||||
generate L(RSA,https://en.wikipedia.org/wiki/RSA_(cryptosystem)),
|
||||
L(DSA,https://en.wikipedia.org/wiki/Digital_Signature_Algorithm) or
|
||||
L(ECC,https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)
|
||||
private keys. 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
|
||||
overridden with the I(select_crypto_backend) option."
|
||||
- This module allows one to (re)generate OpenSSL private keys.
|
||||
- One can generate L(RSA,https://en.wikipedia.org/wiki/RSA_(cryptosystem)),
|
||||
L(DSA,https://en.wikipedia.org/wiki/Digital_Signature_Algorithm) or
|
||||
L(ECC,https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)
|
||||
private keys.
|
||||
- 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
|
||||
overridden with the I(select_crypto_backend) option."
|
||||
requirements:
|
||||
- "One of the following Python libraries:"
|
||||
- "cryptography >= 1.2.3 (older versions might work as well)"
|
||||
- "pyOpenSSL"
|
||||
- Either cryptography >= 1.2.3 (older versions might work as well)
|
||||
- Or pyOpenSSL
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
options:
|
||||
state:
|
||||
required: false
|
||||
default: "present"
|
||||
choices: [ present, absent ]
|
||||
description:
|
||||
- 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:
|
||||
required: false
|
||||
description:
|
||||
- Size (in bits) of the TLS/SSL key to generate.
|
||||
type: int
|
||||
default: 4096
|
||||
description:
|
||||
- Size (in bits) of the TLS/SSL key to generate
|
||||
type:
|
||||
required: false
|
||||
default: "RSA"
|
||||
choices:
|
||||
- RSA
|
||||
- DSA
|
||||
- ECC
|
||||
# - X448
|
||||
# - X25519
|
||||
description:
|
||||
- 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
|
||||
version of the cryptography backend."
|
||||
- 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 version of the cryptography backend.
|
||||
type: str
|
||||
#choices: [ DSA, ECC, RSA, X448, X25519 ]
|
||||
choices: [ DSA, ECC, RSA ]
|
||||
default: RSA
|
||||
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:
|
||||
- secp384r1
|
||||
- secp521r1
|
||||
|
@ -80,105 +79,100 @@ options:
|
|||
- sect283r1
|
||||
- sect233r1
|
||||
- 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"
|
||||
force:
|
||||
required: false
|
||||
default: False
|
||||
type: bool
|
||||
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:
|
||||
required: true
|
||||
description:
|
||||
- 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:
|
||||
required: false
|
||||
description:
|
||||
- The passphrase for the private key.
|
||||
type: str
|
||||
version_added: "2.4"
|
||||
cipher:
|
||||
required: false
|
||||
description:
|
||||
- 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).
|
||||
type: str
|
||||
version_added: "2.4"
|
||||
select_crypto_backend:
|
||||
description:
|
||||
- "Determines which crypto backend to use. The default choice is C(auto),
|
||||
which tries to use C(cryptography) if available, and falls back to
|
||||
C(pyopenssl)."
|
||||
- "If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/)
|
||||
library."
|
||||
- "If set to C(cryptography), will try to use the
|
||||
L(cryptography,https://cryptography.io/) library."
|
||||
- Determines which crypto backend to use.
|
||||
- The default choice is C(auto), which tries to use C(cryptography) if available, and falls back to C(pyopenssl).
|
||||
- If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) library.
|
||||
- If set to C(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
|
||||
type: str
|
||||
default: 'auto'
|
||||
choices:
|
||||
- auto
|
||||
- cryptography
|
||||
- pyopenssl
|
||||
choices: [ auto, cryptography, pyopenssl ]
|
||||
default: auto
|
||||
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 = '''
|
||||
# Generate an OpenSSL private key with the default values (4096 bits, RSA)
|
||||
- openssl_privatekey:
|
||||
EXAMPLES = r'''
|
||||
- name: Generate an OpenSSL private key with the default values (4096 bits, RSA)
|
||||
openssl_privatekey:
|
||||
path: /etc/ssl/private/ansible.com.pem
|
||||
|
||||
# Generate an OpenSSL private key with the default values (4096 bits, RSA)
|
||||
# and a passphrase
|
||||
- openssl_privatekey:
|
||||
- name: Generate an OpenSSL private key with the default values (4096 bits, RSA) and a passphrase
|
||||
openssl_privatekey:
|
||||
path: /etc/ssl/private/ansible.com.pem
|
||||
passphrase: ansible
|
||||
cipher: aes256
|
||||
|
||||
# Generate an OpenSSL private key with a different size (2048 bits)
|
||||
- openssl_privatekey:
|
||||
- name: Generate an OpenSSL private key with a different size (2048 bits)
|
||||
openssl_privatekey:
|
||||
path: /etc/ssl/private/ansible.com.pem
|
||||
size: 2048
|
||||
|
||||
# Force regenerate an OpenSSL private key if it already exists
|
||||
- openssl_privatekey:
|
||||
- name: Force regenerate an OpenSSL private key if it already exists
|
||||
openssl_privatekey:
|
||||
path: /etc/ssl/private/ansible.com.pem
|
||||
force: True
|
||||
force: yes
|
||||
|
||||
# Generate an OpenSSL private key with a different algorithm (DSA)
|
||||
- openssl_privatekey:
|
||||
- name: Generate an OpenSSL private key with a different algorithm (DSA)
|
||||
openssl_privatekey:
|
||||
path: /etc/ssl/private/ansible.com.pem
|
||||
type: DSA
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
RETURN = r'''
|
||||
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
|
||||
type: int
|
||||
sample: 4096
|
||||
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
|
||||
type: str
|
||||
sample: RSA
|
||||
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)
|
||||
type: str
|
||||
sample: secp256k1
|
||||
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
|
||||
type: str
|
||||
sample: /etc/ssl/private/ansible.com.pem
|
||||
fingerprint:
|
||||
description: 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.
|
||||
description:
|
||||
- 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.
|
||||
returned: changed or success
|
||||
type: dict
|
||||
sample:
|
||||
|
|
|
@ -1,117 +1,125 @@
|
|||
#!/usr/bin/python
|
||||
# -*- 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)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: openssl_publickey
|
||||
author: "Yanis Guenane (@Spredzy)"
|
||||
version_added: "2.3"
|
||||
short_description: Generate an OpenSSL public key from its private key.
|
||||
description:
|
||||
- "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
|
||||
in PEM format. This module works only if the version of PyOpenSSL is recent enough (> 16.0.0)."
|
||||
- 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 in PEM format.
|
||||
- This module works only if the version of PyOpenSSL is recent enough (> 16.0.0).
|
||||
requirements:
|
||||
- "python-pyOpenSSL"
|
||||
- python-pyOpenSSL
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
options:
|
||||
state:
|
||||
required: false
|
||||
default: "present"
|
||||
choices: [ present, absent ]
|
||||
description:
|
||||
- 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:
|
||||
required: false
|
||||
default: False
|
||||
type: bool
|
||||
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:
|
||||
required: false
|
||||
default: PEM
|
||||
choices: [ PEM, OpenSSH ]
|
||||
description:
|
||||
- The format of the public key.
|
||||
type: str
|
||||
choices: [ OpenSSH, PEM ]
|
||||
default: PEM
|
||||
version_added: "2.4"
|
||||
path:
|
||||
required: true
|
||||
description:
|
||||
- Name of the file in which the generated TLS/SSL public key will be written.
|
||||
privatekey_path:
|
||||
type: path
|
||||
required: true
|
||||
privatekey_path:
|
||||
description:
|
||||
- Path to the TLS/SSL private key from which to generate the public key.
|
||||
type: path
|
||||
required: true
|
||||
privatekey_passphrase:
|
||||
required: false
|
||||
description:
|
||||
- The passphrase for the privatekey.
|
||||
type: str
|
||||
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 = '''
|
||||
# Generate an OpenSSL public key in PEM format.
|
||||
- openssl_publickey:
|
||||
EXAMPLES = r'''
|
||||
- name: Generate an OpenSSL public key in PEM format
|
||||
openssl_publickey:
|
||||
path: /etc/ssl/public/ansible.com.pem
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
|
||||
# Generate an OpenSSL public key in OpenSSH v2 format.
|
||||
- openssl_publickey:
|
||||
- name: Generate an OpenSSL public key in OpenSSH v2 format
|
||||
openssl_publickey:
|
||||
path: /etc/ssl/public/ansible.com.pem
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
format: OpenSSH
|
||||
|
||||
# Generate an OpenSSL public key with a passphrase protected
|
||||
# private key
|
||||
- openssl_publickey:
|
||||
- name: Generate an OpenSSL public key with a passphrase protected private key
|
||||
openssl_publickey:
|
||||
path: /etc/ssl/public/ansible.com.pem
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
privatekey_passphrase: ansible
|
||||
|
||||
# Force regenerate an OpenSSL public key if it already exists
|
||||
- openssl_publickey:
|
||||
- name: Force regenerate an OpenSSL public key if it already exists
|
||||
openssl_publickey:
|
||||
path: /etc/ssl/public/ansible.com.pem
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
force: True
|
||||
force: yes
|
||||
|
||||
# Remove an OpenSSL public key
|
||||
- openssl_publickey:
|
||||
- name: Remove an OpenSSL public key
|
||||
openssl_publickey:
|
||||
path: /etc/ssl/public/ansible.com.pem
|
||||
privatekey_path: /etc/ssl/private/ansible.com.pem
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
RETURN = r'''
|
||||
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
|
||||
type: str
|
||||
sample: /etc/ssl/private/ansible.com.pem
|
||||
format:
|
||||
description: The format of the public key (PEM, OpenSSH, ...)
|
||||
description: The format of the public key (PEM, OpenSSH, ...).
|
||||
returned: changed or success
|
||||
type: str
|
||||
sample: PEM
|
||||
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
|
||||
type: str
|
||||
sample: /etc/ssl/public/ansible.com.pem
|
||||
fingerprint:
|
||||
description: The fingerprint of the public key. Fingerprint will be generated for each hashlib.algorithms available.
|
||||
Requires PyOpenSSL >= 16.0 for meaningful output.
|
||||
description:
|
||||
- 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
|
||||
type: dict
|
||||
sample:
|
||||
|
@ -259,16 +267,16 @@ def main():
|
|||
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(default='present', choices=['present', 'absent'], type='str'),
|
||||
force=dict(default=False, type='bool'),
|
||||
path=dict(required=True, type='path'),
|
||||
state=dict(type='str', default='present', choices=['present', 'absent']),
|
||||
force=dict(type='bool', default=False),
|
||||
path=dict(type='path', required=True),
|
||||
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),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
required_if=[('state', 'present', ['privatekey_path'])]
|
||||
required_if=[('state', 'present', ['privatekey_path'])],
|
||||
)
|
||||
|
||||
if not pyopenssl_found:
|
||||
|
@ -278,7 +286,7 @@ def main():
|
|||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(
|
||||
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)
|
||||
|
|
|
@ -360,8 +360,6 @@ lib/ansible/modules/clustering/znode.py E326
|
|||
lib/ansible/modules/commands/command.py E322
|
||||
lib/ansible/modules/commands/command.py E323
|
||||
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_query.py E324
|
||||
lib/ansible/modules/database/influxdb/influxdb_retention_policy.py E324
|
||||
|
|
Loading…
Reference in a new issue