Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x509_certificate: add ignore_timestamps option #317

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/317-ignore-timestamps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- "x509_certificate, x509_certificate_pipe - add ``ignore_timestamps`` option which allows to enable idempotency for 'not before' and 'not after' options (https://github.com/ansible-collections/community.crypto/issues/295, https://github.com/ansible-collections/community.crypto/pull/317)."
17 changes: 17 additions & 0 deletions plugins/doc_fragments/module_certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ class ModuleDocFragment(object):
- This is required if the private key is password protected.
type: str

ignore_timestamps:
description:
- Whether the "not before" and "not after" timestamps should be ignored for idempotency checks.
- It is better to keep the default value C(true) when using relative timestamps (like C(+0s) for now).
type: bool
default: true
version_added: 2.0.0

select_crypto_backend:
description:
- Determines which crypto backend to use.
Expand Down Expand Up @@ -185,6 +193,7 @@ class ModuleDocFragment(object):
- The minimum certificate lifetime is 90 days, and maximum is three years.
- If this value is not specified, the certificate will stop being valid 365 days the date of issue.
- This is only used by the C(entrust) provider.
- Please note that this value is B(not) covered by the I(ignore_timestamps) option.
type: str
default: +365d

Expand Down Expand Up @@ -258,6 +267,8 @@ class ModuleDocFragment(object):
+ C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- If this value is not specified, the certificate will start being valid from now.
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
This can be changed by setting the I(ignore_timestamps) option to C(false). Please note that you should
avoid relative timestamps when setting I(ignore_timestamps=false).
- This is only used by the C(ownca) provider.
type: str
default: +0s
Expand All @@ -271,6 +282,8 @@ class ModuleDocFragment(object):
+ C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- If this value is not specified, the certificate will stop being valid 10 years from now.
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
This can be changed by setting the I(ignore_timestamps) option to C(false). Please note that you should
avoid relative timestamps when setting I(ignore_timestamps=false).
- This is only used by the C(ownca) provider.
- On macOS 10.15 and onwards, TLS server certificates must have a validity period of 825 days or fewer.
Please see U(https://support.apple.com/en-us/HT210176) for more details.
Expand Down Expand Up @@ -349,6 +362,8 @@ class ModuleDocFragment(object):
+ C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- If this value is not specified, the certificate will start being valid from now.
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
This can be changed by setting the I(ignore_timestamps) option to C(false). Please note that you should
avoid relative timestamps when setting I(ignore_timestamps=false).
- This is only used by the C(selfsigned) provider.
type: str
default: +0s
Expand All @@ -363,6 +378,8 @@ class ModuleDocFragment(object):
+ C([w | d | h | m | s]) (e.g. C(+32w1d2h).
- If this value is not specified, the certificate will stop being valid 10 years from now.
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
This can be changed by setting the I(ignore_timestamps) option to C(false). Please note that you should
avoid relative timestamps when setting I(ignore_timestamps=false).
- This is only used by the C(selfsigned) provider.
- On macOS 10.15 and onwards, TLS server certificates must have a validity period of 825 days or fewer.
Please see U(https://support.apple.com/en-us/HT210176) for more details.
Expand Down
13 changes: 12 additions & 1 deletion plugins/module_utils/crypto/module_backends/certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def __init__(self, module, backend):
self.backend = backend

self.force = module.params['force']
self.ignore_timestamps = module.params['ignore_timestamps']
self.privatekey_path = module.params['privatekey_path']
self.privatekey_content = module.params['privatekey_content']
if self.privatekey_content is not None:
Expand Down Expand Up @@ -223,7 +224,7 @@ def _check_subject_key_identifier(self):
return False
return True

def needs_regeneration(self):
def needs_regeneration(self, not_before=None, not_after=None):
"""Check whether a regeneration is necessary."""
if self.force or self.existing_certificate_bytes is None:
return True
Expand All @@ -247,6 +248,15 @@ def needs_regeneration(self):
if self.create_subject_key_identifier != 'never_create' and not self._check_subject_key_identifier():
return True

# Check not before
if not_before is not None and not self.ignore_timestamps:
if self.existing_certificate.not_valid_before != not_before:
return True

# Check not after
if not_after is not None and not self.ignore_timestamps:
if self.existing_certificate.not_valid_after != not_after:
return True
return False

def dump(self, include_certificate):
Expand Down Expand Up @@ -328,6 +338,7 @@ def get_certificate_argument_spec():
force=dict(type='bool', default=False,),
csr_path=dict(type='path'),
csr_content=dict(type='str'),
ignore_timestamps=dict(type='bool', default=True),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography']),

# General properties of a certificate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def get_certificate_data(self):
return self.cert.public_bytes(Encoding.PEM)

def needs_regeneration(self):
if super(OwnCACertificateBackendCryptography, self).needs_regeneration():
if super(OwnCACertificateBackendCryptography, self).needs_regeneration(not_before=self.notBefore, not_after=self.notAfter):
return True

# Check AuthorityKeyIdentifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ def get_certificate_data(self):
"""Return bytes for self.cert."""
return self.cert.public_bytes(Encoding.PEM)

def needs_regeneration(self):
return super(SelfSignedCertificateBackendCryptography, self).needs_regeneration(
not_before=self.notBefore, not_after=self.notAfter)

def dump(self, include_certificate):
result = super(SelfSignedCertificateBackendCryptography, self).dump(include_certificate)

Expand Down