mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-05-06 13:22:58 +00:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbadcbeb29 | ||
|
|
e991375f55 | ||
|
|
33c99014ae | ||
|
|
fbd6ff6ead | ||
|
|
c4ab2eb3b5 | ||
|
|
44b6df0ce5 | ||
|
|
14a42505a9 | ||
|
|
44cbd33cb7 | ||
|
|
4411a71d06 | ||
|
|
bfe37bc668 | ||
|
|
d784e0a52b | ||
|
|
d73a2942a2 | ||
|
|
8af4847373 | ||
|
|
44f7367e21 | ||
|
|
0733b0d521 | ||
|
|
771a9eebcf | ||
|
|
0fdede5d7a | ||
|
|
56b2130c6e | ||
|
|
6c018b94da | ||
|
|
63f4598737 | ||
|
|
598cdf0a21 | ||
|
|
eea7bfc6bf | ||
|
|
8521c96e8a | ||
|
|
d90cc5142b | ||
|
|
37aab65396 | ||
|
|
baff003ea8 | ||
|
|
03427e35a7 | ||
|
|
170fa40014 | ||
|
|
330b30d5d2 | ||
|
|
67b8274faf | ||
|
|
02ee3fb974 | ||
|
|
93ced1956c | ||
|
|
a9e358ea57 | ||
|
|
ffcdbc5d0c | ||
|
|
6740cae10f | ||
|
|
915379459d | ||
|
|
a4a12bae27 | ||
|
|
94fc356338 | ||
|
|
08ada24a53 | ||
|
|
b59846b9fa | ||
|
|
c9ec463893 | ||
|
|
38ce150f80 |
@@ -19,6 +19,11 @@ schedules:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- cron: 0 12 * * 0
|
||||
displayName: Weekly (old stable branches)
|
||||
always: true
|
||||
branches:
|
||||
include:
|
||||
- stable-*
|
||||
|
||||
variables:
|
||||
@@ -55,6 +60,17 @@ stages:
|
||||
test: 'devel/sanity/extra'
|
||||
- name: Units
|
||||
test: 'devel/units/1'
|
||||
- stage: Ansible_2_12
|
||||
displayName: Sanity & Units 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: Sanity
|
||||
test: '2.12/sanity/1'
|
||||
- name: Units
|
||||
test: '2.12/units/1'
|
||||
- stage: Ansible_2_11
|
||||
displayName: Sanity & Units 2.11
|
||||
dependsOn: []
|
||||
@@ -97,8 +113,6 @@ stages:
|
||||
parameters:
|
||||
testFormat: devel/linux/{0}/1
|
||||
targets:
|
||||
- name: CentOS 6
|
||||
test: centos6
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
- name: CentOS 8
|
||||
@@ -115,6 +129,24 @@ stages:
|
||||
test: ubuntu1804
|
||||
- name: Ubuntu 20.04
|
||||
test: ubuntu2004
|
||||
- stage: Docker_2_12
|
||||
displayName: Docker 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.12/linux/{0}/1
|
||||
targets:
|
||||
- name: CentOS 6
|
||||
test: centos6
|
||||
- name: CentOS 8
|
||||
test: centos8
|
||||
- name: Fedora 33
|
||||
test: fedora33
|
||||
- name: openSUSE 15 py3
|
||||
test: opensuse15
|
||||
- name: Ubuntu 20.04
|
||||
test: ubuntu2004
|
||||
- stage: Docker_2_11
|
||||
displayName: Docker 2.11
|
||||
dependsOn: []
|
||||
@@ -131,12 +163,8 @@ stages:
|
||||
test: fedora32
|
||||
- name: openSUSE 15 py2
|
||||
test: opensuse15py2
|
||||
- name: openSUSE 15 py3
|
||||
test: opensuse15
|
||||
- name: Ubuntu 18.04
|
||||
test: ubuntu1804
|
||||
- name: Ubuntu 20.04
|
||||
test: ubuntu2004
|
||||
- stage: Docker_2_10
|
||||
displayName: Docker 2.10
|
||||
dependsOn: []
|
||||
@@ -147,22 +175,10 @@ stages:
|
||||
targets:
|
||||
- name: CentOS 6
|
||||
test: centos6
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
- name: CentOS 8
|
||||
test: centos8
|
||||
- name: Fedora 31
|
||||
test: fedora31
|
||||
- name: Fedora 32
|
||||
test: fedora32
|
||||
- name: openSUSE 15 py2
|
||||
test: opensuse15py2
|
||||
- name: openSUSE 15 py3
|
||||
test: opensuse15
|
||||
- name: Ubuntu 16.04
|
||||
test: ubuntu1604
|
||||
- name: Ubuntu 18.04
|
||||
test: ubuntu1804
|
||||
- stage: Docker_2_9
|
||||
displayName: Docker 2.9
|
||||
dependsOn: []
|
||||
@@ -175,16 +191,8 @@ stages:
|
||||
test: centos6
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
- name: CentOS 8
|
||||
test: centos8
|
||||
- name: Fedora 30
|
||||
test: fedora30
|
||||
- name: Fedora 31
|
||||
test: fedora31
|
||||
- name: openSUSE 15 py2
|
||||
test: opensuse15py2
|
||||
- name: openSUSE 15 py3
|
||||
test: opensuse15
|
||||
- name: Ubuntu 16.04
|
||||
test: ubuntu1604
|
||||
- name: Ubuntu 18.04
|
||||
@@ -209,6 +217,20 @@ stages:
|
||||
test: freebsd/12.2
|
||||
- name: FreeBSD 13.0
|
||||
test: freebsd/13.0
|
||||
- stage: Remote_2_12
|
||||
displayName: Remote 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.12/{0}/1
|
||||
targets:
|
||||
- name: macOS 11.1
|
||||
test: macos/11.1
|
||||
- name: RHEL 8.4
|
||||
test: rhel/8.4
|
||||
- name: FreeBSD 13.0
|
||||
test: freebsd/13.0
|
||||
- stage: Remote_2_11
|
||||
displayName: Remote 2.11
|
||||
dependsOn: []
|
||||
@@ -221,8 +243,6 @@ stages:
|
||||
test: rhel/7.9
|
||||
- name: RHEL 8.3
|
||||
test: rhel/8.3
|
||||
- name: macOS 11.1
|
||||
test: macos/11.1
|
||||
- name: FreeBSD 12.2
|
||||
test: freebsd/12.2
|
||||
- stage: Remote_2_10
|
||||
@@ -233,8 +253,6 @@ stages:
|
||||
parameters:
|
||||
testFormat: 2.10/{0}/1
|
||||
targets:
|
||||
- name: RHEL 7.8
|
||||
test: rhel/7.8
|
||||
- name: OS X 10.11
|
||||
test: osx/10.11
|
||||
- name: macOS 10.15
|
||||
@@ -261,7 +279,6 @@ stages:
|
||||
nameFormat: Python {0}
|
||||
testFormat: devel/cloud/{0}/1
|
||||
targets:
|
||||
- test: 2.6
|
||||
- test: 2.7
|
||||
- test: 3.5
|
||||
- test: 3.6
|
||||
@@ -269,6 +286,17 @@ stages:
|
||||
- test: 3.8
|
||||
- test: 3.9
|
||||
- test: "3.10"
|
||||
- stage: Cloud_2_12
|
||||
displayName: Cloud 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.12/cloud/{0}/1
|
||||
targets:
|
||||
- test: 2.6
|
||||
- test: 3.9
|
||||
- stage: Cloud_2_11
|
||||
displayName: Cloud 2.11
|
||||
dependsOn: []
|
||||
@@ -306,20 +334,24 @@ stages:
|
||||
condition: succeededOrFailed()
|
||||
dependsOn:
|
||||
- Ansible_devel
|
||||
- Ansible_2_12
|
||||
- Ansible_2_11
|
||||
- Ansible_2_10
|
||||
- Ansible_2_9
|
||||
- Remote_devel
|
||||
- Docker_devel
|
||||
- Cloud_devel
|
||||
- Remote_2_12
|
||||
- Remote_2_11
|
||||
- Docker_2_11
|
||||
- Cloud_2_11
|
||||
- Remote_2_10
|
||||
- Docker_2_10
|
||||
- Cloud_2_10
|
||||
- Remote_2_9
|
||||
- Docker_devel
|
||||
- Docker_2_12
|
||||
- Docker_2_11
|
||||
- Docker_2_10
|
||||
- Docker_2_9
|
||||
- Cloud_devel
|
||||
- Cloud_2_12
|
||||
- Cloud_2_11
|
||||
- Cloud_2_10
|
||||
- Cloud_2_9
|
||||
jobs:
|
||||
- template: templates/coverage.yml
|
||||
|
||||
@@ -5,6 +5,89 @@ Community Crypto Release Notes
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v1.9.5
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix release to fully support cryptography 35.0.0.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- get_certificate - fix compatibility with the cryptography 35.0.0 release (https://github.com/ansible-collections/community.crypto/pull/294).
|
||||
- openssl_csr_info - fix compatibility with the cryptography 35.0.0 release (https://github.com/ansible-collections/community.crypto/pull/294).
|
||||
- openssl_csr_info - fix compatibility with the cryptography 35.0.0 release in PyOpenSSL backend (https://github.com/ansible-collections/community.crypto/pull/300).
|
||||
- openssl_pkcs12 - fix compatibility with the cryptography 35.0.0 release (https://github.com/ansible-collections/community.crypto/pull/296).
|
||||
- x509_certificate_info - fix compatibility with the cryptography 35.0.0 release (https://github.com/ansible-collections/community.crypto/pull/294).
|
||||
- x509_certificate_info - fix compatibility with the cryptography 35.0.0 release in PyOpenSSL backend (https://github.com/ansible-collections/community.crypto/pull/300).
|
||||
|
||||
v1.9.4
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Regular bugfix release.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- acme_* modules - fix commands composed for OpenSSL backend to retrieve information on CSRs and certificates from stdin to use ``/dev/stdin`` instead of ``-``. This is needed for OpenSSL 1.0.1 and 1.0.2, apparently (https://github.com/ansible-collections/community.crypto/pull/279).
|
||||
- acme_challenge_cert_helper - only return exception when cryptography is not installed, not when a too old version of it is installed. This prevents Ansible's callback to crash (https://github.com/ansible-collections/community.crypto/pull/281).
|
||||
|
||||
v1.9.3
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Regular bugfix release.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- openssl_csr and openssl_csr_pipe - make sure that Unicode strings are used to compare strings with the cryptography backend. This fixes idempotency problems with non-ASCII letters on Python 2 (https://github.com/ansible-collections/community.crypto/issues/270, https://github.com/ansible-collections/community.crypto/pull/271).
|
||||
|
||||
v1.9.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix release to fix the changelog. No other change compared to 1.9.0.
|
||||
|
||||
v1.9.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Accidental 1.9.1 release. Identical to 1.9.0.
|
||||
|
||||
v1.9.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Regular feature release.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- get_certificate - added ``starttls`` option to retrieve certificates from servers which require clients to request an encrypted connection (https://github.com/ansible-collections/community.crypto/pull/264).
|
||||
- openssh_keypair - added ``diff`` support (https://github.com/ansible-collections/community.crypto/pull/260).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- keypair_backend module utils - simplify code to pass sanity tests (https://github.com/ansible-collections/community.crypto/pull/263).
|
||||
- openssh_keypair - fixed ``cryptography`` backend to preserve original file permissions when regenerating a keypair requires existing files to be overwritten (https://github.com/ansible-collections/community.crypto/pull/260).
|
||||
- openssh_keypair - fixed error handling to restore original keypair if regeneration fails (https://github.com/ansible-collections/community.crypto/pull/260).
|
||||
- x509_crl - restore inherited function signature to pass sanity tests (https://github.com/ansible-collections/community.crypto/pull/263).
|
||||
|
||||
v1.8.0
|
||||
======
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Please note that this collection does **not** support Windows targets.
|
||||
|
||||
## Tested with Ansible
|
||||
|
||||
Tested with the current Ansible 2.9, ansible-base 2.10 and ansible-core 2.11 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported.
|
||||
Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11 and ansible-core 2.12 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported.
|
||||
|
||||
## External requirements
|
||||
|
||||
|
||||
@@ -503,3 +503,82 @@ releases:
|
||||
- 257-openssh-keypair-fix-pubkey-permissions.yml
|
||||
- ansible-core-_text.yml
|
||||
release_date: '2021-08-10'
|
||||
1.9.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- keypair_backend module utils - simplify code to pass sanity tests (https://github.com/ansible-collections/community.crypto/pull/263).
|
||||
- openssh_keypair - fixed ``cryptography`` backend to preserve original file
|
||||
permissions when regenerating a keypair requires existing files to be overwritten
|
||||
(https://github.com/ansible-collections/community.crypto/pull/260).
|
||||
- openssh_keypair - fixed error handling to restore original keypair if regeneration
|
||||
fails (https://github.com/ansible-collections/community.crypto/pull/260).
|
||||
- x509_crl - restore inherited function signature to pass sanity tests (https://github.com/ansible-collections/community.crypto/pull/263).
|
||||
minor_changes:
|
||||
- get_certificate - added ``starttls`` option to retrieve certificates from
|
||||
servers which require clients to request an encrypted connection (https://github.com/ansible-collections/community.crypto/pull/264).
|
||||
- openssh_keypair - added ``diff`` support (https://github.com/ansible-collections/community.crypto/pull/260).
|
||||
release_summary: Regular feature release.
|
||||
fragments:
|
||||
- 1.9.0.yml
|
||||
- 260-openssh_keypair-diff-support.yml
|
||||
- 263-sanity.yml
|
||||
- 264-get_certificate-add-starttls-option.yml
|
||||
release_date: '2021-08-30'
|
||||
1.9.1:
|
||||
changes:
|
||||
release_summary: Accidental 1.9.1 release. Identical to 1.9.0.
|
||||
release_date: '2021-08-30'
|
||||
1.9.2:
|
||||
changes:
|
||||
release_summary: Bugfix release to fix the changelog. No other change compared
|
||||
to 1.9.0.
|
||||
fragments:
|
||||
- 1.9.2.yml
|
||||
release_date: '2021-08-30'
|
||||
1.9.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- openssl_csr and openssl_csr_pipe - make sure that Unicode strings are used
|
||||
to compare strings with the cryptography backend. This fixes idempotency problems
|
||||
with non-ASCII letters on Python 2 (https://github.com/ansible-collections/community.crypto/issues/270,
|
||||
https://github.com/ansible-collections/community.crypto/pull/271).
|
||||
release_summary: Regular bugfix release.
|
||||
fragments:
|
||||
- 1.9.3.yml
|
||||
- 271-openssl_csr-utf8.yml
|
||||
release_date: '2021-09-14'
|
||||
1.9.4:
|
||||
changes:
|
||||
bugfixes:
|
||||
- acme_* modules - fix commands composed for OpenSSL backend to retrieve information
|
||||
on CSRs and certificates from stdin to use ``/dev/stdin`` instead of ``-``.
|
||||
This is needed for OpenSSL 1.0.1 and 1.0.2, apparently (https://github.com/ansible-collections/community.crypto/pull/279).
|
||||
- acme_challenge_cert_helper - only return exception when cryptography is not
|
||||
installed, not when a too old version of it is installed. This prevents Ansible's
|
||||
callback to crash (https://github.com/ansible-collections/community.crypto/pull/281).
|
||||
release_summary: Regular bugfix release.
|
||||
fragments:
|
||||
- 1.9.4.yml
|
||||
- 279-acme-openssl.yml
|
||||
- 282-acme_challenge_cert_helper-error.yml
|
||||
release_date: '2021-09-28'
|
||||
1.9.5:
|
||||
changes:
|
||||
bugfixes:
|
||||
- get_certificate - fix compatibility with the cryptography 35.0.0 release (https://github.com/ansible-collections/community.crypto/pull/294).
|
||||
- openssl_csr_info - fix compatibility with the cryptography 35.0.0 release
|
||||
(https://github.com/ansible-collections/community.crypto/pull/294).
|
||||
- openssl_csr_info - fix compatibility with the cryptography 35.0.0 release
|
||||
in PyOpenSSL backend (https://github.com/ansible-collections/community.crypto/pull/300).
|
||||
- openssl_pkcs12 - fix compatibility with the cryptography 35.0.0 release (https://github.com/ansible-collections/community.crypto/pull/296).
|
||||
- x509_certificate_info - fix compatibility with the cryptography 35.0.0 release
|
||||
(https://github.com/ansible-collections/community.crypto/pull/294).
|
||||
- x509_certificate_info - fix compatibility with the cryptography 35.0.0 release
|
||||
in PyOpenSSL backend (https://github.com/ansible-collections/community.crypto/pull/300).
|
||||
release_summary: Bugfix release to fully support cryptography 35.0.0.
|
||||
fragments:
|
||||
- 1.9.5.yml
|
||||
- 294-cryptography-35.0.0.yml
|
||||
- 296-openssl_pkcs12-cryptography-35.yml
|
||||
- 300-pyopenssl-cryptography-35.yml
|
||||
release_date: '2021-10-06'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace: community
|
||||
name: crypto
|
||||
version: 1.8.0
|
||||
version: 1.9.5
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible (github.com/ansible)
|
||||
|
||||
@@ -457,8 +457,8 @@ options:
|
||||
- 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.
|
||||
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
|
||||
- This is only used by the C(ownca) provider.
|
||||
type: str
|
||||
default: +0s
|
||||
@@ -470,8 +470,8 @@ options:
|
||||
- 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.
|
||||
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
|
||||
- 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.
|
||||
@@ -548,8 +548,8 @@ options:
|
||||
- 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.
|
||||
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
|
||||
- This is only used by the C(selfsigned) provider.
|
||||
type: str
|
||||
default: +0s
|
||||
@@ -562,8 +562,8 @@ options:
|
||||
- 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.
|
||||
- Note that this value is B(not used to determine whether an existing certificate should be regenerated).
|
||||
- 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.
|
||||
|
||||
@@ -227,12 +227,11 @@ options:
|
||||
description:
|
||||
- The authority key identifier as a hex string, where two bytes are separated by colons.
|
||||
- "Example: C(00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33)"
|
||||
- If specified, I(authority_cert_issuer) must also be specified.
|
||||
- "Please note that commercial CAs ignore this value, respectively use a value of their
|
||||
own choice. Specifying this option is mostly useful for self-signed certificates
|
||||
or for own CAs."
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
- The C(AuthorityKeyIdentifier) will only be added if at least one of I(authority_key_identifier),
|
||||
- The C(AuthorityKeyIdentifier) extension will only be added if at least one of I(authority_key_identifier),
|
||||
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
|
||||
type: str
|
||||
authority_cert_issuer:
|
||||
@@ -241,23 +240,24 @@ options:
|
||||
- Values must 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)
|
||||
- "Example: C(DNS:ca.example.org)"
|
||||
- If specified, I(authority_key_identifier) must also be specified.
|
||||
- If specified, I(authority_cert_serial_number) must also be specified.
|
||||
- "Please note that commercial CAs ignore this value, respectively use a value of their
|
||||
own choice. Specifying this option is mostly useful for self-signed certificates
|
||||
or for own CAs."
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
- The C(AuthorityKeyIdentifier) will only be added if at least one of I(authority_key_identifier),
|
||||
- The C(AuthorityKeyIdentifier) extension will only be added if at least one of I(authority_key_identifier),
|
||||
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
|
||||
type: list
|
||||
elements: str
|
||||
authority_cert_serial_number:
|
||||
description:
|
||||
- The authority cert serial number.
|
||||
- If specified, I(authority_cert_issuer) must also be specified.
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
- "Please note that commercial CAs ignore this value, respectively use a value of their
|
||||
own choice. Specifying this option is mostly useful for self-signed certificates
|
||||
or for own CAs."
|
||||
- The C(AuthorityKeyIdentifier) will only be added if at least one of I(authority_key_identifier),
|
||||
- The C(AuthorityKeyIdentifier) extension will only be added if at least one of I(authority_key_identifier),
|
||||
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
|
||||
type: int
|
||||
crl_distribution_points:
|
||||
|
||||
@@ -230,7 +230,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
filename = csr_filename
|
||||
data = None
|
||||
if csr_content is not None:
|
||||
filename = '-'
|
||||
filename = '/dev/stdin'
|
||||
data = csr_content.encode('utf-8')
|
||||
|
||||
openssl_csr_cmd = [self.openssl_binary, "req", "-in", filename, "-noout", "-text"]
|
||||
@@ -267,7 +267,7 @@ class OpenSSLCLIBackend(CryptoBackend):
|
||||
filename = cert_filename
|
||||
data = None
|
||||
if cert_content is not None:
|
||||
filename = '-'
|
||||
filename = '/dev/stdin'
|
||||
data = cert_content.encode('utf-8')
|
||||
cert_filename_suffix = ''
|
||||
elif cert_filename is not None:
|
||||
|
||||
@@ -20,6 +20,10 @@ from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
# WARNING: this function no longer works with cryptography 35.0.0 and newer!
|
||||
# It must **ONLY** be used in compatibility code for older
|
||||
# cryptography versions!
|
||||
|
||||
def obj2txt(openssl_lib, openssl_ffi, obj):
|
||||
# Set to 80 on the recommendation of
|
||||
# https://www.openssl.org/docs/crypto/OBJ_nid2ln.html#return_values
|
||||
|
||||
@@ -23,12 +23,15 @@ import base64
|
||||
import binascii
|
||||
import re
|
||||
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
from ansible.module_utils.common.text.converters import to_text, to_bytes
|
||||
from ._asn1 import serialize_asn1_string_as_der
|
||||
|
||||
try:
|
||||
import cryptography
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
import ipaddress
|
||||
except ImportError:
|
||||
@@ -67,9 +70,19 @@ def cryptography_get_extensions_from_cert(cert):
|
||||
# Since cryptography won't give us the DER value for an extension
|
||||
# (that is only stored for unrecognized extensions), we have to re-do
|
||||
# the extension parsing outselves.
|
||||
backend = default_backend()
|
||||
try:
|
||||
# For certain old versions of cryptography, backend is a MultiBackend object,
|
||||
# which has no _lib attribute. In that case, revert to the old approach.
|
||||
backend._lib
|
||||
except AttributeError:
|
||||
backend = cert._backend
|
||||
|
||||
result = dict()
|
||||
backend = cert._backend
|
||||
x509_obj = cert._x509
|
||||
# With cryptography 35.0.0, we can no longer use obj2txt. Unfortunately it still does
|
||||
# not allow to get the raw value of an extension, so we have to use this ugly hack:
|
||||
exts = list(cert.extensions)
|
||||
|
||||
for i in range(backend._lib.X509_get_ext_count(x509_obj)):
|
||||
ext = backend._lib.X509_get_ext(x509_obj, i)
|
||||
@@ -83,8 +96,12 @@ def cryptography_get_extensions_from_cert(cert):
|
||||
critical=(crit == 1),
|
||||
value=base64.b64encode(der),
|
||||
)
|
||||
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
|
||||
try:
|
||||
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
|
||||
except AttributeError:
|
||||
oid = exts[i].oid.dotted_string
|
||||
result[oid] = entry
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -93,7 +110,13 @@ def cryptography_get_extensions_from_csr(csr):
|
||||
# (that is only stored for unrecognized extensions), we have to re-do
|
||||
# the extension parsing outselves.
|
||||
result = dict()
|
||||
backend = csr._backend
|
||||
backend = default_backend()
|
||||
try:
|
||||
# For certain old versions of cryptography, backend is a MultiBackend object,
|
||||
# which has no _lib attribute. In that case, revert to the old approach.
|
||||
backend._lib
|
||||
except AttributeError:
|
||||
backend = csr._backend
|
||||
|
||||
extensions = backend._lib.X509_REQ_get_extensions(csr._x509_req)
|
||||
extensions = backend._ffi.gc(
|
||||
@@ -104,6 +127,10 @@ def cryptography_get_extensions_from_csr(csr):
|
||||
)
|
||||
)
|
||||
|
||||
# With cryptography 35.0.0, we can no longer use obj2txt. Unfortunately it still does
|
||||
# not allow to get the raw value of an extension, so we have to use this ugly hack:
|
||||
exts = list(csr.extensions)
|
||||
|
||||
for i in range(backend._lib.sk_X509_EXTENSION_num(extensions)):
|
||||
ext = backend._lib.sk_X509_EXTENSION_value(extensions, i)
|
||||
if ext == backend._ffi.NULL:
|
||||
@@ -116,8 +143,12 @@ def cryptography_get_extensions_from_csr(csr):
|
||||
critical=(crit == 1),
|
||||
value=base64.b64encode(der),
|
||||
)
|
||||
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
|
||||
try:
|
||||
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
|
||||
except AttributeError:
|
||||
oid = exts[i].oid.dotted_string
|
||||
result[oid] = entry
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -450,9 +481,35 @@ def parse_pkcs12(pkcs12_bytes, passphrase=None):
|
||||
friendly_name = None
|
||||
if certificate:
|
||||
# See https://github.com/pyca/cryptography/issues/5760#issuecomment-842687238
|
||||
maybe_name = certificate._backend._lib.X509_alias_get0(
|
||||
certificate._x509, certificate._backend._ffi.NULL)
|
||||
if maybe_name != certificate._backend._ffi.NULL:
|
||||
friendly_name = certificate._backend._ffi.string(maybe_name)
|
||||
backend = default_backend()
|
||||
try:
|
||||
# For certain old versions of cryptography, backend is a MultiBackend object,
|
||||
# which has no _lib attribute. In that case, revert to the old approach.
|
||||
backend._lib
|
||||
except AttributeError:
|
||||
backend = certificate._backend
|
||||
|
||||
if LooseVersion(cryptography.__version__) >= LooseVersion('35.0'):
|
||||
# This code basically does what load_key_and_certificates() does, but without error-checking.
|
||||
# Since load_key_and_certificates succeeded, it should not fail.
|
||||
pkcs12 = backend._ffi.gc(
|
||||
backend._lib.d2i_PKCS12_bio(backend._bytes_to_bio(pkcs12_bytes).bio, backend._ffi.NULL),
|
||||
backend._lib.PKCS12_free)
|
||||
certificate_x509_ptr = backend._ffi.new("X509 **")
|
||||
with backend._zeroed_null_terminated_buf(to_bytes(passphrase) if passphrase is not None else None) as passphrase_buffer:
|
||||
backend._lib.PKCS12_parse(
|
||||
pkcs12,
|
||||
passphrase_buffer,
|
||||
backend._ffi.new("EVP_PKEY **"),
|
||||
certificate_x509_ptr,
|
||||
backend._ffi.new("Cryptography_STACK_OF_X509 **"))
|
||||
if certificate_x509_ptr[0] != backend._ffi.NULL:
|
||||
maybe_name = backend._lib.X509_alias_get0(certificate_x509_ptr[0], backend._ffi.NULL)
|
||||
if maybe_name != backend._ffi.NULL:
|
||||
friendly_name = backend._ffi.string(maybe_name)
|
||||
else:
|
||||
# cryptography < 35.0.0
|
||||
maybe_name = backend._lib.X509_alias_get0(certificate._x509, backend._ffi.NULL)
|
||||
if maybe_name != backend._ffi.NULL:
|
||||
friendly_name = backend._ffi.string(maybe_name)
|
||||
return private_key, certificate, additional_certificates, friendly_name
|
||||
|
||||
@@ -592,7 +592,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
||||
def _check_csr(self):
|
||||
"""Check whether provided parameters, assuming self.existing_csr and self.privatekey have been populated."""
|
||||
def _check_subject(csr):
|
||||
subject = [(cryptography_name_to_oid(entry[0]), entry[1]) for entry in self.subject]
|
||||
subject = [(cryptography_name_to_oid(entry[0]), to_text(entry[1])) for entry in self.subject]
|
||||
current_subject = [(sub.oid, sub.value) for sub in csr.subject]
|
||||
return set(subject) == set(current_subject)
|
||||
|
||||
@@ -604,8 +604,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
||||
|
||||
def _check_subjectAltName(extensions):
|
||||
current_altnames_ext = _find_extension(extensions, cryptography.x509.SubjectAlternativeName)
|
||||
current_altnames = [str(altname) for altname in current_altnames_ext.value] if current_altnames_ext else []
|
||||
altnames = [str(cryptography_get_name(altname)) for altname in self.subjectAltName] if self.subjectAltName else []
|
||||
current_altnames = [to_text(altname) for altname in current_altnames_ext.value] if current_altnames_ext else []
|
||||
altnames = [to_text(cryptography_get_name(altname)) for altname in self.subjectAltName] if self.subjectAltName else []
|
||||
if set(altnames) != set(current_altnames):
|
||||
return False
|
||||
if altnames:
|
||||
@@ -678,10 +678,10 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
||||
|
||||
def _check_nameConstraints(extensions):
|
||||
current_nc_ext = _find_extension(extensions, cryptography.x509.NameConstraints)
|
||||
current_nc_perm = [str(altname) for altname in current_nc_ext.value.permitted_subtrees] if current_nc_ext else []
|
||||
current_nc_excl = [str(altname) for altname in current_nc_ext.value.excluded_subtrees] if current_nc_ext else []
|
||||
nc_perm = [str(cryptography_get_name(altname, 'name constraints permitted')) for altname in self.name_constraints_permitted]
|
||||
nc_excl = [str(cryptography_get_name(altname, 'name constraints excluded')) for altname in self.name_constraints_excluded]
|
||||
current_nc_perm = [to_text(altname) for altname in current_nc_ext.value.permitted_subtrees] if current_nc_ext else []
|
||||
current_nc_excl = [to_text(altname) for altname in current_nc_ext.value.excluded_subtrees] if current_nc_ext else []
|
||||
nc_perm = [to_text(cryptography_get_name(altname, 'name constraints permitted')) for altname in self.name_constraints_permitted]
|
||||
nc_excl = [to_text(cryptography_get_name(altname, 'name constraints excluded')) for altname in self.name_constraints_excluded]
|
||||
if set(nc_perm) != set(current_nc_perm) or set(nc_excl) != set(current_nc_excl):
|
||||
return False
|
||||
if nc_perm or nc_excl:
|
||||
@@ -710,9 +710,9 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
||||
aci = None
|
||||
csr_aci = None
|
||||
if self.authority_cert_issuer is not None:
|
||||
aci = [str(cryptography_get_name(n, 'authority cert issuer')) for n in self.authority_cert_issuer]
|
||||
aci = [to_text(cryptography_get_name(n, 'authority cert issuer')) for n in self.authority_cert_issuer]
|
||||
if ext.value.authority_cert_issuer is not None:
|
||||
csr_aci = [str(n) for n in ext.value.authority_cert_issuer]
|
||||
csr_aci = [to_text(n) for n in ext.value.authority_cert_issuer]
|
||||
return (ext.value.key_identifier == self.authority_key_identifier
|
||||
and csr_aci == aci
|
||||
and ext.value.authority_cert_serial_number == self.authority_cert_serial_number)
|
||||
|
||||
@@ -21,10 +21,12 @@ __metaclass__ = type
|
||||
|
||||
import base64
|
||||
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.compat import ipaddress as compat_ipaddress
|
||||
|
||||
from ._objects import OID_LOOKUP
|
||||
|
||||
try:
|
||||
import OpenSSL
|
||||
except ImportError:
|
||||
@@ -87,18 +89,25 @@ def pyopenssl_get_extensions_from_cert(cert):
|
||||
critical=bool(ext.get_critical()),
|
||||
value=base64.b64encode(ext.get_data()),
|
||||
)
|
||||
oid = obj2txt(
|
||||
OpenSSL._util.lib,
|
||||
OpenSSL._util.ffi,
|
||||
OpenSSL._util.lib.X509_EXTENSION_get_object(ext._extension)
|
||||
)
|
||||
# This could also be done a bit simpler:
|
||||
#
|
||||
# oid = obj2txt(OpenSSL._util.lib, OpenSSL._util.ffi, OpenSSL._util.lib.OBJ_nid2obj(ext._nid))
|
||||
#
|
||||
# Unfortunately this gives the wrong result in case the linked OpenSSL
|
||||
# doesn't know the OID. That's why we have to get the OID dotted string
|
||||
# similarly to how cryptography does it.
|
||||
try:
|
||||
oid = obj2txt(
|
||||
OpenSSL._util.lib,
|
||||
OpenSSL._util.ffi,
|
||||
OpenSSL._util.lib.X509_EXTENSION_get_object(ext._extension)
|
||||
)
|
||||
# This could also be done a bit simpler:
|
||||
#
|
||||
# oid = obj2txt(OpenSSL._util.lib, OpenSSL._util.ffi, OpenSSL._util.lib.OBJ_nid2obj(ext._nid))
|
||||
#
|
||||
# Unfortunately this gives the wrong result in case the linked OpenSSL
|
||||
# doesn't know the OID. That's why we have to get the OID dotted string
|
||||
# similarly to how cryptography does it.
|
||||
except AttributeError:
|
||||
# When PyOpenSSL is used with cryptography >= 35.0.0, obj2txt cannot be used.
|
||||
# We try to figure out the OID with our internal lookup table, and if we fail,
|
||||
# we use the short name OpenSSL returns.
|
||||
oid = to_native(ext.get_short_name())
|
||||
oid = OID_LOOKUP.get(oid, oid)
|
||||
result[oid] = entry
|
||||
return result
|
||||
|
||||
@@ -113,18 +122,25 @@ def pyopenssl_get_extensions_from_csr(csr):
|
||||
critical=bool(ext.get_critical()),
|
||||
value=base64.b64encode(ext.get_data()),
|
||||
)
|
||||
oid = obj2txt(
|
||||
OpenSSL._util.lib,
|
||||
OpenSSL._util.ffi,
|
||||
OpenSSL._util.lib.X509_EXTENSION_get_object(ext._extension)
|
||||
)
|
||||
# This could also be done a bit simpler:
|
||||
#
|
||||
# oid = obj2txt(OpenSSL._util.lib, OpenSSL._util.ffi, OpenSSL._util.lib.OBJ_nid2obj(ext._nid))
|
||||
#
|
||||
# Unfortunately this gives the wrong result in case the linked OpenSSL
|
||||
# doesn't know the OID. That's why we have to get the OID dotted string
|
||||
# similarly to how cryptography does it.
|
||||
try:
|
||||
oid = obj2txt(
|
||||
OpenSSL._util.lib,
|
||||
OpenSSL._util.ffi,
|
||||
OpenSSL._util.lib.X509_EXTENSION_get_object(ext._extension)
|
||||
)
|
||||
# This could also be done a bit simpler:
|
||||
#
|
||||
# oid = obj2txt(OpenSSL._util.lib, OpenSSL._util.ffi, OpenSSL._util.lib.OBJ_nid2obj(ext._nid))
|
||||
#
|
||||
# Unfortunately this gives the wrong result in case the linked OpenSSL
|
||||
# doesn't know the OID. That's why we have to get the OID dotted string
|
||||
# similarly to how cryptography does it.
|
||||
except AttributeError:
|
||||
# When PyOpenSSL is used with cryptography >= 35.0.0, obj2txt cannot be used.
|
||||
# We try to figure out the OID with our internal lookup table, and if we fail,
|
||||
# we use the short name OpenSSL returns.
|
||||
oid = to_native(ext.get_short_name())
|
||||
oid = OID_LOOKUP.get(oid, oid)
|
||||
result[oid] = entry
|
||||
return result
|
||||
|
||||
|
||||
@@ -18,7 +18,15 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import abc
|
||||
import os
|
||||
import stat
|
||||
|
||||
from ansible.module_utils import six
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import (
|
||||
parse_openssh_version,
|
||||
)
|
||||
|
||||
|
||||
def restore_on_failure(f):
|
||||
@@ -40,3 +48,281 @@ def restore_on_failure(f):
|
||||
@restore_on_failure
|
||||
def safe_atomic_move(module, path, destination):
|
||||
module.atomic_move(path, destination)
|
||||
|
||||
|
||||
def _restore_all_on_failure(f):
|
||||
def backup_and_restore(self, sources_and_destinations, *args, **kwargs):
|
||||
backups = [(d, self.module.backup_local(d)) for s, d in sources_and_destinations if os.path.exists(d)]
|
||||
|
||||
try:
|
||||
f(self, sources_and_destinations, *args, **kwargs)
|
||||
except Exception:
|
||||
for destination, backup in backups:
|
||||
self.module.atomic_move(backup, destination)
|
||||
raise
|
||||
else:
|
||||
for destination, backup in backups:
|
||||
self.module.add_cleanup_file(backup)
|
||||
return backup_and_restore
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class OpensshModule(object):
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
|
||||
self.changed = False
|
||||
self.check_mode = self.module.check_mode
|
||||
|
||||
def execute(self):
|
||||
self._execute()
|
||||
self.module.exit_json(**self.result)
|
||||
|
||||
@abc.abstractmethod
|
||||
def _execute(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def result(self):
|
||||
result = self._result
|
||||
|
||||
result['changed'] = self.changed
|
||||
|
||||
if self.module._diff:
|
||||
result['diff'] = self.diff
|
||||
|
||||
return result
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def _result(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def diff(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def skip_if_check_mode(f):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
if not self.check_mode:
|
||||
f(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
@staticmethod
|
||||
def trigger_change(f):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
f(self, *args, **kwargs)
|
||||
self.changed = True
|
||||
return wrapper
|
||||
|
||||
def _check_if_base_dir(self, path):
|
||||
base_dir = os.path.dirname(path) or '.'
|
||||
if not os.path.isdir(base_dir):
|
||||
self.module.fail_json(
|
||||
name=base_dir,
|
||||
msg='The directory %s does not exist or the file is not a directory' % base_dir
|
||||
)
|
||||
|
||||
def _get_ssh_version(self):
|
||||
ssh_bin = self.module.get_bin_path('ssh')
|
||||
if not ssh_bin:
|
||||
return ""
|
||||
return parse_openssh_version(self.module.run_command([ssh_bin, '-V', '-q'])[2].strip())
|
||||
|
||||
@_restore_all_on_failure
|
||||
def _safe_secure_move(self, sources_and_destinations):
|
||||
"""Moves a list of files from 'source' to 'destination' and restores 'destination' from backup upon failure.
|
||||
If 'destination' does not already exist, then 'source' permissions are preserved to prevent
|
||||
exposing protected data ('atomic_move' uses the 'destination' base directory mask for
|
||||
permissions if 'destination' does not already exists).
|
||||
"""
|
||||
for source, destination in sources_and_destinations:
|
||||
if os.path.exists(destination):
|
||||
self.module.atomic_move(source, destination)
|
||||
else:
|
||||
self.module.preserved_copy(source, destination)
|
||||
|
||||
def _update_permissions(self, path):
|
||||
file_args = self.module.load_file_common_arguments(self.module.params)
|
||||
file_args['path'] = path
|
||||
|
||||
if not self.module.check_file_absent_if_check_mode(path):
|
||||
self.changed = self.module.set_fs_attributes_if_different(file_args, self.changed)
|
||||
else:
|
||||
self.changed = True
|
||||
|
||||
|
||||
class KeygenCommand(object):
|
||||
def __init__(self, module):
|
||||
self._bin_path = module.get_bin_path('ssh-keygen', True)
|
||||
self._run_command = module.run_command
|
||||
|
||||
def generate_certificate(self, certificate_path, identifier, options, pkcs11_provider, principals,
|
||||
serial_number, signature_algorithm, signing_key_path, type,
|
||||
time_parameters, use_agent, **kwargs):
|
||||
args = [self._bin_path, '-s', signing_key_path, '-P', '', '-I', identifier]
|
||||
|
||||
if options:
|
||||
for option in options:
|
||||
args.extend(['-O', option])
|
||||
if pkcs11_provider:
|
||||
args.extend(['-D', pkcs11_provider])
|
||||
if principals:
|
||||
args.extend(['-n', ','.join(principals)])
|
||||
if serial_number is not None:
|
||||
args.extend(['-z', str(serial_number)])
|
||||
if type == 'host':
|
||||
args.extend(['-h'])
|
||||
if use_agent:
|
||||
args.extend(['-U'])
|
||||
if time_parameters.validity_string:
|
||||
args.extend(['-V', time_parameters.validity_string])
|
||||
if signature_algorithm:
|
||||
args.extend(['-t', signature_algorithm])
|
||||
args.append(certificate_path)
|
||||
|
||||
return self._run_command(args, **kwargs)
|
||||
|
||||
def generate_keypair(self, private_key_path, size, type, comment, **kwargs):
|
||||
args = [
|
||||
self._bin_path,
|
||||
'-q',
|
||||
'-N', '',
|
||||
'-b', str(size),
|
||||
'-t', type,
|
||||
'-f', private_key_path,
|
||||
'-C', comment or ''
|
||||
]
|
||||
|
||||
# "y" must be entered in response to the "overwrite" prompt
|
||||
data = 'y' if os.path.exists(private_key_path) else None
|
||||
|
||||
return self._run_command(args, data=data, **kwargs)
|
||||
|
||||
def get_certificate_info(self, certificate_path, **kwargs):
|
||||
return self._run_command([self._bin_path, '-L', '-f', certificate_path], **kwargs)
|
||||
|
||||
def get_matching_public_key(self, private_key_path, **kwargs):
|
||||
return self._run_command([self._bin_path, '-P', '', '-y', '-f', private_key_path], **kwargs)
|
||||
|
||||
def get_private_key(self, private_key_path, **kwargs):
|
||||
return self._run_command([self._bin_path, '-l', '-f', private_key_path], **kwargs)
|
||||
|
||||
def update_comment(self, private_key_path, comment, **kwargs):
|
||||
if os.path.exists(private_key_path) and not os.access(private_key_path, os.W_OK):
|
||||
try:
|
||||
os.chmod(private_key_path, stat.S_IWUSR + stat.S_IRUSR)
|
||||
except (IOError, OSError) as e:
|
||||
raise e("The private key at %s is not writeable preventing a comment update" % private_key_path)
|
||||
|
||||
return self._run_command([self._bin_path, '-q', '-o', '-c', '-C', comment, '-f', private_key_path], **kwargs)
|
||||
|
||||
|
||||
class PrivateKey(object):
|
||||
def __init__(self, size, key_type, fingerprint):
|
||||
self._size = size
|
||||
self._type = key_type
|
||||
self._fingerprint = fingerprint
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self._size
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
@property
|
||||
def fingerprint(self):
|
||||
return self._fingerprint
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, string):
|
||||
properties = string.split()
|
||||
|
||||
return cls(
|
||||
size=int(properties[0]),
|
||||
key_type=properties[-1][1:-1].lower(),
|
||||
fingerprint=properties[1],
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'size': self._size,
|
||||
'type': self._type,
|
||||
'fingerprint': self._fingerprint,
|
||||
}
|
||||
|
||||
|
||||
class PublicKey(object):
|
||||
def __init__(self, type_string, data, comment):
|
||||
self._type_string = type_string
|
||||
self._data = data
|
||||
self._comment = comment
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, type(self)):
|
||||
return NotImplemented
|
||||
|
||||
return all([
|
||||
self._type_string == other._type_string,
|
||||
self._data == other._data,
|
||||
(self._comment == other._comment) if self._comment is not None and other._comment is not None else True
|
||||
])
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __str__(self):
|
||||
return "%s %s" % (self._type_string, self._data)
|
||||
|
||||
@property
|
||||
def comment(self):
|
||||
return self._comment
|
||||
|
||||
@comment.setter
|
||||
def comment(self, value):
|
||||
self._comment = value
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def type_string(self):
|
||||
return self._type_string
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, string):
|
||||
properties = string.strip('\n').split(' ', 2)
|
||||
|
||||
return cls(
|
||||
type_string=properties[0],
|
||||
data=properties[1],
|
||||
comment=properties[2] if len(properties) > 2 else ""
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def load(cls, path):
|
||||
try:
|
||||
with open(path, 'r') as f:
|
||||
properties = f.read().strip(' \n').split(' ', 2)
|
||||
except (IOError, OSError):
|
||||
raise
|
||||
|
||||
if len(properties) < 2:
|
||||
return None
|
||||
|
||||
return cls(
|
||||
type_string=properties[0],
|
||||
data=properties[1],
|
||||
comment='' if len(properties) <= 2 else properties[2],
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'comment': self._comment,
|
||||
'public_key': self._data,
|
||||
}
|
||||
|
||||
@@ -20,16 +20,13 @@ from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import abc
|
||||
import errno
|
||||
import os
|
||||
import stat
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
from ansible.module_utils import six
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible.module_utils.common.text.converters import to_native, to_text, to_bytes
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import parse_openssh_version
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.cryptography import (
|
||||
HAS_OPENSSH_SUPPORT,
|
||||
HAS_OPENSSH_PRIVATE_FORMAT,
|
||||
@@ -39,322 +36,334 @@ from ansible_collections.community.crypto.plugins.module_utils.openssh.cryptogra
|
||||
OpenSSHError,
|
||||
OpensshKeypair,
|
||||
)
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.backends.common import (
|
||||
KeygenCommand,
|
||||
OpensshModule,
|
||||
PrivateKey,
|
||||
PublicKey,
|
||||
)
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import (
|
||||
any_in,
|
||||
file_mode,
|
||||
secure_write,
|
||||
)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class KeypairBackend(object):
|
||||
class KeypairBackend(OpensshModule):
|
||||
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
super(KeypairBackend, self).__init__(module)
|
||||
|
||||
self.path = module.params['path']
|
||||
self.force = module.params['force']
|
||||
self.size = module.params['size']
|
||||
self.type = module.params['type']
|
||||
self.comment = module.params['comment']
|
||||
self.passphrase = module.params['passphrase']
|
||||
self.regenerate = module.params['regenerate']
|
||||
self.comment = self.module.params['comment']
|
||||
self.private_key_path = self.module.params['path']
|
||||
self.public_key_path = self.private_key_path + '.pub'
|
||||
self.regenerate = self.module.params['regenerate'] if not self.module.params['force'] else 'always'
|
||||
self.state = self.module.params['state']
|
||||
self.type = self.module.params['type']
|
||||
|
||||
self.changed = False
|
||||
self.fingerprint = ''
|
||||
self.public_key = {}
|
||||
self.size = self._get_size(self.module.params['size'])
|
||||
self._validate_path()
|
||||
|
||||
if self.regenerate == 'always':
|
||||
self.force = True
|
||||
self.original_private_key = None
|
||||
self.original_public_key = None
|
||||
self.private_key = None
|
||||
self.public_key = None
|
||||
|
||||
def _get_size(self, size):
|
||||
if self.type in ('rsa', 'rsa1'):
|
||||
self.size = 4096 if self.size is None else self.size
|
||||
if self.size < 1024:
|
||||
module.fail_json(msg=('For RSA keys, the minimum size is 1024 bits and the default is 4096 bits. '
|
||||
'Attempting to use bit lengths under 1024 will cause the module to fail.'))
|
||||
result = 4096 if size is None else size
|
||||
if result < 1024:
|
||||
return self.module.fail_json(
|
||||
msg="For RSA keys, the minimum size is 1024 bits and the default is 4096 bits. " +
|
||||
"Attempting to use bit lengths under 1024 will cause the module to fail."
|
||||
)
|
||||
elif self.type == 'dsa':
|
||||
self.size = 1024 if self.size is None else self.size
|
||||
if self.size != 1024:
|
||||
module.fail_json(msg=('DSA keys must be exactly 1024 bits as specified by FIPS 186-2.'))
|
||||
result = 1024 if size is None else size
|
||||
if result != 1024:
|
||||
return self.module.fail_json(msg="DSA keys must be exactly 1024 bits as specified by FIPS 186-2.")
|
||||
elif self.type == 'ecdsa':
|
||||
self.size = 256 if self.size is None else self.size
|
||||
if self.size not in (256, 384, 521):
|
||||
module.fail_json(msg=('For ECDSA keys, size determines the key length by selecting from '
|
||||
'one of three elliptic curve sizes: 256, 384 or 521 bits. '
|
||||
'Attempting to use bit lengths other than these three values for '
|
||||
'ECDSA keys will cause this module to fail. '))
|
||||
result = 256 if size is None else size
|
||||
if result not in (256, 384, 521):
|
||||
return self.module.fail_json(
|
||||
msg="For ECDSA keys, size determines the key length by selecting from one of " +
|
||||
"three elliptic curve sizes: 256, 384 or 521 bits. " +
|
||||
"Attempting to use bit lengths other than these three values for ECDSA keys will " +
|
||||
"cause this module to fail."
|
||||
)
|
||||
elif self.type == 'ed25519':
|
||||
# User input is ignored for `key size` when `key type` is ed25519
|
||||
self.size = 256
|
||||
result = 256
|
||||
else:
|
||||
module.fail_json(msg="%s is not a valid value for key type" % self.type)
|
||||
return self.module.fail_json(msg="%s is not a valid value for key type" % self.type)
|
||||
|
||||
def generate(self):
|
||||
if self.force or not self.is_private_key_valid(perms_required=False):
|
||||
try:
|
||||
if self.exists() and not os.access(self.path, os.W_OK):
|
||||
os.chmod(self.path, stat.S_IWUSR + stat.S_IRUSR)
|
||||
self._generate_keypair()
|
||||
self.changed = True
|
||||
except (IOError, OSError) as e:
|
||||
self.remove()
|
||||
self.module.fail_json(msg="%s" % to_native(e))
|
||||
return result
|
||||
|
||||
self.fingerprint = self._get_current_key_properties()[2]
|
||||
self.public_key = self._get_public_key()
|
||||
elif not self.is_public_key_valid(perms_required=False):
|
||||
pubkey = self._get_public_key()
|
||||
try:
|
||||
with open(self.path + ".pub", "w") as pubkey_f:
|
||||
pubkey_f.write(pubkey + '\n')
|
||||
os.chmod(self.path + ".pub", stat.S_IWUSR + stat.S_IRUSR + stat.S_IRGRP + stat.S_IROTH)
|
||||
except (IOError, OSError):
|
||||
self.module.fail_json(
|
||||
msg='The public key is missing or does not match the private key. '
|
||||
'Unable to regenerate the public key.')
|
||||
self.changed = True
|
||||
self.public_key = pubkey
|
||||
def _validate_path(self):
|
||||
self._check_if_base_dir(self.private_key_path)
|
||||
|
||||
if self.comment:
|
||||
try:
|
||||
if self.exists() and not os.access(self.path, os.W_OK):
|
||||
os.chmod(self.path, stat.S_IWUSR + stat.S_IRUSR)
|
||||
except (IOError, OSError):
|
||||
self.module.fail_json(msg='Unable to update the comment for the public key.')
|
||||
self._update_comment()
|
||||
if os.path.isdir(self.private_key_path):
|
||||
self.module.fail_json(msg='%s is a directory. Please specify a path to a file.' % self.private_key_path)
|
||||
|
||||
private_key_perms_changed = self._permissions_changed()
|
||||
public_key_perms_changed = self._permissions_changed(public_key=True)
|
||||
if private_key_perms_changed or public_key_perms_changed:
|
||||
self.changed = True
|
||||
def _execute(self):
|
||||
self.original_private_key = self._load_private_key()
|
||||
self.original_public_key = self._load_public_key()
|
||||
|
||||
def is_private_key_valid(self, perms_required=True):
|
||||
if not self.exists():
|
||||
return False
|
||||
if self.state == 'present':
|
||||
self._validate_key_load()
|
||||
|
||||
if self._check_pass_protected_or_broken_key():
|
||||
if self.regenerate in ('full_idempotence', 'always'):
|
||||
return False
|
||||
self.module.fail_json(msg='Unable to read the key. The key is protected with a passphrase or broken.'
|
||||
' Will not proceed. To force regeneration, call the module with `generate`'
|
||||
' set to `full_idempotence` or `always`, or with `force=yes`.')
|
||||
if self._should_generate():
|
||||
self._generate()
|
||||
elif not self._public_key_valid():
|
||||
self._restore_public_key()
|
||||
|
||||
if not self._private_key_loadable():
|
||||
if os.path.isdir(self.path):
|
||||
self.module.fail_json(msg='%s is a directory. Please specify a path to a file.' % self.path)
|
||||
self.private_key = self._load_private_key()
|
||||
self.public_key = self._load_public_key()
|
||||
|
||||
if self.regenerate in ('full_idempotence', 'always'):
|
||||
return False
|
||||
self.module.fail_json(msg='Unable to read the key. The key is protected with a passphrase or broken.'
|
||||
' Will not proceed. To force regeneration, call the module with `generate`'
|
||||
' set to `full_idempotence` or `always`, or with `force=yes`.')
|
||||
|
||||
keysize, keytype, self.fingerprint = self._get_current_key_properties()
|
||||
|
||||
if self.regenerate == 'never':
|
||||
return True
|
||||
|
||||
if not (self.type == keytype and self.size == keysize):
|
||||
if self.regenerate in ('partial_idempotence', 'full_idempotence', 'always'):
|
||||
return False
|
||||
self.module.fail_json(
|
||||
msg='Key has wrong type and/or size.'
|
||||
' Will not proceed. To force regeneration, call the module with `generate`'
|
||||
' set to `partial_idempotence`, `full_idempotence` or `always`, or with `force=yes`.'
|
||||
)
|
||||
|
||||
# Perms required short-circuits evaluation to prevent the side-effects of running _permissions_changed
|
||||
# when check_mode is not enabled
|
||||
return not (perms_required and self._permissions_changed())
|
||||
|
||||
def is_public_key_valid(self, perms_required=True):
|
||||
|
||||
def _get_pubkey_content():
|
||||
if self.exists(public_key=True):
|
||||
with open(self.path + ".pub", "r") as pubkey_f:
|
||||
present_pubkey = pubkey_f.read().strip(' \n')
|
||||
return present_pubkey
|
||||
else:
|
||||
return ''
|
||||
|
||||
def _parse_pubkey(pubkey_content):
|
||||
if pubkey_content:
|
||||
parts = pubkey_content.split(' ', 2)
|
||||
if len(parts) < 2:
|
||||
return ()
|
||||
return parts[0], parts[1], '' if len(parts) <= 2 else parts[2]
|
||||
return ()
|
||||
|
||||
def _pubkey_valid(pubkey):
|
||||
if pubkey_parts and _parse_pubkey(pubkey):
|
||||
return pubkey_parts[:2] == _parse_pubkey(pubkey)[:2]
|
||||
return False
|
||||
|
||||
def _comment_valid():
|
||||
if pubkey_parts:
|
||||
return pubkey_parts[2] == self.comment
|
||||
return False
|
||||
|
||||
pubkey_parts = _parse_pubkey(_get_pubkey_content())
|
||||
|
||||
pubkey = self._get_public_key()
|
||||
if _pubkey_valid(pubkey):
|
||||
self.public_key = pubkey
|
||||
for path in (self.private_key_path, self.public_key_path):
|
||||
self._update_permissions(path)
|
||||
else:
|
||||
return False
|
||||
if self._should_remove():
|
||||
self._remove()
|
||||
|
||||
if self.comment and not _comment_valid():
|
||||
return False
|
||||
|
||||
# Perms required short-circuits evaluation to prevent the side-effects of running _permissions_changes
|
||||
# when check_mode is not enabled
|
||||
return not (perms_required and self._permissions_changed(public_key=True))
|
||||
|
||||
def _permissions_changed(self, public_key=False):
|
||||
file_args = self.module.load_file_common_arguments(self.module.params)
|
||||
if public_key:
|
||||
file_args['path'] = file_args['path'] + '.pub'
|
||||
if self.module.check_file_absent_if_check_mode(file_args['path']):
|
||||
return True
|
||||
return self.module.set_fs_attributes_if_different(file_args, False)
|
||||
|
||||
@property
|
||||
def result(self):
|
||||
return {
|
||||
'changed': self.changed,
|
||||
'size': self.size,
|
||||
'type': self.type,
|
||||
'filename': self.path,
|
||||
'fingerprint': self.fingerprint if self.fingerprint else '',
|
||||
'public_key': self.public_key,
|
||||
'comment': self.comment if self.comment else '',
|
||||
}
|
||||
|
||||
def remove(self):
|
||||
"""Remove the resource from the filesystem."""
|
||||
|
||||
try:
|
||||
os.remove(self.path)
|
||||
self.changed = True
|
||||
except (IOError, OSError) as exc:
|
||||
if exc.errno != errno.ENOENT:
|
||||
self.module.fail_json(msg=to_native(exc))
|
||||
else:
|
||||
def _load_private_key(self):
|
||||
result = None
|
||||
if self._private_key_exists():
|
||||
try:
|
||||
result = self._get_private_key()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if self.exists(public_key=True):
|
||||
return result
|
||||
|
||||
def _private_key_exists(self):
|
||||
return os.path.exists(self.private_key_path)
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_private_key(self):
|
||||
pass
|
||||
|
||||
def _load_public_key(self):
|
||||
result = None
|
||||
if self._public_key_exists():
|
||||
try:
|
||||
os.remove(self.path + ".pub")
|
||||
self.changed = True
|
||||
except (IOError, OSError) as exc:
|
||||
if exc.errno != errno.ENOENT:
|
||||
self.module.fail_json(msg=to_native(exc))
|
||||
else:
|
||||
pass
|
||||
result = PublicKey.load(self.public_key_path)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
return result
|
||||
|
||||
def exists(self, public_key=False):
|
||||
return os.path.exists(self.path if not public_key else self.path + ".pub")
|
||||
def _public_key_exists(self):
|
||||
return os.path.exists(self.public_key_path)
|
||||
|
||||
def _validate_key_load(self):
|
||||
if (self._private_key_exists()
|
||||
and self.regenerate in ('never', 'fail', 'partial_idempotence')
|
||||
and (self.original_private_key is None or not self._private_key_readable())):
|
||||
self.module.fail_json(
|
||||
msg="Unable to read the key. The key is protected with a passphrase or broken. " +
|
||||
"Will not proceed. To force regeneration, call the module with `generate` " +
|
||||
"set to `full_idempotence` or `always`, or with `force=yes`."
|
||||
)
|
||||
|
||||
@abc.abstractmethod
|
||||
def _generate_keypair(self):
|
||||
def _private_key_readable(self):
|
||||
pass
|
||||
|
||||
def _should_generate(self):
|
||||
if self.regenerate == 'never':
|
||||
return self.original_private_key is None
|
||||
elif self.regenerate == 'fail':
|
||||
if not self._private_key_valid():
|
||||
self.module.fail_json(
|
||||
msg="Key has wrong type and/or size. Will not proceed. " +
|
||||
"To force regeneration, call the module with `generate` set to " +
|
||||
"`partial_idempotence`, `full_idempotence` or `always`, or with `force=yes`."
|
||||
)
|
||||
return self.original_private_key is None
|
||||
elif self.regenerate in ('partial_idempotence', 'full_idempotence'):
|
||||
return not self._private_key_valid()
|
||||
else:
|
||||
return True
|
||||
|
||||
def _private_key_valid(self):
|
||||
if self.original_private_key is None:
|
||||
return False
|
||||
|
||||
return all([
|
||||
self.size == self.original_private_key.size,
|
||||
self.type == self.original_private_key.type,
|
||||
])
|
||||
|
||||
@OpensshModule.trigger_change
|
||||
@OpensshModule.skip_if_check_mode
|
||||
def _generate(self):
|
||||
temp_private_key, temp_public_key = self._generate_temp_keypair()
|
||||
|
||||
try:
|
||||
self._safe_secure_move([(temp_private_key, self.private_key_path), (temp_public_key, self.public_key_path)])
|
||||
except OSError as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
|
||||
def _generate_temp_keypair(self):
|
||||
temp_private_key = os.path.join(self.module.tmpdir, os.path.basename(self.private_key_path))
|
||||
temp_public_key = temp_private_key + '.pub'
|
||||
|
||||
try:
|
||||
self._generate_keypair(temp_private_key)
|
||||
except (IOError, OSError) as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
|
||||
for f in (temp_private_key, temp_public_key):
|
||||
self.module.add_cleanup_file(f)
|
||||
|
||||
return temp_private_key, temp_public_key
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_current_key_properties(self):
|
||||
def _generate_keypair(self, private_key_path):
|
||||
pass
|
||||
|
||||
def _public_key_valid(self):
|
||||
if self.original_public_key is None:
|
||||
return False
|
||||
|
||||
valid_public_key = self._get_public_key()
|
||||
valid_public_key.comment = self.comment
|
||||
|
||||
return self.original_public_key == valid_public_key
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_public_key(self):
|
||||
pass
|
||||
|
||||
@OpensshModule.trigger_change
|
||||
@OpensshModule.skip_if_check_mode
|
||||
def _restore_public_key(self):
|
||||
try:
|
||||
temp_public_key = self._create_temp_public_key(str(self._get_public_key()) + '\n')
|
||||
self._safe_secure_move([
|
||||
(temp_public_key, self.public_key_path)
|
||||
])
|
||||
except (IOError, OSError):
|
||||
self.module.fail_json(
|
||||
msg="The public key is missing or does not match the private key. " +
|
||||
"Unable to regenerate the public key."
|
||||
)
|
||||
|
||||
if self.comment:
|
||||
self._update_comment()
|
||||
|
||||
def _create_temp_public_key(self, content):
|
||||
temp_public_key = os.path.join(self.module.tmpdir, os.path.basename(self.public_key_path))
|
||||
|
||||
default_permissions = 0o644
|
||||
existing_permissions = file_mode(self.public_key_path)
|
||||
|
||||
try:
|
||||
secure_write(temp_public_key, existing_permissions or default_permissions, to_bytes(content))
|
||||
except (IOError, OSError) as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
self.module.add_cleanup_file(temp_public_key)
|
||||
|
||||
return temp_public_key
|
||||
|
||||
@abc.abstractmethod
|
||||
def _update_comment(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _private_key_loadable(self):
|
||||
pass
|
||||
def _should_remove(self):
|
||||
return self._private_key_exists() or self._public_key_exists()
|
||||
|
||||
@abc.abstractmethod
|
||||
def _check_pass_protected_or_broken_key(self):
|
||||
pass
|
||||
@OpensshModule.trigger_change
|
||||
@OpensshModule.skip_if_check_mode
|
||||
def _remove(self):
|
||||
try:
|
||||
if self._private_key_exists():
|
||||
os.remove(self.private_key_path)
|
||||
if self._public_key_exists():
|
||||
os.remove(self.public_key_path)
|
||||
except (IOError, OSError) as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
|
||||
@property
|
||||
def _result(self):
|
||||
private_key = self.private_key or self.original_private_key
|
||||
public_key = self.public_key or self.original_public_key
|
||||
|
||||
return {
|
||||
'size': self.size,
|
||||
'type': self.type,
|
||||
'filename': self.private_key_path,
|
||||
'fingerprint': private_key.fingerprint if private_key else '',
|
||||
'public_key': str(public_key) if public_key else '',
|
||||
'comment': public_key.comment if public_key else '',
|
||||
}
|
||||
|
||||
@property
|
||||
def diff(self):
|
||||
before = self.original_private_key.to_dict() if self.original_private_key else {}
|
||||
before.update(self.original_public_key.to_dict() if self.original_public_key else {})
|
||||
|
||||
after = self.private_key.to_dict() if self.private_key else {}
|
||||
after.update(self.public_key.to_dict() if self.public_key else {})
|
||||
|
||||
return {
|
||||
'before': before,
|
||||
'after': after,
|
||||
}
|
||||
|
||||
|
||||
class KeypairBackendOpensshBin(KeypairBackend):
|
||||
|
||||
def __init__(self, module):
|
||||
super(KeypairBackendOpensshBin, self).__init__(module)
|
||||
|
||||
self.openssh_bin = module.get_bin_path('ssh-keygen')
|
||||
self.ssh_keygen = KeygenCommand(self.module)
|
||||
|
||||
def _load_privatekey(self):
|
||||
return self.module.run_command([self.openssh_bin, '-lf', self.path])
|
||||
def _generate_keypair(self, private_key_path):
|
||||
self.ssh_keygen.generate_keypair(private_key_path, self.size, self.type, self.comment)
|
||||
|
||||
def _get_publickey_from_privatekey(self):
|
||||
# -P '' is always included as an option to induce the expected standard output for
|
||||
# _check_pass_protected_or_broken_key, but introduces no side-effects when used to
|
||||
# output a matching public key
|
||||
return self.module.run_command([self.openssh_bin, '-P', '', '-yf', self.path])
|
||||
|
||||
def _generate_keypair(self):
|
||||
args = [
|
||||
self.openssh_bin,
|
||||
'-q',
|
||||
'-N', '',
|
||||
'-b', str(self.size),
|
||||
'-t', self.type,
|
||||
'-f', self.path,
|
||||
'-C', self.comment if self.comment else ''
|
||||
]
|
||||
|
||||
# "y" must be entered in response to the "overwrite" prompt
|
||||
stdin_data = 'y' if self.exists() else None
|
||||
|
||||
self.module.run_command(args, data=stdin_data)
|
||||
|
||||
def _get_current_key_properties(self):
|
||||
rc, stdout, stderr = self._load_privatekey()
|
||||
properties = stdout.split()
|
||||
keysize = int(properties[0])
|
||||
fingerprint = properties[1]
|
||||
keytype = properties[-1][1:-1].lower()
|
||||
|
||||
return keysize, keytype, fingerprint
|
||||
def _get_private_key(self):
|
||||
private_key_content = self.ssh_keygen.get_private_key(self.private_key_path)[1]
|
||||
return PrivateKey.from_string(private_key_content)
|
||||
|
||||
def _get_public_key(self):
|
||||
rc, stdout, stderr = self._get_publickey_from_privatekey()
|
||||
return stdout.strip('\n')
|
||||
public_key_content = self.ssh_keygen.get_matching_public_key(self.private_key_path)[1]
|
||||
return PublicKey.from_string(public_key_content)
|
||||
|
||||
def _private_key_readable(self):
|
||||
rc, stdout, stderr = self.ssh_keygen.get_matching_public_key(self.private_key_path)
|
||||
return not (rc == 255 or any_in(stderr, 'is not a public key file', 'incorrect passphrase', 'load failed'))
|
||||
|
||||
def _update_comment(self):
|
||||
return self.module.run_command([self.openssh_bin, '-q', '-o', '-c', '-C', self.comment, '-f', self.path])
|
||||
|
||||
def _private_key_loadable(self):
|
||||
rc, stdout, stderr = self._load_privatekey()
|
||||
return rc == 0
|
||||
|
||||
def _check_pass_protected_or_broken_key(self):
|
||||
rc, stdout, stderr = self._get_publickey_from_privatekey()
|
||||
return rc == 255 or any_in(stderr, 'is not a public key file', 'incorrect passphrase', 'load failed')
|
||||
try:
|
||||
self.ssh_keygen.update_comment(self.private_key_path, self.comment)
|
||||
except (IOError, OSError) as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
|
||||
|
||||
class KeypairBackendCryptography(KeypairBackend):
|
||||
|
||||
def __init__(self, module):
|
||||
super(KeypairBackendCryptography, self).__init__(module)
|
||||
|
||||
if module.params['private_key_format'] == 'auto':
|
||||
ssh = module.get_bin_path('ssh')
|
||||
if ssh:
|
||||
proc = module.run_command([ssh, '-Vq'])
|
||||
ssh_version = parse_openssh_version(proc[2].strip())
|
||||
else:
|
||||
# Default to OpenSSH 7.8 compatibility when OpenSSH is not installed
|
||||
ssh_version = "7.8"
|
||||
if self.type == 'rsa1':
|
||||
self.module.fail_json(msg="RSA1 keys are not supported by the cryptography backend")
|
||||
|
||||
self.private_key_format = 'SSH'
|
||||
self.passphrase = to_bytes(module.params['passphrase']) if module.params['passphrase'] else None
|
||||
self.private_key_format = self._get_key_format(module.params['private_key_format'])
|
||||
|
||||
def _get_key_format(self, key_format):
|
||||
result = 'SSH'
|
||||
|
||||
if key_format == 'auto':
|
||||
# Default to OpenSSH 7.8 compatibility when OpenSSH is not installed
|
||||
ssh_version = self._get_ssh_version() or "7.8"
|
||||
|
||||
if LooseVersion(ssh_version) < LooseVersion("7.8") and self.type != 'ed25519':
|
||||
# OpenSSH made SSH formatted private keys available in version 6.5,
|
||||
# but still defaulted to PKCS1 format with the exception of ed25519 keys
|
||||
self.private_key_format = 'PKCS1'
|
||||
result = 'PKCS1'
|
||||
|
||||
if self.private_key_format == 'SSH' and not HAS_OPENSSH_PRIVATE_FORMAT:
|
||||
module.fail_json(
|
||||
if result == 'SSH' and not HAS_OPENSSH_PRIVATE_FORMAT:
|
||||
self.module.fail_json(
|
||||
msg=missing_required_lib(
|
||||
'cryptography >= 3.0',
|
||||
reason="to load/dump private keys in the default OpenSSH format for OpenSSH >= 7.8 " +
|
||||
@@ -362,96 +371,72 @@ class KeypairBackendCryptography(KeypairBackend):
|
||||
)
|
||||
)
|
||||
|
||||
if self.type == 'rsa1':
|
||||
module.fail_json(msg="RSA1 keys are not supported by the cryptography backend")
|
||||
return result
|
||||
|
||||
self.passphrase = to_bytes(self.passphrase) if self.passphrase else None
|
||||
|
||||
def _load_privatekey(self):
|
||||
return OpensshKeypair.load(path=self.path, passphrase=self.passphrase, no_public_key=True)
|
||||
|
||||
def _generate_keypair(self):
|
||||
def _generate_keypair(self, private_key_path):
|
||||
keypair = OpensshKeypair.generate(
|
||||
keytype=self.type,
|
||||
size=self.size,
|
||||
passphrase=self.passphrase,
|
||||
comment=self.comment if self.comment else "",
|
||||
comment=self.comment or '',
|
||||
)
|
||||
with open(self.path, 'w+b') as f:
|
||||
f.write(
|
||||
OpensshKeypair.encode_openssh_privatekey(
|
||||
keypair.asymmetric_keypair,
|
||||
self.private_key_format
|
||||
)
|
||||
)
|
||||
# ssh-keygen defaults private key permissions to 0600 octal
|
||||
os.chmod(self.path, stat.S_IWUSR + stat.S_IRUSR)
|
||||
with open(self.path + '.pub', 'w+b') as f:
|
||||
f.write(keypair.public_key)
|
||||
# ssh-keygen defaults public key permissions to 0644 octal
|
||||
os.chmod(self.path + ".pub", stat.S_IWUSR + stat.S_IRUSR + stat.S_IRGRP + stat.S_IROTH)
|
||||
|
||||
def _get_current_key_properties(self):
|
||||
keypair = self._load_privatekey()
|
||||
encoded_private_key = OpensshKeypair.encode_openssh_privatekey(
|
||||
keypair.asymmetric_keypair, self.private_key_format
|
||||
)
|
||||
secure_write(private_key_path, 0o600, encoded_private_key)
|
||||
|
||||
return keypair.size, keypair.key_type, keypair.fingerprint
|
||||
public_key_path = private_key_path + '.pub'
|
||||
secure_write(public_key_path, 0o644, keypair.public_key)
|
||||
|
||||
def _get_private_key(self):
|
||||
keypair = OpensshKeypair.load(path=self.private_key_path, passphrase=self.passphrase, no_public_key=True)
|
||||
|
||||
return PrivateKey(
|
||||
size=keypair.size,
|
||||
key_type=keypair.key_type,
|
||||
fingerprint=keypair.fingerprint,
|
||||
)
|
||||
|
||||
def _get_public_key(self):
|
||||
try:
|
||||
keypair = self._load_privatekey()
|
||||
keypair = OpensshKeypair.load(path=self.private_key_path, passphrase=self.passphrase, no_public_key=True)
|
||||
except OpenSSHError:
|
||||
# Simulates the null output of ssh-keygen
|
||||
return ""
|
||||
|
||||
return to_text(keypair.public_key)
|
||||
return PublicKey.from_string(to_text(keypair.public_key))
|
||||
|
||||
def _update_comment(self):
|
||||
keypair = self._load_privatekey()
|
||||
def _private_key_readable(self):
|
||||
try:
|
||||
keypair.comment = self.comment
|
||||
with open(self.path + ".pub", "w+b") as pubkey_file:
|
||||
pubkey_file.write(keypair.public_key + b'\n')
|
||||
except (InvalidCommentError, IOError, OSError) as e:
|
||||
# Return values while unused currently are made to simulate the output of run_command()
|
||||
return 1, "Comment could not be updated", to_native(e)
|
||||
return 0, "Comment updated successfully", ""
|
||||
|
||||
def _private_key_loadable(self):
|
||||
try:
|
||||
self._load_privatekey()
|
||||
except OpenSSHError:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _check_pass_protected_or_broken_key(self):
|
||||
try:
|
||||
OpensshKeypair.load(
|
||||
path=self.path,
|
||||
passphrase=self.passphrase,
|
||||
no_public_key=True,
|
||||
)
|
||||
OpensshKeypair.load(path=self.private_key_path, passphrase=self.passphrase, no_public_key=True)
|
||||
except (InvalidPrivateKeyFileError, InvalidPassphraseError):
|
||||
return True
|
||||
return False
|
||||
|
||||
# Cryptography >= 3.0 uses a SSH key loader which does not raise an exception when a passphrase is provided
|
||||
# when loading an unencrypted key
|
||||
if self.passphrase:
|
||||
try:
|
||||
OpensshKeypair.load(
|
||||
path=self.path,
|
||||
passphrase=None,
|
||||
no_public_key=True,
|
||||
)
|
||||
OpensshKeypair.load(path=self.private_key_path, passphrase=None, no_public_key=True)
|
||||
except (InvalidPrivateKeyFileError, InvalidPassphraseError):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
return False
|
||||
return True
|
||||
|
||||
def _update_comment(self):
|
||||
keypair = OpensshKeypair.load(path=self.private_key_path, passphrase=self.passphrase, no_public_key=True)
|
||||
try:
|
||||
keypair.comment = self.comment
|
||||
except InvalidCommentError as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
|
||||
def any_in(sequence, *elements):
|
||||
return any([e in sequence for e in elements])
|
||||
try:
|
||||
temp_public_key = self._create_temp_public_key(keypair.public_key + b'\n')
|
||||
self._safe_secure_move([(temp_public_key, self.public_key_path)])
|
||||
except (IOError, OSError) as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
|
||||
|
||||
def select_backend(module, backend):
|
||||
|
||||
@@ -555,6 +555,11 @@ class OpensshCertificate(object):
|
||||
def signing_key(self):
|
||||
return to_text(self._cert_info.signing_key_fingerprint())
|
||||
|
||||
@property
|
||||
def signature_type(self):
|
||||
signature_data = OpensshParser.signature_data(self.signature)
|
||||
return to_text(signature_data['signature_type'])
|
||||
|
||||
@staticmethod
|
||||
def _parse_cert_info(pub_key_type, parser):
|
||||
cert_info = get_cert_info_object(pub_key_type)
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
import re
|
||||
from contextlib import contextmanager
|
||||
from struct import Struct
|
||||
|
||||
from ansible.module_utils.six import PY3
|
||||
@@ -54,6 +56,16 @@ _UINT64 = Struct(b'!Q')
|
||||
_UINT64_MAX = 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
|
||||
def any_in(sequence, *elements):
|
||||
return any(e in sequence for e in elements)
|
||||
|
||||
|
||||
def file_mode(path):
|
||||
if not os.path.exists(path):
|
||||
return 0o000
|
||||
return os.stat(path).st_mode & 0o777
|
||||
|
||||
|
||||
def parse_openssh_version(version_string):
|
||||
"""Parse the version output of ssh -V and return version numbers that can be compared"""
|
||||
|
||||
@@ -68,6 +80,20 @@ def parse_openssh_version(version_string):
|
||||
return version
|
||||
|
||||
|
||||
@contextmanager
|
||||
def secure_open(path, mode):
|
||||
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, mode)
|
||||
try:
|
||||
yield fd
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
def secure_write(path, mode, content):
|
||||
with secure_open(path, mode) as fd:
|
||||
os.write(fd, content)
|
||||
|
||||
|
||||
# See https://datatracker.ietf.org/doc/html/rfc4251#section-5 for SSH data types
|
||||
class OpensshParser(object):
|
||||
"""Parser for OpenSSH encoded objects"""
|
||||
@@ -175,8 +201,9 @@ class OpensshParser(object):
|
||||
signature_blob = parser.string()
|
||||
|
||||
blob_parser = cls(signature_blob)
|
||||
if signature_type == b'ssh-rsa':
|
||||
if signature_type in (b'ssh-rsa', b'rsa-sha2-256', b'rsa-sha2-512'):
|
||||
# https://datatracker.ietf.org/doc/html/rfc4253#section-6.6
|
||||
# https://datatracker.ietf.org/doc/html/rfc8332#section-3
|
||||
signature_data['s'] = cls._big_int(signature_blob, "big")
|
||||
elif signature_type == b'ssh-dss':
|
||||
# https://datatracker.ietf.org/doc/html/rfc4253#section-6.6
|
||||
|
||||
@@ -202,7 +202,10 @@ def main():
|
||||
),
|
||||
)
|
||||
if not HAS_CRYPTOGRAPHY:
|
||||
module.fail_json(msg=missing_required_lib('cryptography >= 1.3'), exception=CRYPTOGRAPHY_IMP_ERR)
|
||||
# Some callbacks die when exception is provided with value None
|
||||
if CRYPTOGRAPHY_IMP_ERR:
|
||||
module.fail_json(msg=missing_required_lib('cryptography >= 1.3'), exception=CRYPTOGRAPHY_IMP_ERR)
|
||||
module.fail_json(msg=missing_required_lib('cryptography >= 1.3'))
|
||||
|
||||
try:
|
||||
# Get parameters
|
||||
|
||||
@@ -50,6 +50,14 @@ options:
|
||||
- Proxy port used when get a certificate.
|
||||
type: int
|
||||
default: 8080
|
||||
starttls:
|
||||
description:
|
||||
- Requests a secure connection for protocols which require clients to initiate encryption.
|
||||
- Only available for C(mysql) currently.
|
||||
type: str
|
||||
choices:
|
||||
- mysql
|
||||
version_added: 1.9.0
|
||||
timeout:
|
||||
description:
|
||||
- The timeout in seconds
|
||||
@@ -209,6 +217,20 @@ else:
|
||||
CRYPTOGRAPHY_FOUND = True
|
||||
|
||||
|
||||
def send_starttls_packet(sock, server_type):
|
||||
if server_type == 'mysql':
|
||||
ssl_request_packet = (
|
||||
b'\x20\x00\x00\x01\x85\xae\x7f\x00' +
|
||||
b'\x00\x00\x00\x01\x21\x00\x00\x00' +
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00' +
|
||||
b'\x00\x00\x00\x00\x00\x00\x00\x00' +
|
||||
b'\x00\x00\x00\x00'
|
||||
)
|
||||
|
||||
sock.recv(8192) # discard initial handshake from server for this naive implementation
|
||||
sock.send(ssl_request_packet)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
@@ -220,6 +242,7 @@ def main():
|
||||
server_name=dict(type='str'),
|
||||
timeout=dict(type='int', default=10),
|
||||
select_crypto_backend=dict(type='str', choices=['auto', 'pyopenssl', 'cryptography'], default='auto'),
|
||||
starttls=dict(type='str', choices=['mysql']),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -230,6 +253,7 @@ def main():
|
||||
proxy_port = module.params.get('proxy_port')
|
||||
timeout = module.params.get('timeout')
|
||||
server_name = module.params.get('server_name')
|
||||
start_tls_server_type = module.params.get('starttls')
|
||||
|
||||
backend = module.params.get('select_crypto_backend')
|
||||
if backend == 'auto':
|
||||
@@ -305,6 +329,9 @@ def main():
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = CERT_NONE
|
||||
|
||||
if start_tls_server_type is not None:
|
||||
send_starttls_packet(sock, start_tls_server_type)
|
||||
|
||||
cert = ctx.wrap_socket(sock, server_hostname=server_name or host).getpeercert(True)
|
||||
cert = DER_cert_to_PEM_cert(cert)
|
||||
except Exception as e:
|
||||
|
||||
@@ -44,12 +44,12 @@ options:
|
||||
required: true
|
||||
regenerate:
|
||||
description:
|
||||
- When C(never) the task will fail if a certificate already exists at I(path) and is unreadable.
|
||||
Otherwise, a new certificate will only be generated if there is no existing certificate.
|
||||
- When C(never) the task will fail if a certificate already exists at I(path) and is unreadable
|
||||
otherwise a new certificate will only be generated if there is no existing certificate.
|
||||
- When C(fail) the task will fail if a certificate already exists at I(path) and does not
|
||||
match the module's options.
|
||||
- When C(partial_idempotence) an existing certificate will be regenerated based on
|
||||
I(serial), I(type), I(valid_from), I(valid_to), I(valid_at), and I(principals).
|
||||
I(serial), I(signature_algorithm), I(type), I(valid_from), I(valid_to), I(valid_at), and I(principals).
|
||||
- When C(full_idempotence) I(identifier), I(options), I(public_key), and I(signing_key)
|
||||
are also considered when compared against an existing certificate.
|
||||
- C(always) is equivalent to I(force=true).
|
||||
@@ -62,6 +62,26 @@ options:
|
||||
- always
|
||||
default: partial_idempotence
|
||||
version_added: 1.8.0
|
||||
signature_algorithm:
|
||||
description:
|
||||
- As of OpenSSH 8.2 the SHA-1 signature algorithm for RSA keys has been disabled and C(ssh) will refuse
|
||||
host certificates signed with the SHA-1 algorithm. OpenSSH 8.1 made C(rsa-sha2-512) the default algorithm
|
||||
when acting as a CA and signing certificates with a RSA key. However, for OpenSSH versions less than 8.1
|
||||
the SHA-2 signature algorithms, C(rsa-sha2-256) or C(rsa-sha2-512), must be specified using this option
|
||||
if compatibility with newer C(ssh) clients is required. Conversely if hosts using OpenSSH version 8.2
|
||||
or greater must remain compatible with C(ssh) clients using OpenSSH less than 7.2, then C(ssh-rsa)
|
||||
can be used when generating host certificates (a corresponding change to the sshd_config to add C(ssh-rsa)
|
||||
to the C(CASignatureAlgorithms) keyword is also required).
|
||||
- Using any value for this option with a non-RSA I(signing_key) will cause this module to fail.
|
||||
- "Note: OpenSSH versions prior to 7.2 do not support SHA-2 signature algorithms for RSA keys and OpenSSH
|
||||
versions prior to 7.3 do not support SHA-2 signature algorithms for certificates."
|
||||
- See U(https://www.openssh.com/txt/release-8.2) for more information.
|
||||
type: str
|
||||
choices:
|
||||
- ssh-rsa
|
||||
- rsa-sha2-256
|
||||
- rsa-sha2-512
|
||||
version_added: 1.10.0
|
||||
signing_key:
|
||||
description:
|
||||
- The path to the private openssh key that is used for signing the public key in order to generate the certificate.
|
||||
@@ -239,12 +259,15 @@ info:
|
||||
|
||||
import os
|
||||
from distutils.version import LooseVersion
|
||||
from sys import version_info
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native, to_text
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.backends.common import safe_atomic_move
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.backends.common import (
|
||||
KeygenCommand,
|
||||
OpensshModule,
|
||||
PrivateKey,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.certificate import (
|
||||
OpensshCertificate,
|
||||
@@ -252,153 +275,122 @@ from ansible_collections.community.crypto.plugins.module_utils.openssh.certifica
|
||||
parse_option_list,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import (
|
||||
parse_openssh_version,
|
||||
)
|
||||
|
||||
PY27 = version_info[0:2] >= (2, 7)
|
||||
|
||||
|
||||
class Certificate(object):
|
||||
class Certificate(OpensshModule):
|
||||
def __init__(self, module):
|
||||
self.check_mode = module.check_mode
|
||||
self.module = module
|
||||
self.ssh_keygen = module.get_bin_path('ssh-keygen', True)
|
||||
super(Certificate, self).__init__(module)
|
||||
self.ssh_keygen = KeygenCommand(self.module)
|
||||
|
||||
self.force = module.params['force']
|
||||
self.identifier = module.params['identifier'] or ""
|
||||
self.options = module.params['options'] or []
|
||||
self.path = module.params['path']
|
||||
self.pkcs11_provider = module.params['pkcs11_provider']
|
||||
self.principals = module.params['principals'] or []
|
||||
self.public_key = module.params['public_key']
|
||||
self.regenerate = module.params['regenerate'] if not self.force else 'always'
|
||||
self.serial_number = module.params['serial_number']
|
||||
self.signing_key = module.params['signing_key']
|
||||
self.state = module.params['state']
|
||||
self.type = module.params['type']
|
||||
self.use_agent = module.params['use_agent']
|
||||
self.valid_at = module.params['valid_at']
|
||||
self.identifier = self.module.params['identifier'] or ""
|
||||
self.options = self.module.params['options'] or []
|
||||
self.path = self.module.params['path']
|
||||
self.pkcs11_provider = self.module.params['pkcs11_provider']
|
||||
self.principals = self.module.params['principals'] or []
|
||||
self.public_key = self.module.params['public_key']
|
||||
self.regenerate = self.module.params['regenerate'] if not self.module.params['force'] else 'always'
|
||||
self.serial_number = self.module.params['serial_number']
|
||||
self.signature_algorithm = self.module.params['signature_algorithm']
|
||||
self.signing_key = self.module.params['signing_key']
|
||||
self.state = self.module.params['state']
|
||||
self.type = self.module.params['type']
|
||||
self.use_agent = self.module.params['use_agent']
|
||||
self.valid_at = self.module.params['valid_at']
|
||||
|
||||
self._check_if_base_dir(self.path)
|
||||
|
||||
if self.state == 'present':
|
||||
self._validate_parameters()
|
||||
|
||||
self.changed = False
|
||||
self.data = None
|
||||
self.original_data = None
|
||||
if self._exists():
|
||||
self._load_certificate()
|
||||
|
||||
self.time_parameters = None
|
||||
|
||||
if self.state == 'present':
|
||||
try:
|
||||
self.time_parameters = OpensshCertificateTimeParameters(
|
||||
valid_from=module.params['valid_from'],
|
||||
valid_to=module.params['valid_to'],
|
||||
)
|
||||
except ValueError as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
self._set_time_parameters()
|
||||
|
||||
if self.exists():
|
||||
try:
|
||||
self.original_data = OpensshCertificate.load(self.path)
|
||||
except (TypeError, ValueError) as e:
|
||||
if self.regenerate in ('never', 'fail'):
|
||||
self.module.fail_json(msg="Unable to read existing certificate: %s" % to_native(e))
|
||||
self.module.warn("Unable to read existing certificate: %s" % to_native(e))
|
||||
def _validate_parameters(self):
|
||||
for path in (self.public_key, self.signing_key):
|
||||
self._check_if_base_dir(path)
|
||||
|
||||
self._validate_parameters()
|
||||
if self.options and self.type == "host":
|
||||
self.module.fail_json(msg="Options can only be used with user certificates.")
|
||||
|
||||
def exists(self):
|
||||
return os.path.exists(self.path)
|
||||
if self.use_agent:
|
||||
self._use_agent_available()
|
||||
|
||||
def generate(self):
|
||||
if self._should_generate():
|
||||
if not self.check_mode:
|
||||
temp_cert = self._generate_temp_certificate()
|
||||
|
||||
try:
|
||||
safe_atomic_move(self.module, temp_cert, self.path)
|
||||
except OSError as e:
|
||||
self.module.fail_json(msg="Unable to write certificate to %s: %s" % (self.path, to_native(e)))
|
||||
|
||||
try:
|
||||
self.data = OpensshCertificate.load(self.path)
|
||||
except (TypeError, ValueError) as e:
|
||||
self.module.fail_json(msg="Unable to read new certificate: %s" % to_native(e))
|
||||
|
||||
self.changed = True
|
||||
|
||||
if self.exists():
|
||||
self._update_permissions()
|
||||
|
||||
def remove(self):
|
||||
if self.exists():
|
||||
if not self.check_mode:
|
||||
try:
|
||||
os.remove(self.path)
|
||||
except OSError as e:
|
||||
self.module.fail_json(msg="Unable to remove existing certificate: %s" % to_native(e))
|
||||
self.changed = True
|
||||
|
||||
@property
|
||||
def result(self):
|
||||
result = {'changed': self.changed}
|
||||
|
||||
if self.module._diff:
|
||||
result['diff'] = {
|
||||
'before': get_cert_dict(self.original_data),
|
||||
'after': get_cert_dict(self.data)
|
||||
}
|
||||
|
||||
if self.state == 'present':
|
||||
result.update({
|
||||
'type': self.type,
|
||||
'filename': self.path,
|
||||
'info': format_cert_info(self._get_cert_info()),
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
def _check_if_base_dir(self, path):
|
||||
base_dir = os.path.dirname(path) or '.'
|
||||
if not os.path.isdir(base_dir):
|
||||
def _use_agent_available(self):
|
||||
ssh_version = self._get_ssh_version()
|
||||
if not ssh_version:
|
||||
self.module.fail_json(msg="Failed to determine ssh version")
|
||||
elif LooseVersion(ssh_version) < LooseVersion("7.6"):
|
||||
self.module.fail_json(
|
||||
name=base_dir,
|
||||
msg='The directory %s does not exist or the file is not a directory' % base_dir
|
||||
msg="Signing with CA key in ssh agent requires ssh 7.6 or newer." +
|
||||
" Your version is: %s" % ssh_version
|
||||
)
|
||||
|
||||
def _command_arguments(self, key_copy_path):
|
||||
result = [
|
||||
self.ssh_keygen,
|
||||
'-s', self.signing_key,
|
||||
'-P', '',
|
||||
'-I', self.identifier,
|
||||
]
|
||||
def _exists(self):
|
||||
return os.path.exists(self.path)
|
||||
|
||||
if self.options:
|
||||
for option in self.options:
|
||||
result.extend(['-O', option])
|
||||
if self.pkcs11_provider:
|
||||
result.extend(['-D', self.pkcs11_provider])
|
||||
if self.principals:
|
||||
result.extend(['-n', ','.join(self.principals)])
|
||||
if self.serial_number is not None:
|
||||
result.extend(['-z', str(self.serial_number)])
|
||||
if self.type == 'host':
|
||||
result.extend(['-h'])
|
||||
if self.use_agent:
|
||||
result.extend(['-U'])
|
||||
if self.time_parameters.validity_string:
|
||||
result.extend(['-V', self.time_parameters.validity_string])
|
||||
result.append(key_copy_path)
|
||||
|
||||
return result
|
||||
|
||||
def _compare_options(self):
|
||||
def _load_certificate(self):
|
||||
try:
|
||||
critical_options, extensions = parse_option_list(self.options)
|
||||
except ValueError as e:
|
||||
return self.module.fail_json(msg=to_native(e))
|
||||
self.original_data = OpensshCertificate.load(self.path)
|
||||
except (TypeError, ValueError) as e:
|
||||
if self.regenerate in ('never', 'fail'):
|
||||
self.module.fail_json(msg="Unable to read existing certificate: %s" % to_native(e))
|
||||
self.module.warn("Unable to read existing certificate: %s" % to_native(e))
|
||||
|
||||
def _set_time_parameters(self):
|
||||
try:
|
||||
self.time_parameters = OpensshCertificateTimeParameters(
|
||||
valid_from=self.module.params['valid_from'],
|
||||
valid_to=self.module.params['valid_to'],
|
||||
)
|
||||
except ValueError as e:
|
||||
self.module.fail_json(msg=to_native(e))
|
||||
|
||||
def _execute(self):
|
||||
if self.state == 'present':
|
||||
if self._should_generate():
|
||||
self._generate()
|
||||
self._update_permissions(self.path)
|
||||
else:
|
||||
if self._exists():
|
||||
self._remove()
|
||||
|
||||
def _should_generate(self):
|
||||
if self.regenerate == 'never':
|
||||
return self.original_data is None
|
||||
elif self.regenerate == 'fail':
|
||||
if self.original_data and not self._is_fully_valid():
|
||||
self.module.fail_json(
|
||||
msg="Certificate does not match the provided options.",
|
||||
cert=get_cert_dict(self.original_data)
|
||||
)
|
||||
return self.original_data is None
|
||||
elif self.regenerate == 'partial_idempotence':
|
||||
return self.original_data is None or not self._is_partially_valid()
|
||||
elif self.regenerate == 'full_idempotence':
|
||||
return self.original_data is None or not self._is_fully_valid()
|
||||
else:
|
||||
return True
|
||||
|
||||
def _is_fully_valid(self):
|
||||
return self._is_partially_valid() and all([
|
||||
self._compare_options(),
|
||||
self.original_data.key_id == self.identifier,
|
||||
self.original_data.public_key == self._get_key_fingerprint(self.public_key),
|
||||
self.original_data.signing_key == self._get_key_fingerprint(self.signing_key),
|
||||
])
|
||||
|
||||
def _is_partially_valid(self):
|
||||
return all([
|
||||
set(self.original_data.critical_options) == set(critical_options),
|
||||
set(self.original_data.extensions) == set(extensions)
|
||||
set(self.original_data.principals) == set(self.principals),
|
||||
self.original_data.signature_type == self.signature_algorithm if self.signature_algorithm else True,
|
||||
self.original_data.serial == self.serial_number if self.serial_number is not None else True,
|
||||
self.original_data.type == self.type,
|
||||
self._compare_time_parameters(),
|
||||
])
|
||||
|
||||
def _compare_time_parameters(self):
|
||||
@@ -415,6 +407,35 @@ class Certificate(object):
|
||||
original_time_parameters.within_range(self.valid_at)
|
||||
])
|
||||
|
||||
def _compare_options(self):
|
||||
try:
|
||||
critical_options, extensions = parse_option_list(self.options)
|
||||
except ValueError as e:
|
||||
return self.module.fail_json(msg=to_native(e))
|
||||
|
||||
return all([
|
||||
set(self.original_data.critical_options) == set(critical_options),
|
||||
set(self.original_data.extensions) == set(extensions)
|
||||
])
|
||||
|
||||
def _get_key_fingerprint(self, path):
|
||||
private_key_content = self.ssh_keygen.get_private_key(path, check_rc=True)[1]
|
||||
return PrivateKey.from_string(private_key_content).fingerprint
|
||||
|
||||
@OpensshModule.trigger_change
|
||||
@OpensshModule.skip_if_check_mode
|
||||
def _generate(self):
|
||||
try:
|
||||
temp_certificate = self._generate_temp_certificate()
|
||||
self._safe_secure_move([(temp_certificate, self.path)])
|
||||
except OSError as e:
|
||||
self.module.fail_json(msg="Unable to write certificate to %s: %s" % (self.path, to_native(e)))
|
||||
|
||||
try:
|
||||
self.data = OpensshCertificate.load(self.path)
|
||||
except (TypeError, ValueError) as e:
|
||||
self.module.fail_json(msg="Unable to read new certificate: %s" % to_native(e))
|
||||
|
||||
def _generate_temp_certificate(self):
|
||||
key_copy = os.path.join(self.module.tmpdir, os.path.basename(self.public_key))
|
||||
|
||||
@@ -424,77 +445,44 @@ class Certificate(object):
|
||||
self.module.fail_json(msg="Unable to stage temporary key: %s" % to_native(e))
|
||||
self.module.add_cleanup_file(key_copy)
|
||||
|
||||
self.module.run_command(self._command_arguments(key_copy), environ_update=dict(TZ="UTC"), check_rc=True)
|
||||
self.ssh_keygen.generate_certificate(
|
||||
key_copy, self.identifier, self.options, self.pkcs11_provider, self.principals, self.serial_number,
|
||||
self.signature_algorithm, self.signing_key, self.type, self.time_parameters, self.use_agent,
|
||||
environ_update=dict(TZ="UTC"), check_rc=True
|
||||
)
|
||||
|
||||
temp_cert = os.path.splitext(key_copy)[0] + '-cert.pub'
|
||||
self.module.add_cleanup_file(temp_cert)
|
||||
|
||||
return temp_cert
|
||||
|
||||
def _get_cert_info(self):
|
||||
return self.module.run_command([self.ssh_keygen, '-Lf', self.path])[1]
|
||||
@OpensshModule.trigger_change
|
||||
@OpensshModule.skip_if_check_mode
|
||||
def _remove(self):
|
||||
try:
|
||||
os.remove(self.path)
|
||||
except OSError as e:
|
||||
self.module.fail_json(msg="Unable to remove existing certificate: %s" % to_native(e))
|
||||
|
||||
def _get_key_fingerprint(self, path):
|
||||
stdout = self.module.run_command([self.ssh_keygen, '-lf', path], check_rc=True)[1]
|
||||
return stdout.split()[1]
|
||||
@property
|
||||
def _result(self):
|
||||
if self.state != 'present':
|
||||
return {}
|
||||
|
||||
def _is_valid(self):
|
||||
partial_result = all([
|
||||
set(self.original_data.principals) == set(self.principals),
|
||||
self.original_data.serial == self.serial_number if self.serial_number is not None else True,
|
||||
self.original_data.type == self.type,
|
||||
self._compare_time_parameters(),
|
||||
])
|
||||
certificate_info = self.ssh_keygen.get_certificate_info(self.path)[1]
|
||||
|
||||
if self.regenerate == 'partial_idempotence':
|
||||
return partial_result
|
||||
return {
|
||||
'type': self.type,
|
||||
'filename': self.path,
|
||||
'info': format_cert_info(certificate_info),
|
||||
}
|
||||
|
||||
return partial_result and all([
|
||||
self._compare_options(),
|
||||
self.original_data.key_id == self.identifier,
|
||||
self.original_data.public_key == self._get_key_fingerprint(self.public_key),
|
||||
self.original_data.signing_key == self._get_key_fingerprint(self.signing_key),
|
||||
])
|
||||
|
||||
def _should_generate(self):
|
||||
if self.regenerate == 'never':
|
||||
return self.original_data is None
|
||||
elif self.regenerate == 'fail':
|
||||
if self.original_data and not self._is_valid():
|
||||
self.module.fail_json(
|
||||
msg="Certificate does not match the provided options.",
|
||||
cert=get_cert_dict(self.original_data)
|
||||
)
|
||||
return self.original_data is None
|
||||
elif self.regenerate in ('partial_idempotence', 'full_idempotence'):
|
||||
return self.original_data is None or not self._is_valid()
|
||||
else:
|
||||
return True
|
||||
|
||||
def _update_permissions(self):
|
||||
file_args = self.module.load_file_common_arguments(self.module.params)
|
||||
self.changed = self.module.set_fs_attributes_if_different(file_args, self.changed)
|
||||
|
||||
def _validate_parameters(self):
|
||||
self._check_if_base_dir(self.path)
|
||||
|
||||
if self.state == 'present':
|
||||
for path in (self.public_key, self.signing_key):
|
||||
self._check_if_base_dir(path)
|
||||
|
||||
if self.options and self.type == "host":
|
||||
self.module.fail_json(msg="Options can only be used with user certificates.")
|
||||
|
||||
if self.use_agent:
|
||||
ssh_version_string = self.module.run_command([self.module.get_bin_path('ssh', True), '-Vq'])[2].strip()
|
||||
ssh_version = parse_openssh_version(ssh_version_string)
|
||||
if ssh_version is None:
|
||||
self.module.fail_json(msg="Failed to parse ssh version from: %s" % ssh_version_string)
|
||||
elif LooseVersion(ssh_version) < LooseVersion("7.6"):
|
||||
self.module.fail_json(
|
||||
msg="Signing with CA key in ssh agent requires ssh 7.6 or newer." +
|
||||
" Your version is: %s" % ssh_version_string
|
||||
)
|
||||
@property
|
||||
def diff(self):
|
||||
return {
|
||||
'before': get_cert_dict(self.original_data),
|
||||
'after': get_cert_dict(self.data)
|
||||
}
|
||||
|
||||
|
||||
def format_cert_info(cert_info):
|
||||
@@ -519,6 +507,8 @@ def get_cert_dict(data):
|
||||
|
||||
result = data.to_dict()
|
||||
result.pop('nonce')
|
||||
result['signature_algorithm'] = data.signature_type
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -537,6 +527,7 @@ def main():
|
||||
default='partial_idempotence',
|
||||
choices=['never', 'fail', 'partial_idempotence', 'full_idempotence', 'always']
|
||||
),
|
||||
signature_algorithm=dict(type='str', choices=['ssh-rsa', 'rsa-sha2-256', 'rsa-sha2-512']),
|
||||
signing_key=dict(type='path'),
|
||||
serial_number=dict(type='int'),
|
||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||
@@ -551,14 +542,7 @@ def main():
|
||||
required_if=[('state', 'present', ['type', 'signing_key', 'public_key', 'valid_from', 'valid_to'])],
|
||||
)
|
||||
|
||||
certificate = Certificate(module)
|
||||
|
||||
if certificate.state == 'present':
|
||||
certificate.generate()
|
||||
else:
|
||||
certificate.remove()
|
||||
|
||||
module.exit_json(**certificate.result)
|
||||
Certificate(module).execute()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -186,8 +186,6 @@ comment:
|
||||
sample: test@comment
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.backends.keypair_backend import (
|
||||
@@ -218,32 +216,9 @@ def main():
|
||||
add_file_common_args=True,
|
||||
)
|
||||
|
||||
base_dir = os.path.dirname(module.params['path']) or '.'
|
||||
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
|
||||
)
|
||||
|
||||
keypair = select_backend(module, module.params['backend'])[1]
|
||||
|
||||
if module.params['state'] == 'present':
|
||||
if module.check_mode:
|
||||
keypair.changed = any([
|
||||
keypair.force,
|
||||
not keypair.is_private_key_valid(),
|
||||
not keypair.is_public_key_valid()
|
||||
])
|
||||
else:
|
||||
keypair.generate()
|
||||
else:
|
||||
# When `state=absent` no details from an existing key at the given `path` are returned in the module result
|
||||
if module.check_mode:
|
||||
keypair.changed = keypair.exists()
|
||||
else:
|
||||
keypair.remove()
|
||||
|
||||
module.exit_json(**keypair.result)
|
||||
keypair.execute()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -597,7 +597,7 @@ class CRL(OpenSSLObject):
|
||||
entry['invalidity_date_critical'],
|
||||
)
|
||||
|
||||
def check(self, perms_required=True, ignore_conversion=True):
|
||||
def check(self, module, perms_required=True, ignore_conversion=True):
|
||||
"""Ensure the resource is in its desired state."""
|
||||
|
||||
state_and_perms = super(CRL, self).check(self.module, perms_required)
|
||||
@@ -689,9 +689,9 @@ class CRL(OpenSSLObject):
|
||||
|
||||
def generate(self):
|
||||
result = None
|
||||
if not self.check(perms_required=False, ignore_conversion=True) or self.force:
|
||||
if not self.check(self.module, perms_required=False, ignore_conversion=True) or self.force:
|
||||
result = self._generate_crl()
|
||||
elif not self.check(perms_required=False, ignore_conversion=False) and self.crl:
|
||||
elif not self.check(self.module, perms_required=False, ignore_conversion=False) and self.crl:
|
||||
if self.format == 'pem':
|
||||
result = self.crl.public_bytes(Encoding.PEM)
|
||||
else:
|
||||
@@ -834,7 +834,7 @@ def main():
|
||||
if module.params['state'] == 'present':
|
||||
if module.check_mode:
|
||||
result = crl.dump(check_mode=True)
|
||||
result['changed'] = module.params['force'] or not crl.check() or not crl.check(ignore_conversion=False)
|
||||
result['changed'] = module.params['force'] or not crl.check(module) or not crl.check(module, ignore_conversion=False)
|
||||
module.exit_json(**result)
|
||||
|
||||
crl.generate()
|
||||
|
||||
@@ -1,2 +1,14 @@
|
||||
shippable/cloud/group1
|
||||
cloud/acme
|
||||
|
||||
# Since skipping below fails miserably with ansible-core 2.11 and earlier, we have to skip all POSIX tests...
|
||||
# (https://github.com/ansible/ansible/issues/75711)
|
||||
# shippable/posix/group1
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
# (TODO: remove when ansible-core 2.12 is the earliest version we support)
|
||||
# skip/aix
|
||||
# skip/freebsd
|
||||
# skip/macos
|
||||
# skip/osx
|
||||
# skip/rhel
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
dependencies:
|
||||
- setup_acme
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
- block:
|
||||
- name: Generate account keys
|
||||
openssl_privatekey:
|
||||
path: "{{ output_dir }}/{{ item.name }}.pem"
|
||||
passphrase: "{{ item.pass | default(omit, true) }}"
|
||||
cipher: "{{ 'auto' if item.pass | default() else omit }}"
|
||||
path: "{{ remote_tmp_dir }}/{{ item.name }}.pem"
|
||||
passphrase: "{{ item.pass | default(omit) | default(omit, true) }}"
|
||||
cipher: "{{ 'auto' if (item.pass | default(false)) else omit }}"
|
||||
type: ECC
|
||||
curve: secp256r1
|
||||
force: true
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
- name: Parse account keys (to ease debugging some test failures)
|
||||
openssl_privatekey_info:
|
||||
path: "{{ output_dir }}/{{ item.name }}.pem"
|
||||
passphrase: "{{ item.pass | default(omit, true) }}"
|
||||
path: "{{ remote_tmp_dir }}/{{ item.name }}.pem"
|
||||
passphrase: "{{ item.pass | default(omit) | default(omit, true) }}"
|
||||
return_private_key_data: true
|
||||
loop: "{{ account_keys }}"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
- name: Do not try to create account
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -40,7 +40,7 @@
|
||||
- name: Create it now (check mode, diff)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -56,7 +56,7 @@
|
||||
- name: Create it now
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -70,7 +70,7 @@
|
||||
- name: Create it now (idempotent)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -81,10 +81,15 @@
|
||||
- mailto:example@example.org
|
||||
register: account_created_idempotent
|
||||
|
||||
- name: Read account key
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/accountkey.pem'
|
||||
register: slurp
|
||||
|
||||
- name: Change email address (check mode, diff)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/accountkey.pem') }}"
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -99,7 +104,7 @@
|
||||
- name: Change email address
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/accountkey.pem') }}"
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -112,7 +117,7 @@
|
||||
- name: Change email address (idempotent)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_created.account_uri }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
@@ -126,7 +131,7 @@
|
||||
- name: Cannot access account with wrong URI
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_created.account_uri ~ '12345thisdoesnotexist' }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
@@ -139,7 +144,7 @@
|
||||
- name: Clear contact email addresses (check mode, diff)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -153,7 +158,7 @@
|
||||
- name: Clear contact email addresses
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -165,7 +170,7 @@
|
||||
- name: Clear contact email addresses (idempotent)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -177,11 +182,11 @@
|
||||
- name: Change account key (check mode, diff)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
new_account_key_src: "{{ output_dir }}/accountkey2.pem"
|
||||
new_account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
new_account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
state: changed_key
|
||||
contact:
|
||||
@@ -193,11 +198,11 @@
|
||||
- name: Change account key
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
new_account_key_src: "{{ output_dir }}/accountkey2.pem"
|
||||
new_account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
new_account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
state: changed_key
|
||||
contact:
|
||||
@@ -207,7 +212,7 @@
|
||||
- name: Deactivate account (check mode, diff)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey2.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
@@ -220,7 +225,7 @@
|
||||
- name: Deactivate account
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey2.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
@@ -231,7 +236,7 @@
|
||||
- name: Deactivate account (idempotent)
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey2.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
@@ -242,7 +247,7 @@
|
||||
- name: Do not try to create account II
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey2.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
@@ -255,7 +260,7 @@
|
||||
- name: Do not try to create account III
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -267,7 +272,7 @@
|
||||
- name: Create account with External Account Binding
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/{{ item.account }}.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/{{ item.account }}.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1,2 +1,14 @@
|
||||
shippable/cloud/group1
|
||||
cloud/acme
|
||||
|
||||
# Since skipping below fails miserably with ansible-core 2.11 and earlier, we have to skip all POSIX tests...
|
||||
# (https://github.com/ansible/ansible/issues/75711)
|
||||
# shippable/posix/group1
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
# (TODO: remove when ansible-core 2.12 is the earliest version we support)
|
||||
# skip/aix
|
||||
# skip/freebsd
|
||||
# skip/macos
|
||||
# skip/osx
|
||||
# skip/rhel
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
dependencies:
|
||||
- setup_acme
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
- block:
|
||||
- name: Generate account keys
|
||||
openssl_privatekey:
|
||||
path: "{{ output_dir }}/{{ item }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/{{ item }}.pem"
|
||||
type: ECC
|
||||
curve: secp256r1
|
||||
force: true
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
- name: Parse account keys (to ease debugging some test failures)
|
||||
openssl_privatekey_info:
|
||||
path: "{{ output_dir }}/{{ item }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/{{ item }}.pem"
|
||||
return_private_key_data: true
|
||||
loop: "{{ account_keys }}"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- name: Check that account does not exist
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -31,7 +31,7 @@
|
||||
- name: Create it now
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -44,16 +44,21 @@
|
||||
- name: Check that account exists
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
register: account_created
|
||||
|
||||
- name: Read account key
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/accountkey.pem'
|
||||
register: slurp
|
||||
|
||||
- name: Clear email address
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/accountkey.pem') }}"
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -64,7 +69,7 @@
|
||||
- name: Check that account was modified
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -74,7 +79,7 @@
|
||||
- name: Check with wrong account URI
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -84,7 +89,7 @@
|
||||
- name: Check with wrong account key
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/accountkey2.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1,2 +1,14 @@
|
||||
shippable/cloud/group1
|
||||
cloud/acme
|
||||
|
||||
# Since skipping below fails miserably with ansible-core 2.11 and earlier, we have to skip all POSIX tests...
|
||||
# (https://github.com/ansible/ansible/issues/75711)
|
||||
# shippable/posix/group1
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
# (TODO: remove when ansible-core 2.12 is the earliest version we support)
|
||||
# skip/aix
|
||||
# skip/freebsd
|
||||
# skip/macos
|
||||
# skip/osx
|
||||
# skip/rhel
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
dependencies:
|
||||
- setup_acme
|
||||
- setup_pyopenssl # needed for Ubuntu 16.04
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- block:
|
||||
- name: Generate account keys
|
||||
openssl_privatekey:
|
||||
path: "{{ output_dir }}/{{ item.name }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/{{ item.name }}.pem"
|
||||
type: "{{ item.type }}"
|
||||
size: "{{ item.size | default(omit) }}"
|
||||
curve: "{{ item.curve | default(omit) }}"
|
||||
@@ -28,15 +28,19 @@
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
state: absent
|
||||
- name: Read account key (EC384)
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/account-ec384.pem'
|
||||
register: slurp
|
||||
- name: Create ECC384 account
|
||||
acme_account:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/account-ec384.pem') }}"
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
@@ -49,7 +53,7 @@
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/account-rsa.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-rsa.pem"
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
@@ -115,6 +119,10 @@
|
||||
set_fact:
|
||||
cert_2_obtain_results: "{{ certificate_obtain_result }}"
|
||||
cert_2_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
|
||||
- name: Read account key (RSA)
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/account-rsa.pem'
|
||||
register: slurp_account_key
|
||||
- name: Obtain cert 3
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
@@ -123,7 +131,7 @@
|
||||
key_type: ec384
|
||||
subject_alt_name: "DNS:*.example.com,DNS:example.org,DNS:t1.example.com"
|
||||
subject_alt_name_critical: no
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/account-rsa.pem') }}"
|
||||
account_key_content: "{{ slurp_account_key.content | b64decode }}"
|
||||
challenge: dns-01
|
||||
modify_account: no
|
||||
deactivate_authzs: no
|
||||
@@ -231,6 +239,10 @@
|
||||
set_fact:
|
||||
cert_5_recreate_2: "{{ challenge_data is changed }}"
|
||||
cert_5c_obtain_results: "{{ certificate_obtain_result }}"
|
||||
- name: Read account key (EC384)
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/account-ec384.pem'
|
||||
register: slurp_account_key
|
||||
- name: Obtain cert 5 (should again by force)
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
@@ -239,7 +251,7 @@
|
||||
key_type: ec521
|
||||
subject_alt_name: "DNS:t2.example.com"
|
||||
subject_alt_name_critical: no
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/account-ec384.pem') }}"
|
||||
account_key_content: "{{ slurp_account_key.content | b64decode }}"
|
||||
challenge: http-01
|
||||
modify_account: no
|
||||
deactivate_authzs: yes
|
||||
@@ -252,189 +264,204 @@
|
||||
set_fact:
|
||||
cert_5_recreate_3: "{{ challenge_data is changed }}"
|
||||
cert_5d_obtain_results: "{{ certificate_obtain_result }}"
|
||||
- name: Obtain cert 6
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
certgen_title: Certificate 6
|
||||
certificate_name: cert-6
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.org"
|
||||
subject_alt_name_critical: no
|
||||
account_key: account-ec256
|
||||
challenge: tls-alpn-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
account_email: "example@example.org"
|
||||
acme_expected_root_number: 0
|
||||
select_chain:
|
||||
# All intermediates have the same subject key identifier, so always
|
||||
# the first chain will be found, and we need a second condition to
|
||||
# make sure that the first condition actually works. (The second
|
||||
# condition has been tested above.)
|
||||
- test_certificates: first
|
||||
subject_key_identifier: "{{ acme_intermediates[0].subject_key_identifier }}"
|
||||
- test_certificates: last
|
||||
issuer: "{{ acme_roots[1].subject }}"
|
||||
use_csr_content: true
|
||||
- name: Store obtain results for cert 6
|
||||
set_fact:
|
||||
cert_6_obtain_results: "{{ certificate_obtain_result }}"
|
||||
cert_6_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
|
||||
- name: Obtain cert 7
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
certgen_title: Certificate 7
|
||||
certificate_name: cert-7
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name:
|
||||
- "IP:127.0.0.1"
|
||||
# - "IP:::1"
|
||||
subject_alt_name_critical: no
|
||||
account_key: account-ec256
|
||||
challenge: http-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
account_email: "example@example.org"
|
||||
acme_expected_root_number: 2
|
||||
select_chain:
|
||||
- test_certificates: last
|
||||
authority_key_identifier: "{{ acme_roots[2].subject_key_identifier }}"
|
||||
use_csr_content: false
|
||||
- name: Store obtain results for cert 7
|
||||
set_fact:
|
||||
cert_7_obtain_results: "{{ certificate_obtain_result }}"
|
||||
cert_7_alternate: "{{ 2 if select_crypto_backend == 'cryptography' else 0 }}"
|
||||
- name: Obtain cert 8
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
certgen_title: Certificate 8
|
||||
certificate_name: cert-8
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name:
|
||||
- "IP:127.0.0.1"
|
||||
# IPv4 only since our test validation server doesn't work
|
||||
# with IPv6 (thanks to Python's socketserver).
|
||||
subject_alt_name_critical: no
|
||||
account_key: account-ec256
|
||||
challenge: tls-alpn-01
|
||||
challenge_alpn_tls: acme_challenge_cert_helper
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
account_email: "example@example.org"
|
||||
use_csr_content: true
|
||||
- name: Store obtain results for cert 8
|
||||
set_fact:
|
||||
cert_8_obtain_results: "{{ certificate_obtain_result }}"
|
||||
cert_8_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
|
||||
- block:
|
||||
- name: Obtain cert 6
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
certgen_title: Certificate 6
|
||||
certificate_name: cert-6
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.org"
|
||||
subject_alt_name_critical: no
|
||||
account_key: account-ec256
|
||||
challenge: tls-alpn-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
account_email: "example@example.org"
|
||||
acme_expected_root_number: 0
|
||||
select_chain:
|
||||
# All intermediates have the same subject key identifier, so always
|
||||
# the first chain will be found, and we need a second condition to
|
||||
# make sure that the first condition actually works. (The second
|
||||
# condition has been tested above.)
|
||||
- test_certificates: first
|
||||
subject_key_identifier: "{{ acme_intermediates[0].subject_key_identifier }}"
|
||||
- test_certificates: last
|
||||
issuer: "{{ acme_roots[1].subject }}"
|
||||
use_csr_content: true
|
||||
- name: Store obtain results for cert 6
|
||||
set_fact:
|
||||
cert_6_obtain_results: "{{ certificate_obtain_result }}"
|
||||
cert_6_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
|
||||
when: acme_intermediates[0].subject_key_identifier is defined
|
||||
- block:
|
||||
- name: Obtain cert 7
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
certgen_title: Certificate 7
|
||||
certificate_name: cert-7
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name:
|
||||
- "IP:127.0.0.1"
|
||||
# - "IP:::1"
|
||||
subject_alt_name_critical: no
|
||||
account_key: account-ec256
|
||||
challenge: http-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
account_email: "example@example.org"
|
||||
acme_expected_root_number: 2
|
||||
select_chain:
|
||||
- test_certificates: last
|
||||
authority_key_identifier: "{{ acme_roots[2].subject_key_identifier }}"
|
||||
use_csr_content: false
|
||||
- name: Store obtain results for cert 7
|
||||
set_fact:
|
||||
cert_7_obtain_results: "{{ certificate_obtain_result }}"
|
||||
cert_7_alternate: "{{ 2 if select_crypto_backend == 'cryptography' else 0 }}"
|
||||
when: acme_roots[2].subject_key_identifier is defined
|
||||
- block:
|
||||
- name: Obtain cert 8
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
certgen_title: Certificate 8
|
||||
certificate_name: cert-8
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name:
|
||||
- "IP:127.0.0.1"
|
||||
# IPv4 only since our test validation server doesn't work
|
||||
# with IPv6 (thanks to Python's socketserver).
|
||||
subject_alt_name_critical: no
|
||||
account_key: account-ec256
|
||||
challenge: tls-alpn-01
|
||||
challenge_alpn_tls: acme_challenge_cert_helper
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
account_email: "example@example.org"
|
||||
use_csr_content: true
|
||||
- name: Store obtain results for cert 8
|
||||
set_fact:
|
||||
cert_8_obtain_results: "{{ certificate_obtain_result }}"
|
||||
cert_8_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
## DISSECT CERTIFICATES #######################################################################
|
||||
# Make sure certificates are valid. Root certificate for Pebble equals the chain certificate.
|
||||
- name: Verifying cert 1
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-1-root.pem" -untrusted "{{ output_dir }}/cert-1-chain.pem" "{{ output_dir }}/cert-1.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-1-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-1-chain.pem" "{{ remote_tmp_dir }}/cert-1.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_1_valid
|
||||
- name: Verifying cert 2
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-2-root.pem" -untrusted "{{ output_dir }}/cert-2-chain.pem" "{{ output_dir }}/cert-2.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-2-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-2-chain.pem" "{{ remote_tmp_dir }}/cert-2.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_2_valid
|
||||
- name: Verifying cert 3
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-3-root.pem" -untrusted "{{ output_dir }}/cert-3-chain.pem" "{{ output_dir }}/cert-3.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-3-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-3-chain.pem" "{{ remote_tmp_dir }}/cert-3.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_3_valid
|
||||
- name: Verifying cert 4
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-4-root.pem" -untrusted "{{ output_dir }}/cert-4-chain.pem" "{{ output_dir }}/cert-4.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-4-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-4-chain.pem" "{{ remote_tmp_dir }}/cert-4.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_4_valid
|
||||
- name: Verifying cert 5
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-5-root.pem" -untrusted "{{ output_dir }}/cert-5-chain.pem" "{{ output_dir }}/cert-5.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-5-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-5-chain.pem" "{{ remote_tmp_dir }}/cert-5.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_5_valid
|
||||
- name: Verifying cert 6
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-6-root.pem" -untrusted "{{ output_dir }}/cert-6-chain.pem" "{{ output_dir }}/cert-6.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-6-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-6-chain.pem" "{{ remote_tmp_dir }}/cert-6.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_6_valid
|
||||
when: acme_intermediates[0].subject_key_identifier is defined
|
||||
- name: Verifying cert 7
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-7-root.pem" -untrusted "{{ output_dir }}/cert-7-chain.pem" "{{ output_dir }}/cert-7.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-7-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-7-chain.pem" "{{ remote_tmp_dir }}/cert-7.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_7_valid
|
||||
when: acme_roots[2].subject_key_identifier is defined
|
||||
- name: Verifying cert 8
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-8-root.pem" -untrusted "{{ output_dir }}/cert-8-chain.pem" "{{ output_dir }}/cert-8.pem"'
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-8-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-8-chain.pem" "{{ remote_tmp_dir }}/cert-8.pem"'
|
||||
ignore_errors: yes
|
||||
register: cert_8_valid
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
# Dump certificate info
|
||||
- name: Dumping cert 1
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-1.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-1.pem" -noout -text'
|
||||
register: cert_1_text
|
||||
- name: Dumping cert 2
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-2.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-2.pem" -noout -text'
|
||||
register: cert_2_text
|
||||
- name: Dumping cert 3
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-3.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-3.pem" -noout -text'
|
||||
register: cert_3_text
|
||||
- name: Dumping cert 4
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-4.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-4.pem" -noout -text'
|
||||
register: cert_4_text
|
||||
- name: Dumping cert 5
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-5.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-5.pem" -noout -text'
|
||||
register: cert_5_text
|
||||
- name: Dumping cert 6
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-6.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-6.pem" -noout -text'
|
||||
register: cert_6_text
|
||||
when: acme_intermediates[0].subject_key_identifier is defined
|
||||
- name: Dumping cert 7
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-7.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-7.pem" -noout -text'
|
||||
register: cert_7_text
|
||||
when: acme_roots[2].subject_key_identifier is defined
|
||||
- name: Dumping cert 8
|
||||
command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-8.pem" -noout -text'
|
||||
command: '{{ openssl_binary }} x509 -in "{{ remote_tmp_dir }}/cert-8.pem" -noout -text'
|
||||
register: cert_8_text
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
# Dump certificate info
|
||||
- name: Dumping cert 1
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-1.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-1.pem"
|
||||
register: cert_1_info
|
||||
- name: Dumping cert 2
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-2.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-2.pem"
|
||||
register: cert_2_info
|
||||
- name: Dumping cert 3
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-3.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-3.pem"
|
||||
register: cert_3_info
|
||||
- name: Dumping cert 4
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-4.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-4.pem"
|
||||
register: cert_4_info
|
||||
- name: Dumping cert 5
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-5.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-5.pem"
|
||||
register: cert_5_info
|
||||
- name: Dumping cert 6
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-6.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-6.pem"
|
||||
register: cert_6_info
|
||||
when: acme_intermediates[0].subject_key_identifier is defined
|
||||
- name: Dumping cert 7
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-7.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-7.pem"
|
||||
register: cert_7_info
|
||||
when: acme_roots[2].subject_key_identifier is defined
|
||||
- name: Dumping cert 8
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/cert-8.pem"
|
||||
path: "{{ remote_tmp_dir }}/cert-8.pem"
|
||||
register: cert_8_info
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
## GET ACCOUNT ORDERS #########################################################################
|
||||
- name: Don't retrieve orders
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -443,7 +470,7 @@
|
||||
- name: Retrieve orders as URL list (1/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -452,7 +479,7 @@
|
||||
- name: Retrieve orders as URL list (2/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec384.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec384.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -461,7 +488,7 @@
|
||||
- name: Retrieve orders as object list (1/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -470,7 +497,7 @@
|
||||
- name: Retrieve orders as object list (2/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec384.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec384.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
|
||||
@@ -8,38 +8,48 @@
|
||||
- name: Obtain root and intermediate certificates
|
||||
get_url:
|
||||
url: "http://{{ acme_host }}:5000/{{ item.0 }}-certificate-for-ca/{{ item.1 }}"
|
||||
dest: "{{ output_dir }}/acme-{{ item.0 }}-{{ item.1 }}.pem"
|
||||
dest: "{{ remote_tmp_dir }}/acme-{{ item.0 }}-{{ item.1 }}.pem"
|
||||
loop: "{{ query('nested', types, root_numbers) }}"
|
||||
|
||||
- name: Analyze root certificates
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/acme-root-{{ item }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/acme-root-{{ item }}.pem"
|
||||
loop: "{{ root_numbers }}"
|
||||
register: acme_roots
|
||||
|
||||
- name: Analyze intermediate certificates
|
||||
x509_certificate_info:
|
||||
path: "{{ output_dir }}/acme-intermediate-{{ item }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/acme-intermediate-{{ item }}.pem"
|
||||
loop: "{{ root_numbers }}"
|
||||
register: acme_intermediates
|
||||
|
||||
- set_fact:
|
||||
x__: "{{ item | dict2items | selectattr('key', 'in', interesting_keys) | list | items2dict }}"
|
||||
y__: "{{ lookup('file', output_dir ~ '/acme-root-' ~ item.item ~ '.pem', rstrip=False) }}"
|
||||
loop: "{{ acme_roots.results }}"
|
||||
register: acme_roots_tmp
|
||||
- name: Read root certificates
|
||||
slurp:
|
||||
src: "{{ remote_tmp_dir ~ '/acme-root-' ~ item ~ '.pem' }}"
|
||||
loop: "{{ root_numbers }}"
|
||||
register: slurp_roots
|
||||
|
||||
- set_fact:
|
||||
x__: "{{ item | dict2items | selectattr('key', 'in', interesting_keys) | list | items2dict }}"
|
||||
loop: "{{ acme_roots.results }}"
|
||||
register: acme_roots_tmp
|
||||
|
||||
- name: Read intermediate certificates
|
||||
slurp:
|
||||
src: "{{ remote_tmp_dir ~ '/acme-intermediate-' ~ item ~ '.pem' }}"
|
||||
loop: "{{ root_numbers }}"
|
||||
register: slurp_intermediates
|
||||
|
||||
- set_fact:
|
||||
x__: "{{ item | dict2items | selectattr('key', 'in', interesting_keys) | list | items2dict }}"
|
||||
y__: "{{ lookup('file', output_dir ~ '/acme-intermediate-' ~ item.item ~ '.pem', rstrip=False) }}"
|
||||
loop: "{{ acme_intermediates.results }}"
|
||||
register: acme_intermediates_tmp
|
||||
|
||||
- set_fact:
|
||||
acme_roots: "{{ acme_roots_tmp.results | map(attribute='ansible_facts.x__') | list }}"
|
||||
acme_root_certs: "{{ acme_roots_tmp.results | map(attribute='ansible_facts.y__') | list }}"
|
||||
acme_root_certs: "{{ slurp_roots.results | map(attribute='content') | map('b64decode') | list }}"
|
||||
acme_intermediates: "{{ acme_intermediates_tmp.results | map(attribute='ansible_facts.x__') | list }}"
|
||||
acme_intermediate_certs: "{{ acme_intermediates_tmp.results | map(attribute='ansible_facts.y__') | list }}"
|
||||
acme_intermediate_certs: "{{ slurp_intermediates.results | map(attribute='content') | map('b64decode') | list }}"
|
||||
|
||||
vars:
|
||||
types:
|
||||
@@ -88,12 +98,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
assert:
|
||||
that:
|
||||
- "'DNS:example.com' in cert_1_text.stdout"
|
||||
- name: Read certificate 1 files
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/{{ item }}'
|
||||
loop:
|
||||
- cert-1.pem
|
||||
- cert-1-chain.pem
|
||||
- cert-1-fullchain.pem
|
||||
register: slurp
|
||||
- name: Check that certificate 1 retrieval got all chains
|
||||
assert:
|
||||
that:
|
||||
@@ -15,9 +23,9 @@
|
||||
- "'cert' in cert_1_obtain_results.all_chains[cert_1_alternate | int]"
|
||||
- "'chain' in cert_1_obtain_results.all_chains[cert_1_alternate | int]"
|
||||
- "'full_chain' in cert_1_obtain_results.all_chains[cert_1_alternate | int]"
|
||||
- "lookup('file', output_dir ~ '/cert-1.pem', rstrip=False) == cert_1_obtain_results.all_chains[cert_1_alternate | int].cert"
|
||||
- "lookup('file', output_dir ~ '/cert-1-chain.pem', rstrip=False) == cert_1_obtain_results.all_chains[cert_1_alternate | int].chain"
|
||||
- "lookup('file', output_dir ~ '/cert-1-fullchain.pem', rstrip=False) == cert_1_obtain_results.all_chains[cert_1_alternate | int].full_chain"
|
||||
- "(slurp.results[0].content | b64decode) == cert_1_obtain_results.all_chains[cert_1_alternate | int].cert"
|
||||
- "(slurp.results[1].content | b64decode) == cert_1_obtain_results.all_chains[cert_1_alternate | int].chain"
|
||||
- "(slurp.results[2].content | b64decode) == cert_1_obtain_results.all_chains[cert_1_alternate | int].full_chain"
|
||||
|
||||
- name: Check that certificate 2 is valid
|
||||
assert:
|
||||
@@ -28,6 +36,14 @@
|
||||
that:
|
||||
- "'DNS:*.example.com' in cert_2_text.stdout"
|
||||
- "'DNS:example.com' in cert_2_text.stdout"
|
||||
- name: Read certificate 2 files
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/{{ item }}'
|
||||
loop:
|
||||
- cert-2.pem
|
||||
- cert-2-chain.pem
|
||||
- cert-2-fullchain.pem
|
||||
register: slurp
|
||||
- name: Check that certificate 1 retrieval got all chains
|
||||
assert:
|
||||
that:
|
||||
@@ -36,9 +52,9 @@
|
||||
- "'cert' in cert_2_obtain_results.all_chains[cert_2_alternate | int]"
|
||||
- "'chain' in cert_2_obtain_results.all_chains[cert_2_alternate | int]"
|
||||
- "'full_chain' in cert_2_obtain_results.all_chains[cert_2_alternate | int]"
|
||||
- "lookup('file', output_dir ~ '/cert-2.pem', rstrip=False) == cert_2_obtain_results.all_chains[cert_2_alternate | int].cert"
|
||||
- "lookup('file', output_dir ~ '/cert-2-chain.pem', rstrip=False) == cert_2_obtain_results.all_chains[cert_2_alternate | int].chain"
|
||||
- "lookup('file', output_dir ~ '/cert-2-fullchain.pem', rstrip=False) == cert_2_obtain_results.all_chains[cert_2_alternate | int].full_chain"
|
||||
- "(slurp.results[0].content | b64decode) == cert_2_obtain_results.all_chains[cert_2_alternate | int].cert"
|
||||
- "(slurp.results[1].content | b64decode) == cert_2_obtain_results.all_chains[cert_2_alternate | int].chain"
|
||||
- "(slurp.results[2].content | b64decode) == cert_2_obtain_results.all_chains[cert_2_alternate | int].full_chain"
|
||||
|
||||
- name: Check that certificate 3 is valid
|
||||
assert:
|
||||
@@ -50,6 +66,14 @@
|
||||
- "'DNS:*.example.com' in cert_3_text.stdout"
|
||||
- "'DNS:example.org' in cert_3_text.stdout"
|
||||
- "'DNS:t1.example.com' in cert_3_text.stdout"
|
||||
- name: Read certificate 3 files
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/{{ item }}'
|
||||
loop:
|
||||
- cert-3.pem
|
||||
- cert-3-chain.pem
|
||||
- cert-3-fullchain.pem
|
||||
register: slurp
|
||||
- name: Check that certificate 1 retrieval got all chains
|
||||
assert:
|
||||
that:
|
||||
@@ -58,9 +82,9 @@
|
||||
- "'cert' in cert_3_obtain_results.all_chains[cert_3_alternate | int]"
|
||||
- "'chain' in cert_3_obtain_results.all_chains[cert_3_alternate | int]"
|
||||
- "'full_chain' in cert_3_obtain_results.all_chains[cert_3_alternate | int]"
|
||||
- "lookup('file', output_dir ~ '/cert-3.pem', rstrip=False) == cert_3_obtain_results.all_chains[cert_3_alternate | int].cert"
|
||||
- "lookup('file', output_dir ~ '/cert-3-chain.pem', rstrip=False) == cert_3_obtain_results.all_chains[cert_3_alternate | int].chain"
|
||||
- "lookup('file', output_dir ~ '/cert-3-fullchain.pem', rstrip=False) == cert_3_obtain_results.all_chains[cert_3_alternate | int].full_chain"
|
||||
- "(slurp.results[0].content | b64decode) == cert_3_obtain_results.all_chains[cert_3_alternate | int].cert"
|
||||
- "(slurp.results[1].content | b64decode) == cert_3_obtain_results.all_chains[cert_3_alternate | int].chain"
|
||||
- "(slurp.results[2].content | b64decode) == cert_3_obtain_results.all_chains[cert_3_alternate | int].full_chain"
|
||||
|
||||
- name: Check that certificate 4 is valid
|
||||
assert:
|
||||
@@ -100,14 +124,38 @@
|
||||
that:
|
||||
- cert_5_recreate_3 == True
|
||||
|
||||
- name: Check that certificate 6 is valid
|
||||
assert:
|
||||
that:
|
||||
- cert_6_valid is not failed
|
||||
- name: Check that certificate 6 contains correct SANs
|
||||
assert:
|
||||
that:
|
||||
- "'DNS:example.org' in cert_6_text.stdout"
|
||||
- block:
|
||||
- name: Check that certificate 6 is valid
|
||||
assert:
|
||||
that:
|
||||
- cert_6_valid is not failed
|
||||
- name: Check that certificate 6 contains correct SANs
|
||||
assert:
|
||||
that:
|
||||
- "'DNS:example.org' in cert_6_text.stdout"
|
||||
when: acme_intermediates[0].subject_key_identifier is defined
|
||||
|
||||
- block:
|
||||
- name: Check that certificate 7 is valid
|
||||
assert:
|
||||
that:
|
||||
- cert_7_valid is not failed
|
||||
- name: Check that certificate 7 contains correct SANs
|
||||
assert:
|
||||
that:
|
||||
- "'IP Address:127.0.0.1' in cert_8_text.stdout or 'IP:127.0.0.1' in cert_8_text.stdout"
|
||||
when: acme_roots[2].subject_key_identifier is defined
|
||||
|
||||
- block:
|
||||
- name: Check that certificate 8 is valid
|
||||
assert:
|
||||
that:
|
||||
- cert_8_valid is not failed
|
||||
- name: Check that certificate 8 contains correct SANs
|
||||
assert:
|
||||
that:
|
||||
- "'IP Address:127.0.0.1' in cert_8_text.stdout or 'IP:127.0.0.1' in cert_8_text.stdout"
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Validate that orders were not retrieved
|
||||
assert:
|
||||
|
||||
@@ -1,2 +1,14 @@
|
||||
shippable/cloud/group1
|
||||
cloud/acme
|
||||
|
||||
# Since skipping below fails miserably with ansible-core 2.11 and earlier, we have to skip all POSIX tests...
|
||||
# (https://github.com/ansible/ansible/issues/75711)
|
||||
# shippable/posix/group1
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
# (TODO: remove when ansible-core 2.12 is the earliest version we support)
|
||||
# skip/aix
|
||||
# skip/freebsd
|
||||
# skip/macos
|
||||
# skip/osx
|
||||
# skip/rhel
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
dependencies:
|
||||
- setup_acme
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- block:
|
||||
- name: Generate account keys
|
||||
openssl_privatekey:
|
||||
path: "{{ output_dir }}/{{ item.name }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/{{ item.name }}.pem"
|
||||
type: "{{ item.type }}"
|
||||
size: "{{ item.size | default(omit) }}"
|
||||
curve: "{{ item.curve | default(omit) }}"
|
||||
@@ -22,6 +22,10 @@
|
||||
type: RSA
|
||||
size: "{{ default_rsa_key_size }}"
|
||||
## CREATE ACCOUNTS AND OBTAIN CERTIFICATES ####################################################
|
||||
- name: Read account key (EC256)
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/account-ec256.pem'
|
||||
register: slurp_account_key
|
||||
- name: Obtain cert 1
|
||||
include_tasks: obtain-cert.yml
|
||||
vars:
|
||||
@@ -31,7 +35,7 @@
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.com"
|
||||
subject_alt_name_critical: no
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/account-ec256.pem') }}"
|
||||
account_key_content: "{{ slurp_account_key.content | b64decode }}"
|
||||
challenge: http-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
@@ -76,8 +80,8 @@
|
||||
- name: Revoke certificate 1 via account key
|
||||
acme_certificate_revoke:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
certificate: "{{ output_dir }}/cert-1.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
certificate: "{{ remote_tmp_dir }}/cert-1.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
@@ -86,19 +90,23 @@
|
||||
- name: Revoke certificate 2 via certificate private key
|
||||
acme_certificate_revoke:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
private_key_src: "{{ output_dir }}/cert-2.key"
|
||||
private_key_src: "{{ remote_tmp_dir }}/cert-2.key"
|
||||
private_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
certificate: "{{ output_dir }}/cert-2.pem"
|
||||
certificate: "{{ remote_tmp_dir }}/cert-2.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
ignore_errors: yes
|
||||
register: cert_2_revoke
|
||||
- name: Read account key (RSA)
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/account-rsa.pem'
|
||||
register: slurp_account_key
|
||||
- name: Revoke certificate 3 via account key (fullchain)
|
||||
acme_certificate_revoke:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_content: "{{ lookup('file', output_dir ~ '/account-rsa.pem') }}"
|
||||
certificate: "{{ output_dir }}/cert-3-fullchain.pem"
|
||||
account_key_content: "{{ slurp_account_key.content | b64decode }}"
|
||||
certificate: "{{ remote_tmp_dir }}/cert-3-fullchain.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1,2 +1,14 @@
|
||||
shippable/cloud/group1
|
||||
cloud/acme
|
||||
|
||||
# Since skipping below fails miserably with ansible-core 2.11 and earlier, we have to skip all POSIX tests...
|
||||
# (https://github.com/ansible/ansible/issues/75711)
|
||||
# shippable/posix/group1
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
# (TODO: remove when ansible-core 2.12 is the earliest version we support)
|
||||
# skip/aix
|
||||
# skip/freebsd
|
||||
# skip/macos
|
||||
# skip/osx
|
||||
# skip/rhel
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
dependencies:
|
||||
- setup_acme
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
- block:
|
||||
- name: Generate ECC256 accoun keys
|
||||
openssl_privatekey:
|
||||
path: "{{ output_dir }}/account-ec256.pem"
|
||||
path: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
type: ECC
|
||||
curve: secp256r1
|
||||
force: true
|
||||
@@ -31,4 +31,4 @@
|
||||
terms_agreed: yes
|
||||
account_email: "example@example.org"
|
||||
|
||||
when: openssl_version.stdout is version('1.0.0', '>=') or cryptography_version.stdout is version('1.5', '>=')
|
||||
when: cryptography_version.stdout is version('1.5', '>=')
|
||||
|
||||
@@ -1,2 +1,14 @@
|
||||
shippable/cloud/group1
|
||||
cloud/acme
|
||||
|
||||
# Since skipping below fails miserably with ansible-core 2.11 and earlier, we have to skip all POSIX tests...
|
||||
# (https://github.com/ansible/ansible/issues/75711)
|
||||
# shippable/posix/group1
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
# (TODO: remove when ansible-core 2.12 is the earliest version we support)
|
||||
# skip/aix
|
||||
# skip/freebsd
|
||||
# skip/macos
|
||||
# skip/osx
|
||||
# skip/rhel
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
dependencies:
|
||||
- setup_acme
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
- block:
|
||||
- name: Generate account keys
|
||||
openssl_privatekey:
|
||||
path: "{{ output_dir }}/{{ item }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/{{ item }}.pem"
|
||||
type: ECC
|
||||
curve: secp256r1
|
||||
force: true
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
- name: Parse account keys (to ease debugging some test failures)
|
||||
openssl_privatekey_info:
|
||||
path: "{{ output_dir }}/{{ item }}.pem"
|
||||
path: "{{ remote_tmp_dir }}/{{ item }}.pem"
|
||||
return_private_key_data: true
|
||||
loop: "{{ account_keys }}"
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
url: "{{ directory.directory.newAccount}}"
|
||||
method: post
|
||||
content: '{"termsOfServiceAgreed":true}'
|
||||
@@ -46,7 +46,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ account_creation.headers.location }}"
|
||||
method: get
|
||||
@@ -58,7 +58,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ account_creation.headers.location }}"
|
||||
method: post
|
||||
@@ -77,7 +77,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ directory.directory.newOrder }}"
|
||||
method: post
|
||||
@@ -100,7 +100,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ new_order.headers.location }}"
|
||||
method: get
|
||||
@@ -112,7 +112,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ item }}"
|
||||
method: get
|
||||
@@ -125,7 +125,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ (item.challenges | selectattr('type', 'equalto', 'http-01') | list)[0].url }}"
|
||||
method: get
|
||||
@@ -138,7 +138,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ item.url }}"
|
||||
method: post
|
||||
@@ -152,7 +152,7 @@
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
account_key_src: "{{ output_dir }}/accountkey.pem"
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ item.url }}"
|
||||
method: get
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: register cryptography version
|
||||
command: '{{ ansible_python.executable }} -c ''import cryptography; print(cryptography.__version__)'''
|
||||
register: cryptography_version
|
||||
- block:
|
||||
- name: Make sure testhost directory exists
|
||||
file:
|
||||
@@ -16,10 +13,9 @@
|
||||
copy:
|
||||
src: '{{ role_path }}/files/'
|
||||
dest: '{{ remote_tmp_dir }}/files/'
|
||||
remote_src: yes
|
||||
- name: Find root for cert 1
|
||||
certificate_complete_chain:
|
||||
input_chain: '{{ lookup(''file'', ''cert1-fullchain.pem'', rstrip=False) }}'
|
||||
input_chain: '{{ lookup("file", "cert1-fullchain.pem", rstrip=False) }}'
|
||||
root_certificates:
|
||||
- '{{ remote_tmp_dir }}/files/roots/'
|
||||
register: cert1_root
|
||||
@@ -30,7 +26,7 @@
|
||||
- cert1_root.root == lookup('file', 'cert1-root.pem', rstrip=False)
|
||||
- name: Find rootchain for cert 1
|
||||
certificate_complete_chain:
|
||||
input_chain: '{{ lookup(''file'', ''cert1.pem'', rstrip=False) }}'
|
||||
input_chain: '{{ lookup("file", "cert1.pem", rstrip=False) }}'
|
||||
intermediate_certificates:
|
||||
- '{{ remote_tmp_dir }}/files/cert1-chain.pem'
|
||||
root_certificates:
|
||||
@@ -44,7 +40,7 @@
|
||||
- cert1_rootchain.root == lookup('file', 'cert1-root.pem', rstrip=False)
|
||||
- name: Find root for cert 2
|
||||
certificate_complete_chain:
|
||||
input_chain: '{{ lookup(''file'', ''cert2-fullchain.pem'', rstrip=False) }}'
|
||||
input_chain: '{{ lookup("file", "cert2-fullchain.pem", rstrip=False) }}'
|
||||
root_certificates:
|
||||
- '{{ remote_tmp_dir }}/files/roots/'
|
||||
register: cert2_root
|
||||
@@ -55,7 +51,7 @@
|
||||
- cert2_root.root == lookup('file', 'cert2-root.pem', rstrip=False)
|
||||
- name: Find rootchain for cert 2
|
||||
certificate_complete_chain:
|
||||
input_chain: '{{ lookup(''file'', ''cert2.pem'', rstrip=False) }}'
|
||||
input_chain: '{{ lookup("file", "cert2.pem", rstrip=False) }}'
|
||||
intermediate_certificates:
|
||||
- '{{ remote_tmp_dir }}/files/cert2-chain.pem'
|
||||
root_certificates:
|
||||
@@ -69,7 +65,7 @@
|
||||
- cert2_rootchain.root == lookup('file', 'cert2-root.pem', rstrip=False)
|
||||
- name: Find alternate rootchain for cert 2
|
||||
certificate_complete_chain:
|
||||
input_chain: '{{ lookup(''file'', ''cert2.pem'', rstrip=True) }}'
|
||||
input_chain: '{{ lookup("file", "cert2.pem", rstrip=True) }}'
|
||||
intermediate_certificates:
|
||||
- '{{ remote_tmp_dir }}/files/cert2-altchain.pem'
|
||||
root_certificates:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
needs/httptester
|
||||
|
||||
@@ -4,16 +4,35 @@
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- set_fact:
|
||||
skip_tests: false
|
||||
|
||||
- block:
|
||||
|
||||
- name: Get servers certificate with backend auto-detection
|
||||
get_certificate:
|
||||
host: "{{ httpbin_host }}"
|
||||
port: 443
|
||||
ignore_errors: true
|
||||
register: result
|
||||
|
||||
- set_fact:
|
||||
skip_tests: |
|
||||
{{
|
||||
result is failed and (
|
||||
'error: [Errno 1] _ssl.c:492: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure' in result.msg
|
||||
or
|
||||
'error: _ssl.c:314: Invalid SSL protocol variant specified.' in result.msg
|
||||
)
|
||||
}}
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is success or skip_tests
|
||||
|
||||
when: |
|
||||
pyopenssl_version.stdout is version('0.15', '>=') or
|
||||
(cryptography_version.stdout is version('1.6', '>=') and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6))
|
||||
cryptography_version.stdout is version('1.6', '>=')
|
||||
|
||||
- block:
|
||||
|
||||
@@ -21,17 +40,7 @@
|
||||
vars:
|
||||
select_crypto_backend: pyopenssl
|
||||
|
||||
when: pyopenssl_version.stdout is version('0.15', '>=')
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
state: directory
|
||||
when: pyopenssl_version.stdout is version('0.15', '>=') and not skip_tests
|
||||
|
||||
- block:
|
||||
|
||||
@@ -42,6 +51,4 @@
|
||||
# The module doesn't work with CentOS 6. Since the pyOpenSSL installed there is too old,
|
||||
# we never noticed before. This becomes a problem with the new cryptography backend,
|
||||
# since there is a new enough cryptography version...
|
||||
when: |
|
||||
cryptography_version.stdout is version('1.6', '>=') and
|
||||
(ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
|
||||
when: cryptography_version.stdout is version('1.6', '>=') and not skip_tests
|
||||
|
||||
@@ -97,14 +97,19 @@
|
||||
# We got the correct response from the module
|
||||
- "'ca_cert file does not exist' == result.msg"
|
||||
|
||||
- name: Get a temp directory
|
||||
tempfile:
|
||||
state: directory
|
||||
register: my_temp_dir
|
||||
|
||||
- name: Download CA Cert as pem from server
|
||||
get_url:
|
||||
url: "http://ansible.http.tests/cacert.pem"
|
||||
dest: "{{ output_dir }}/temp.pem"
|
||||
dest: "{{ my_temp_dir.path }}/temp.pem"
|
||||
|
||||
- name: Get servers certificate comparing it to its own ca_cert file
|
||||
get_certificate:
|
||||
ca_cert: '{{ output_dir }}/temp.pem'
|
||||
ca_cert: '{{ my_temp_dir.path }}/temp.pem'
|
||||
host: "{{ httpbin_host }}"
|
||||
port: 443
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
@@ -115,11 +120,6 @@
|
||||
- result is not changed
|
||||
- result is not failed
|
||||
|
||||
- name: Get a temp directory
|
||||
tempfile:
|
||||
state: directory
|
||||
register: my_temp_dir
|
||||
|
||||
- name: Deploy the bogus_ca.pem file
|
||||
copy:
|
||||
src: "bogus_ca.pem"
|
||||
|
||||
2
tests/integration/targets/luks_device/meta/main.yml
Normal file
2
tests/integration/targets/luks_device/meta/main.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
dependencies:
|
||||
- setup_remote_tmp_dir
|
||||
@@ -4,18 +4,25 @@
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Copy keyfiles
|
||||
copy:
|
||||
src: '{{ item }}'
|
||||
dest: '{{ remote_tmp_dir }}/{{ item }}'
|
||||
loop:
|
||||
- keyfile1
|
||||
- keyfile2
|
||||
- name: Make sure cryptsetup is installed
|
||||
package:
|
||||
name: cryptsetup
|
||||
state: present
|
||||
become: yes
|
||||
- name: Create cryptfile
|
||||
command: dd if=/dev/zero of={{ output_dir.replace('~', ansible_env.HOME) }}/cryptfile bs=1M count=32
|
||||
command: dd if=/dev/zero of={{ remote_tmp_dir.replace('~', ansible_env.HOME) }}/cryptfile bs=1M count=32
|
||||
- name: Create lookback device
|
||||
command: losetup -f {{ output_dir.replace('~', ansible_env.HOME) }}/cryptfile
|
||||
command: losetup -f {{ remote_tmp_dir.replace('~', ansible_env.HOME) }}/cryptfile
|
||||
become: yes
|
||||
- name: Determine loop device name
|
||||
command: losetup -j {{ output_dir.replace('~', ansible_env.HOME) }}/cryptfile --output name
|
||||
command: losetup -j {{ remote_tmp_dir.replace('~', ansible_env.HOME) }}/cryptfile --output name
|
||||
become: yes
|
||||
register: cryptfile_device_output
|
||||
- set_fact:
|
||||
@@ -37,5 +44,5 @@
|
||||
- command: losetup -d "{{ cryptfile_device }}"
|
||||
become: yes
|
||||
- file:
|
||||
dest: "{{ output_dir }}/cryptfile"
|
||||
dest: "{{ remote_tmp_dir }}/cryptfile"
|
||||
state: absent
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
@@ -13,7 +13,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
@@ -22,7 +22,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
@@ -31,7 +31,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
@@ -48,7 +48,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
check_mode: yes
|
||||
become: yes
|
||||
register: open_check
|
||||
@@ -56,21 +56,21 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
register: open
|
||||
- name: Open (idempotent)
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
register: open_idem
|
||||
- name: Open (idempotent, check)
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
check_mode: yes
|
||||
become: yes
|
||||
register: open_idem_check
|
||||
@@ -118,7 +118,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
|
||||
- name: Closed (via device, check)
|
||||
@@ -158,7 +158,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
|
||||
- name: Absent (check)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
luks_device:
|
||||
device: /dev/asdfasdfasdf
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
@@ -14,7 +14,7 @@
|
||||
luks_device:
|
||||
device: /dev/asdfasdfasdf
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
ignore_errors: yes
|
||||
@@ -31,7 +31,7 @@
|
||||
luks_device:
|
||||
device: /tmp/
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
check_mode: yes
|
||||
@@ -42,7 +42,7 @@
|
||||
luks_device:
|
||||
device: /tmp/
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
ignore_errors: yes
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
@@ -14,7 +14,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -31,7 +31,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -43,8 +43,8 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
new_keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
new_keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
@@ -54,8 +54,8 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
new_keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
new_keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
become: yes
|
||||
register: result_2
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -91,8 +91,8 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
remove_keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
remove_keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
register: result_1
|
||||
|
||||
@@ -100,8 +100,8 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
remove_keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
remove_keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
register: result_2
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -128,7 +128,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -149,8 +149,8 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile2"
|
||||
remove_keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
remove_keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: remove_last_key
|
||||
@@ -165,7 +165,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -182,8 +182,8 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile2"
|
||||
remove_keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
remove_keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
force_remove_last_key: yes
|
||||
become: yes
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile2"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile2"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
keysize: 256
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
@@ -13,7 +13,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
keysize: 256
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
@@ -23,7 +23,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
keysize: 512
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
@@ -33,7 +33,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: present
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
pbkdf:
|
||||
iteration_count: 1000
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
state: closed
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
new_passphrase: "{{ cryptfile_passphrase2 }}"
|
||||
new_keyfile: "{{ role_path }}/files/keyfile1"
|
||||
new_keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
@@ -122,7 +122,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -135,7 +135,7 @@
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
new_keyfile: "{{ role_path }}/files/keyfile1"
|
||||
new_keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
become: yes
|
||||
@@ -144,7 +144,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
remove_keyfile: "{{ role_path }}/files/keyfile1"
|
||||
remove_keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
remove_passphrase: "{{ cryptfile_passphrase1 }}"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
@@ -157,7 +157,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: opened
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
become: yes
|
||||
ignore_errors: yes
|
||||
register: open_try
|
||||
@@ -219,7 +219,7 @@
|
||||
luks_device:
|
||||
device: "{{ cryptfile_device }}"
|
||||
state: closed
|
||||
keyfile: "{{ role_path }}/files/keyfile1"
|
||||
keyfile: "{{ remote_tmp_dir }}/keyfile1"
|
||||
new_passphrase: "{{ cryptfile_passphrase3 }}"
|
||||
pbkdf:
|
||||
iteration_time: 0.1
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
dependencies:
|
||||
- setup_ssh_keygen
|
||||
- setup_ssh_agent
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
- name: Declare global variables
|
||||
set_fact:
|
||||
signing_key: '{{ output_dir }}/id_key'
|
||||
public_key: '{{ output_dir }}/id_key.pub'
|
||||
certificate_path: '{{ output_dir }}/id_cert'
|
||||
signing_key: '{{ remote_tmp_dir }}/id_key'
|
||||
public_key: '{{ remote_tmp_dir }}/id_key.pub'
|
||||
certificate_path: '{{ remote_tmp_dir }}/id_cert'
|
||||
|
||||
- name: Generate keypair
|
||||
openssh_keypair:
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
####################################################################
|
||||
|
||||
- set_fact:
|
||||
new_signing_key: "{{ output_dir }}/new_key"
|
||||
new_public_key: "{{ output_dir }}/new_key.pub"
|
||||
new_signing_key: "{{ remote_tmp_dir }}/new_key"
|
||||
new_public_key: "{{ remote_tmp_dir }}/new_key.pub"
|
||||
|
||||
- name: Generate new test key
|
||||
openssh_keypair:
|
||||
@@ -20,6 +20,81 @@
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
|
||||
- block:
|
||||
- name: Generate cert with updated signature algorithm
|
||||
openssh_cert:
|
||||
type: user
|
||||
path: "{{ certificate_path }}"
|
||||
public_key: "{{ public_key }}"
|
||||
signing_key: "{{ signing_key }}"
|
||||
signature_algorithm: rsa-sha2-256
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
register: updated_signature_algorithm
|
||||
|
||||
- name: Assert signature algorithm update causes change
|
||||
assert:
|
||||
that:
|
||||
- updated_signature_algorithm is changed
|
||||
|
||||
- name: Generate cert with updated signature algorithm (idempotent)
|
||||
openssh_cert:
|
||||
type: user
|
||||
path: "{{ certificate_path }}"
|
||||
public_key: "{{ public_key }}"
|
||||
signing_key: "{{ signing_key }}"
|
||||
signature_algorithm: rsa-sha2-256
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
register: updated_signature_algorithm_idempotent
|
||||
|
||||
- name: Assert signature algorithm update is idempotent
|
||||
assert:
|
||||
that:
|
||||
- updated_signature_algorithm_idempotent is not changed
|
||||
|
||||
- name: Generate cert with original signature algorithm
|
||||
openssh_cert:
|
||||
type: user
|
||||
path: "{{ certificate_path }}"
|
||||
public_key: "{{ public_key }}"
|
||||
signing_key: "{{ signing_key }}"
|
||||
signature_algorithm: ssh-rsa
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
register: second_signature_algorithm
|
||||
|
||||
- name: Assert second signature algorithm update causes change
|
||||
assert:
|
||||
that:
|
||||
- second_signature_algorithm is changed
|
||||
|
||||
- name: Omit signature algorithm
|
||||
openssh_cert:
|
||||
type: user
|
||||
path: "{{ certificate_path }}"
|
||||
public_key: "{{ public_key }}"
|
||||
signing_key: "{{ signing_key }}"
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
register: omitted_signature_algorithm
|
||||
|
||||
- name: Assert omitted_signature_algorithm does not cause change
|
||||
assert:
|
||||
that:
|
||||
- omitted_signature_algorithm is not changed
|
||||
|
||||
- name: Revert to original certificate
|
||||
openssh_cert:
|
||||
type: user
|
||||
path: "{{ certificate_path }}"
|
||||
public_key: "{{ public_key }}"
|
||||
signing_key: "{{ signing_key }}"
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
regenerate: always
|
||||
when: openssh_version is version("7.3", ">=")
|
||||
|
||||
- name: Generate cert with new signing key
|
||||
openssh_cert:
|
||||
type: user
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
type: user
|
||||
signing_key: "{{ signing_key }}"
|
||||
public_key: "{{ public_key }}"
|
||||
path: '{{ output_dir }}/id_cert_with_agent'
|
||||
path: '{{ remote_tmp_dir }}/id_cert_with_agent'
|
||||
use_agent: true
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
@@ -33,7 +33,7 @@
|
||||
type: user
|
||||
signing_key: "{{ signing_key }}"
|
||||
public_key: "{{ public_key }}"
|
||||
path: '{{ output_dir }}/id_cert_with_agent'
|
||||
path: '{{ remote_tmp_dir }}/id_cert_with_agent'
|
||||
use_agent: true
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
@@ -44,7 +44,7 @@
|
||||
type: user
|
||||
signing_key: "{{ signing_key }}"
|
||||
public_key: "{{ public_key }}"
|
||||
path: '{{ output_dir }}/id_cert_with_agent'
|
||||
path: '{{ remote_tmp_dir }}/id_cert_with_agent'
|
||||
use_agent: true
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
@@ -54,7 +54,7 @@
|
||||
type: user
|
||||
signing_key: "{{ signing_key }}"
|
||||
public_key: "{{ public_key }}"
|
||||
path: '{{ output_dir }}/id_cert_with_agent'
|
||||
path: '{{ remote_tmp_dir }}/id_cert_with_agent'
|
||||
use_agent: true
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
@@ -71,7 +71,7 @@
|
||||
type: user
|
||||
signing_key: "{{ signing_key }}"
|
||||
public_key: "{{ public_key }}"
|
||||
path: '{{ output_dir }}/id_cert_with_agent'
|
||||
path: '{{ remote_tmp_dir }}/id_cert_with_agent'
|
||||
use_agent: true
|
||||
valid_from: always
|
||||
valid_to: forever
|
||||
@@ -80,4 +80,4 @@
|
||||
- name: Remove certificate
|
||||
openssh_cert:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/id_cert_with_agent'
|
||||
path: '{{ remote_tmp_dir }}/id_cert_with_agent'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
dependencies:
|
||||
- setup_ssh_keygen
|
||||
- setup_openssl
|
||||
- setup_bcrypt
|
||||
- setup_bcrypt
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- name: Backend auto-detection test
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/auto_backend_key'
|
||||
path: '{{ remote_tmp_dir }}/auto_backend_key'
|
||||
state: "{{ item }}"
|
||||
loop: ['present', 'absent']
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- name: "({{ backend }}) Generate key (check mode)"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/core"
|
||||
path: "{{ remote_tmp_dir }}/core"
|
||||
size: 2048
|
||||
backend: "{{ backend }}"
|
||||
register: check_core_output
|
||||
@@ -14,14 +14,14 @@
|
||||
|
||||
- name: "({{ backend }}) Generate key"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/core"
|
||||
path: "{{ remote_tmp_dir }}/core"
|
||||
size: 2048
|
||||
backend: "{{ backend }}"
|
||||
register: core_output
|
||||
|
||||
- name: "({{ backend }}) Generate key (check mode idempotent)"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/core"
|
||||
path: "{{ remote_tmp_dir }}/core"
|
||||
size: 2048
|
||||
backend: "{{ backend }}"
|
||||
register: idempotency_check_core_output
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
- name: "({{ backend }}) Generate key (idempotent)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/core'
|
||||
path: '{{ remote_tmp_dir }}/core'
|
||||
size: 2048
|
||||
backend: "{{ backend }}"
|
||||
register: idempotency_core_output
|
||||
@@ -52,8 +52,8 @@
|
||||
that:
|
||||
- core_output['fingerprint'] is string
|
||||
- core_output['fingerprint'].startswith('SHA256:')
|
||||
# only distro old enough that it still gives md5 with no prefix
|
||||
when: not (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6')
|
||||
# SHA256 was made the default hashing algorithm for fingerprints in OpenSSH 6.8
|
||||
when: not (backend == 'opensshbin' and openssh_version is version('6.8', '<'))
|
||||
|
||||
- name: "({{ backend }}) Assert key returns public_key"
|
||||
assert:
|
||||
@@ -74,7 +74,7 @@
|
||||
- core_output['type'] == 'rsa'
|
||||
|
||||
- name: "({{ backend }}) Retrieve key size from 'ssh-keygen'"
|
||||
shell: "ssh-keygen -lf {{ output_dir }}/core | grep -o -E '^[0-9]+'"
|
||||
shell: "ssh-keygen -lf {{ remote_tmp_dir }}/core | grep -o -E '^[0-9]+'"
|
||||
register: core_size_ssh_keygen
|
||||
|
||||
- name: "({{ backend }}) Assert key size matches 'ssh-keygen' output"
|
||||
@@ -82,13 +82,18 @@
|
||||
that:
|
||||
- core_size_ssh_keygen.stdout == '2048'
|
||||
|
||||
- name: "({{ backend }}) Read core.pub"
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/core.pub'
|
||||
register: slurp
|
||||
|
||||
- name: "({{ backend }}) Assert public key module return equal to the public key content"
|
||||
assert:
|
||||
that:
|
||||
- "core_output.public_key == lookup('file', output_dir ~ '/core.pub').strip('\n')"
|
||||
- "core_output.public_key == (slurp.content | b64decode).strip('\n ')"
|
||||
|
||||
- name: "({{ backend }}) Remove key"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/core'
|
||||
path: '{{ remote_tmp_dir }}/core'
|
||||
backend: "{{ backend }}"
|
||||
state: absent
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
- name: Generate a password protected key
|
||||
command: 'ssh-keygen -f {{ output_dir }}/password_protected -N {{ passphrase }}'
|
||||
command: 'ssh-keygen -f {{ remote_tmp_dir }}/password_protected -N {{ passphrase }}'
|
||||
|
||||
- name: Modify the password protected key with passphrase
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/password_protected'
|
||||
path: '{{ remote_tmp_dir }}/password_protected'
|
||||
size: 1024
|
||||
passphrase: "{{ passphrase }}"
|
||||
backend: cryptography
|
||||
@@ -12,14 +12,14 @@
|
||||
|
||||
- name: Check password protected key idempotency
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/password_protected'
|
||||
path: '{{ remote_tmp_dir }}/password_protected'
|
||||
size: 1024
|
||||
passphrase: "{{ passphrase }}"
|
||||
backend: cryptography
|
||||
register: password_protected_idempotency_output
|
||||
|
||||
- name: Ensure that ssh-keygen can read keys generated with passphrase
|
||||
command: 'ssh-keygen -yf {{ output_dir }}/password_protected -P {{ passphrase }}'
|
||||
command: 'ssh-keygen -yf {{ remote_tmp_dir }}/password_protected -P {{ passphrase }}'
|
||||
register: password_protected_ssh_keygen_output
|
||||
|
||||
- name: Check that password protected key with passphrase was regenerated
|
||||
@@ -31,18 +31,18 @@
|
||||
|
||||
- name: Remove password protected key
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/password_protected'
|
||||
path: '{{ remote_tmp_dir }}/password_protected'
|
||||
backend: cryptography
|
||||
state: absent
|
||||
|
||||
- name: Generate an unprotected key
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/unprotected'
|
||||
path: '{{ remote_tmp_dir }}/unprotected'
|
||||
backend: cryptography
|
||||
|
||||
- name: Modify unprotected key with passphrase
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/unprotected'
|
||||
path: '{{ remote_tmp_dir }}/unprotected'
|
||||
size: 2048
|
||||
passphrase: "{{ passphrase }}"
|
||||
backend: cryptography
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
- name: Modify unprotected key with passphrase (force)
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/unprotected'
|
||||
path: '{{ remote_tmp_dir }}/unprotected'
|
||||
size: 2048
|
||||
passphrase: "{{ passphrase }}"
|
||||
force: true
|
||||
@@ -66,16 +66,16 @@
|
||||
|
||||
- name: Remove unprotected key
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/unprotected'
|
||||
path: '{{ remote_tmp_dir }}/unprotected'
|
||||
backend: cryptography
|
||||
state: absent
|
||||
|
||||
- name: Generate PEM encoded key with passphrase
|
||||
command: 'ssh-keygen -b 4096 -f {{ output_dir }}/pem_encoded -N {{ passphrase }} -m PEM'
|
||||
command: 'ssh-keygen -b 4096 -f {{ remote_tmp_dir }}/pem_encoded -N {{ passphrase }} -m PEM'
|
||||
|
||||
- name: Try to verify a PEM encoded key
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/pem_encoded'
|
||||
path: '{{ remote_tmp_dir }}/pem_encoded'
|
||||
passphrase: "{{ passphrase }}"
|
||||
backend: cryptography
|
||||
register: pem_encoded_output
|
||||
@@ -87,6 +87,6 @@
|
||||
|
||||
- name: Remove PEM encoded key
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/pem_encoded'
|
||||
path: '{{ remote_tmp_dir }}/pem_encoded'
|
||||
backend: cryptography
|
||||
state: absent
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
content: ''
|
||||
mode: '0700'
|
||||
loop:
|
||||
- "{{ output_dir }}/broken"
|
||||
- "{{ output_dir }}/broken.pub"
|
||||
- "{{ remote_tmp_dir }}/broken"
|
||||
- "{{ remote_tmp_dir }}/broken.pub"
|
||||
|
||||
- name: "({{ backend }}) Regenerate key - broken"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/broken"
|
||||
path: "{{ remote_tmp_dir }}/broken"
|
||||
backend: "{{ backend }}"
|
||||
register: broken_output
|
||||
ignore_errors: true
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate key with force - broken"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/broken"
|
||||
path: "{{ remote_tmp_dir }}/broken"
|
||||
backend: "{{ backend }}"
|
||||
force: true
|
||||
register: force_broken_output
|
||||
@@ -40,24 +40,24 @@
|
||||
|
||||
- name: "({{ backend }}) Remove key - broken"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/broken"
|
||||
path: "{{ remote_tmp_dir }}/broken"
|
||||
backend: "{{ backend }}"
|
||||
state: absent
|
||||
|
||||
- name: "({{ backend }}) Generate key - write-only"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/write-only"
|
||||
path: "{{ remote_tmp_dir }}/write-only"
|
||||
mode: "0200"
|
||||
backend: "{{ backend }}"
|
||||
|
||||
- name: "({{ backend }}) Check private key status - write-only"
|
||||
stat:
|
||||
path: '{{ output_dir }}/write-only'
|
||||
path: '{{ remote_tmp_dir }}/write-only'
|
||||
register: write_only_private_key
|
||||
|
||||
- name: "({{ backend }}) Check public key status - write-only"
|
||||
stat:
|
||||
path: '{{ output_dir }}/write-only.pub'
|
||||
path: '{{ remote_tmp_dir }}/write-only.pub'
|
||||
register: write_only_public_key
|
||||
|
||||
- name: "({{ backend }}) Assert that private and public keys match permissions - write-only"
|
||||
@@ -68,14 +68,14 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate key with force - write-only"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/write-only"
|
||||
path: "{{ remote_tmp_dir }}/write-only"
|
||||
backend: "{{ backend }}"
|
||||
force: true
|
||||
register: write_only_output
|
||||
|
||||
- name: "({{ backend }}) Check private key status after regeneration - write-only"
|
||||
stat:
|
||||
path: '{{ output_dir }}/write-only'
|
||||
path: '{{ remote_tmp_dir }}/write-only'
|
||||
register: write_only_private_key_after
|
||||
|
||||
- name: "({{ backend }}) Assert key is regenerated - write-only"
|
||||
@@ -87,26 +87,19 @@
|
||||
assert:
|
||||
that:
|
||||
- write_only_private_key_after.stat.mode == '0200'
|
||||
when: backend == 'opensshbin'
|
||||
|
||||
- name: "({{ backend }}) Assert key permissions are not preserved with 'cryptography'"
|
||||
assert:
|
||||
that:
|
||||
- write_only_private_key_after.stat.mode == '0600'
|
||||
when: backend == 'cryptography'
|
||||
|
||||
- name: "({{ backend }}) Remove key - write-only"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/write-only"
|
||||
path: "{{ remote_tmp_dir }}/write-only"
|
||||
backend: "{{ backend }}"
|
||||
state: absent
|
||||
|
||||
- name: "({{ backend }}) Generate key with ssh-keygen - password_protected"
|
||||
command: "ssh-keygen -f {{ output_dir }}/password_protected -N {{ passphrase }}"
|
||||
command: "ssh-keygen -f {{ remote_tmp_dir }}/password_protected -N {{ passphrase }}"
|
||||
|
||||
- name: "({{ backend }}) Modify key - password_protected"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/password_protected"
|
||||
path: "{{ remote_tmp_dir }}/password_protected"
|
||||
size: 2048
|
||||
backend: "{{ backend }}"
|
||||
register: password_protected_output
|
||||
@@ -120,7 +113,7 @@
|
||||
|
||||
- name: "({{ backend }}) Modify key with 'force=true' - password_protected"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/password_protected"
|
||||
path: "{{ remote_tmp_dir }}/password_protected"
|
||||
size: 2048
|
||||
backend: "{{ backend }}"
|
||||
force: true
|
||||
@@ -133,6 +126,6 @@
|
||||
|
||||
- name: "({{ backend }}) Remove key - password_protected"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/password_protected"
|
||||
path: "{{ remote_tmp_dir }}/password_protected"
|
||||
backend: "{{ backend }}"
|
||||
state: absent
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
- name: "({{ backend }}) Generate keys with default size - size"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/default_size_{{ item }}"
|
||||
path: "{{ remote_tmp_dir }}/default_size_{{ item }}"
|
||||
type: "{{ item }}"
|
||||
backend: "{{ backend }}"
|
||||
loop: "{{ key_types }}"
|
||||
|
||||
- name: "({{ backend }}) Retrieve key size from 'ssh-keygen' - size"
|
||||
shell: "ssh-keygen -lf {{ output_dir }}/default_size_{{ item }} | grep -o -E '^[0-9]+'"
|
||||
shell: "ssh-keygen -lf {{ remote_tmp_dir }}/default_size_{{ item }} | grep -o -E '^[0-9]+'"
|
||||
loop: "{{ key_types }}"
|
||||
register: key_size_output
|
||||
|
||||
@@ -31,19 +31,19 @@
|
||||
|
||||
- name: "({{ backend }}) Remove keys - size"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/default_size_{{ item }}"
|
||||
path: "{{ remote_tmp_dir }}/default_size_{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ key_types }}"
|
||||
|
||||
- block:
|
||||
- name: "({{ backend }}) Generate ed25519 key with default size - size"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/default_size_ed25519"
|
||||
path: "{{ remote_tmp_dir }}/default_size_ed25519"
|
||||
type: ed25519
|
||||
backend: "{{ backend }}"
|
||||
|
||||
- name: "({{ backend }}) Retrieve ed25519 key size from 'ssh-keygen' - size"
|
||||
shell: "ssh-keygen -lf {{ output_dir }}/default_size_ed25519 | grep -o -E '^[0-9]+'"
|
||||
shell: "ssh-keygen -lf {{ remote_tmp_dir }}/default_size_ed25519 | grep -o -E '^[0-9]+'"
|
||||
register: ed25519_key_size_output
|
||||
|
||||
- name: "({{ backend }}) Assert ed25519 key size matches default size - size"
|
||||
@@ -53,19 +53,20 @@
|
||||
|
||||
- name: "({{ backend }}) Remove ed25519 key - size"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/default_size_ed25519"
|
||||
path: "{{ remote_tmp_dir }}/default_size_ed25519"
|
||||
state: absent
|
||||
when: not (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6')
|
||||
# Support for ed25519 keys was added in OpenSSH 6.5
|
||||
when: not (backend == 'opensshbin' and openssh_version is version('6.5', '<'))
|
||||
|
||||
- name: "({{ backend }}) Generate key - force"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/force"
|
||||
path: "{{ remote_tmp_dir }}/force"
|
||||
type: rsa
|
||||
backend: "{{ backend }}"
|
||||
|
||||
- name: "({{ backend }}) Regenerate key - force"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/force"
|
||||
path: "{{ remote_tmp_dir }}/force"
|
||||
type: rsa
|
||||
force: true
|
||||
backend: "{{ backend }}"
|
||||
@@ -78,33 +79,39 @@
|
||||
|
||||
- name: "({{ backend }}) Remove key - force"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/force"
|
||||
path: "{{ remote_tmp_dir }}/force"
|
||||
state: absent
|
||||
backend: "{{ backend }}"
|
||||
|
||||
- name: "({{ backend }}) Generate key - comment"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/comment"
|
||||
path: "{{ remote_tmp_dir }}/comment"
|
||||
comment: "test@comment"
|
||||
backend: "{{ backend }}"
|
||||
register: comment_output
|
||||
|
||||
- name: "({{ backend }}) Modify comment - comment"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/comment"
|
||||
path: "{{ remote_tmp_dir }}/comment"
|
||||
comment: "test_modified@comment"
|
||||
backend: "{{ backend }}"
|
||||
register: modified_comment_output
|
||||
|
||||
- name: "({{ backend }}) Assert only comment changed - comment"
|
||||
- name: "({{ backend }}) Assert comment preserved public key - comment"
|
||||
assert:
|
||||
that:
|
||||
- comment_output.public_key == modified_comment_output.public_key
|
||||
- comment_output.comment == 'test@comment'
|
||||
|
||||
- name: "({{ backend }}) Assert comment changed - comment"
|
||||
assert:
|
||||
that:
|
||||
- modified_comment_output.comment == 'test_modified@comment'
|
||||
# Support for updating comments for key types other than rsa1 was added in OpenSSH 7.2
|
||||
when: not (backend == 'opensshbin' and openssh_version is version('7.2', '<'))
|
||||
|
||||
- name: "({{ backend }}) Remove key - comment"
|
||||
openssh_keypair:
|
||||
path: "{{ output_dir }}/comment"
|
||||
path: "{{ remote_tmp_dir }}/comment"
|
||||
state: absent
|
||||
backend: "{{ backend }}"
|
||||
|
||||
@@ -5,27 +5,33 @@
|
||||
####################################################################
|
||||
|
||||
# Ensures no conflicts from previous test runs
|
||||
- name: "({{ backend }}) Find old test artifacts"
|
||||
ansible.builtin.find:
|
||||
paths: "{{ remote_tmp_dir }}"
|
||||
patterns:
|
||||
- "regenerate*"
|
||||
register: old_test_artifacts
|
||||
|
||||
- name: "({{ backend }}) Cleanup Output Directory"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
path: "{{ item.path }}"
|
||||
state: absent
|
||||
with_fileglob:
|
||||
- "{{ output_dir }}/regenerate*"
|
||||
loop: "{{ old_test_artifacts.files }}"
|
||||
|
||||
- name: "({{ backend }}) Regenerate - setup simple keys"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
backend: "{{ backend }}"
|
||||
loop: "{{ regenerate_values }}"
|
||||
- name: "({{ backend }}) Regenerate - setup password protected keys"
|
||||
command: 'ssh-keygen -f {{ output_dir }}/regenerate-b-{{ item }} -N {{ passphrase }}'
|
||||
command: 'ssh-keygen -f {{ remote_tmp_dir }}/regenerate-b-{{ item }} -N {{ passphrase }}'
|
||||
loop: "{{ regenerate_values }}"
|
||||
|
||||
- name: "({{ backend }}) Regenerate - setup broken keys"
|
||||
copy:
|
||||
dest: '{{ output_dir }}/regenerate-c-{{ item.0 }}{{ item.1 }}'
|
||||
dest: '{{ remote_tmp_dir }}/regenerate-c-{{ item.0 }}{{ item.1 }}'
|
||||
content: 'broken key'
|
||||
mode: '0700'
|
||||
with_nested:
|
||||
@@ -33,12 +39,12 @@
|
||||
- [ '', '.pub' ]
|
||||
|
||||
- name: "({{ backend }}) Regenerate - setup password protected keys for passphrse test"
|
||||
command: 'ssh-keygen -f {{ output_dir }}/regenerate-d-{{ item }} -N {{ passphrase }}'
|
||||
command: 'ssh-keygen -f {{ remote_tmp_dir }}/regenerate-d-{{ item }} -N {{ passphrase }}'
|
||||
loop: "{{ regenerate_values }}"
|
||||
|
||||
- name: "({{ backend }}) Regenerate - modify broken keys (check mode)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-c-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-c-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -60,7 +66,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - modify broken keys"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-c-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-c-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -81,7 +87,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - modify password protected keys (check mode)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-b-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -103,7 +109,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - modify password protected keys with passphrase (check mode)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-b-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
passphrase: "{{ passphrase }}"
|
||||
@@ -127,7 +133,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - modify password protected keys"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-b-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -148,7 +154,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - modify password protected keys with passphrase"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-d-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-d-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
passphrase: "{{ passphrase }}"
|
||||
@@ -171,7 +177,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - not modify regular keys (check mode)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -189,7 +195,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - not modify regular keys"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: rsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -206,7 +212,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - adjust key size (check mode)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: rsa
|
||||
size: 1048
|
||||
regenerate: '{{ item }}'
|
||||
@@ -226,7 +232,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - adjust key size"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: rsa
|
||||
size: 1048
|
||||
regenerate: '{{ item }}'
|
||||
@@ -245,8 +251,8 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - redistribute keys"
|
||||
copy:
|
||||
src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
|
||||
dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
|
||||
src: '{{ remote_tmp_dir }}/regenerate-a-always{{ item.1 }}'
|
||||
dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
|
||||
remote_src: true
|
||||
with_nested:
|
||||
- "{{ regenerate_values }}"
|
||||
@@ -255,7 +261,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - adjust key type (check mode)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: dsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -275,7 +281,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - adjust key type"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: dsa
|
||||
size: 1024
|
||||
regenerate: '{{ item }}'
|
||||
@@ -294,8 +300,8 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - redistribute keys"
|
||||
copy:
|
||||
src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
|
||||
dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
|
||||
src: '{{ remote_tmp_dir }}/regenerate-a-always{{ item.1 }}'
|
||||
dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
|
||||
remote_src: true
|
||||
with_nested:
|
||||
- "{{ regenerate_values }}"
|
||||
@@ -304,7 +310,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - adjust comment (check mode)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: dsa
|
||||
size: 1024
|
||||
comment: test comment
|
||||
@@ -320,7 +326,7 @@
|
||||
|
||||
- name: "({{ backend }}) Regenerate - adjust comment"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
|
||||
type: dsa
|
||||
size: 1024
|
||||
comment: test comment
|
||||
|
||||
@@ -6,36 +6,36 @@
|
||||
|
||||
- name: "({{ backend }}) Generate key"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/removed'
|
||||
path: '{{ remote_tmp_dir }}/removed'
|
||||
backend: "{{ backend }}"
|
||||
state: present
|
||||
|
||||
- name: "({{ backend }}) Generate key (idempotency)"
|
||||
openssh_keypair:
|
||||
path: '{{ output_dir }}/removed'
|
||||
path: '{{ remote_tmp_dir }}/removed'
|
||||
backend: "{{ backend }}"
|
||||
state: present
|
||||
|
||||
- name: "({{ backend }}) Remove key"
|
||||
openssh_keypair:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/removed'
|
||||
path: '{{ remote_tmp_dir }}/removed'
|
||||
backend: "{{ backend }}"
|
||||
|
||||
- name: "({{ backend }}) Remove key (idempotency)"
|
||||
openssh_keypair:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/removed'
|
||||
path: '{{ remote_tmp_dir }}/removed'
|
||||
backend: "{{ backend }}"
|
||||
|
||||
- name: "({{ backend }}) Check private key status"
|
||||
stat:
|
||||
path: '{{ output_dir }}/removed'
|
||||
path: '{{ remote_tmp_dir }}/removed'
|
||||
register: removed_private_key
|
||||
|
||||
- name: "({{ backend }}) Check public key status"
|
||||
stat:
|
||||
path: '{{ output_dir }}/removed.pub'
|
||||
path: '{{ remote_tmp_dir }}/removed.pub'
|
||||
register: removed_public_key
|
||||
|
||||
- name: "({{ backend }}) Assert key pair files are removed"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_pyopenssl
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (check mode)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -27,8 +27,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -37,8 +37,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (idempotent, check mode)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -48,8 +48,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR without SAN (check mode)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
useCommonNameForSAN: no
|
||||
@@ -59,8 +59,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR without SAN"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
useCommonNameForSAN: no
|
||||
@@ -69,8 +69,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR without SAN (idempotent)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
useCommonNameForSAN: no
|
||||
@@ -79,8 +79,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR without SAN (idempotent, check mode)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr-nosan.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
useCommonNameForSAN: no
|
||||
@@ -94,8 +94,8 @@
|
||||
# and vice-versa for biometricInfo
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
CN: www.ansible.com
|
||||
keyUsage:
|
||||
@@ -110,8 +110,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU (test idempotency)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: 'www.ansible.com'
|
||||
keyUsage:
|
||||
@@ -127,8 +127,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU (test XKU change)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: 'www.ansible.com'
|
||||
keyUsage:
|
||||
@@ -143,8 +143,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU (test KU change)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ku_xku.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: 'www.ansible.com'
|
||||
keyUsage:
|
||||
@@ -158,15 +158,15 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with old API"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_oldapi.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_oldapi.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with invalid SAN (1/2)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csrinvsan.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csrinvsan.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject_alt_name: invalid-san.example.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: generate_csr_invalid_san
|
||||
@@ -174,8 +174,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with invalid SAN (2/2)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csrinvsan2.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csrinvsan2.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject_alt_name: "DNS:system:kube-controller-manager"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: generate_csr_invalid_san_2
|
||||
@@ -183,16 +183,16 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with OCSP Must Staple"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ocsp.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ocsp.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject_alt_name: "DNS:www.ansible.com"
|
||||
ocsp_must_staple: true
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with OCSP Must Staple (test idempotency)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ocsp.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ocsp.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject_alt_name: "DNS:www.ansible.com"
|
||||
ocsp_must_staple: true
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -200,22 +200,22 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate ECC privatekey"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
type: ECC
|
||||
curve: secp384r1
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with ECC privatekey"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr2.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr2.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with text common name"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr3.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr3.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
subject:
|
||||
commonName: This is for Ansible
|
||||
useCommonNameForSAN: no
|
||||
@@ -223,24 +223,24 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with country name"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
country_name: de
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: country_idempotent_1
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with country name (idempotent)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
country_name: de
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: country_idempotent_2
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with country name (idempotent 2)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
subject:
|
||||
C: de
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -248,8 +248,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with country name (bad country name)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr4.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
subject:
|
||||
C: dex
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -258,7 +258,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey with password"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
select_crypto_backend: cryptography
|
||||
@@ -266,16 +266,16 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with privatekey passphrase"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_pw.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_pw.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: passphrase_1
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (failed passphrase 1)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_pw1.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_pw1.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
ignore_errors: yes
|
||||
@@ -283,8 +283,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (failed passphrase 2)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_pw2.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_pw2.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: wrong_password
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
ignore_errors: yes
|
||||
@@ -292,20 +292,20 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (failed passphrase 3)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_pw3.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_pw3.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
ignore_errors: yes
|
||||
register: passphrase_error_3
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Create broken CSR"
|
||||
copy:
|
||||
dest: "{{ output_dir }}/csrbroken.csr"
|
||||
dest: "{{ remote_tmp_dir }}/csrbroken.csr"
|
||||
content: "broken"
|
||||
- name: "({{ select_crypto_backend }}) Regenerate broken CSR"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csrbroken.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/csrbroken.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
subject:
|
||||
commonName: This is for Ansible
|
||||
useCommonNameForSAN: no
|
||||
@@ -314,8 +314,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_backup.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_backup.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
backup: yes
|
||||
@@ -323,8 +323,8 @@
|
||||
register: csr_backup_1
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_backup.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_backup.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
backup: yes
|
||||
@@ -332,8 +332,8 @@
|
||||
register: csr_backup_2
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (change)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_backup.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_backup.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: ansible.com
|
||||
backup: yes
|
||||
@@ -341,7 +341,7 @@
|
||||
register: csr_backup_3
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (remove)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_backup.csr'
|
||||
path: '{{ remote_tmp_dir }}/csr_backup.csr'
|
||||
state: absent
|
||||
backup: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -349,7 +349,7 @@
|
||||
register: csr_backup_4
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (remove, idempotent)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_backup.csr'
|
||||
path: '{{ remote_tmp_dir }}/csr_backup.csr'
|
||||
state: absent
|
||||
backup: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -357,8 +357,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
subject_key_identifier: "00:11:22:33"
|
||||
@@ -368,8 +368,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (idempotency)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
subject_key_identifier: "00:11:22:33"
|
||||
@@ -379,8 +379,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (change)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
subject_key_identifier: "44:55:66:77:88"
|
||||
@@ -390,8 +390,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (auto-create)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
create_subject_key_identifier: yes
|
||||
@@ -401,8 +401,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (auto-create idempotency)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
create_subject_key_identifier: yes
|
||||
@@ -412,8 +412,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (remove)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -422,8 +422,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_key_identifier: "00:11:22:33"
|
||||
@@ -433,8 +433,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier (idempotency)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_key_identifier: "00:11:22:33"
|
||||
@@ -444,8 +444,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier (change)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_key_identifier: "44:55:66:77:88"
|
||||
@@ -455,8 +455,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier (remove)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -465,8 +465,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
@@ -479,8 +479,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (idempotency)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
@@ -493,8 +493,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (change issuer)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
@@ -507,8 +507,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (change serial number)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
@@ -521,8 +521,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (remove)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
@@ -530,20 +530,20 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with everything"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.example.com
|
||||
C: de
|
||||
L: Somewhere
|
||||
ST: Zurich
|
||||
streetAddress: Welcome Street
|
||||
O: Ansible
|
||||
organizationalUnitName: Crypto Department
|
||||
ST: Zürich
|
||||
streetAddress: Welcome Street N° 5
|
||||
O: Ansiblé
|
||||
organizationalUnitName: Crÿpto Depârtment ☺
|
||||
serialNumber: "1234"
|
||||
SN: Last Name
|
||||
SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
GN: First Name
|
||||
title: Chief
|
||||
title: Chïeff
|
||||
pseudonym: test
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
@@ -638,20 +638,20 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with everything (idempotent, check mode)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.example.com
|
||||
C: de
|
||||
CN: www.example.com
|
||||
countryName: de
|
||||
L: Somewhere
|
||||
ST: Zurich
|
||||
streetAddress: Welcome Street
|
||||
O: Ansible
|
||||
organizationalUnitName: Crypto Department
|
||||
ST: Zürich
|
||||
streetAddress: Welcome Street N° 5
|
||||
organizationName: Ansiblé
|
||||
organizationalUnitName: Crÿpto Depârtment ☺
|
||||
serialNumber: "1234"
|
||||
SN: Last Name
|
||||
SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
GN: First Name
|
||||
title: Chief
|
||||
title: Chïeff
|
||||
pseudonym: test
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
@@ -747,20 +747,20 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with everything (idempotent)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.example.com
|
||||
C: de
|
||||
CN: www.example.com
|
||||
countryName: de
|
||||
L: Somewhere
|
||||
ST: Zurich
|
||||
streetAddress: Welcome Street
|
||||
O: Ansible
|
||||
organizationalUnitName: Crypto Department
|
||||
ST: Zürich
|
||||
streetAddress: Welcome Street N° 5
|
||||
organizationName: Ansiblé
|
||||
organizationalUnitName: Crÿpto Depârtment ☺
|
||||
serialNumber: "1234"
|
||||
SN: Last Name
|
||||
SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
GN: First Name
|
||||
title: Chief
|
||||
title: Chïeff
|
||||
pseudonym: test
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
@@ -855,7 +855,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Get info from CSR with everything"
|
||||
community.crypto.openssl_csr_info:
|
||||
path: '{{ output_dir }}/csr_everything.csr'
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: everything_info
|
||||
|
||||
@@ -863,7 +863,7 @@
|
||||
block:
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekeys"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_{{ item }}.pem'
|
||||
type: '{{ item }}'
|
||||
loop:
|
||||
- Ed25519
|
||||
@@ -877,8 +877,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_{{ item }}.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_{{ item }}.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey_{{ item }}.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -890,8 +890,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_{{ item }}.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_{{ item }}.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey_{{ item }}.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -907,8 +907,8 @@
|
||||
block:
|
||||
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
crl_distribution_points:
|
||||
@@ -930,8 +930,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (idempotence)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
crl_distribution_points:
|
||||
@@ -953,8 +953,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (change)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
crl_distribution_points:
|
||||
@@ -975,8 +975,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (no endpoints)"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -984,8 +984,8 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints"
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_crl_d_e.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
crl_distribution_points:
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
- name: Prepare private key for backend autodetection test
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_backend_selection.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_backend_selection.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
- name: Run module with backend autodetection
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_backend_selection.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_backend_selection.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_backend_selection.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey_backend_selection.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (test - privatekey modulus)"
|
||||
shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
|
||||
shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ remote_tmp_dir }}/privatekey.pem'
|
||||
register: privatekey_modulus
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (test - Common Name)"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr.csr -nameopt oneline,-space_eq"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ remote_tmp_dir }}/csr.csr -nameopt oneline,-space_eq"
|
||||
register: csr_cn
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (test - csr modulus)"
|
||||
shell: '{{ openssl_binary }} req -noout -modulus -in {{ output_dir }}/csr.csr'
|
||||
shell: '{{ openssl_binary }} req -noout -modulus -in {{ remote_tmp_dir }}/csr.csr'
|
||||
register: csr_modulus
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (assert)"
|
||||
@@ -25,11 +25,16 @@
|
||||
- generate_csr_idempotent is not changed
|
||||
- generate_csr_idempotent_check is not changed
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read CSR"
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/csr.csr'
|
||||
register: slurp
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (data retrieval)"
|
||||
assert:
|
||||
that:
|
||||
- generate_csr_check.csr is none
|
||||
- generate_csr.csr == lookup('file', output_dir ~ '/csr.csr', rstrip=False)
|
||||
- generate_csr.csr == (slurp.content | b64decode)
|
||||
- generate_csr.csr == generate_csr_idempotent.csr
|
||||
- generate_csr.csr == generate_csr_idempotent_check.csr
|
||||
|
||||
@@ -49,11 +54,11 @@
|
||||
- csr_ku_xku_change_2 is changed
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate old_API CSR (test - Common Name)"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr_oldapi.csr -nameopt oneline,-space_eq"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ remote_tmp_dir }}/csr_oldapi.csr -nameopt oneline,-space_eq"
|
||||
register: csr_oldapi_cn
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate old_API CSR (test - csr modulus)"
|
||||
shell: '{{ openssl_binary }} req -noout -modulus -in {{ output_dir }}/csr_oldapi.csr'
|
||||
shell: '{{ openssl_binary }} req -noout -modulus -in {{ remote_tmp_dir }}/csr_oldapi.csr'
|
||||
register: csr_oldapi_modulus
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate old_API CSR (assert)"
|
||||
@@ -78,7 +83,7 @@
|
||||
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.0', '<')
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate OCSP Must Staple CSR (test - everything)"
|
||||
shell: "{{ openssl_binary }} req -noout -in {{ output_dir }}/csr_ocsp.csr -text"
|
||||
shell: "{{ openssl_binary }} req -noout -in {{ remote_tmp_dir }}/csr_ocsp.csr -text"
|
||||
register: csr_ocsp
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate OCSP Must Staple CSR (assert)"
|
||||
@@ -93,15 +98,15 @@
|
||||
- csr_ocsp_idempotency is not changed
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate ECC CSR (test - privatekey's public key)"
|
||||
shell: '{{ openssl_binary }} ec -pubout -in {{ output_dir }}/privatekey2.pem'
|
||||
shell: '{{ openssl_binary }} ec -pubout -in {{ remote_tmp_dir }}/privatekey2.pem'
|
||||
register: privatekey_ecc_key
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate ECC CSR (test - Common Name)"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr2.csr -nameopt oneline,-space_eq"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ remote_tmp_dir }}/csr2.csr -nameopt oneline,-space_eq"
|
||||
register: csr_ecc_cn
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate ECC CSR (test - CSR pubkey)"
|
||||
shell: '{{ openssl_binary }} req -noout -pubkey -in {{ output_dir }}/csr2.csr'
|
||||
shell: '{{ openssl_binary }} req -noout -pubkey -in {{ remote_tmp_dir }}/csr2.csr'
|
||||
register: csr_ecc_pubkey
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate ECC CSR (assert)"
|
||||
@@ -111,7 +116,7 @@
|
||||
- csr_ecc_pubkey.stdout == privatekey_ecc_key.stdout
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (text common name - Common Name)"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr3.csr -nameopt oneline,-space_eq"
|
||||
shell: "{{ openssl_binary }} req -noout -subject -in {{ remote_tmp_dir }}/csr3.csr -nameopt oneline,-space_eq"
|
||||
register: csr3_cn
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (assert)"
|
||||
@@ -219,16 +224,16 @@
|
||||
- everything_info.subject.emailAddress == "test@example.com"
|
||||
- everything_info.subject.givenName == "First Name"
|
||||
- everything_info.subject.localityName == "Somewhere"
|
||||
- everything_info.subject.organizationName == "Ansible"
|
||||
- everything_info.subject.organizationalUnitName == "Crypto Department"
|
||||
- everything_info.subject.organizationName == "Ansiblé"
|
||||
- everything_info.subject.organizationalUnitName == "Crÿpto Depârtment ☺"
|
||||
- everything_info.subject.postalAddress == "1234 Somewhere"
|
||||
- everything_info.subject.postalCode == "1234"
|
||||
- everything_info.subject.pseudonym == "test"
|
||||
- everything_info.subject.serialNumber == "1234"
|
||||
- everything_info.subject.stateOrProvinceName == "Zurich"
|
||||
- everything_info.subject.streetAddress == "Welcome Street"
|
||||
- everything_info.subject.surname == "Last Name"
|
||||
- everything_info.subject.title == "Chief"
|
||||
- everything_info.subject.stateOrProvinceName == "Zürich"
|
||||
- everything_info.subject.streetAddress == "Welcome Street N° 5"
|
||||
- everything_info.subject.surname == "Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr."
|
||||
- everything_info.subject.title == "Chïeff"
|
||||
- everything_info.subject.userId == "asdf"
|
||||
- everything_info.subject | length == 16
|
||||
- everything_info.subject_alt_name_critical == false
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_pyopenssl
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Get CSR info"
|
||||
openssl_csr_info:
|
||||
path: '{{ output_dir }}/csr_1.csr'
|
||||
path: '{{ remote_tmp_dir }}/csr_1.csr'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
@@ -34,9 +34,14 @@
|
||||
set_fact:
|
||||
info_results: "{{ info_results + [result] }}"
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read CSR"
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/csr_1.csr'
|
||||
register: slurp
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Get CSR info directly"
|
||||
openssl_csr_info:
|
||||
content: '{{ lookup("file", output_dir ~ "/csr_1.csr") }}'
|
||||
content: '{{ slurp.content | b64decode }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result_direct
|
||||
|
||||
@@ -47,7 +52,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Get CSR info"
|
||||
openssl_csr_info:
|
||||
path: '{{ output_dir }}/csr_2.csr'
|
||||
path: '{{ remote_tmp_dir }}/csr_2.csr'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
@@ -57,7 +62,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Get CSR info"
|
||||
openssl_csr_info:
|
||||
path: '{{ output_dir }}/csr_3.csr'
|
||||
path: '{{ remote_tmp_dir }}/csr_3.csr'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
@@ -79,7 +84,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Get CSR info"
|
||||
openssl_csr_info:
|
||||
path: '{{ output_dir }}/csr_4.csr'
|
||||
path: '{{ remote_tmp_dir }}/csr_4.csr'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
- name: Generate privatekey
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: Generate privatekey with password
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
select_crypto_backend: cryptography
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
- name: Generate CSR 1
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_1.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_1.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.example.com
|
||||
C: de
|
||||
@@ -87,8 +87,8 @@
|
||||
|
||||
- name: Generate CSR 2
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_2.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_2.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
useCommonNameForSAN: no
|
||||
basic_constraints:
|
||||
@@ -96,8 +96,8 @@
|
||||
|
||||
- name: Generate CSR 3
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_3.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_3.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: no
|
||||
subject_alt_name:
|
||||
- "DNS:*.ansible.com"
|
||||
@@ -114,8 +114,8 @@
|
||||
|
||||
- name: Generate CSR 4
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_4.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/csr_4.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: no
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_pyopenssl
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (check mode)"
|
||||
openssl_csr_pipe:
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR"
|
||||
openssl_csr_pipe:
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -24,7 +24,7 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
|
||||
openssl_csr_pipe:
|
||||
content: "{{ generate_csr.csr }}"
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -33,7 +33,7 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (idempotent, check mode)"
|
||||
openssl_csr_pipe:
|
||||
content: "{{ generate_csr.csr }}"
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -43,7 +43,7 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (changed)"
|
||||
openssl_csr_pipe:
|
||||
content: "{{ generate_csr.csr }}"
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -52,7 +52,7 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR (changed, check mode)"
|
||||
openssl_csr_pipe:
|
||||
content: "{{ generate_csr.csr }}"
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -60,7 +60,7 @@
|
||||
register: generate_csr_changed_check
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (test - privatekey modulus)"
|
||||
shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
|
||||
shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ remote_tmp_dir }}/privatekey.pem'
|
||||
register: privatekey_modulus
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate CSR (test - Common Name)"
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
- name: Prepare private key for backend autodetection test
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_backend_selection.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_backend_selection.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
- name: Run module with backend autodetection
|
||||
openssl_csr_pipe:
|
||||
privatekey_path: '{{ output_dir }}/privatekey_backend_selection.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey_backend_selection.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- name: "[{{ select_crypto_backend }}] Generate parameter (check mode)"
|
||||
openssl_dhparam:
|
||||
size: 768
|
||||
path: '{{ output_dir }}/dh768.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh768.pem'
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
return_content: yes
|
||||
check_mode: true
|
||||
@@ -13,7 +13,7 @@
|
||||
- name: "[{{ select_crypto_backend }}] Generate parameter"
|
||||
openssl_dhparam:
|
||||
size: 768
|
||||
path: '{{ output_dir }}/dh768.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh768.pem'
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
return_content: yes
|
||||
register: dhparam
|
||||
@@ -21,7 +21,7 @@
|
||||
- name: "[{{ select_crypto_backend }}] Don't regenerate parameters with no change (check mode)"
|
||||
openssl_dhparam:
|
||||
size: 768
|
||||
path: '{{ output_dir }}/dh768.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh768.pem'
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
return_content: yes
|
||||
check_mode: true
|
||||
@@ -30,39 +30,39 @@
|
||||
- name: "[{{ select_crypto_backend }}] Don't regenerate parameters with no change"
|
||||
openssl_dhparam:
|
||||
size: 768
|
||||
path: '{{ output_dir }}/dh768.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh768.pem'
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
return_content: yes
|
||||
register: dhparam_changed
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Generate parameters with size option"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh512.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh512.pem'
|
||||
size: 512
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Don't regenerate parameters with size option and no change"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh512.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh512.pem'
|
||||
size: 512
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
register: dhparam_changed_512
|
||||
|
||||
- copy:
|
||||
src: '{{ output_dir }}/dh768.pem'
|
||||
src: '{{ remote_tmp_dir }}/dh768.pem'
|
||||
remote_src: yes
|
||||
dest: '{{ output_dir }}/dh512.pem'
|
||||
dest: '{{ remote_tmp_dir }}/dh512.pem'
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Re-generate if size is different"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh512.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh512.pem'
|
||||
size: 512
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
register: dhparam_changed_to_512
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Force re-generate parameters with size option"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh512.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh512.pem'
|
||||
size: 512
|
||||
force: yes
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
@@ -70,11 +70,11 @@
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Create broken params"
|
||||
copy:
|
||||
dest: "{{ output_dir }}/dhbroken.pem"
|
||||
dest: "{{ remote_tmp_dir }}/dhbroken.pem"
|
||||
content: "broken"
|
||||
- name: "[{{ select_crypto_backend }}] Regenerate broken params"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dhbroken.pem'
|
||||
path: '{{ remote_tmp_dir }}/dhbroken.pem'
|
||||
size: 512
|
||||
force: yes
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
@@ -82,21 +82,21 @@
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Generate params"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh_backup.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh_backup.pem'
|
||||
size: 512
|
||||
backup: yes
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
register: dhparam_backup_1
|
||||
- name: "[{{ select_crypto_backend }}] Generate params (idempotent)"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh_backup.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh_backup.pem'
|
||||
size: 512
|
||||
backup: yes
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
register: dhparam_backup_2
|
||||
- name: "[{{ select_crypto_backend }}] Generate params (change)"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh_backup.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh_backup.pem'
|
||||
size: 512
|
||||
force: yes
|
||||
backup: yes
|
||||
@@ -104,7 +104,7 @@
|
||||
register: dhparam_backup_3
|
||||
- name: "[{{ select_crypto_backend }}] Generate params (remove)"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh_backup.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh_backup.pem'
|
||||
state: absent
|
||||
backup: yes
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
@@ -112,7 +112,7 @@
|
||||
register: dhparam_backup_4
|
||||
- name: "[{{ select_crypto_backend }}] Generate params (remove, idempotent)"
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh_backup.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh_backup.pem'
|
||||
state: absent
|
||||
backup: yes
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
- name: Run module with backend autodetection
|
||||
openssl_dhparam:
|
||||
path: '{{ output_dir }}/dh_backend_selection.pem'
|
||||
path: '{{ remote_tmp_dir }}/dh_backend_selection.pem'
|
||||
size: 512
|
||||
|
||||
- block:
|
||||
@@ -24,12 +24,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
- name: "[{{ select_crypto_backend }}] Validate generated params"
|
||||
shell: '{{ openssl_binary }} dhparam -in {{ output_dir }}/{{ item }}.pem -noout -check'
|
||||
shell: '{{ openssl_binary }} dhparam -in {{ remote_tmp_dir }}/{{ item }}.pem -noout -check'
|
||||
with_items:
|
||||
- dh768
|
||||
- dh512
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Get bit size of 768"
|
||||
shell: '{{ openssl_binary }} dhparam -noout -in {{ output_dir }}/dh768.pem -text | head -n1 | sed -ne "s@.*(\\([[:digit:]]\{1,\}\\) bit).*@\\1@p"'
|
||||
shell: '{{ openssl_binary }} dhparam -noout -in {{ remote_tmp_dir }}/dh768.pem -text | head -n1 | sed -ne "s@.*(\\([[:digit:]]\{1,\}\\) bit).*@\\1@p"'
|
||||
register: bit_size_dhparam
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Check bit size of default"
|
||||
@@ -15,7 +15,7 @@
|
||||
- bit_size_dhparam.stdout == "768"
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Get bit size of 512"
|
||||
shell: '{{ openssl_binary }} dhparam -noout -in {{ output_dir }}/dh512.pem -text | head -n1 | sed -ne "s@.*(\\([[:digit:]]\{1,\}\\) bit).*@\\1@p"'
|
||||
shell: '{{ openssl_binary }} dhparam -noout -in {{ remote_tmp_dir }}/dh512.pem -text | head -n1 | sed -ne "s@.*(\\([[:digit:]]\{1,\}\\) bit).*@\\1@p"'
|
||||
register: bit_size_dhparam_512
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Check bit size of default"
|
||||
@@ -34,10 +34,15 @@
|
||||
- dhparam_changed_to_512 is changed
|
||||
- dhparam_changed_force is changed
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Read result"
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/dh768.pem'
|
||||
register: slurp
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Make sure correct values are returned"
|
||||
assert:
|
||||
that:
|
||||
- dhparam.dhparams == lookup('file', output_dir ~ '/dh768.pem', rstrip=False)
|
||||
- dhparam.dhparams == (slurp.content | b64decode)
|
||||
- dhparam.dhparams == dhparam_changed.dhparams
|
||||
|
||||
- name: "[{{ select_crypto_backend }}] Verify that broken params will be regenerated"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_pyopenssl
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (check mode)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
return_content: true
|
||||
check_mode: true
|
||||
@@ -14,10 +14,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
return_content: true
|
||||
register: p12_standard
|
||||
@@ -25,10 +25,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file again, idempotency (check mode)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
return_content: true
|
||||
check_mode: true
|
||||
@@ -37,17 +37,17 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file again, idempotency"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
return_content: true
|
||||
register: p12_standard_idempotency
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read ansible.p12"
|
||||
slurp:
|
||||
src: '{{ output_dir }}/ansible.p12'
|
||||
src: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
register: ansible_p12_content
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate PKCS#12"
|
||||
@@ -59,10 +59,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (force)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
force: true
|
||||
register: p12_force
|
||||
@@ -70,10 +70,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (force + change mode)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
force: true
|
||||
mode: '0644'
|
||||
@@ -82,8 +82,8 @@
|
||||
- name: "({{ select_crypto_backend }}) Dump PKCS#12"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
src: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ output_dir }}/ansible_parse.pem'
|
||||
src: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_parse.pem'
|
||||
action: parse
|
||||
state: present
|
||||
register: p12_dumped
|
||||
@@ -91,8 +91,8 @@
|
||||
- name: "({{ select_crypto_backend }}) Dump PKCS#12 file again, idempotency"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
src: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ output_dir }}/ansible_parse.pem'
|
||||
src: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_parse.pem'
|
||||
action: parse
|
||||
state: present
|
||||
register: p12_dumped_idempotency
|
||||
@@ -100,8 +100,8 @@
|
||||
- name: "({{ select_crypto_backend }}) Dump PKCS#12, check mode"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
src: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ output_dir }}/ansible_parse.pem'
|
||||
src: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_parse.pem'
|
||||
action: parse
|
||||
state: present
|
||||
check_mode: true
|
||||
@@ -110,36 +110,36 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file with multiple certs and passphrase"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_multi_certs.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_multi_certs.p12'
|
||||
friendly_name: abracadabra
|
||||
passphrase: hunter3
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
other_certificates:
|
||||
- '{{ output_dir }}/ansible2.crt'
|
||||
- '{{ output_dir }}/ansible3.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible2.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible3.crt'
|
||||
state: present
|
||||
register: p12_multiple_certs
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file with multiple certs and passphrase, again (idempotency)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_multi_certs.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_multi_certs.p12'
|
||||
friendly_name: abracadabra
|
||||
passphrase: hunter3
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
other_certificates:
|
||||
- '{{ output_dir }}/ansible2.crt'
|
||||
- '{{ output_dir }}/ansible3.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible2.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible3.crt'
|
||||
state: present
|
||||
register: p12_multiple_certs_idempotency
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Dump PKCS#12 with multiple certs and passphrase"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
src: '{{ output_dir }}/ansible_multi_certs.p12'
|
||||
path: '{{ output_dir }}/ansible_parse_multi_certs.pem'
|
||||
src: '{{ remote_tmp_dir }}/ansible_multi_certs.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_parse_multi_certs.pem'
|
||||
passphrase: hunter3
|
||||
action: parse
|
||||
state: present
|
||||
@@ -147,11 +147,11 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (password fail 1)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_pw1.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_pw1.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
ignore_errors: true
|
||||
register: passphrase_error_1
|
||||
@@ -159,11 +159,11 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (password fail 2)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_pw2.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_pw2.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: wrong_password
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
ignore_errors: true
|
||||
register: passphrase_error_2
|
||||
@@ -171,10 +171,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (password fail 3)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_pw3.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_pw3.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
ignore_errors: true
|
||||
register: passphrase_error_3
|
||||
@@ -182,24 +182,24 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file, no privatekey"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_no_pkey.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_no_pkey.p12'
|
||||
friendly_name: abracadabra
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
register: p12_no_pkey
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Create broken PKCS#12"
|
||||
copy:
|
||||
dest: '{{ output_dir }}/broken.p12'
|
||||
dest: '{{ remote_tmp_dir }}/broken.p12'
|
||||
content: broken
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate broken PKCS#12"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/broken.p12'
|
||||
path: '{{ remote_tmp_dir }}/broken.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
force: true
|
||||
mode: '0644'
|
||||
@@ -208,10 +208,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_backup.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_backup.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
backup: true
|
||||
register: p12_backup_1
|
||||
@@ -219,10 +219,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (idempotent)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_backup.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_backup.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
backup: true
|
||||
register: p12_backup_2
|
||||
@@ -230,10 +230,10 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (change)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_backup.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_backup.p12'
|
||||
friendly_name: abra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
force: true
|
||||
backup: true
|
||||
@@ -242,7 +242,7 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (remove)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_backup.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_backup.p12'
|
||||
state: absent
|
||||
backup: true
|
||||
return_content: true
|
||||
@@ -251,7 +251,7 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file (remove, idempotent)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_backup.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_backup.p12'
|
||||
state: absent
|
||||
backup: true
|
||||
register: p12_backup_5
|
||||
@@ -259,11 +259,11 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate 'empty' PKCS#12 file"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_empty.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_empty.p12'
|
||||
friendly_name: abracadabra
|
||||
other_certificates:
|
||||
- '{{ output_dir }}/ansible2.crt'
|
||||
- '{{ output_dir }}/ansible3.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible2.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible3.crt'
|
||||
state: present
|
||||
register: p12_empty
|
||||
|
||||
@@ -271,21 +271,21 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate 'empty' PKCS#12 file (idempotent)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_empty.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_empty.p12'
|
||||
friendly_name: abracadabra
|
||||
other_certificates:
|
||||
- '{{ output_dir }}/ansible3.crt'
|
||||
- '{{ output_dir }}/ansible2.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible3.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible2.crt'
|
||||
state: present
|
||||
register: p12_empty_idem
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate 'empty' PKCS#12 file (idempotent, concatenated other certificates)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
path: '{{ output_dir }}/ansible_empty.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_empty.p12'
|
||||
friendly_name: abracadabra
|
||||
other_certificates:
|
||||
- '{{ output_dir }}/ansible23.crt'
|
||||
- '{{ remote_tmp_dir }}/ansible23.crt'
|
||||
other_certificates_parse_all: true
|
||||
state: present
|
||||
register: p12_empty_concat_idem
|
||||
@@ -293,8 +293,8 @@
|
||||
- name: "({{ select_crypto_backend }}) Generate 'empty' PKCS#12 file (parse)"
|
||||
openssl_pkcs12:
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
src: '{{ output_dir }}/ansible_empty.p12'
|
||||
path: '{{ output_dir }}/ansible_empty.pem'
|
||||
src: '{{ remote_tmp_dir }}/ansible_empty.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible_empty.pem'
|
||||
action: parse
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
@@ -303,7 +303,7 @@
|
||||
- name: "({{ select_crypto_backend }}) Delete PKCS#12 file"
|
||||
openssl_pkcs12:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/{{ item }}.p12'
|
||||
path: '{{ remote_tmp_dir }}/{{ item }}.p12'
|
||||
loop:
|
||||
- ansible
|
||||
- ansible_no_pkey
|
||||
|
||||
@@ -7,50 +7,56 @@
|
||||
- block:
|
||||
- name: Generate private keys
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/ansible_pkey{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/ansible_pkey{{ item }}.pem'
|
||||
size: '{{ default_rsa_key_size_certifiates }}'
|
||||
loop: "{{ range(1, 4) | list }}"
|
||||
|
||||
- name: Generate privatekey with password
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: Generate CSRs
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/ansible{{ item }}.csr'
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/ansible{{ item }}.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey{{ item }}.pem'
|
||||
commonName: www{{ item }}.ansible.com
|
||||
loop: "{{ range(1, 4) | list }}"
|
||||
|
||||
- name: Generate certificate
|
||||
x509_certificate:
|
||||
path: '{{ output_dir }}/ansible{{ item }}.crt'
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey{{ item }}.pem'
|
||||
csr_path: '{{ output_dir }}/ansible{{ item }}.csr'
|
||||
path: '{{ remote_tmp_dir }}/ansible{{ item }}.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey{{ item }}.pem'
|
||||
csr_path: '{{ remote_tmp_dir }}/ansible{{ item }}.csr'
|
||||
provider: selfsigned
|
||||
loop: "{{ range(1, 4) | list }}"
|
||||
|
||||
- name: Read files
|
||||
slurp:
|
||||
src: '{{ item }}'
|
||||
loop:
|
||||
- "{{ remote_tmp_dir ~ '/ansible2.crt' }}"
|
||||
- "{{ remote_tmp_dir ~ '/ansible3.crt' }}"
|
||||
register: slurp
|
||||
|
||||
- name: Generate concatenated PEM file
|
||||
copy:
|
||||
dest: '{{ output_dir }}/ansible23.crt'
|
||||
content: |
|
||||
{{ lookup("file", output_dir ~ "/ansible2.crt") }}
|
||||
{{ lookup("file", output_dir ~ "/ansible3.crt") }}
|
||||
dest: '{{ remote_tmp_dir }}/ansible23.crt'
|
||||
content: '{{ slurp.results[0].content | b64decode }}{{ slurp.results[1].content | b64decode }}'
|
||||
|
||||
- name: Generate PKCS#12 file with backend autodetection
|
||||
openssl_pkcs12:
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
friendly_name: abracadabra
|
||||
privatekey_path: '{{ output_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ output_dir }}/ansible1.crt'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
|
||||
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
|
||||
state: present
|
||||
|
||||
- name: Delete result
|
||||
file:
|
||||
path: '{{ output_dir }}/ansible.p12'
|
||||
path: '{{ remote_tmp_dir }}/ansible.p12'
|
||||
state: absent
|
||||
|
||||
- block:
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
- name: '({{ select_crypto_backend }}) Validate PKCS#12'
|
||||
command: "{{ openssl_binary }} pkcs12 -info -in {{ output_dir }}/ansible.p12 -nodes -passin pass:''"
|
||||
command: "{{ openssl_binary }} pkcs12 -info -in {{ remote_tmp_dir }}/ansible.p12 -nodes -passin pass:''"
|
||||
register: p12
|
||||
|
||||
- name: '({{ select_crypto_backend }}) Validate PKCS#12 with no private key'
|
||||
command: "{{ openssl_binary }} pkcs12 -info -in {{ output_dir }}/ansible_no_pkey.p12 -nodes -passin pass:''"
|
||||
command: "{{ openssl_binary }} pkcs12 -info -in {{ remote_tmp_dir }}/ansible_no_pkey.p12 -nodes -passin pass:''"
|
||||
register: p12_validate_no_pkey
|
||||
|
||||
- name: '({{ select_crypto_backend }}) Validate PKCS#12 with multiple certs'
|
||||
shell: "{{ openssl_binary }} pkcs12 -info -in {{ output_dir }}/ansible_multi_certs.p12 -nodes -passin pass:'hunter3' | grep subject"
|
||||
shell: "{{ openssl_binary }} pkcs12 -info -in {{ remote_tmp_dir }}/ansible_multi_certs.p12 -nodes -passin pass:'hunter3' | grep subject"
|
||||
register: p12_validate_multi_certs
|
||||
|
||||
- name: '({{ select_crypto_backend }}) Validate PKCS#12 (assert)'
|
||||
@@ -62,11 +62,20 @@
|
||||
- p12_backup_5.backup_file is undefined
|
||||
- p12_backup_4.pkcs12 is none
|
||||
|
||||
- name: '({{ select_crypto_backend }}) Read files'
|
||||
slurp:
|
||||
src: '{{ item }}'
|
||||
loop:
|
||||
- "{{ remote_tmp_dir ~ '/ansible_empty.pem' }}"
|
||||
- "{{ remote_tmp_dir ~ '/ansible2.crt' }}"
|
||||
- "{{ remote_tmp_dir ~ '/ansible3.crt' }}"
|
||||
register: slurp
|
||||
|
||||
- name: '({{ select_crypto_backend }}) Load "empty" file'
|
||||
set_fact:
|
||||
empty_contents: "{{ lookup('file', output_dir ~ '/ansible_empty.pem') }}"
|
||||
empty_expected_pyopenssl: "{{ lookup('file', output_dir ~ '/ansible3.crt') ~ '\n' ~ lookup('file', output_dir ~ '/ansible2.crt') }}"
|
||||
empty_expected_cryptography: "{{ lookup('file', output_dir ~ '/ansible2.crt') ~ '\n' ~ lookup('file', output_dir ~ '/ansible3.crt') }}"
|
||||
empty_contents: "{{ slurp.results[0].content | b64decode }}"
|
||||
empty_expected_pyopenssl: "{{ (slurp.results[2].content | b64decode) ~ (slurp.results[1].content | b64decode) }}"
|
||||
empty_expected_cryptography: "{{ (slurp.results[1].content | b64decode) ~ (slurp.results[2].content | b64decode) }}"
|
||||
|
||||
- name: '({{ select_crypto_backend }}) Check "empty" file'
|
||||
assert:
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_pyopenssl
|
||||
- setup_remote_tmp_dir
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey1 - standard (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey1.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
return_content: yes
|
||||
check_mode: true
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey1 - standard"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey1.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
return_content: yes
|
||||
register: privatekey1
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey1 - standard (idempotence, check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey1.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
return_content: yes
|
||||
check_mode: true
|
||||
@@ -24,34 +24,34 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey1 - standard (idempotence)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey1.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
return_content: yes
|
||||
register: privatekey1_idempotence
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey2 - size 2048"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey2.pem'
|
||||
size: 2048
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey3 - type DSA"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey3.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey3.pem'
|
||||
type: DSA
|
||||
size: 3072
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey4 - standard"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey4.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Delete privatekey4 - standard"
|
||||
openssl_privatekey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey4.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
return_content: yes
|
||||
register: privatekey4_delete
|
||||
@@ -59,13 +59,13 @@
|
||||
- name: "({{ select_crypto_backend }}) Delete privatekey4 - standard (idempotence)"
|
||||
openssl_privatekey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey4.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey4_delete_idempotence
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey5 - standard - with passphrase"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey5.pem'
|
||||
passphrase: ansible
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey5 - standard - idempotence"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey5.pem'
|
||||
passphrase: ansible
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey6 - standard - with non-ASCII passphrase"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey6.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey6.pem'
|
||||
passphrase: ànsïblé
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Test ECC key generation"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey-{{ item.curve }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey-{{ item.curve }}.pem'
|
||||
type: ECC
|
||||
curve: "{{ item.curve }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -168,7 +168,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Test ECC key generation (idempotency)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey-{{ item.curve }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey-{{ item.curve }}.pem'
|
||||
type: ECC
|
||||
curve: "{{ item.curve }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -183,7 +183,7 @@
|
||||
- block:
|
||||
- name: "({{ select_crypto_backend }}) Test other type generation"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey-{{ item.type }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey-{{ item.type }}.pem'
|
||||
type: "{{ item.type }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: cryptography_version.stdout is version(item.min_version, '>=')
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Test other type generation (idempotency)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey-{{ item.type }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey-{{ item.type }}.pem'
|
||||
type: "{{ item.type }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: cryptography_version.stdout is version(item.min_version, '>=')
|
||||
@@ -219,7 +219,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey with passphrase"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -229,7 +229,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey with passphrase (idempotent)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -239,7 +239,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate privatekey without passphrase"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
backup: yes
|
||||
@@ -247,7 +247,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate privatekey without passphrase (idempotent)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
backup: yes
|
||||
@@ -255,7 +255,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate privatekey with passphrase"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -265,18 +265,18 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Create broken key"
|
||||
copy:
|
||||
dest: "{{ output_dir }}/broken"
|
||||
dest: "{{ remote_tmp_dir }}/broken"
|
||||
content: "broken"
|
||||
- name: "({{ select_crypto_backend }}) Regenerate broken key"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/broken.pem'
|
||||
path: '{{ remote_tmp_dir }}/broken.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: output_broken
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Remove module"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -287,7 +287,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Remove module (idempotent)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -298,19 +298,19 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_mode (mode 0400)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_mode.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_mode.pem'
|
||||
mode: '0400'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey_mode_1
|
||||
- name: "({{ select_crypto_backend }}) Stat for privatekey_mode"
|
||||
stat:
|
||||
path: '{{ output_dir }}/privatekey_mode.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_mode.pem'
|
||||
register: privatekey_mode_1_stat
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_mode (mode 0400, idempotency)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_mode.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_mode.pem'
|
||||
mode: '0400'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -325,7 +325,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_mode (mode 0400, force)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_mode.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_mode.pem'
|
||||
mode: '0400'
|
||||
force: yes
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -333,13 +333,13 @@
|
||||
register: privatekey_mode_3
|
||||
- name: "({{ select_crypto_backend }}) Stat for privatekey_mode"
|
||||
stat:
|
||||
path: '{{ output_dir }}/privatekey_mode.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_mode.pem'
|
||||
register: privatekey_mode_3_stat
|
||||
|
||||
- block:
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: auto
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -347,7 +347,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format (idempotent)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: auto
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -355,7 +355,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS1 format"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: pkcs1
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -363,7 +363,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: pkcs8
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -371,7 +371,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (idempotent)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: pkcs8
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -379,7 +379,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format (ignore)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: auto_ignore
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -387,7 +387,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format (no ignore)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: auto
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -395,7 +395,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - raw format (fail)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: raw
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -404,13 +404,13 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (convert)"
|
||||
openssl_privatekey_info:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey_fmt_1_step_9_before
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (convert)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
format: pkcs8
|
||||
format_mismatch: convert
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
@@ -419,7 +419,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (convert)"
|
||||
openssl_privatekey_info:
|
||||
path: '{{ output_dir }}/privatekey_fmt_1.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_1.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey_fmt_1_step_9_after
|
||||
|
||||
@@ -428,7 +428,7 @@
|
||||
- block:
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - PKCS8 format"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_2.pem'
|
||||
type: X448
|
||||
format: pkcs8
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -437,7 +437,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - PKCS8 format (idempotent)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_2.pem'
|
||||
type: X448
|
||||
format: pkcs8
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -446,7 +446,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - raw format"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_2.pem'
|
||||
type: X448
|
||||
format: raw
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -456,7 +456,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read privatekey_fmt_2.pem"
|
||||
slurp:
|
||||
src: "{{ output_dir }}/privatekey_fmt_2.pem"
|
||||
src: "{{ remote_tmp_dir }}/privatekey_fmt_2.pem"
|
||||
ignore_errors: yes
|
||||
register: content
|
||||
|
||||
@@ -468,7 +468,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - raw format (idempotent)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_2.pem'
|
||||
type: X448
|
||||
format: raw
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -478,7 +478,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read privatekey_fmt_2.pem"
|
||||
slurp:
|
||||
src: "{{ output_dir }}/privatekey_fmt_2.pem"
|
||||
src: "{{ remote_tmp_dir }}/privatekey_fmt_2.pem"
|
||||
ignore_errors: yes
|
||||
register: content
|
||||
|
||||
@@ -490,7 +490,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - auto format (ignore)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_2.pem'
|
||||
type: X448
|
||||
format: auto_ignore
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -500,7 +500,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read privatekey_fmt_2.pem"
|
||||
slurp:
|
||||
src: "{{ output_dir }}/privatekey_fmt_2.pem"
|
||||
src: "{{ remote_tmp_dir }}/privatekey_fmt_2.pem"
|
||||
ignore_errors: yes
|
||||
register: content
|
||||
|
||||
@@ -512,7 +512,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - auto format (no ignore)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_fmt_2.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_fmt_2.pem'
|
||||
type: X448
|
||||
format: auto
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
@@ -520,10 +520,16 @@
|
||||
ignore_errors: yes
|
||||
register: privatekey_fmt_2_step_6
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read private key"
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/privatekey_fmt_2.pem'
|
||||
register: slurp
|
||||
when: privatekey_fmt_2_step_1 is not failed
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - verify that returned content is not base64 encoded"
|
||||
assert:
|
||||
that:
|
||||
- privatekey_fmt_2_step_6.privatekey == lookup('file', output_dir ~ '/privatekey_fmt_2.pem', rstrip=False)
|
||||
- privatekey_fmt_2_step_6.privatekey == (slurp.content | b64decode)
|
||||
when: privatekey_fmt_2_step_1 is not failed
|
||||
|
||||
when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=")'
|
||||
@@ -534,14 +540,14 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - setup simple keys"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
loop: "{{ regenerate_values }}"
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - setup password protected keys"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-b-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
passphrase: hunter2
|
||||
@@ -550,14 +556,14 @@
|
||||
loop: "{{ regenerate_values }}"
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - setup broken keys"
|
||||
copy:
|
||||
dest: '{{ output_dir }}/regenerate-c-{{ item }}.pem'
|
||||
dest: '{{ remote_tmp_dir }}/regenerate-c-{{ item }}.pem'
|
||||
content: 'broken key'
|
||||
mode: '0700'
|
||||
loop: "{{ regenerate_values }}"
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - modify broken keys (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-c-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-c-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -579,7 +585,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - modify broken keys"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-c-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-c-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -600,7 +606,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - modify password protected keys (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-b-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -622,7 +628,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - modify password protected keys"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-b-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -643,7 +649,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - not modify regular keys (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -661,7 +667,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - not modify regular keys"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -678,7 +684,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - adjust key size (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size + 20 }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -698,7 +704,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - adjust key size"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size + 20 }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -717,15 +723,15 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - redistribute keys"
|
||||
copy:
|
||||
src: '{{ output_dir }}/regenerate-a-always.pem'
|
||||
dest: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
src: '{{ remote_tmp_dir }}/regenerate-a-always.pem'
|
||||
dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
remote_src: true
|
||||
loop: "{{ regenerate_values }}"
|
||||
when: "item != 'always'"
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - adjust key type (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: DSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -745,7 +751,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - adjust key type"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: DSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
regenerate: '{{ item }}'
|
||||
@@ -765,15 +771,15 @@
|
||||
- block:
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - redistribute keys"
|
||||
copy:
|
||||
src: '{{ output_dir }}/regenerate-a-always.pem'
|
||||
dest: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
src: '{{ remote_tmp_dir }}/regenerate-a-always.pem'
|
||||
dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
remote_src: true
|
||||
loop: "{{ regenerate_values }}"
|
||||
when: "item != 'always'"
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - format mismatch (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: DSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
format: pkcs8
|
||||
@@ -794,7 +800,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - format mismatch"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: DSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
format: pkcs8
|
||||
@@ -814,15 +820,15 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - redistribute keys"
|
||||
copy:
|
||||
src: '{{ output_dir }}/regenerate-a-always.pem'
|
||||
dest: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
src: '{{ remote_tmp_dir }}/regenerate-a-always.pem'
|
||||
dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
remote_src: true
|
||||
loop: "{{ regenerate_values }}"
|
||||
when: "item != 'always'"
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - convert format (check mode)"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: DSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
format: pkcs1
|
||||
@@ -842,7 +848,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Regenerate - convert format"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}.pem'
|
||||
type: DSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
format: pkcs1
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
- name: Run module with backend autodetection
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_backend_selection.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey_backend_selection.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- block:
|
||||
@@ -51,12 +51,12 @@
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
@@ -75,7 +75,7 @@
|
||||
block:
|
||||
- name: "Fingerprint comparison: pyOpenSSL"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/fingerprint-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/fingerprint-{{ item }}.pem'
|
||||
type: "{{ item }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: pyopenssl
|
||||
@@ -86,7 +86,7 @@
|
||||
|
||||
- name: "Fingerprint comparison: cryptography"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/fingerprint-{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/fingerprint-{{ item }}.pem'
|
||||
type: "{{ item }}"
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
select_crypto_backend: cryptography
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
- set_fact:
|
||||
system_potentially_has_no_algorithm_support: "{{ ansible_os_family == 'FreeBSD' }}"
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Read private key"
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/privatekey1.pem'
|
||||
register: slurp
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey1 idempotency and content returned"
|
||||
assert:
|
||||
that:
|
||||
@@ -9,12 +14,12 @@
|
||||
- privatekey1 is changed
|
||||
- privatekey1_idempotence_check is not changed
|
||||
- privatekey1_idempotence is not changed
|
||||
- privatekey1.privatekey == lookup('file', output_dir ~ '/privatekey1.pem', rstrip=False)
|
||||
- privatekey1.privatekey == (slurp.content | b64decode)
|
||||
- privatekey1.privatekey == privatekey1_idempotence.privatekey
|
||||
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey1 (test - RSA key with size 4096 bits)"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey1.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey1.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
register: privatekey1
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey1 (assert - RSA key with size 4096 bits)"
|
||||
@@ -24,7 +29,7 @@
|
||||
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey2 (test - RSA key with size 2048 bits)"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey2.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey2.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
register: privatekey2
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey2 (assert - RSA key with size 2048 bits)"
|
||||
@@ -34,7 +39,7 @@
|
||||
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey3 (test - DSA key with size 3072 bits)"
|
||||
shell: "{{ openssl_binary }} dsa -noout -text -in {{ output_dir }}/privatekey3.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
shell: "{{ openssl_binary }} dsa -noout -text -in {{ remote_tmp_dir }}/privatekey3.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
register: privatekey3
|
||||
|
||||
- name: Validate privatekey3 (assert - DSA key with size 3072 bits)
|
||||
@@ -45,7 +50,7 @@
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey4 (test - Ensure key has been removed)"
|
||||
stat:
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
path: '{{ remote_tmp_dir }}/privatekey4.pem'
|
||||
register: privatekey4
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey4 (assert - Ensure key has been removed)"
|
||||
@@ -62,7 +67,7 @@
|
||||
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey5 (test - Passphrase protected key + idempotence)"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey5.pem -passin pass:ansible | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey5.pem -passin pass:ansible | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
register: privatekey5
|
||||
# Current version of OS/X that runs in the CI (10.11) does not have an up to date version of the OpenSSL library
|
||||
# leading to this test to fail when run in the CI. However, this test has been run for 10.12 and has returned succesfully.
|
||||
@@ -81,7 +86,7 @@
|
||||
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate privatekey6 (test - Passphrase protected key with non ascii character)"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey6.pem -passin pass:ànsïblé | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey6.pem -passin pass:ànsïblé | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
|
||||
register: privatekey6
|
||||
when: openssl_version.stdout is version('0.9.8zh', '>=')
|
||||
|
||||
@@ -92,7 +97,7 @@
|
||||
when: openssl_version.stdout is version('0.9.8zh', '>=')
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Validate ECC generation (dump with OpenSSL)"
|
||||
shell: "{{ openssl_binary }} ec -in {{ output_dir }}/privatekey-{{ item.item.curve }}.pem -noout -text | grep 'ASN1 OID: ' | sed 's/ASN1 OID: \\([^ ]*\\)/\\1/'"
|
||||
shell: "{{ openssl_binary }} ec -in {{ remote_tmp_dir }}/privatekey-{{ item.item.curve }}.pem -noout -text | grep 'ASN1 OID: ' | sed 's/ASN1 OID: \\([^ ]*\\)/\\1/'"
|
||||
loop: "{{ privatekey_ecc_generate.results }}"
|
||||
register: privatekey_ecc_dump
|
||||
when: openssl_version.stdout is version('0.9.8zh', '>=') and 'skip_reason' not in item
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
shippable/cloud/group1
|
||||
shippable/posix/group1
|
||||
destructive
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_pyopenssl
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user