Compare commits

...

88 Commits
2.1.0 ... 2.4.0

Author SHA1 Message Date
Felix Fontein
4dcbbfba5b Release 2.4.0. 2022-07-09 13:20:28 +02:00
Felix Fontein
036c4c8e6f Prepare 2.4.0. 2022-07-09 13:19:48 +02:00
Felix Fontein
9ed4526fee openssl_pkcs12: fix crash when trying to get non-existing other certificates (#487)
* Fix crash when trying to get non-existing other certificates.

* Add test.
2022-07-07 22:30:22 +02:00
Felix Fontein
b16f12faa3 Add docs PR workflow that a) builds docs and b) show the docs diff that a PR ceates. (#484) 2022-06-29 20:46:25 +02:00
Felix Fontein
9df02aa335 Next expected release is 2.4.0. 2022-06-21 12:22:01 +02:00
Felix Fontein
d60d3fe1cb Revert "Revert "Revert "Revert "Revert "Revert "Deprecate Ansible 2.9 and ansible-base 2.10 support. (#460)""""""
This reverts commit 4a1842c004.
2022-06-21 12:21:46 +02:00
Felix Fontein
a554a588c9 Release 2.3.4. 2022-06-21 12:11:22 +02:00
Felix Fontein
4a1842c004 Revert "Revert "Revert "Revert "Revert "Deprecate Ansible 2.9 and ansible-base 2.10 support. (#460)"""""
This reverts commit 39ec208171.
2022-06-21 12:09:00 +02:00
Felix Fontein
39ec208171 Revert "Revert "Revert "Revert "Deprecate Ansible 2.9 and ansible-base 2.10 support. (#460)""""
This reverts commit f5ccc1516b.
2022-06-17 09:26:38 +02:00
Felix Fontein
899de8227d Next expected release is 2.4.0. 2022-06-17 09:26:36 +02:00
Felix Fontein
5af4a16e57 Release 2.3.3. 2022-06-17 08:25:13 +02:00
Felix Fontein
fc07de73e3 Prepare 2.3.3 release. 2022-06-17 08:24:47 +02:00
Felix Fontein
f5ccc1516b Revert "Revert "Revert "Deprecate Ansible 2.9 and ansible-base 2.10 support. (#460)"""
(So we can do yet another bugfix release.)

This reverts commit cb77d81f8d.
2022-06-17 08:24:03 +02:00
Felix Fontein
de0ec1f739 Add Apache 2.0 license; simplify and standardize license headers (#478)
* Add Apache 2.0 license for Apache 2.0 licensed parts.

* Unify license headers.

* Move additional licenses to licenses/.

* Revert "Move additional licenses to licenses/."

This reverts commit c12b22de1c.
2022-06-17 08:20:40 +02:00
Songmin Li
b29f238083 Fix ValueError: excluded_subtrees must be a non-empty list or None (#481) 2022-06-17 07:53:07 +02:00
Felix Fontein
2941bb9bb8 Prepare 2.4.0 release. 2022-06-15 22:16:49 +02:00
Felix Fontein
297b44f24b x509_crl: do not crash when signing with Ed25519 or Ed448 (#475)
* Do not crash when signing with Ed25519 or Ed448.

* Forgot replace.
2022-06-15 22:06:40 +02:00
Felix Fontein
429ed5faa5 Skip Ansible 2.9 coverage reporting with new AZP container. (#476)
ci_coverage
2022-06-14 21:41:27 +02:00
Felix Fontein
b3029f75cd Bump AZP container version. (#472) 2022-06-13 21:16:19 +02:00
Felix Fontein
f7bc3aa77c Disable broken CI platforms. (#469) 2022-06-05 23:11:29 +02:00
Felix Fontein
cb77d81f8d Revert "Revert "Deprecate Ansible 2.9 and ansible-base 2.10 support. (#460)""
This reverts commit 798d12b499.
2022-06-02 12:52:58 +02:00
Felix Fontein
b87617945e Next expected release is 2.4.0. 2022-06-02 12:52:37 +02:00
Felix Fontein
9289ce8534 Release 2.3.2. 2022-06-02 12:28:12 +02:00
Felix Fontein
798d12b499 Revert "Deprecate Ansible 2.9 and ansible-base 2.10 support. (#460)"
(This is so we can do a bugfix release now. Deprecations are not alloewd in bugfix releases.)

This reverts commit 74960eaeac.
2022-06-02 07:49:28 +02:00
Felix Fontein
5146760def Adjust release summary, since there are other fragments. 2022-06-02 07:49:16 +02:00
Felix Fontein
48649d50b5 Prepare 2.3.2 release. 2022-06-02 07:46:42 +02:00
Felix Fontein
ccd66419f4 Add simplified_bsd.txt license file (#467)
* Add simplified_bsd.txt and adjust references.

* Add changelog.
2022-06-02 07:45:50 +02:00
Felix Fontein
80334884fb Update CI matrix. (#464) 2022-05-27 11:00:01 +02:00
Andrew Pantuso
4ab45e8c21 ci: enable rhel9.0 tests for openssh_cert (#463)
* ci: enable rhel9.0 tests for openssh_cert

* ci: allow openssh_cert second signature algorithm test for versions >8.7

* ci: narrowing condition to not attempt RSA1 signing exclusively on RHEL >=9

* ci: grouping and documenting condition
2022-05-21 16:43:54 +02:00
Felix Fontein
c566a7abf3 Add RHEL 9.0, FreeBSD 13.1, Ubuntu 22.04 and Fedora 36 to CI (#456)
* Add RHEL 9.0 and FreeBSD 13.1 to CI.

* Add Ubuntu 22.04 and Fedora 36 to CI.

* Switch orders so that root doesn't have a SHA1 signature.

* Skip openssh_cert test on RHEL 9.0.

* Make it possible that pyOpenSSL isn't installed *at all*.

* Work with default.
2022-05-20 23:03:54 +02:00
Felix Fontein
fd0048827d Remove FreeBSD 12.1 from CI. The remote seems to be no longer working. (#459) 2022-05-20 14:47:05 +02:00
Felix Fontein
74960eaeac Deprecate Ansible 2.9 and ansible-base 2.10 support. (#460) 2022-05-20 14:45:56 +02:00
Felix Fontein
c49102d688 certificate_complete_chain: do not stop execution on unsupported algorithm (#457)
* Do not stop execution on unsupported algorithm.

* Fix typo.
2022-05-20 07:22:35 +02:00
Felix Fontein
40cf8ba2ce Next expected release is 2.4.0. 2022-05-16 13:02:15 +02:00
Felix Fontein
ffc0ab2d40 Release 2.3.1. 2022-05-16 12:27:29 +02:00
Felix Fontein
7183596586 Update with actual CPython 3.9.5 license. (#454) 2022-05-16 08:24:43 +02:00
Felix Fontein
5664bfe4b6 Add PSF-license.txt file. (#453) 2022-05-16 07:40:04 +02:00
Felix Fontein
4074ff4132 Prepare 2.3.1 release. 2022-05-16 07:13:15 +02:00
Felix Fontein
e7f9885aa3 Next expected release is 2.4.0. 2022-05-09 21:11:07 +02:00
Felix Fontein
5641e2ac9b Release 2.3.0. 2022-05-09 20:53:39 +02:00
Felix Fontein
4cf951596f Improve handling of IDNA/Unicode domains (#436)
* Prepare IDNA/Unicode conversion code. Use to normalize input.

* Use IDNA library first (IDNA2008) and Python's IDNA2003 implementation as a fallback.

* Make sure idna is installed.

* Add changelog fragment.

* 'punycode' → 'idna'.

* Add name_encoding options and tests.

* Avoid invalid character for IDNA2008.

* Linting.

* Forgot to upate value.

* Work around cryptography bug. Fix port handling for URIs.

* Forgot other place sensitive to cryptography bug.

* Forgot one. (Will likely still fail.)

* Decode IDNA in _compress_entry() to avoid comparison screw-ups.

* Work around Python 3.5 problem in Ansible 2.9's default test container.

* Update changelog fragment.

* Fix error, add tests.

* Python 2 compatibility.

* Update requirements.
2022-05-09 19:57:14 +02:00
Felix Fontein
90efcc1ca7 Add privatekey_content option. (#452) 2022-05-09 19:56:08 +02:00
Felix Fontein
8a1c60e54a Incorporate feedback from #443 that ACME modules work with Sectigo ACME Service for InCommon (#451)
* Incorporate feedback from #443.

* Update comment.
2022-05-09 13:28:03 +02:00
Felix Fontein
43665a3892 Prepare 2.3.0 release. 2022-05-03 19:24:20 +02:00
Felix Fontein
640bdbc066 Add EE support (#440)
* Add EE files.

* Install cryptography and PyOpenSSL from PyPi.

* Revert "Install cryptography and PyOpenSSL from PyPi."

This reverts commit 6b90a1efae.

* Only run test when cryptography has a new enough version.

* And another one.

* Extend changelog.
2022-05-03 19:22:55 +02:00
Jonas Verhofsté
c16d9f78b8 Make request timeout configurable for all acme modules (#448)
* Make request timeout configurable for all acme modules

Fixes #447.

* Log change made in #448
2022-05-03 17:29:38 +02:00
Felix Fontein
91f192ce5b Fix main for new cryptography 37.0.0 release (#445)
* Fix empty check for openssl_pkcs12 tests.

* Remove unnecessary imports.

* Prevent crash if PyOpenSSL cannot be imported because of an AttributeError.

* Add changelog fragment.

* Fix constraints file.

* Use Python 2.7 instead of 3.5 for 2.9 cloud tests (pip module is broken).

* Prevent upgrading cryptography on ansible-core 2.12's default container with Python 3.9.
2022-04-26 22:18:37 +02:00
Felix Fontein
e560acdac5 Remove distutils from unit tests. (#444) 2022-04-21 11:05:18 +02:00
Felix Fontein
9d03178b00 Fix crash in x509_crl when certificate issuer is specified (#441)
* Fix x509_crl certificate issuer issue.

* Add tests.

* Add changelog fragment.
2022-04-18 08:17:27 +02:00
Yauhen
041fff5057 Add persistent and perf options to the luks_device (#434)
Read and write work queue significantly degrades performance on
SSD/NVME devices[1].

In Debian 11 crypttab does not support no-read-workqueue and
no-write-workqueue flags, so the persistent flag is workaround: once
opened with perf parameters persists forever.

[1] https://blog.cloudflare.com/speeding-up-linux-disk-encryption/

Signed-off-by: Yauhen Artsiukhou <jsirex@gmail.com>
2022-04-10 14:30:10 +02:00
Felix Fontein
c7f581daad Switch from antsibull to antsibull-docs. (#438) 2022-04-10 10:43:36 +02:00
Felix Fontein
b47168994d Remove OpenSuSE Python 2 from devel CI. (#435) 2022-04-02 18:09:09 +02:00
bluikko
635b25519b Document OpenSSH 7.7 required for validity always (#429)
* Document OpenSSH 7.7 required for validity always

* Document cert start time option for OpenSSH <7.7

* Improve language of "always" time support

* Update language on `always` to suggested

* Fix indetation
2022-04-02 12:02:42 -04:00
Felix Fontein
bc00c30faf Replace antsibull-lint collection-docs with antsibull-docs lint-collection-docs. (#432) 2022-03-30 08:00:14 +02:00
Felix Fontein
a28b2a5b4b Add stable-2.13 to CI, thin out older version matrix (#425)
* Add stable-2.13 to CI, thin out older version matrix.

* Thin out a bit more.
2022-03-29 06:49:38 +02:00
Felix Fontein
9e611a6148 Next expected release is 2.3.0. 2022-03-22 13:44:19 +01:00
Felix Fontein
025091c3fb Release 2.2.4 2022-03-22 13:17:36 +01:00
Felix Fontein
b0cede8231 Prepare 2.2.4 release. 2022-03-22 07:31:54 +01:00
Felix Fontein
22084b26d4 Add collection links file. (#421) 2022-03-22 07:04:23 +01:00
Felix Fontein
867158a942 Run ACME tests on more targets. (#419) 2022-03-12 08:55:06 +01:00
Andrew Pantuso
033bab7db1 openssh_* - catch and report top-level exceptions via fail_json (#417)
* ensure exceptions are properly reported

* adding changelog fragment

* applying review suggestions

* typo

* adding back exception msg
2022-03-08 13:23:09 +01:00
Felix Fontein
47d9fad45f Next expected release is 2.3.0. 2022-03-04 08:12:32 +01:00
Felix Fontein
f82dcbea21 Release 2.2.3. 2022-03-04 07:38:44 +01:00
Felix Fontein
67f511b5ad Prepare 2.2.3 release. 2022-03-03 21:18:07 +01:00
Andrew Pantuso
010f1a4d2d fixing public key return value docs (#412) 2022-03-02 13:52:07 +01:00
Felix Fontein
0d4b3ed991 Fix parsing of lsblk output. (#410) 2022-03-02 13:48:38 +01:00
Felix Fontein
2f2c8b57e8 Next expected release is 2.3.0. 2022-02-21 22:41:39 +01:00
Felix Fontein
b952b103e2 Releasing 2.2.2. 2022-02-21 22:11:55 +01:00
Felix Fontein
c85659ebfc Prepare 2.2.2 release. 2022-02-19 18:55:41 +01:00
Felix Fontein
73c8577b61 Integrate Alpine into CI (#408)
* Integrate Alpine into CI.

* Fix package names.
2022-02-19 17:54:05 +00:00
Felix Fontein
84c1a20af7 CI: add community ansible-test images (#404)
* Use community ansible-test images.

* Adjust tests for new operating systems, and pass on Python version as well.

* Fix Python version.

Co-authored-by: David Moreau Simard <moi@dmsimard.com>

* Fix package name.

Co-authored-by: David Moreau Simard <moi@dmsimard.com>
2022-02-17 22:29:50 +01:00
Felix Fontein
28729657ac x509_certificate: check existing certificate's signature for selfsigned and ownca provider (#407)
* Verify whether signature matches.

* Add changelog fragment.

* Forgot imports.

* Fix wrong name.

* Check whether the CA private key fits to the CA certificate. Use correct key in tests.

* Refactor code.
2022-02-16 07:38:11 +01:00
Felix Fontein
3ebc132c03 Regenerate certificate on CA's subject change. (#402) 2022-02-14 18:04:29 +01:00
Felix Fontein
11a14543c8 certificate_complete_chain: handle duplicate intermediate subjects (#403)
* Allow multiple intermediate CAs to have same subject.

* Add tests.

* Fix test name.

* Don't use CN for SAN.

* Make a bit more compatible.

* Include jinja2 compat for CentOS 6.
2022-02-14 13:29:19 +01:00
Felix Fontein
7e92f04c93 Next expected release is 2.3.0. 2022-02-05 21:51:19 +01:00
Felix Fontein
8a74b3e259 Release 2.2.1. 2022-02-05 21:28:47 +01:00
Felix Fontein
a9fcd584e9 Prepare 2.2.1 release. 2022-02-05 20:18:32 +01:00
Andrew Pantuso
a307618872 openssh_cert - fix full_idempotence for host certificates (#396)
* fixing host cert idempotence

* adding changelog fragment
2022-02-04 20:53:50 +01:00
Felix Fontein
12749088a0 Next expected release is 2.3.0. 2022-02-01 06:25:49 +01:00
Felix Fontein
90da233341 Release 2.2.0. 2022-02-01 05:49:27 +01:00
Felix Fontein
23226dce8f Drop CentOS 8 from CI. (#393) 2022-01-31 21:17:41 +00:00
Felix Fontein
9faed1dad0 Prepare 2.2.0 release. 2022-01-31 06:02:48 +01:00
Felix Fontein
ea2e45d63f Set LANG and similar env variables to prevent translated cryptsetup output. (#388) 2022-01-30 21:30:56 +01:00
Felix Fontein
5abfe8fca9 PyOpenSSL 22.0.0 no longer supports Python 2.7. (#387) 2022-01-30 13:59:32 +01:00
JochenKorge
b339e71973 Added 'ignore_timestamps' parameter (#381)
* Added 'ignore_timestamps' parameter

* Update plugins/modules/openssh_cert.py

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

* Update plugins/modules/openssh_cert.py

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

* Update plugins/modules/openssh_cert.py

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

* Added fragment

* Update plugins/modules/openssh_cert.py

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

* added ignore_timestamps to example

* corrected styling

* fixed styling (again)

* Update changelogs/fragments/381_openssh_cert_add_ignore_timestamps.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* splitted description as suggested by felixfontein

* fixed linebreak

* Mentioned ignore_timestamps in regenerate

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-20 16:15:50 +01:00
Felix Fontein
a467f036b1 Fix indentation of when in example. (#382) 2022-01-18 21:52:53 +01:00
Felix Fontein
cd5ed011a5 Update CI matrix for Remote Devel (#377)
* Update CI matrix for Remote Devel.

* Add Python info entries.
2022-01-13 09:18:48 +01:00
Felix Fontein
9dfdaaf471 Next expected release is 2.2.0. 2022-01-10 23:03:02 +01:00
122 changed files with 2876 additions and 680 deletions

View File

@@ -41,7 +41,7 @@ variables:
resources:
containers:
- container: default
image: quay.io/ansible/azure-pipelines-test-container:1.9.0
image: quay.io/ansible/azure-pipelines-test-container:3.0.0
pool: Standard
@@ -60,6 +60,17 @@ stages:
test: 'devel/sanity/extra'
- name: Units
test: 'devel/units/1'
- stage: Ansible_2_13
displayName: Sanity & Units 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
targets:
- name: Sanity
test: '2.13/sanity/1'
- name: Units
test: '2.13/units/1'
- stage: Ansible_2_12
displayName: Sanity & Units 2.12
dependsOn: []
@@ -115,18 +126,34 @@ stages:
targets:
- name: CentOS 7
test: centos7
- name: Fedora 34
test: fedora34
- name: Fedora 35
test: fedora35
- name: openSUSE 15 py2
test: opensuse15py2
- name: openSUSE 15 py3
- name: Fedora 36
test: fedora36
- name: openSUSE 15
test: opensuse15
- name: Ubuntu 18.04
test: ubuntu1804
- name: Ubuntu 20.04
test: ubuntu2004
- name: Ubuntu 22.04
test: ubuntu2204
- name: Alpine 3
test: alpine3
- stage: Docker_2_13
displayName: Docker 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/linux/{0}/1
targets:
- name: openSUSE 15 py2
test: opensuse15py2
- name: Fedora 34
test: fedora34
- name: Ubuntu 18.04
test: ubuntu1804
- name: Alpine 3
test: alpine3
- stage: Docker_2_12
displayName: Docker 2.12
dependsOn: []
@@ -137,14 +164,8 @@ stages:
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: []
@@ -155,14 +176,10 @@ stages:
targets:
- name: CentOS 7
test: centos7
- name: CentOS 8
test: centos8
- name: Fedora 32
test: fedora32
- name: openSUSE 15 py2
test: opensuse15py2
- name: Ubuntu 18.04
test: ubuntu1804
- name: Alpine 3
test: alpine3
- stage: Docker_2_10
displayName: Docker 2.10
dependsOn: []
@@ -173,8 +190,6 @@ stages:
targets:
- name: CentOS 6
test: centos6
- name: Fedora 31
test: fedora31
- stage: Docker_2_9
displayName: Docker 2.9
dependsOn: []
@@ -183,17 +198,27 @@ stages:
parameters:
testFormat: 2.9/linux/{0}/1
targets:
- name: CentOS 6
test: centos6
- name: CentOS 7
test: centos7
- name: Fedora 31
test: fedora31
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 18.04
test: ubuntu1804
### Community Docker
- stage: Docker_community_devel
displayName: Docker (community images) devel
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux-community/{0}/1
targets:
- name: Debian Bullseye
test: debian-bullseye/3.9
- name: ArchLinux
test: archlinux/3.10
- name: CentOS Stream 8
test: centos-stream8/3.8
### Remote
- stage: Remote_devel
displayName: Remote devel
@@ -203,14 +228,28 @@ stages:
parameters:
testFormat: devel/{0}/1
targets:
- name: macOS 11.1
test: macos/11.1
- name: macOS 12.0
test: macos/12.0
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 9.0
test: rhel/9.0
- name: FreeBSD 12.3
test: freebsd/12.3
- name: FreeBSD 13.1
test: freebsd/13.1
- stage: Remote_2_13
displayName: Remote 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/{0}/1
targets:
- name: macOS 12.0
test: macos/12.0
- name: RHEL 8.5
test: rhel/8.5
- name: FreeBSD 12.2
test: freebsd/12.2
- name: FreeBSD 13.0
test: freebsd/13.0
- stage: Remote_2_12
@@ -221,12 +260,10 @@ stages:
parameters:
testFormat: 2.12/{0}/1
targets:
- name: macOS 11.1
test: macos/11.1
# - 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: []
@@ -235,8 +272,6 @@ stages:
parameters:
testFormat: 2.11/{0}/1
targets:
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.3
test: rhel/8.3
- name: FreeBSD 12.2
@@ -251,10 +286,8 @@ stages:
targets:
- name: OS X 10.11
test: osx/10.11
- name: macOS 10.15
test: macos/10.15
- name: FreeBSD 12.1
test: freebsd/12.1
# - name: macOS 10.15
# test: macos/10.15
- stage: Remote_2_9
displayName: Remote 2.9
dependsOn: []
@@ -282,6 +315,17 @@ stages:
- test: 3.8
- test: 3.9
- test: "3.10"
- stage: Cloud_2_13
displayName: Cloud 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.13/cloud/{0}/1
targets:
- test: 2.7
- test: 3.7
- stage: Cloud_2_12
displayName: Cloud 2.12
dependsOn: []
@@ -322,7 +366,7 @@ stages:
nameFormat: Python {0}
testFormat: 2.9/cloud/{0}/1
targets:
- test: 3.5
- test: 2.7
## Finally
@@ -330,21 +374,26 @@ stages:
condition: succeededOrFailed()
dependsOn:
- Ansible_devel
- Ansible_2_13
- Ansible_2_12
- Ansible_2_11
- Ansible_2_10
- Ansible_2_9
- Remote_devel
- Remote_2_13
- Remote_2_12
- Remote_2_11
- Remote_2_10
- Remote_2_9
- Docker_devel
- Docker_2_13
- Docker_2_12
- Docker_2_11
- Docker_2_10
- Docker_2_9
- Docker_community_devel
- Cloud_devel
- Cloud_2_13
- Cloud_2_12
- Cloud_2_11
- Cloud_2_10

View File

@@ -9,6 +9,10 @@ PATH="${PWD}/bin:${PATH}"
mkdir "${agent_temp_directory}/coverage/"
if [[ "$(ansible --version)" =~ \ 2\.9\. ]]; then
exit
fi
options=(--venv --venv-system-site-packages --color -v)
ansible-test coverage combine --group-by command --export "${agent_temp_directory}/coverage/" "${options[@]}"

View File

@@ -5,6 +5,10 @@ set -o pipefail -eu
PATH="${PWD}/bin:${PATH}"
if [[ "$(ansible --version)" =~ \ 2\.9\. ]]; then
exit
fi
if ! ansible-test --help >/dev/null 2>&1; then
# Install the devel version of ansible-test for generating code coverage reports.
# This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).

54
.github/workflows/docs-pr.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Collection Docs
concurrency:
group: docs-${{ github.head_ref }}
cancel-in-progress: true
on:
pull_request_target:
types: [opened, synchronize, reopened, closed]
jobs:
build-docs:
permissions:
contents: read
name: Build Ansible Docs
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main
with:
init-fail-on-error: true
ansible-ref: devel
comment:
permissions:
pull-requests: write
runs-on: ubuntu-latest
needs: build-docs
name: PR comments
steps:
- name: PR comment
uses: ansible-community/github-docs-build/actions/ansible-docs-build-comment@main
with:
body-includes: '## Docs Build'
reactions: heart
action: ${{ needs.build-docs.outputs.changed != 'true' && 'remove' || '' }}
on-closed-body: |
## Docs Build 📝
This PR is closed and any previously published docsite has been unpublished.
on-merged-body: |
## Docs Build 📝
Thank you for contribution!✨
This PR has been merged and your docs changes will be incorporated when they are next published.
body: |
## Docs Build 📝
Thank you for contribution!✨
The docsite for **this PR** is available for download as an artifact from this run:
${{ needs.build-docs.outputs.artifact-url }}
File changes:
${{ needs.build-docs.outputs.diff-files-rendered }}
${{ needs.build-docs.outputs.diff-rendered }}

109
.github/workflows/ee.yml vendored Normal file
View File

@@ -0,0 +1,109 @@
---
name: execution environment
on:
# Run CI against all pushes (direct commits, also merged PRs), Pull Requests
push:
branches:
- main
- stable-*
pull_request:
# Run CI once per day (at 04:45 UTC)
# This ensures that even if there haven't been commits that we are still testing against latest version of ansible-builder
schedule:
- cron: '45 4 * * *'
env:
NAMESPACE: community
COLLECTION_NAME: crypto
jobs:
build:
name: Build and test EE (Ⓐ${{ matrix.runner_tag }})
strategy:
matrix:
runner_tag:
- devel
- stable-2.12-latest
- stable-2.11-latest
- stable-2.9-latest
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
with:
path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.10'
- name: Install ansible-builder and ansible-navigator
run: pip install ansible-builder ansible-navigator
- name: Verify requirements
run: ansible-builder introspect --sanitize .
- name: Make sure galaxy.yml has version entry
run: >-
python -c
'import yaml ;
f = open("galaxy.yml", "rb") ;
data = yaml.safe_load(f) ;
f.close() ;
data["version"] = data.get("version") or "0.0.1" ;
f = open("galaxy.yml", "wb") ;
f.write(yaml.dump(data).encode("utf-8")) ;
f.close() ;
'
working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
- name: Build collection
run: |
ansible-galaxy collection build --output-path ../../../
working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
- name: Create files for building execution environment
run: |
COLLECTION_FILENAME="$(ls "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz)"
# EE config
cat > execution-environment.yml <<EOF
---
version: 1
build_arg_defaults:
EE_BASE_IMAGE: 'quay.io/ansible/ansible-runner:${{ matrix.runner_tag }}'
dependencies:
galaxy: requirements.yml
EOF
echo "::group::execution-environment.yml"
cat execution-environment.yml
echo "::endgroup::"
# Requirements
cat > requirements.yml <<EOF
---
collections:
- name: ${COLLECTION_FILENAME}
type: file
EOF
echo "::group::requirements.yml"
cat requirements.yml
echo "::endgroup::"
- name: Build image based on ${{ matrix.runner_tag }}
run: |
mkdir -p context/_build/
cp "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz context/_build/
ansible-builder build -v 3 -t test-ee:latest --container-runtime=podman
- name: Run basic tests
run: >
ansible-navigator run
--mode stdout
--pull-policy never
--set-environment-variable ANSIBLE_PRIVATE_ROLE_VARS=true
--execution-environment-image test-ee:latest
-v
all.yml
working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}/tests/ee

202
Apache-2.0.txt Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -5,6 +5,188 @@ Community Crypto Release Notes
.. contents:: Topics
v2.4.0
======
Release Summary
---------------
Deprecation and bugfix release. No new features this time.
Deprecated Features
-------------------
- Support for Ansible 2.9 and ansible-base 2.10 is deprecated, and will be removed in the next major release (community.crypto 3.0.0). Some modules might still work with these versions afterwards, but we will no longer keep compatibility code that was needed to support them (https://github.com/ansible-collections/community.crypto/pull/460).
Bugfixes
--------
- openssl_pkcs12 - when using the pyOpenSSL backend, do not crash when trying to read non-existing other certificates (https://github.com/ansible-collections/community.crypto/issues/486, https://github.com/ansible-collections/community.crypto/pull/487).
v2.3.4
======
Release Summary
---------------
Re-release of what was intended to be 2.3.3.
A mistake during the release process caused the 2.3.3 tag to end up on the
commit for 1.9.17, which caused the release pipeline to re-publish 1.9.17
as 2.3.3.
This release is identical to what should have been 2.3.3, except that the
version number has been bumped to 2.3.4 and this changelog entry for 2.3.4
has been added.
v2.3.3
======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- Include ``Apache-2.0.txt`` file for ``plugins/module_utils/crypto/_obj2txt.py`` and ``plugins/module_utils/crypto/_objects_data.py``.
- openssl_csr - the module no longer crashes with 'permitted_subtrees/excluded_subtrees must be a non-empty list or None' if only one of ``name_constraints_permitted`` and ``name_constraints_excluded`` is provided (https://github.com/ansible-collections/community.crypto/issues/481).
- x509_crl - do not crash when signing CRL with Ed25519 or Ed448 keys (https://github.com/ansible-collections/community.crypto/issues/473, https://github.com/ansible-collections/community.crypto/pull/474).
v2.3.2
======
Release Summary
---------------
Maintenance and bugfix release.
Bugfixes
--------
- Include ``simplified_bsd.txt`` license file for the ECS module utils.
- certificate_complete_chain - do not stop execution if an unsupported signature algorithm is encountered; warn instead (https://github.com/ansible-collections/community.crypto/pull/457).
v2.3.1
======
Release Summary
---------------
Maintenance release.
Bugfixes
--------
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
v2.3.0
======
Release Summary
---------------
Feature and bugfix release.
Minor Changes
-------------
- Prepare collection for inclusion in an Execution Environment by declaring its dependencies. Please note that system packages are used for cryptography and PyOpenSSL, which can be rather limited. If you need features from newer cryptography versions, you will have to manually force a newer version to be installed by pip by specifying something like ``cryptography >= 37.0.0`` in your Execution Environment's Python dependencies file (https://github.com/ansible-collections/community.crypto/pull/440).
- Support automatic conversion for Internalionalized Domain Names (IDNs). When passing general names, for example Subject Altenative Names to ``community.crypto.openssl_csr``, these will automatically be converted to IDNA. Conversion will be done per label to IDNA2008 if possible, and IDNA2003 if IDNA2008 conversion fails for that label. Note that IDNA conversion requires `the Python idna library <https://pypi.org/project/idna/>`_ to be installed. Please note that depending on which versions of the cryptography library are used, it could try to process the converted IDNA another time with the Python ``idna`` library and reject IDNA2003 encoded values. Using a new enough ``cryptography`` version avoids this (https://github.com/ansible-collections/community.crypto/issues/426, https://github.com/ansible-collections/community.crypto/pull/436).
- acme_* modules - add parameter ``request_timeout`` to manage HTTP(S) request timeout (https://github.com/ansible-collections/community.crypto/issues/447, https://github.com/ansible-collections/community.crypto/pull/448).
- luks_devices - added ``perf_same_cpu_crypt``, ``perf_submit_from_crypt_cpus``, ``perf_no_read_workqueue``, ``perf_no_write_workqueue`` for performance tuning when opening LUKS2 containers (https://github.com/ansible-collections/community.crypto/issues/427).
- luks_devices - added ``persistent`` option when opening LUKS2 containers (https://github.com/ansible-collections/community.crypto/pull/434).
- openssl_csr_info - add ``name_encoding`` option to control the encoding (IDNA, Unicode) used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
- openssl_pkcs12 - allow to provide the private key as text instead of having to read it from a file. This allows to store the private key in an encrypted form, for example in Ansible Vault (https://github.com/ansible-collections/community.crypto/pull/452).
- x509_certificate_info - add ``name_encoding`` option to control the encoding (IDNA, Unicode) used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
- x509_crl - add ``name_encoding`` option to control the encoding (IDNA, Unicode) used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
- x509_crl_info - add ``name_encoding`` option to control the encoding (IDNA, Unicode) used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
Bugfixes
--------
- Make collection more robust when PyOpenSSL is used with an incompatible cryptography version (https://github.com/ansible-collections/community.crypto/pull/445).
- x509_crl - fix crash when ``issuer`` for a revoked certificate is specified (https://github.com/ansible-collections/community.crypto/pull/441).
v2.2.4
======
Release Summary
---------------
Regular maintenance release.
Bugfixes
--------
- openssh_* modules - fix exception handling to report traceback to users for enhanced traceability (https://github.com/ansible-collections/community.crypto/pull/417).
v2.2.3
======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- luks_device - fix parsing of ``lsblk`` output when device name ends with ``crypt`` (https://github.com/ansible-collections/community.crypto/issues/409, https://github.com/ansible-collections/community.crypto/pull/410).
v2.2.2
======
Release Summary
---------------
Regular bugfix release.
In this release, we extended the test matrix to include Alpine 3, ArchLinux, Debian Bullseye, and CentOS Stream 8. CentOS 8 was removed from the test matrix.
Bugfixes
--------
- certificate_complete_chain - allow multiple potential intermediate certificates to have the same subject (https://github.com/ansible-collections/community.crypto/issues/399, https://github.com/ansible-collections/community.crypto/pull/403).
- x509_certificate - for the ``ownca`` provider, check whether the CA private key actually belongs to the CA certificate (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's public key changes for ``provider=ownca`` (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's subject changes for ``provider=ownca`` (https://github.com/ansible-collections/community.crypto/issues/400, https://github.com/ansible-collections/community.crypto/pull/402).
- x509_certificate - regenerate certificate when the private key changes for ``provider=selfsigned`` (https://github.com/ansible-collections/community.crypto/pull/407).
v2.2.1
======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- openssh_cert - fixed false ``changed`` status for ``host`` certificates when using ``full_idempotence`` (https://github.com/ansible-collections/community.crypto/issues/395, https://github.com/ansible-collections/community.crypto/pull/396).
v2.2.0
======
Release Summary
---------------
Regular bugfix and feature release.
Minor Changes
-------------
- openssh_cert - added ``ignore_timestamps`` parameter so it can be used semi-idempotent with relative timestamps in ``valid_to``/``valid_from`` (https://github.com/ansible-collections/community.crypto/issues/379).
Bugfixes
--------
- luks_devices - set ``LANG`` and similar environment variables to avoid translated output, which can break some of the module's functionality like key management (https://github.com/ansible-collections/community.crypto/pull/388, https://github.com/ansible-collections/community.crypto/issues/385).
v2.1.0
======

48
PSF-license.txt Normal file
View File

@@ -0,0 +1,48 @@
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.

View File

@@ -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, 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.
Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12 and ansible-core 2.13 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported.
## External requirements

View File

@@ -737,3 +737,207 @@ releases:
name: openssl_privatekey_convert
namespace: ''
release_date: '2022-01-10'
2.2.0:
changes:
bugfixes:
- luks_devices - set ``LANG`` and similar environment variables to avoid translated
output, which can break some of the module's functionality like key management
(https://github.com/ansible-collections/community.crypto/pull/388, https://github.com/ansible-collections/community.crypto/issues/385).
minor_changes:
- openssh_cert - added ``ignore_timestamps`` parameter so it can be used semi-idempotent
with relative timestamps in ``valid_to``/``valid_from`` (https://github.com/ansible-collections/community.crypto/issues/379).
release_summary: Regular bugfix and feature release.
fragments:
- 2.2.0.yml
- 381_openssh_cert_add_ignore_timestamps.yml
- 388-luks_device-i18n.yml
release_date: '2022-02-01'
2.2.1:
changes:
bugfixes:
- openssh_cert - fixed false ``changed`` status for ``host`` certificates when
using ``full_idempotence`` (https://github.com/ansible-collections/community.crypto/issues/395,
https://github.com/ansible-collections/community.crypto/pull/396).
release_summary: Bugfix release.
fragments:
- 2.2.1.yml
- 396-openssh_cert-host-cert-idempotence-fix.yml
release_date: '2022-02-05'
2.2.2:
changes:
bugfixes:
- certificate_complete_chain - allow multiple potential intermediate certificates
to have the same subject (https://github.com/ansible-collections/community.crypto/issues/399,
https://github.com/ansible-collections/community.crypto/pull/403).
- x509_certificate - for the ``ownca`` provider, check whether the CA private
key actually belongs to the CA certificate (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's public key changes
for ``provider=ownca`` (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's subject changes for
``provider=ownca`` (https://github.com/ansible-collections/community.crypto/issues/400,
https://github.com/ansible-collections/community.crypto/pull/402).
- x509_certificate - regenerate certificate when the private key changes for
``provider=selfsigned`` (https://github.com/ansible-collections/community.crypto/pull/407).
release_summary: 'Regular bugfix release.
In this release, we extended the test matrix to include Alpine 3, ArchLinux,
Debian Bullseye, and CentOS Stream 8. CentOS 8 was removed from the test matrix.
'
fragments:
- 2.2.2.yml
- 402-x509_certificate-ownca-subject.yml
- 403-certificate_complete_chain-same-subject.yml
- 407-x509_certificate-signature.yml
release_date: '2022-02-21'
2.2.3:
changes:
bugfixes:
- luks_device - fix parsing of ``lsblk`` output when device name ends with ``crypt``
(https://github.com/ansible-collections/community.crypto/issues/409, https://github.com/ansible-collections/community.crypto/pull/410).
release_summary: Regular bugfix release.
fragments:
- 2.2.3.yml
- 410-luks_device-lsblk-parsing.yml
release_date: '2022-03-04'
2.2.4:
changes:
bugfixes:
- openssh_* modules - fix exception handling to report traceback to users for
enhanced traceability (https://github.com/ansible-collections/community.crypto/pull/417).
release_summary: Regular maintenance release.
fragments:
- 2.2.4.yml
- 417-openssh_modules-fix-exception-reporting.yml
release_date: '2022-03-22'
2.3.0:
changes:
bugfixes:
- Make collection more robust when PyOpenSSL is used with an incompatible cryptography
version (https://github.com/ansible-collections/community.crypto/pull/445).
- x509_crl - fix crash when ``issuer`` for a revoked certificate is specified
(https://github.com/ansible-collections/community.crypto/pull/441).
minor_changes:
- Prepare collection for inclusion in an Execution Environment by declaring
its dependencies. Please note that system packages are used for cryptography
and PyOpenSSL, which can be rather limited. If you need features from newer
cryptography versions, you will have to manually force a newer version to
be installed by pip by specifying something like ``cryptography >= 37.0.0``
in your Execution Environment's Python dependencies file (https://github.com/ansible-collections/community.crypto/pull/440).
- Support automatic conversion for Internalionalized Domain Names (IDNs). When
passing general names, for example Subject Altenative Names to ``community.crypto.openssl_csr``,
these will automatically be converted to IDNA. Conversion will be done per
label to IDNA2008 if possible, and IDNA2003 if IDNA2008 conversion fails for
that label. Note that IDNA conversion requires `the Python idna library <https://pypi.org/project/idna/>`_
to be installed. Please note that depending on which versions of the cryptography
library are used, it could try to process the converted IDNA another time
with the Python ``idna`` library and reject IDNA2003 encoded values. Using
a new enough ``cryptography`` version avoids this (https://github.com/ansible-collections/community.crypto/issues/426,
https://github.com/ansible-collections/community.crypto/pull/436).
- acme_* modules - add parameter ``request_timeout`` to manage HTTP(S) request
timeout (https://github.com/ansible-collections/community.crypto/issues/447,
https://github.com/ansible-collections/community.crypto/pull/448).
- luks_devices - added ``perf_same_cpu_crypt``, ``perf_submit_from_crypt_cpus``,
``perf_no_read_workqueue``, ``perf_no_write_workqueue`` for performance tuning
when opening LUKS2 containers (https://github.com/ansible-collections/community.crypto/issues/427).
- luks_devices - added ``persistent`` option when opening LUKS2 containers (https://github.com/ansible-collections/community.crypto/pull/434).
- openssl_csr_info - add ``name_encoding`` option to control the encoding (IDNA,
Unicode) used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
- openssl_pkcs12 - allow to provide the private key as text instead of having
to read it from a file. This allows to store the private key in an encrypted
form, for example in Ansible Vault (https://github.com/ansible-collections/community.crypto/pull/452).
- x509_certificate_info - add ``name_encoding`` option to control the encoding
(IDNA, Unicode) used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
- x509_crl - add ``name_encoding`` option to control the encoding (IDNA, Unicode)
used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
- x509_crl_info - add ``name_encoding`` option to control the encoding (IDNA,
Unicode) used to return domain names in general names (https://github.com/ansible-collections/community.crypto/pull/436).
release_summary: Feature and bugfix release.
fragments:
- 2.3.0.yml
- 434-add-persistent-and-perf-options.yml
- 436-idns.yml
- 440-ee.yml
- 441-x509-crl-cert-issuer.yml
- 445-fix.yml
- 448-acme-request-timeouts.yml
- 452-openssl_pkcs12-private-key-content.yml
release_date: '2022-05-09'
2.3.1:
changes:
bugfixes:
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
release_summary: Maintenance release.
fragments:
- 2.3.1.yml
- psf-license.yml
release_date: '2022-05-16'
2.3.2:
changes:
bugfixes:
- Include ``simplified_bsd.txt`` license file for the ECS module utils.
- certificate_complete_chain - do not stop execution if an unsupported signature
algorithm is encountered; warn instead (https://github.com/ansible-collections/community.crypto/pull/457).
release_summary: Maintenance and bugfix release.
fragments:
- 2.3.2.yml
- 457-certificate_complete_chain-unsupported-algorithm.yml
- simplified-bsd-license.yml
release_date: '2022-06-02'
2.3.3:
changes:
bugfixes:
- Include ``Apache-2.0.txt`` file for ``plugins/module_utils/crypto/_obj2txt.py``
and ``plugins/module_utils/crypto/_objects_data.py``.
- openssl_csr - the module no longer crashes with 'permitted_subtrees/excluded_subtrees
must be a non-empty list or None' if only one of ``name_constraints_permitted``
and ``name_constraints_excluded`` is provided (https://github.com/ansible-collections/community.crypto/issues/481).
- x509_crl - do not crash when signing CRL with Ed25519 or Ed448 keys (https://github.com/ansible-collections/community.crypto/issues/473,
https://github.com/ansible-collections/community.crypto/pull/474).
release_summary: Bugfix release.
fragments:
- 2.3.3.yml
- 474-x509_crl-ed25519-ed448.yml
- 481-fix-excluded_subtrees-must-be-a-non-empty-list-or-None.yml
- apache-license.yml
release_date: '2022-06-17'
2.3.4:
changes:
release_summary: 'Re-release of what was intended to be 2.3.3.
A mistake during the release process caused the 2.3.3 tag to end up on the
commit for 1.9.17, which caused the release pipeline to re-publish 1.9.17
as 2.3.3.
This release is identical to what should have been 2.3.3, except that the
version number has been bumped to 2.3.4 and this changelog entry for 2.3.4
has been added.
'
fragments:
- 2.3.4.yml
release_date: '2022-06-21'
2.4.0:
changes:
bugfixes:
- openssl_pkcs12 - when using the pyOpenSSL backend, do not crash when trying
to read non-existing other certificates (https://github.com/ansible-collections/community.crypto/issues/486,
https://github.com/ansible-collections/community.crypto/pull/487).
deprecated_features:
- Support for Ansible 2.9 and ansible-base 2.10 is deprecated, and will be removed
in the next major release (community.crypto 3.0.0). Some modules might still
work with these versions afterwards, but we will no longer keep compatibility
code that was needed to support them (https://github.com/ansible-collections/community.crypto/pull/460).
release_summary: Deprecation and bugfix release. No new features this time.
fragments:
- 2.4.0.yml
- 487-openssl_pkcs12-other-certs-crash.yml
- deprecate-ansible-2.9-2.10.yml
release_date: '2022-07-09'

23
docs/docsite/links.yml Normal file
View File

@@ -0,0 +1,23 @@
---
edit_on_github:
repository: ansible-collections/community.crypto
branch: main
path_prefix: ''
extra_links:
- description: Submit a bug report
url: https://github.com/ansible-collections/community.crypto/issues/new?assignees=&labels=&template=bug_report.md
- description: Request a feature
url: https://github.com/ansible-collections/community.crypto/issues/new?assignees=&labels=&template=feature_request.md
communication:
matrix_rooms:
- topic: General usage and support questions
room: '#users:ansible.im'
irc_channels:
- topic: General usage and support questions
network: Libera
channel: '#ansible'
mailing_lists:
- topic: Ansible Project List
url: https://groups.google.com/g/ansible-project

View File

@@ -1,6 +1,6 @@
namespace: community
name: crypto
version: 2.1.0
version: 2.4.0
readme: README.md
authors:
- Ansible (github.com/ansible)

10
meta/ee-bindep.txt Normal file
View File

@@ -0,0 +1,10 @@
cryptsetup [platform:dpkg]
cryptsetup [platform:rpm]
openssh-client [platform:dpkg]
openssh-clients [platform:rpm]
openssl [platform:dpkg]
openssl [platform:rpm]
python3-cryptography [platform:dpkg]
python3-cryptography [platform:rpm]
python3-openssl [platform:dpkg]
python3-pyOpenSSL [platform:rpm]

1
meta/ee-requirements.txt Normal file
View File

@@ -0,0 +1 @@
PyYAML

View File

@@ -0,0 +1,5 @@
---
version: 1
dependencies:
python: meta/ee-requirements.txt
system: meta/ee-bindep.txt

View File

@@ -23,6 +23,14 @@ notes:
the L(Let's Encrypt,https://letsencrypt.org/) CA, the module can in
principle be used with any CA providing an ACME endpoint, such as
L(Buypass Go SSL,https://www.buypass.com/ssl/products/acme)."
- "So far, the ACME modules have only been tested by the developers against
Let's Encrypt (staging and production), Buypass (staging and production), ZeroSSL (production),
and L(Pebble testing server,https://github.com/letsencrypt/Pebble). We have got
community feedback that they also work with Sectigo ACME Service for InCommon.
If you experience problems with another ACME server, please
L(create an issue,https://github.com/ansible-collections/community.crypto/issues/new/choose)
to help us supporting it. Feedback that an ACME server not mentioned does work
is also appreciated."
requirements:
- either openssl or L(cryptography,https://cryptography.io/) >= 1.5
- ipaddress
@@ -96,13 +104,8 @@ options:
U(https://api.buypass.com/acme/directory)."
- "For B(ZeroSSL), the production directory URL for ACME v2 is
U(https://acme.zerossl.com/v2/DV90)."
- "B(Warning:) So far, the ACME modules have only been tested against Let's Encrypt
(staging and production), Buypass (staging and production), ZeroSSL (production),
and L(Pebble testing server,https://github.com/letsencrypt/Pebble). If you
experience problems with another ACME server, please
L(create an issue,https://github.com/ansible-collections/community.crypto/issues/new/choose)
to help us supporting it. Feedback that an ACME server not mentioned does work
is also appreciated."
- The notes for this module contain a list of ACME services this module has
been tested against.
required: true
type: str
validate_certs:
@@ -123,4 +126,11 @@ options:
type: str
default: auto
choices: [ auto, cryptography, openssl ]
request_timeout:
description:
- The time Ansible should wait for a response from the ACME API.
- This timeout is applied to all HTTP(S) requests (HEAD, GET, POST).
type: int
default: 10
version_added: 2.3.0
'''

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
name_encoding:
description:
- How to encode names (DNS names, URIs, email addresses) in return values.
- C(ignore) will use the encoding returned by the backend.
- C(idna) will convert all labels of domain names to IDNA encoding.
IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 encoding fails.
- C(unicode) will convert all labels of domain names to Unicode.
IDNA2008 will be preferred, and IDNA2003 will be used if IDNA2008 decoding fails.
- B(Note) that C(idna) and C(unicode) require the L(idna Python library,https://pypi.org/project/idna/) to be installed.
type: str
default: ignore
choices:
- ignore
- idna
- unicode
requirements:
- If I(name_encoding) is set to another value than C(ignore), the L(idna Python library,https://pypi.org/project/idna/) needs to be installed.
'''

View File

@@ -3,7 +3,7 @@
# Implements multiple version numbering conventions for the
# Python Module Distribution Utilities.
#
# PSF License (see licenses/PSF-license.txt or https://opensource.org/licenses/Python-2.0)
# PSF License (see PSF-license.txt or https://opensource.org/licenses/Python-2.0)
#
"""Provides classes to represent module version numbers (one class for

View File

@@ -83,6 +83,8 @@ class ACMEDirectory(object):
self.directory, dummy = account.get_request(self.directory_root, get_only=True)
self.request_timeout = module.params['request_timeout']
# Check whether self.version matches what we expect
if self.version == 1:
for key in ('new-reg', 'new-authz', 'new-cert'):
@@ -103,7 +105,7 @@ class ACMEDirectory(object):
url = self.directory_root if self.version == 1 else self.directory['newNonce']
if resource is not None:
url = resource
dummy, info = fetch_url(self.module, url, method='HEAD')
dummy, info = fetch_url(self.module, url, method='HEAD', timeout=self.request_timeout)
if info['status'] not in (200, 204):
raise NetworkException("Failed to get replay-nonce, got status {0}".format(info['status']))
return info['replay-nonce']
@@ -131,6 +133,8 @@ class ACMEClient(object):
# Make sure empty string is treated as None.
self.account_uri = module.params.get('account_uri') or None
self.request_timeout = module.params['request_timeout']
self.account_key_data = None
self.account_jwk = None
self.account_jws_header = None
@@ -235,7 +239,7 @@ class ACMEClient(object):
headers = {
'Content-Type': 'application/jose+json',
}
resp, info = fetch_url(self.module, url, data=data, headers=headers, method='POST')
resp, info = fetch_url(self.module, url, data=data, headers=headers, method='POST', timeout=self.request_timeout)
_assert_fetch_url_success(self.module, resp, info)
result = {}
@@ -294,7 +298,7 @@ class ACMEClient(object):
if get_only:
# Perform unauthenticated GET
resp, info = fetch_url(self.module, uri, method='GET', headers=headers)
resp, info = fetch_url(self.module, uri, method='GET', headers=headers, timeout=self.request_timeout)
_assert_fetch_url_success(self.module, resp, info)
@@ -342,6 +346,7 @@ def get_default_argspec():
acme_version=dict(type='int', required=True, choices=[1, 2]),
validate_certs=dict(type='bool', default=True),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
request_timeout=dict(type='int', default=10),
)

View File

@@ -1,7 +1,15 @@
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is licensed under the
# Apache 2.0 License. Modules you write using this snippet, which is embedded
# dynamically by Ansible, still belong to the author of the module, and may assign
# their own license to the complete work.
# This excerpt is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file at
# https://github.com/pyca/cryptography/blob/master/LICENSE for complete details.
#
# The Apache 2.0 license has been included as Apache-2.0.txt in this collection.
#
# Adapted from cryptography's hazmat/backends/openssl/decode_asn1.py
#
# Copyright (c) 2015, 2016 Paul Kehrer (@reaperhulk)

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2019, Felix Fontein <felix@fontein.de>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -1,3 +1,9 @@
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is licensed under the
# Apache 2.0 License. Modules you write using this snippet, which is embedded
# dynamically by Ansible, still belong to the author of the module, and may assign
# their own license to the complete work.
# This has been extracted from the OpenSSL project's objects.txt:
# https://github.com/openssl/openssl/blob/9537fe5757bb07761fa275d779bbd40bcf5530e4/crypto/objects/objects.txt
# Extracted with https://gist.github.com/felixfontein/376748017ad65ead093d56a45a5bf376
@@ -5,7 +11,7 @@
# In case the following data structure has any copyrightable content, note that it is licensed as follows:
# Copyright (c) the OpenSSL contributors
# Licensed under the Apache License 2.0
# https://github.com/openssl/openssl/blob/master/LICENSE
# https://github.com/openssl/openssl/blob/master/LICENSE.txt or Apache-2.0.txt
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -2,19 +2,7 @@
#
# (c) 2016, Yanis Guenane <yanis+ansible@guenane.org>
# (c) 2020, Felix Fontein <felix@fontein.de>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2019, Felix Fontein <felix@fontein.de>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
@@ -95,12 +83,12 @@ def cryptography_decode_revoked_certificate(cert):
return result
def cryptography_dump_revoked(entry):
def cryptography_dump_revoked(entry, idn_rewrite='ignore'):
return {
'serial_number': entry['serial_number'],
'revocation_date': entry['revocation_date'].strftime(TIMESTAMP_FORMAT),
'issuer':
[cryptography_decode_name(issuer) for issuer in entry['issuer']]
[cryptography_decode_name(issuer, idn_rewrite=idn_rewrite) for issuer in entry['issuer']]
if entry['issuer'] is not None else None,
'issuer_critical': entry['issuer_critical'],
'reason': REVOCATION_REASON_MAP_INVERSE.get(entry['reason']) if entry['reason'] is not None else None,

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2019, Felix Fontein <felix@fontein.de>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
@@ -23,8 +11,11 @@ import base64
import binascii
import re
import sys
import traceback
from ansible.module_utils.common.text.converters import to_text, to_bytes
from ansible.module_utils.six.moves.urllib.parse import urlparse, urlunparse, ParseResult
from ._asn1 import serialize_asn1_string_as_der
from ansible_collections.community.crypto.plugins.module_utils.version import LooseVersion
@@ -32,13 +23,36 @@ from ansible_collections.community.crypto.plugins.module_utils.version import Lo
try:
import cryptography
from cryptography import x509
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
import ipaddress
except ImportError:
# Error handled in the calling module.
pass
try:
import cryptography.hazmat.primitives.asymmetric.rsa
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.ec
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.dsa
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.ed25519
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.ed448
except ImportError:
pass
try:
# This is a separate try/except since this is only present in cryptography 2.5 or newer
from cryptography.hazmat.primitives.serialization.pkcs12 import (
@@ -57,9 +71,24 @@ except ImportError:
# Error handled in the calling module.
_load_pkcs12 = None
try:
import idna
HAS_IDNA = True
except ImportError:
HAS_IDNA = False
IDNA_IMP_ERROR = traceback.format_exc()
from ansible.module_utils.basic import missing_required_lib
from .basic import (
CRYPTOGRAPHY_HAS_DSA_SIGN,
CRYPTOGRAPHY_HAS_EC_SIGN,
CRYPTOGRAPHY_HAS_ED25519,
CRYPTOGRAPHY_HAS_ED25519_SIGN,
CRYPTOGRAPHY_HAS_ED448,
CRYPTOGRAPHY_HAS_ED448_SIGN,
CRYPTOGRAPHY_HAS_RSA_SIGN,
CRYPTOGRAPHY_HAS_X25519,
CRYPTOGRAPHY_HAS_X25519_FULL,
CRYPTOGRAPHY_HAS_X448,
@@ -331,6 +360,80 @@ def cryptography_parse_relative_distinguished_name(rdn):
return cryptography.x509.RelativeDistinguishedName(names)
def _is_ascii(value):
'''Check whether the Unicode string `value` contains only ASCII characters.'''
try:
value.encode("ascii")
return True
except UnicodeEncodeError:
return False
def _adjust_idn(value, idn_rewrite):
if idn_rewrite == 'ignore' or not value:
return value
if idn_rewrite == 'idna' and _is_ascii(value):
return value
if idn_rewrite not in ('idna', 'unicode'):
raise ValueError('Invalid value for idn_rewrite: "{0}"'.format(idn_rewrite))
if not HAS_IDNA:
raise OpenSSLObjectError(
missing_required_lib('idna', reason='to transform {what} DNS name "{name}" to {dest}'.format(
name=value,
what='IDNA' if idn_rewrite == 'unicode' else 'Unicode',
dest='Unicode' if idn_rewrite == 'unicode' else 'IDNA',
)))
# Since IDNA does not like '*' or empty labels (except one empty label at the end),
# we split and let IDNA only handle labels that are neither empty or '*'.
parts = value.split(u'.')
for index, part in enumerate(parts):
if part in (u'', u'*'):
continue
try:
if idn_rewrite == 'idna':
parts[index] = idna.encode(part).decode('ascii')
elif idn_rewrite == 'unicode' and part.startswith(u'xn--'):
parts[index] = idna.decode(part)
except idna.IDNAError as exc2008:
try:
if idn_rewrite == 'idna':
parts[index] = part.encode('idna').decode('ascii')
elif idn_rewrite == 'unicode' and part.startswith(u'xn--'):
parts[index] = part.encode('ascii').decode('idna')
except Exception as exc2003:
raise OpenSSLObjectError(
u'Error while transforming part "{part}" of {what} DNS name "{name}" to {dest}.'
u' IDNA2008 transformation resulted in "{exc2008}", IDNA2003 transformation resulted in "{exc2003}".'.format(
part=part,
name=value,
what='IDNA' if idn_rewrite == 'unicode' else 'Unicode',
dest='Unicode' if idn_rewrite == 'unicode' else 'IDNA',
exc2003=exc2003,
exc2008=exc2008,
))
return u'.'.join(parts)
def _adjust_idn_email(value, idn_rewrite):
idx = value.find(u'@')
if idx < 0:
return value
return u'{0}@{1}'.format(value[:idx], _adjust_idn(value[idx + 1:], idn_rewrite))
def _adjust_idn_url(value, idn_rewrite):
url = urlparse(value)
host = _adjust_idn(url.hostname, idn_rewrite)
if url.username is not None and url.password is not None:
host = u'{0}:{1}@{2}'.format(url.username, url.password, host)
elif url.username is not None:
host = u'{0}@{1}'.format(url.username, host)
if url.port is not None:
host = u'{0}:{1}'.format(host, url.port)
return urlunparse(
ParseResult(scheme=url.scheme, netloc=host, path=url.path, params=url.params, query=url.query, fragment=url.fragment))
def cryptography_get_name(name, what='Subject Alternative Name'):
'''
Given a name string, returns a cryptography x509.GeneralName object.
@@ -338,16 +441,16 @@ def cryptography_get_name(name, what='Subject Alternative Name'):
'''
try:
if name.startswith('DNS:'):
return x509.DNSName(to_text(name[4:]))
return x509.DNSName(_adjust_idn(to_text(name[4:]), 'idna'))
if name.startswith('IP:'):
address = to_text(name[3:])
if '/' in address:
return x509.IPAddress(ipaddress.ip_network(address))
return x509.IPAddress(ipaddress.ip_address(address))
if name.startswith('email:'):
return x509.RFC822Name(to_text(name[6:]))
return x509.RFC822Name(_adjust_idn_email(to_text(name[6:]), 'idna'))
if name.startswith('URI:'):
return x509.UniformResourceIdentifier(to_text(name[4:]))
return x509.UniformResourceIdentifier(_adjust_idn_url(to_text(name[4:]), 'idna'))
if name.startswith('RID:'):
m = re.match(r'^([0-9]+(?:\.[0-9]+)*)$', to_text(name[4:]))
if not m:
@@ -394,21 +497,23 @@ def _dn_escape_value(value):
return value
def cryptography_decode_name(name):
def cryptography_decode_name(name, idn_rewrite='ignore'):
'''
Given a cryptography x509.GeneralName object, returns a string.
Raises an OpenSSLObjectError if the name is not supported.
'''
if idn_rewrite not in ('ignore', 'idna', 'unicode'):
raise AssertionError('idn_rewrite must be one of "ignore", "idna", or "unicode"')
if isinstance(name, x509.DNSName):
return u'DNS:{0}'.format(name.value)
return u'DNS:{0}'.format(_adjust_idn(name.value, idn_rewrite))
if isinstance(name, x509.IPAddress):
if isinstance(name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)):
return u'IP:{0}/{1}'.format(name.value.network_address.compressed, name.value.prefixlen)
return u'IP:{0}'.format(name.value.compressed)
if isinstance(name, x509.RFC822Name):
return u'email:{0}'.format(name.value)
return u'email:{0}'.format(_adjust_idn_email(name.value, idn_rewrite))
if isinstance(name, x509.UniformResourceIdentifier):
return u'URI:{0}'.format(name.value)
return u'URI:{0}'.format(_adjust_idn_url(name.value, idn_rewrite))
if isinstance(name, x509.DirectoryName):
# According to https://datatracker.ietf.org/doc/html/rfc4514.html#section-2.1 the
# list needs to be reversed, and joined by commas
@@ -664,3 +769,40 @@ def _parse_pkcs12_legacy(pkcs12_bytes, passphrase=None):
if maybe_name != backend._ffi.NULL:
friendly_name = backend._ffi.string(maybe_name)
return private_key, certificate, additional_certificates, friendly_name
def cryptography_verify_signature(signature, data, hash_algorithm, signer_public_key):
'''
Check whether the given signature of the given data was signed by the given public key object.
'''
try:
if CRYPTOGRAPHY_HAS_RSA_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey):
signer_public_key.verify(signature, data, padding.PKCS1v15(), hash_algorithm)
return True
if CRYPTOGRAPHY_HAS_EC_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey):
signer_public_key.verify(signature, data, cryptography.hazmat.primitives.asymmetric.ec.ECDSA(hash_algorithm))
return True
if CRYPTOGRAPHY_HAS_DSA_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey):
signer_public_key.verify(signature, data, hash_algorithm)
return True
if CRYPTOGRAPHY_HAS_ED25519_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey):
signer_public_key.verify(signature, data)
return True
if CRYPTOGRAPHY_HAS_ED448_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey):
signer_public_key.verify(signature, data)
return True
raise OpenSSLObjectError(u'Unsupported public key type {0}'.format(type(signer_public_key)))
except InvalidSignature:
return False
def cryptography_verify_certificate_signature(certificate, signer_public_key):
'''
Check whether the given X509 certificate object was signed by the given public key object.
'''
return cryptography_verify_signature(
certificate.signature,
certificate.tbs_certificate_bytes,
certificate.signature_hash_algorithm,
signer_public_key
)

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2019, Felix Fontein <felix@fontein.de>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -12,12 +12,11 @@ __metaclass__ = type
import abc
import binascii
import datetime
import re
import traceback
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.module_utils.common.text.converters import to_native
from ansible_collections.community.crypto.plugins.module_utils.version import LooseVersion
@@ -208,6 +207,7 @@ class CertificateInfoRetrievalCryptography(CertificateInfoRetrieval):
"""Validate the supplied cert, using the cryptography backend"""
def __init__(self, module, content):
super(CertificateInfoRetrievalCryptography, self).__init__(module, 'cryptography', content)
self.name_encoding = module.params.get('name_encoding', 'ignore')
def _get_der_bytes(self):
return self.cert.public_bytes(serialization.Encoding.DER)
@@ -310,7 +310,7 @@ class CertificateInfoRetrievalCryptography(CertificateInfoRetrieval):
def _get_subject_alt_name(self):
try:
san_ext = self.cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
result = [cryptography_decode_name(san) for san in san_ext.value]
result = [cryptography_decode_name(san, idn_rewrite=self.name_encoding) for san in san_ext.value]
return result, san_ext.critical
except cryptography.x509.ExtensionNotFound:
return None, False
@@ -342,7 +342,7 @@ class CertificateInfoRetrievalCryptography(CertificateInfoRetrieval):
ext = self.cert.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier)
issuer = None
if ext.value.authority_cert_issuer is not None:
issuer = [cryptography_decode_name(san) for san in ext.value.authority_cert_issuer]
issuer = [cryptography_decode_name(san, idn_rewrite=self.name_encoding) for san in ext.value.authority_cert_issuer]
return ext.value.key_identifier, issuer, ext.value.authority_cert_serial_number
except cryptography.x509.ExtensionNotFound:
return None, None, None

View File

@@ -12,8 +12,6 @@ import os
from random import randrange
from ansible.module_utils.common.text.converters import to_bytes
from ansible_collections.community.crypto.plugins.module_utils.version import LooseVersion
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
@@ -28,8 +26,10 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
cryptography_compare_public_keys,
cryptography_key_needs_digest_for_signing,
cryptography_serial_number_of_cert,
cryptography_verify_certificate_signature,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.certificate import (
@@ -39,11 +39,6 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.module_bac
CertificateProvider,
)
try:
from OpenSSL import crypto
except ImportError:
pass
try:
import cryptography
from cryptography import x509
@@ -107,6 +102,9 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
except OpenSSLBadPassphraseError as exc:
module.fail_json(msg=str(exc))
if not cryptography_compare_public_keys(self.ca_cert.public_key(), self.ca_private_key.public_key()):
raise CertificateError('The CA private key does not belong to the CA certificate')
if cryptography_key_needs_digest_for_signing(self.ca_private_key):
if self.digest is None:
raise CertificateError(
@@ -173,6 +171,16 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
if super(OwnCACertificateBackendCryptography, self).needs_regeneration(not_before=self.notBefore, not_after=self.notAfter):
return True
self._ensure_existing_certificate_loaded()
# Check whether certificate is signed by CA certificate
if not cryptography_verify_certificate_signature(self.existing_certificate, self.ca_cert.public_key()):
return True
# Check subject
if self.ca_cert.subject != self.existing_certificate.issuer:
return True
# Check AuthorityKeyIdentifier
if self.create_authority_key_identifier:
try:
@@ -185,7 +193,6 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
except cryptography.x509.ExtensionNotFound:
expected_ext = x509.AuthorityKeyIdentifier.from_issuer_public_key(self.ca_cert.public_key())
self._ensure_existing_certificate_loaded()
try:
ext = self.existing_certificate.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier)
if ext.value != expected_ext:

View File

@@ -12,8 +12,6 @@ import os
from random import randrange
from ansible.module_utils.common.text.converters import to_bytes
from ansible_collections.community.crypto.plugins.module_utils.crypto.support import (
get_relative_time_option,
select_message_digest,
@@ -22,6 +20,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
cryptography_key_needs_digest_for_signing,
cryptography_serial_number_of_cert,
cryptography_verify_certificate_signature,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.certificate import (
@@ -30,11 +29,6 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.module_bac
CertificateProvider,
)
try:
from OpenSSL import crypto
except ImportError:
pass
try:
import cryptography
from cryptography import x509
@@ -135,8 +129,16 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend):
return self.cert.public_bytes(Encoding.PEM)
def needs_regeneration(self):
return super(SelfSignedCertificateBackendCryptography, self).needs_regeneration(
not_before=self.notBefore, not_after=self.notAfter)
if super(SelfSignedCertificateBackendCryptography, self).needs_regeneration(not_before=self.notBefore, not_after=self.notAfter):
return True
self._ensure_existing_certificate_loaded()
# Check whether certificate is signed by private key
if not cryptography_verify_certificate_signature(self.existing_certificate, self.privatekey.public_key()):
return True
return False
def dump(self, include_certificate):
result = super(SelfSignedCertificateBackendCryptography, self).dump(include_certificate)

View File

@@ -51,6 +51,7 @@ class CRLInfoRetrieval(object):
self.module = module
self.content = content
self.list_revoked_certificates = list_revoked_certificates
self.name_encoding = module.params.get('name_encoding', 'ignore')
def get_info(self):
self.crl_pem = identify_pem_format(self.content)
@@ -86,7 +87,7 @@ class CRLInfoRetrieval(object):
result['revoked_certificates'] = []
for cert in self.crl:
entry = cryptography_decode_revoked_certificate(cert)
result['revoked_certificates'].append(cryptography_dump_revoked(entry))
result['revoked_certificates'].append(cryptography_dump_revoked(entry, idn_rewrite=self.name_encoding))
return result

View File

@@ -14,7 +14,7 @@ import traceback
from ansible.module_utils import six
from ansible.module_utils.basic import missing_required_lib
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.common.text.converters import to_native, to_text
from ansible_collections.community.crypto.plugins.module_utils.version import LooseVersion
@@ -345,8 +345,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
if self.name_constraints_permitted or self.name_constraints_excluded:
try:
csr = csr.add_extension(cryptography.x509.NameConstraints(
[cryptography_get_name(name, 'name constraints permitted') for name in self.name_constraints_permitted],
[cryptography_get_name(name, 'name constraints excluded') for name in self.name_constraints_excluded],
[cryptography_get_name(name, 'name constraints permitted') for name in self.name_constraints_permitted] or None,
[cryptography_get_name(name, 'name constraints excluded') for name in self.name_constraints_excluded] or None,
), critical=self.name_constraints_critical)
except TypeError as e:
raise OpenSSLObjectError('Error while parsing name constraint: {0}'.format(e))
@@ -498,8 +498,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
def _check_nameConstraints(extensions):
current_nc_ext = _find_extension(extensions, cryptography.x509.NameConstraints)
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 []
current_nc_perm = [to_text(altname) for altname in current_nc_ext.value.permitted_subtrees or []] if current_nc_ext else []
current_nc_excl = [to_text(altname) for altname in current_nc_ext.value.excluded_subtrees or []] 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):

View File

@@ -15,13 +15,12 @@ import traceback
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.module_utils.common.text.converters import to_native
from ansible_collections.community.crypto.plugins.module_utils.version import LooseVersion
from ansible_collections.community.crypto.plugins.module_utils.crypto.support import (
load_certificate_request,
get_fingerprint_of_bytes,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
@@ -175,6 +174,7 @@ class CSRInfoRetrievalCryptography(CSRInfoRetrieval):
"""Validate the supplied CSR, using the cryptography backend"""
def __init__(self, module, content, validate_signature):
super(CSRInfoRetrievalCryptography, self).__init__(module, 'cryptography', content, validate_signature)
self.name_encoding = module.params.get('name_encoding', 'ignore')
def _get_subject_ordered(self):
result = []
@@ -257,7 +257,7 @@ class CSRInfoRetrievalCryptography(CSRInfoRetrieval):
def _get_subject_alt_name(self):
try:
san_ext = self.csr.extensions.get_extension_for_class(x509.SubjectAlternativeName)
result = [cryptography_decode_name(san) for san in san_ext.value]
result = [cryptography_decode_name(san, idn_rewrite=self.name_encoding) for san in san_ext.value]
return result, san_ext.critical
except cryptography.x509.ExtensionNotFound:
return None, False
@@ -265,8 +265,8 @@ class CSRInfoRetrievalCryptography(CSRInfoRetrieval):
def _get_name_constraints(self):
try:
nc_ext = self.csr.extensions.get_extension_for_class(x509.NameConstraints)
permitted = [cryptography_decode_name(san) for san in nc_ext.value.permitted_subtrees or []]
excluded = [cryptography_decode_name(san) for san in nc_ext.value.excluded_subtrees or []]
permitted = [cryptography_decode_name(san, idn_rewrite=self.name_encoding) for san in nc_ext.value.permitted_subtrees or []]
excluded = [cryptography_decode_name(san, idn_rewrite=self.name_encoding) for san in nc_ext.value.excluded_subtrees or []]
return permitted, excluded, nc_ext.critical
except cryptography.x509.ExtensionNotFound:
return None, None, False
@@ -292,7 +292,7 @@ class CSRInfoRetrievalCryptography(CSRInfoRetrieval):
ext = self.csr.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier)
issuer = None
if ext.value.authority_cert_issuer is not None:
issuer = [cryptography_decode_name(san) for san in ext.value.authority_cert_issuer]
issuer = [cryptography_decode_name(san, idn_rewrite=self.name_encoding) for san in ext.value.authority_cert_issuer]
return ext.value.key_identifier, issuer, ext.value.authority_cert_serial_number
except cryptography.x509.ExtensionNotFound:
return None, None, None

View File

@@ -25,11 +25,9 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.basic impo
CRYPTOGRAPHY_HAS_ED25519,
CRYPTOGRAPHY_HAS_ED448,
OpenSSLObjectError,
OpenSSLBadPassphraseError,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.support import (
load_privatekey,
get_fingerprint_of_privatekey,
)

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2020, Doug Stanley <doug+ansible@technologixllc.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2019, Felix Fontein <felix@fontein.de>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2016, Yanis Guenane <yanis+ansible@guenane.org>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
@@ -32,7 +20,7 @@ from ansible.module_utils.common.text.converters import to_native, to_bytes
try:
from OpenSSL import crypto
HAS_PYOPENSSL = True
except ImportError:
except (ImportError, AttributeError):
# Error handled in the calling module.
HAS_PYOPENSSL = False

View File

@@ -7,25 +7,7 @@
# their own license to the complete work.
#
# Copyright (c), Entrust Datacard Corporation, 2019
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Simplified BSD License (see simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
from __future__ import absolute_import, division, print_function
@@ -34,7 +16,6 @@ __metaclass__ = type
import json
import os
import re
import time
import traceback
from ansible.module_utils.common.text.converters import to_text, to_native

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# (c) 2016, Yanis Guenane <yanis+ansible@guenane.org>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright: (c) 2021, Andrew Pantuso (@ajpantuso) <ajpantuso@gmail.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
@@ -21,9 +9,11 @@ __metaclass__ = type
import abc
import os
import stat
import traceback
from ansible.module_utils import six
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import (
parse_openssh_version,
)
@@ -75,7 +65,14 @@ class OpensshModule(object):
self.check_mode = self.module.check_mode
def execute(self):
self._execute()
try:
self._execute()
except Exception as e:
self.module.fail_json(
msg="unexpected error occurred: %s" % to_native(e),
exception=traceback.format_exc(),
)
self.module.exit_json(**self.result)
@abc.abstractmethod

View File

@@ -2,19 +2,7 @@
#
# Copyright: (c) 2018, David Kainz <dkainz@mgit.at> <dave.jokain@gmx.at>
# Copyright: (c) 2021, Andrew Pantuso (@ajpantuso) <ajpantuso@gmail.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright: (c) 2021, Andrew Pantuso (@ajpantuso) <ajpantuso@gmail.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -1,19 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright: (c) 2021, Andrew Pantuso (@ajpantuso) <ajpantuso@gmail.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -2,19 +2,7 @@
#
# Copyright: (c) 2020, Doug Stanley <doug+ansible@technologixllc.com>
# Copyright: (c) 2021, Andrew Pantuso (@ajpantuso) <ajpantuso@gmail.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -308,7 +308,7 @@ EXAMPLES = r'''
# - copy:
# dest: /var/www/html/{{ sample_com_challenge['challenge_data']['sample.com']['http-01']['resource'] }}
# content: "{{ sample_com_challenge['challenge_data']['sample.com']['http-01']['resource_value'] }}"
# when: sample_com_challenge is changed and 'sample.com' in sample_com_challenge['challenge_data']
# when: sample_com_challenge is changed and 'sample.com' in sample_com_challenge['challenge_data']
#
# Alternative way:
#

View File

@@ -133,6 +133,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import
CRYPTOGRAPHY_IMP_ERR = None
try:
import cryptography
import cryptography.exceptions
import cryptography.hazmat.backends
import cryptography.hazmat.primitives.serialization
import cryptography.hazmat.primitives.asymmetric.rsa
@@ -190,6 +191,9 @@ def is_parent(module, cert, potential_parent):
return True
except cryptography.exceptions.InvalidSignature as dummy:
return False
except cryptography.exceptions.UnsupportedAlgorithm as dummy:
module.warn('Unsupported algorithm "{0}"'.format(cert.cert.signature_hash_algorithm))
return False
except Exception as e:
module.fail_json(msg='Unknown error on signature validation: {0}'.format(e))
@@ -237,14 +241,16 @@ class CertificateSet(object):
def __init__(self, module):
self.module = module
self.certificates = set()
self.certificate_by_issuer = dict()
self.certificates_by_issuer = dict()
self.certificate_by_cert = dict()
def _load_file(self, path):
certs = load_PEM_list(self.module, path, fail_on_error=False)
for cert in certs:
self.certificates.add(cert)
self.certificate_by_issuer[cert.cert.subject] = cert
if cert.cert.subject not in self.certificates_by_issuer:
self.certificates_by_issuer[cert.cert.subject] = []
self.certificates_by_issuer[cert.cert.subject].append(cert)
self.certificate_by_cert[cert.cert] = cert
def load(self, path):
@@ -263,8 +269,8 @@ class CertificateSet(object):
'''
Search for the parent (issuer) of a certificate. Return ``None`` if none was found.
'''
potential_parent = self.certificate_by_issuer.get(cert.cert.issuer)
if potential_parent is not None:
potential_parents = self.certificates_by_issuer.get(cert.cert.issuer, [])
for potential_parent in potential_parents:
if is_parent(self.module, cert, potential_parent):
return potential_parent
return None

View File

@@ -217,6 +217,48 @@ options:
- "Will only be used on container creation."
type: int
version_added: '1.5.0'
perf_same_cpu_crypt:
description:
- "Allows the user to perform encryption using the same CPU that IO was submitted on."
- "The default is to use an unbound workqueue so that encryption work is automatically balanced between available CPUs."
- "Will only be used when opening containers."
type: bool
default: false
version_added: '2.3.0'
perf_submit_from_crypt_cpus:
description:
- "Allows the user to disable offloading writes to a separate thread after encryption."
- "There are some situations where offloading block write IO operations from the encryption threads
to a single thread degrades performance significantly."
- "The default is to offload block write IO operations to the same thread."
- "Will only be used when opening containers."
type: bool
default: false
version_added: '2.3.0'
perf_no_read_workqueue:
description:
- "Allows the user to bypass dm-crypt internal workqueue and process read requests synchronously."
- "Will only be used when opening containers."
type: bool
default: false
version_added: '2.3.0'
perf_no_write_workqueue:
description:
- "Allows the user to bypass dm-crypt internal workqueue and process write requests synchronously."
- "Will only be used when opening containers."
type: bool
default: false
version_added: '2.3.0'
persistent:
description:
- "Allows the user to store options into container's metadata persistently and automatically use them next time.
Only I(perf_same_cpu_crypt), I(perf_submit_from_crypt_cpus), I(perf_no_read_workqueue), and I(perf_no_write_workqueue)
can be stored persistently."
- "Will only work with LUKS2 containers."
- "Will only be used when opening containers."
type: bool
default: false
version_added: '2.3.0'
requirements:
- "cryptsetup"
@@ -350,7 +392,7 @@ STDERR = 2
# used to get <luks-name> out of lsblk output in format 'crypt <luks-name>'
# regex takes care of any possible blank characters
LUKS_NAME_REGEX = re.compile(r'\s*crypt\s+([^\s]*)\s*')
LUKS_NAME_REGEX = re.compile(r'^crypt\s+([^\s]*)\s*$')
# used to get </luks/device> out of lsblk output
# in format 'device: </luks/device>'
LUKS_DEVICE_REGEX = re.compile(r'\s*device:\s+([^\s]*)\s*')
@@ -446,13 +488,11 @@ class CryptHandler(Handler):
raise ValueError('Error while obtaining LUKS name for %s: %s'
% (device, result[STDERR]))
m = LUKS_NAME_REGEX.search(result[STDOUT])
try:
name = m.group(1)
except AttributeError:
name = None
return name
for line in result[STDOUT].splitlines(False):
m = LUKS_NAME_REGEX.match(line)
if m:
return m.group(1)
return None
def get_container_device_by_name(self, name):
''' obtain device name based on the LUKS container name
@@ -519,10 +559,21 @@ class CryptHandler(Handler):
raise ValueError('Error while creating LUKS on %s: %s'
% (device, result[STDERR]))
def run_luks_open(self, device, keyfile, passphrase, name):
def run_luks_open(self, device, keyfile, passphrase, perf_same_cpu_crypt, perf_submit_from_crypt_cpus,
perf_no_read_workqueue, perf_no_write_workqueue, persistent, name):
args = [self._cryptsetup_bin]
if keyfile:
args.extend(['--key-file', keyfile])
if perf_same_cpu_crypt:
args.extend(['--perf-same_cpu_crypt'])
if perf_submit_from_crypt_cpus:
args.extend(['--perf-submit_from_crypt_cpus'])
if perf_no_read_workqueue:
args.extend(['--perf-no_read_workqueue'])
if perf_no_write_workqueue:
args.extend(['--perf-no_write_workqueue'])
if persistent:
args.extend(['--persistent'])
args.extend(['open', '--type', 'luks', device, name])
result = self._run_command(args, data=passphrase)
@@ -804,6 +855,11 @@ def run_module():
mutually_exclusive=[('iteration_time', 'iteration_count')],
),
sector_size=dict(type='int'),
perf_same_cpu_crypt=dict(type='bool', default=False),
perf_submit_from_crypt_cpus=dict(type='bool', default=False),
perf_no_read_workqueue=dict(type='bool', default=False),
perf_no_write_workqueue=dict(type='bool', default=False),
persistent=dict(type='bool', default=False),
)
mutually_exclusive = [
@@ -821,6 +877,7 @@ def run_module():
module = AnsibleModule(argument_spec=module_args,
supports_check_mode=True,
mutually_exclusive=mutually_exclusive)
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
if module.params['device'] is not None:
try:
@@ -878,6 +935,11 @@ def run_module():
crypt.run_luks_open(conditions.device,
module.params['keyfile'],
module.params['passphrase'],
module.params['perf_same_cpu_crypt'],
module.params['perf_submit_from_crypt_cpus'],
module.params['perf_no_read_workqueue'],
module.params['perf_no_write_workqueue'],
module.params['persistent'],
name)
except ValueError as e:
module.fail_json(msg="luks_device error: %s" % e)

View File

@@ -50,6 +50,7 @@ options:
match the module's options.
- When C(partial_idempotence) an existing certificate will be regenerated based on
I(serial), I(signature_algorithm), I(type), I(valid_from), I(valid_to), I(valid_at), and I(principals).
I(valid_from) and I(valid_to) can be excluded by I(ignore_timestamps=true).
- 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).
@@ -112,6 +113,9 @@ options:
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS | YYYY-MM-DD HH:MM:SS | always)
where timespec can be an integer + C([w | d | h | m | s]) (for example C(+32w1d2h)).
Note that if using relative time this module is NOT idempotent."
- "The value C(always) is only supported for OpenSSH 7.7 and greater, however, the value C(1970-01-01T00:00:01)
can be used with earlier versions as an equivalent expression."
- "To ignore this value during comparison with an existing certificate set I(ignore_timestamps=true)."
- Required if I(state) is C(present).
type: str
valid_to:
@@ -120,6 +124,7 @@ options:
Time will always be interpreted as UTC. Valid formats are: C([+-]timespec | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS | YYYY-MM-DD HH:MM:SS | forever)
where timespec can be an integer + C([w | d | h | m | s]) (for example C(+32w1d2h)).
Note that if using relative time this module is NOT idempotent."
- "To ignore this value during comparison with an existing certificate set I(ignore_timestamps=true)."
- Required if I(state) is C(present).
type: str
valid_at:
@@ -128,6 +133,13 @@ options:
Time will always be interpreted as UTC. Mainly to be used with relative timespec for I(valid_from) and / or I(valid_to).
Note that if using relative time this module is NOT idempotent."
type: str
ignore_timestamps:
description:
- "Whether the I(valid_from) and I(valid_to) timestamps should be ignored for idempotency checks."
- "However, the values will still be applied to a new certificate if it meets any other necessary conditions for generation/regeneration."
type: bool
default: false
version_added: 2.2.0
principals:
description:
- "Certificates may be limited to be valid for a set of principal (user/host) names.
@@ -192,6 +204,7 @@ EXAMPLES = '''
valid_from: +0s
valid_to: +32w
valid_at: +2w
ignore_timestamps: true
- name: Generate an OpenSSH host certificate that is valid forever and only for example.com and examplehost
community.crypto.openssh_cert:
@@ -260,7 +273,7 @@ info:
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.common.text.converters import to_native, to_text
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.crypto.plugins.module_utils.version import LooseVersion
@@ -296,6 +309,7 @@ class Certificate(OpensshModule):
self.type = self.module.params['type']
self.use_agent = self.module.params['use_agent']
self.valid_at = self.module.params['valid_at']
self.ignore_timestamps = self.module.params['ignore_timestamps']
self._check_if_base_dir(self.path)
@@ -379,7 +393,7 @@ class Certificate(OpensshModule):
def _is_fully_valid(self):
return self._is_partially_valid() and all([
self._compare_options(),
self._compare_options() if self.original_data.type == 'user' else True,
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),
@@ -403,6 +417,9 @@ class Certificate(OpensshModule):
except ValueError as e:
return self.module.fail_json(msg=to_native(e))
if self.ignore_timestamps:
return original_time_parameters.within_range(self.valid_at)
return all([
original_time_parameters == self.time_parameters,
original_time_parameters.within_range(self.valid_at)
@@ -537,6 +554,7 @@ def main():
valid_at=dict(type='str'),
valid_from=dict(type='str'),
valid_to=dict(type='str'),
ignore_timestamps=dict(type='bool', default=False),
),
supports_check_mode=True,
add_file_common_args=True,

View File

@@ -178,7 +178,7 @@ public_key:
description: The public key of the generated SSH private key.
returned: changed or success
type: str
sample: ssh-rsa AAAAB3Nza(...omitted...)veL4E3Xcw== test_key
sample: ssh-rsa AAAAB3Nza(...omitted...)veL4E3Xcw==
comment:
description: The comment of the generated key.
returned: changed or success

View File

@@ -44,6 +44,9 @@ options:
default: auto
choices: [ auto, cryptography ]
extends_documentation_fragment:
- community.crypto.name_encoding
seealso:
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_csr_pipe
@@ -124,7 +127,9 @@ key_usage_critical:
returned: success
type: bool
subject_alt_name:
description: Entries in the C(subject_alt_name) extension, or C(none) if extension is not present.
description:
- Entries in the C(subject_alt_name) extension, or C(none) if extension is not present.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: list
elements: str
@@ -152,6 +157,7 @@ name_constraints_excluded:
description:
- List of excluded subtrees the CA cannot sign certificates for.
- Is C(none) if extension is not present.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: list
elements: str
@@ -281,6 +287,7 @@ authority_cert_issuer:
description:
- The CSR's authority cert issuer as a list of general names.
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: list
elements: str
@@ -312,6 +319,7 @@ def main():
argument_spec=dict(
path=dict(type='path'),
content=dict(type='str'),
name_encoding=dict(type='str', default='ignore', choices=['ignore', 'idna', 'unicode']),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography']),
),
required_one_of=(

View File

@@ -92,7 +92,14 @@ options:
privatekey_path:
description:
- File to read private key from.
- Mutually exclusive with I(privatekey_content).
type: path
privatekey_content:
description:
- Content of the private key file.
- Mutually exclusive with I(privatekey_path).
type: str
version_added: "2.3.0"
state:
description:
- Whether the file should exist or not.
@@ -160,7 +167,7 @@ EXAMPLES = r'''
action: export
path: /opt/certs/ansible.p12
friendly_name: raclette
privatekey_path: /opt/certs/keys/key.pem
privatekey_content: '{{ private_key_contents }}'
certificate_path: /opt/certs/cert.pem
other_certificates_parse_all: true
other_certificates:
@@ -276,7 +283,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:
@@ -328,6 +335,7 @@ class Pkcs(OpenSSLObject):
self.pkcs12 = None
self.privatekey_passphrase = module.params['privatekey_passphrase']
self.privatekey_path = module.params['privatekey_path']
self.privatekey_content = module.params['privatekey_content']
self.pkcs12_bytes = None
self.return_content = module.params['return_content']
self.src = module.params['src']
@@ -338,6 +346,15 @@ class Pkcs(OpenSSLObject):
self.backup = module.params['backup']
self.backup_file = None
if self.privatekey_path is not None:
try:
with open(self.privatekey_path, 'rb') as fh:
self.privatekey_content = fh.read()
except (IOError, OSError) as exc:
raise PkcsError(exc)
elif self.privatekey_content is not None:
self.privatekey_content = to_bytes(self.privatekey_content)
if self.other_certificates:
if self.other_certificates_parse_all:
filenames = list(self.other_certificates)
@@ -382,7 +399,7 @@ class Pkcs(OpenSSLObject):
def _check_pkey_passphrase():
if self.privatekey_passphrase:
try:
load_privatekey(self.privatekey_path, self.privatekey_passphrase, backend=self.backend)
load_privatekey(None, content=self.privatekey_content, passphrase=self.privatekey_passphrase, backend=self.backend)
except OpenSSLObjectError:
return False
return True
@@ -397,11 +414,11 @@ class Pkcs(OpenSSLObject):
pkcs12_privatekey, pkcs12_certificate, pkcs12_other_certificates, pkcs12_friendly_name = self.parse()
except OpenSSLObjectError:
return False
if (pkcs12_privatekey is not None) and (self.privatekey_path is not None):
if (pkcs12_privatekey is not None) and (self.privatekey_content is not None):
expected_pkey = self._dump_privatekey(self.pkcs12)
if pkcs12_privatekey != expected_pkey:
return False
elif bool(pkcs12_privatekey) != bool(self.privatekey_path):
elif bool(pkcs12_privatekey) != bool(self.privatekey_content):
return False
if (pkcs12_certificate is not None) and (self.certificate_path is not None):
@@ -504,10 +521,10 @@ class PkcsPyOpenSSL(Pkcs):
if self.friendly_name:
self.pkcs12.set_friendlyname(to_bytes(self.friendly_name))
if self.privatekey_path:
if self.privatekey_content:
try:
self.pkcs12.set_privatekey(
load_privatekey(self.privatekey_path, self.privatekey_passphrase, backend=self.backend))
load_privatekey(None, content=self.privatekey_content, passphrase=self.privatekey_passphrase, backend=self.backend))
except OpenSSLBadPassphraseError as exc:
raise PkcsError(exc)
@@ -542,6 +559,8 @@ class PkcsPyOpenSSL(Pkcs):
return crypto.dump_certificate(crypto.FILETYPE_PEM, cert) if cert else None
def _dump_other_certificates(self, pkcs12):
if pkcs12.get_ca_certificates() is None:
return []
return [
crypto.dump_certificate(crypto.FILETYPE_PEM, other_cert)
for other_cert in pkcs12.get_ca_certificates()
@@ -558,9 +577,9 @@ class PkcsCryptography(Pkcs):
def generate_bytes(self, module):
"""Generate PKCS#12 file archive."""
pkey = None
if self.privatekey_path:
if self.privatekey_content:
try:
pkey = load_privatekey(self.privatekey_path, self.privatekey_passphrase, backend=self.backend)
pkey = load_privatekey(None, content=self.privatekey_content, passphrase=self.privatekey_passphrase, backend=self.backend)
except OpenSSLBadPassphraseError as exc:
raise PkcsError(exc)
@@ -683,6 +702,7 @@ def main():
path=dict(type='path', required=True),
privatekey_passphrase=dict(type='str', no_log=True),
privatekey_path=dict(type='path'),
privatekey_content=dict(type='str', no_log=True),
state=dict(type='str', default='present', choices=['absent', 'present']),
src=dict(type='path'),
backup=dict(type='bool', default=False),
@@ -694,10 +714,15 @@ def main():
['action', 'parse', ['src']],
]
mutually_exclusive = [
['privatekey_path', 'privatekey_content'],
]
module = AnsibleModule(
add_file_common_args=True,
argument_spec=argument_spec,
required_if=required_if,
mutually_exclusive=mutually_exclusive,
supports_check_mode=True,
)

View File

@@ -142,7 +142,6 @@ privatekey:
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.crypto.plugins.module_utils.io import (

View File

@@ -123,7 +123,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
load_privatekey,
)
from ansible.module_utils.common.text.converters import to_native, to_bytes
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.basic import AnsibleModule, missing_required_lib

View File

@@ -123,7 +123,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
load_certificate,
)
from ansible.module_utils.common.text.converters import to_native, to_bytes
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.basic import AnsibleModule, missing_required_lib

View File

@@ -62,6 +62,9 @@ options:
default: auto
choices: [ auto, cryptography ]
extends_documentation_fragment:
- community.crypto.name_encoding
notes:
- All timestamp values are provided in ASN.1 TIME format, in other words, following the C(YYYYMMDDHHMMSSZ) pattern.
They are all in UTC.
@@ -168,7 +171,9 @@ key_usage_critical:
returned: success
type: bool
subject_alt_name:
description: Entries in the C(subject_alt_name) extension, or C(none) if extension is not present.
description:
- Entries in the C(subject_alt_name) extension, or C(none) if extension is not present.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: list
elements: str
@@ -355,6 +360,7 @@ authority_cert_issuer:
description:
- The certificate's authority cert issuer as a list of general names.
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: list
elements: str
@@ -397,6 +403,7 @@ def main():
path=dict(type='path'),
content=dict(type='str'),
valid_at=dict(type='dict'),
name_encoding=dict(type='str', default='ignore', choices=['ignore', 'idna', 'unicode']),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography']),
),
required_one_of=(

View File

@@ -123,8 +123,6 @@ certificate:
'''
import os
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.certificate import (

View File

@@ -242,6 +242,7 @@ options:
extends_documentation_fragment:
- files
- community.crypto.name_encoding
notes:
- All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.
@@ -297,6 +298,7 @@ issuer:
description:
- The CRL's issuer.
- Note that for repeated values, only the last one will be returned.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: dict
sample: '{"organizationName": "Ansible", "commonName": "ca.example.com"}'
@@ -336,7 +338,9 @@ revoked_certificates:
type: str
sample: 20190413202428Z
issuer:
description: The certificate's issuer.
description:
- The certificate's issuer.
- See I(name_encoding) for how IDNs are handled.
type: list
elements: str
sample: '["DNS:ca.example.org"]'
@@ -405,7 +409,9 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
cryptography_decode_name,
cryptography_get_name,
cryptography_key_needs_digest_for_signing,
cryptography_name_to_oid,
cryptography_oid_to_name,
cryptography_serial_number_of_cert,
@@ -468,6 +474,7 @@ class CRL(OpenSSLObject):
self.update = module.params['mode'] == 'update'
self.ignore_timestamps = module.params['ignore_timestamps']
self.return_content = module.params['return_content']
self.name_encoding = module.params['name_encoding']
self.crl_content = None
self.privatekey_path = module.params['privatekey_path']
@@ -595,11 +602,20 @@ class CRL(OpenSSLObject):
super(CRL, self).remove(self.module)
def _compress_entry(self, entry):
issuer = None
if entry['issuer'] is not None:
# Normalize to IDNA. If this is used-provided, it was already converted to
# IDNA (by cryptography_get_name) and thus the `idna` library is present.
# If this is coming from cryptography and isn't already in IDNA (i.e. ascii),
# cryptography < 2.1 must be in use, which depends on `idna`. So this should
# not require `idna` except if it was already used by code earlier during
# this invocation.
issuer = tuple(cryptography_decode_name(issuer, idn_rewrite='idna') for issuer in entry['issuer'])
if self.ignore_timestamps:
# Throw out revocation_date
return (
entry['serial_number'],
tuple(entry['issuer']) if entry['issuer'] is not None else None,
issuer,
entry['issuer_critical'],
entry['reason'],
entry['reason_critical'],
@@ -610,7 +626,7 @@ class CRL(OpenSSLObject):
return (
entry['serial_number'],
entry['revocation_date'],
tuple(entry['issuer']) if entry['issuer'] is not None else None,
issuer,
entry['issuer_critical'],
entry['reason'],
entry['reason_critical'],
@@ -633,8 +649,12 @@ class CRL(OpenSSLObject):
return False
if self.next_update != self.crl.next_update and not self.ignore_timestamps:
return False
if self.digest.name != self.crl.signature_hash_algorithm.name:
return False
if cryptography_key_needs_digest_for_signing(self.privatekey):
if self.crl.signature_hash_algorithm is None or self.digest.name != self.crl.signature_hash_algorithm.name:
return False
else:
if self.crl.signature_hash_algorithm is not None:
return False
want_issuer = [(cryptography_name_to_oid(entry[0]), entry[1]) for entry in self.issuer]
is_issuer = [(sub.oid, sub.value) for sub in self.crl.issuer]
@@ -689,9 +709,7 @@ class CRL(OpenSSLObject):
revoked_cert = revoked_cert.revocation_date(entry['revocation_date'])
if entry['issuer'] is not None:
revoked_cert = revoked_cert.add_extension(
x509.CertificateIssuer([
cryptography_get_name(name, 'issuer') for name in entry['issuer']
]),
x509.CertificateIssuer(entry['issuer']),
entry['issuer_critical']
)
if entry['reason'] is not None:
@@ -706,7 +724,10 @@ class CRL(OpenSSLObject):
)
crl = crl.add_revoked_certificate(revoked_cert.build(backend))
self.crl = crl.sign(self.privatekey, self.digest, backend=backend)
digest = None
if cryptography_key_needs_digest_for_signing(self.privatekey):
digest = self.digest
self.crl = crl.sign(self.privatekey, digest, backend=backend)
if self.format == 'pem':
return self.crl.public_bytes(Encoding.PEM)
else:
@@ -767,7 +788,7 @@ class CRL(OpenSSLObject):
result['issuer'][k] = v
result['revoked_certificates'] = []
for entry in self.revoked_certificates:
result['revoked_certificates'].append(cryptography_dump_revoked(entry))
result['revoked_certificates'].append(cryptography_dump_revoked(entry, idn_rewrite=self.name_encoding))
elif self.crl:
result['last_update'] = self.crl.last_update.strftime(TIMESTAMP_FORMAT)
result['next_update'] = self.crl.next_update.strftime(TIMESTAMP_FORMAT)
@@ -782,7 +803,7 @@ class CRL(OpenSSLObject):
result['revoked_certificates'] = []
for cert in self.crl:
entry = cryptography_decode_revoked_certificate(cert)
result['revoked_certificates'].append(cryptography_dump_revoked(entry))
result['revoked_certificates'].append(cryptography_dump_revoked(entry, idn_rewrite=self.name_encoding))
if self.return_content:
result['crl'] = self.crl_content
@@ -838,6 +859,7 @@ def main():
required_one_of=[['path', 'content', 'serial_number']],
mutually_exclusive=[['path', 'content', 'serial_number']],
),
name_encoding=dict(type='str', default='ignore', choices=['ignore', 'idna', 'unicode']),
),
required_if=[
('state', 'present', ['privatekey_path', 'privatekey_content'], True),

View File

@@ -40,6 +40,9 @@ options:
default: true
version_added: 1.7.0
extends_documentation_fragment:
- community.crypto.name_encoding
notes:
- All timestamp values are provided in ASN.1 TIME format, in other words, following the C(YYYYMMDDHHMMSSZ) pattern.
They are all in UTC.
@@ -76,6 +79,7 @@ issuer:
description:
- The CRL's issuer.
- Note that for repeated values, only the last one will be returned.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: dict
sample: '{"organizationName": "Ansible", "commonName": "ca.example.com"}'
@@ -115,7 +119,9 @@ revoked_certificates:
type: str
sample: 20190413202428Z
issuer:
description: The certificate's issuer.
description:
- The certificate's issuer.
- See I(name_encoding) for how IDNs are handled.
type: list
elements: str
sample: '["DNS:ca.example.org"]'
@@ -173,6 +179,7 @@ def main():
path=dict(type='path'),
content=dict(type='str'),
list_revoked_certificates=dict(type='bool', default=True),
name_encoding=dict(type='str', default='ignore', choices=['ignore', 'idna', 'unicode']),
),
required_one_of=(
['path', 'content'],

8
simplified_bsd.txt Normal file
View File

@@ -0,0 +1,8 @@
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

34
tests/ee/all.yml Normal file
View File

@@ -0,0 +1,34 @@
- hosts: localhost
tasks:
- name: Register cryptography version
command: "{{ ansible_python.executable }} -c 'import cryptography; print(cryptography.__version__)'"
register: cryptography_version
- name: Determine output directory
set_fact:
output_path: "{{ 'output-%0x' % ((2**32) | random) }}"
- name: Find all roles
ansible.builtin.find:
paths:
- "{{ (playbook_dir | default('.')) ~ '/roles' }}"
file_type: directory
depth: 1
register: result
- name: Create output directory
ansible.builtin.file:
path: "{{ output_path }}"
state: directory
- block:
- name: Include all roles
ansible.builtin.include_role:
name: "{{ item }}"
loop: "{{ result.files | map(attribute='path') | map('regex_replace', '.*/', '') | sort }}"
always:
- name: Remove output directory
ansible.builtin.file:
path: "{{ output_path }}"
state: absent

View File

@@ -0,0 +1,27 @@
---
- name: Run crypto_info
community.crypto.crypto_info:
register: result
- name: Dump result
debug:
var: result
- name: Validate result
assert:
that:
- result.openssl_present
- result.python_cryptography_installed
- result.python_cryptography_capabilities.has_dsa
- result.python_cryptography_capabilities.has_dsa_sign
- result.python_cryptography_capabilities.has_ec
- result.python_cryptography_capabilities.has_ec_sign
- result.python_cryptography_capabilities.has_ed25519
- result.python_cryptography_capabilities.has_ed25519_sign
- result.python_cryptography_capabilities.has_ed448
- result.python_cryptography_capabilities.has_ed448_sign
- result.python_cryptography_capabilities.has_rsa
- result.python_cryptography_capabilities.has_rsa_sign
- result.python_cryptography_capabilities.has_x25519
- result.python_cryptography_capabilities.has_x25519_serialization
- result.python_cryptography_capabilities.has_x448

View File

@@ -0,0 +1,45 @@
---
- name: Run cryptsetup (smoke test)
ansible.builtin.command: cryptsetup --version
- name: Determine cryptfile path
ansible.builtin.set_fact:
cryptfile_path: "{{ output_path }}/cryptfile"
keyfile_path: "{{ output_path }}/keyfile"
- name: Create cryptfile
ansible.builtin.command: dd if=/dev/zero of={{ cryptfile_path }} bs=1M count=32
- name: Create keyfile
ansible.builtin.copy:
dest: "{{ keyfile_path }}"
content: hunter2
- # Creating devices doesn't work well. We will have to try this again when luks_device
# supports working with container files directly.
when: false
block:
- name: Create lookback device
command: losetup -f {{ cryptfile_path }}
- name: Determine loop device name
command: losetup -j {{ cryptfile_path }} --output name
register: cryptfile_device_output
- set_fact:
cryptfile_device: "{{ cryptfile_device_output.stdout_lines[1] }}"
- name: Create LUKS container
community.crypto.luks_device:
device: "{{ cryptfile_device }}"
# device: "{{ cryptfile_path }}"
state: present
keyfile: "{{ keyfile_path }}"
pbkdf:
iteration_time: 0.1
- name: Destroy LUKS container
community.crypto.luks_device:
device: "{{ cryptfile_device }}"
# device: "{{ cryptfile_path }}"
state: absent

View File

@@ -0,0 +1,13 @@
---
- name: Generate key with OpenSSH binary backend
community.crypto.openssh_keypair:
path: "{{ output_path }}/openssh-key-1"
size: 2048
backend: opensshbin
- name: Generate key with cryptography backend
community.crypto.openssh_keypair:
path: "{{ output_path }}/openssh-key-2"
size: 2048
backend: cryptography
when: cryptography_version.stdout is ansible.builtin.version('3.0', '>=')

View File

@@ -0,0 +1,41 @@
---
- name: Create private key
community.crypto.openssl_privatekey:
path: "{{ output_path }}/pkcs12-cert.key"
type: ECC
curve: secp256r1
- name: Create CSR
community.crypto.openssl_csr:
path: "{{ output_path }}/pkcs12-cert.csr"
privatekey_path: "{{ output_path }}/pkcs12-cert.key"
- name: Create certificate
community.crypto.x509_certificate:
path: "{{ output_path }}/pkcs12-cert.pem"
csr_path: "{{ output_path }}/pkcs12-cert.csr"
privatekey_path: "{{ output_path }}/pkcs12-cert.key"
provider: selfsigned
- name: Create PKCS#12 with cryptography backend
community.crypto.openssl_pkcs12:
action: export
path: "{{ output_path }}/pkcs12-1.p12"
mode: '0644'
friendly_name: foo
privatekey_path: "{{ output_path }}/pkcs12-cert.key"
certificate_path: "{{ output_path }}/pkcs12-cert.pem"
state: present
select_crypto_backend: cryptography
when: cryptography_version.stdout is ansible.builtin.version('3.0', '>=')
- name: Create PKCS#12 with PyOpenSSL backend
community.crypto.openssl_pkcs12:
action: export
path: "{{ output_path }}/pkcs12-2.p12"
mode: '0644'
friendly_name: foo
privatekey_path: "{{ output_path }}/pkcs12-cert.key"
certificate_path: "{{ output_path }}/pkcs12-cert.pem"
state: present
select_crypto_backend: pyopenssl

View File

@@ -0,0 +1,11 @@
---
- name: Create RSA private key
community.crypto.openssl_privatekey:
path: "{{ output_path }}/privatekey-1"
size: 2048
- name: Create ECC private key
community.crypto.openssl_privatekey:
path: "{{ output_path }}/privatekey-2"
type: ECC
curve: secp256r1

View File

@@ -0,0 +1,48 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022 Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r'''
---
module: smoke_ipaddress
short_description: Check whether ipaddress is present
author:
- Felix Fontein (@felixfontein)
description:
- Check whether C(ipaddress) is present.
options: {}
'''
EXAMPLES = r''' # '''
RETURN = r''' # '''
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
import ipaddress
HAS_IPADDRESS = True
except ImportError as exc:
IPADDRESS_IMP_ERR = traceback.format_exc()
HAS_IPADDRESS = False
def main():
module = AnsibleModule(argument_spec=dict(), supports_check_mode=True)
if not HAS_IPADDRESS:
module.fail_json(msg=missing_required_lib('ipaddress'), exception=IPADDRESS_IMP_ERR)
module.exit_json(msg='Everything is ok')
if __name__ == '__main__': # pragma: no cover
main() # pragma: no cover

View File

@@ -0,0 +1,48 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2022 Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r'''
---
module: smoke_pyyaml
short_description: Check whether PyYAML is present
author:
- Felix Fontein (@felixfontein)
description:
- Check whether C(yaml) is present.
options: {}
'''
EXAMPLES = r''' # '''
RETURN = r''' # '''
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
import yaml
HAS_PYYAML = True
except ImportError as exc:
PYYAML_IMP_ERR = traceback.format_exc()
HAS_PYYAML = False
def main():
module = AnsibleModule(argument_spec=dict(), supports_check_mode=True)
if not HAS_PYYAML:
module.fail_json(msg=missing_required_lib('PyYAML'), exception=PYYAML_IMP_ERR)
module.exit_json(msg='Everything is ok')
if __name__ == '__main__': # pragma: no cover
main() # pragma: no cover

View File

@@ -0,0 +1,18 @@
---
- name: Check whether ipaddress is present
smoke_ipaddress:
register: result
- name: Validate result
assert:
that:
- result.msg == 'Everything is ok'
- name: Check whether PyYAML is present
smoke_pyyaml:
register: result
- name: Validate result
assert:
that:
- result.msg == 'Everything is ok'

View File

@@ -0,0 +1,18 @@
---
- name: Create private key
community.crypto.openssl_privatekey:
path: "{{ output_path }}/cert.key"
type: ECC
curve: secp256r1
- name: Create CSR
community.crypto.openssl_csr:
path: "{{ output_path }}/cert.csr"
privatekey_path: "{{ output_path }}/cert.key"
- name: Create certificate
community.crypto.x509_certificate:
path: "{{ output_path }}/cert.pem"
csr_path: "{{ output_path }}/cert.csr"
privatekey_path: "{{ output_path }}/cert.key"
provider: selfsigned

View File

@@ -1,14 +1,10 @@
shippable/cloud/group1
shippable/posix/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
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel

View File

@@ -1,14 +1,10 @@
shippable/cloud/group1
shippable/posix/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
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel

View File

@@ -1,14 +1,10 @@
shippable/cloud/group1
shippable/posix/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
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel

View File

@@ -1,14 +1,10 @@
shippable/cloud/group1
shippable/posix/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
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel

View File

@@ -1,14 +1,10 @@
shippable/cloud/group1
shippable/posix/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
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel

View File

@@ -1,14 +1,10 @@
shippable/cloud/group1
shippable/posix/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
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel

View File

@@ -1,3 +1,4 @@
dependencies:
- prepare_jinja2_compat
- setup_openssl
- setup_remote_tmp_dir

View File

@@ -0,0 +1,20 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: Generate CSR for {{ certificate.name }}
openssl_csr:
path: '{{ remote_tmp_dir }}/{{ certificate.name }}.csr'
privatekey_path: '{{ remote_tmp_dir }}/{{ certificate.name }}.key'
subject: '{{ certificate.subject }}'
useCommonNameForSAN: false
- name: Generate certificate for {{ certificate.name }}
x509_certificate:
path: '{{ remote_tmp_dir }}/{{ certificate.name }}.pem'
csr_path: '{{ remote_tmp_dir }}/{{ certificate.name }}.csr'
privatekey_path: '{{ remote_tmp_dir }}/{{ certificate.name }}.key'
provider: '{{ "selfsigned" if certificate.parent is not defined else "ownca" }}'
ownca_path: '{{ (remote_tmp_dir ~ "/" ~ certificate.parent ~ ".pem") if certificate.parent is defined else omit }}'
ownca_privatekey_path: '{{ (remote_tmp_dir ~ "/" ~ certificate.parent ~ ".key") if certificate.parent is defined else omit }}'

View File

@@ -0,0 +1,49 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- block:
- name: Create private keys
openssl_privatekey:
path: '{{ remote_tmp_dir }}/{{ item.name }}.key'
size: '{{ default_rsa_key_size_certifiates }}'
loop: '{{ certificates }}'
- name: Generate certificates
include_tasks: create-single-certificate.yml
loop: '{{ certificates }}'
loop_control:
loop_var: certificate
- name: Read certificates
slurp:
src: '{{ remote_tmp_dir }}/{{ item.name }}.pem'
loop: '{{ certificates }}'
register: certificates_read
- name: Store read certificates
set_fact:
read_certificates: >-
{{ certificates_read.results | map(attribute='content') | map('b64decode')
| zip(certificates | map(attribute='name'))
| list
| items2dict(key_name=1, value_name=0) }}
vars:
certificates:
- name: a-root
subject:
commonName: root common name
- name: b-intermediate
subject:
commonName: intermediate common name
parent: a-root
- name: c-intermediate
subject:
commonName: intermediate common name
parent: a-root
- name: d-leaf
subject:
commonName: leaf certificate
parent: b-intermediate

View File

@@ -0,0 +1,44 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: Case A => works
certificate_complete_chain:
input_chain: "{{ read_certificates['d-leaf'] }}"
intermediate_certificates:
- '{{ remote_tmp_dir }}/b-intermediate.pem'
root_certificates:
- '{{ remote_tmp_dir }}/a-root.pem'
- name: Case B => doesn't work, but this is expected
failed_when: no
register: caseb
certificate_complete_chain:
input_chain: "{{ read_certificates['d-leaf'] }}"
intermediate_certificates:
- '{{ remote_tmp_dir }}/c-intermediate.pem'
root_certificates:
- '{{ remote_tmp_dir }}/a-root.pem'
- name: Assert that case B failed
assert:
that: "'Cannot complete chain' in caseb.msg"
- name: Case C => works
certificate_complete_chain:
input_chain: "{{ read_certificates['d-leaf'] }}"
intermediate_certificates:
- '{{ remote_tmp_dir }}/c-intermediate.pem'
- '{{ remote_tmp_dir }}/b-intermediate.pem'
root_certificates:
- '{{ remote_tmp_dir }}/a-root.pem'
- name: Case D => works as well after PR 403
certificate_complete_chain:
input_chain: "{{ read_certificates['d-leaf'] }}"
intermediate_certificates:
- '{{ remote_tmp_dir }}/b-intermediate.pem'
- '{{ remote_tmp_dir }}/c-intermediate.pem'
root_certificates:
- '{{ remote_tmp_dir }}/a-root.pem'

View File

@@ -0,0 +1,144 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- block:
- name: Find root for cert 1 using directory
certificate_complete_chain:
input_chain: '{{ fullchain | trim }}'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots/'
register: cert1_root
- name: Verify root for cert 1
assert:
that:
- cert1_root.complete_chain | join('') == (fullchain ~ root)
- cert1_root.root == root
vars:
fullchain: "{{ lookup('file', 'cert1-fullchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert1-root.pem', rstrip=False) }}"
- block:
- name: Find rootchain for cert 1 using intermediate and root PEM
certificate_complete_chain:
input_chain: '{{ cert }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert1-chain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert1_rootchain
- name: Verify rootchain for cert 1
assert:
that:
- cert1_rootchain.complete_chain | join('') == (cert ~ chain ~ root)
- cert1_rootchain.chain[:-1] | join('') == chain
- cert1_rootchain.root == root
vars:
cert: "{{ lookup('file', 'cert1.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert1-chain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert1-root.pem', rstrip=False) }}"
- block:
- name: Find root for cert 2 using directory
certificate_complete_chain:
input_chain: "{{ fullchain | trim }}"
root_certificates:
- '{{ remote_tmp_dir }}/files/roots/'
register: cert2_root
- name: Verify root for cert 2
assert:
that:
- cert2_root.complete_chain | join('') == (fullchain ~ root)
- cert2_root.root == root
vars:
fullchain: "{{ lookup('file', 'cert2-fullchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-root.pem', rstrip=False) }}"
- block:
- name: Find rootchain for cert 2 using intermediate and root PEM
certificate_complete_chain:
input_chain: '{{ cert }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert2-chain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_rootchain
- name: Verify rootchain for cert 2
assert:
that:
- cert2_rootchain.complete_chain | join('') == (cert ~ chain ~ root)
- cert2_rootchain.chain[:-1] | join('') == chain
- cert2_rootchain.root == root
vars:
cert: "{{ lookup('file', 'cert2.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert2-chain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-root.pem', rstrip=False) }}"
- block:
- name: Find alternate rootchain for cert 2 using intermediate and root PEM
certificate_complete_chain:
input_chain: '{{ cert }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert2-altchain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_rootchain_alt
- name: Verify rootchain for cert 2
assert:
that:
- cert2_rootchain_alt.complete_chain | join('') == (cert ~ chain ~ root)
- cert2_rootchain_alt.chain[:-1] | join('') == chain
- cert2_rootchain_alt.root == root
vars:
cert: "{{ lookup('file', 'cert2.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert2-altchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-altroot.pem', rstrip=False) }}"
- block:
- name: Find alternate rootchain for cert 2 when complete chain is already presented to the module
certificate_complete_chain:
input_chain: '{{ cert ~ chain ~ root }}'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_complete_chain
- name: Verify rootchain for cert 2
assert:
that:
- cert2_complete_chain.complete_chain | join('') == (cert ~ chain ~ root)
- cert2_complete_chain.chain == []
- cert2_complete_chain.root == root
vars:
cert: "{{ lookup('file', 'cert2.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert2-altchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-altroot.pem', rstrip=False) }}"
- name: Check failure when no intermediate certificate can be found
certificate_complete_chain:
input_chain: '{{ lookup("file", "cert2.pem", rstrip=True) }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert1-chain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_no_intermediate
ignore_errors: true
- name: Verify failure
assert:
that:
- cert2_no_intermediate is failed
- "cert2_no_intermediate.msg.startswith('Cannot complete chain. Stuck at certificate ')"
- name: Check failure when infinite loop is found
certificate_complete_chain:
input_chain: '{{ lookup("file", "cert1-fullchain.pem", rstrip=True) }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/cert2-chain.pem'
register: cert2_infinite_loop
ignore_errors: true
- name: Verify failure
assert:
that:
- cert2_infinite_loop is failed
- "cert2_infinite_loop.msg == 'Found cycle while building certificate chain'"

View File

@@ -15,144 +15,13 @@
src: '{{ role_path }}/files/'
dest: '{{ remote_tmp_dir }}/files/'
- block:
- name: Find root for cert 1 using directory
certificate_complete_chain:
input_chain: '{{ fullchain | trim }}'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots/'
register: cert1_root
- name: Verify root for cert 1
assert:
that:
- cert1_root.complete_chain | join('') == (fullchain ~ root)
- cert1_root.root == root
vars:
fullchain: "{{ lookup('file', 'cert1-fullchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert1-root.pem', rstrip=False) }}"
- name: Run tests with copied certificates
import_tasks: existing.yml
- block:
- name: Find rootchain for cert 1 using intermediate and root PEM
certificate_complete_chain:
input_chain: '{{ cert }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert1-chain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert1_rootchain
- name: Verify rootchain for cert 1
assert:
that:
- cert1_rootchain.complete_chain | join('') == (cert ~ chain ~ root)
- cert1_rootchain.chain[:-1] | join('') == chain
- cert1_rootchain.root == root
vars:
cert: "{{ lookup('file', 'cert1.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert1-chain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert1-root.pem', rstrip=False) }}"
- name: Create more certificates
import_tasks: create.yml
- block:
- name: Find root for cert 2 using directory
certificate_complete_chain:
input_chain: "{{ fullchain | trim }}"
root_certificates:
- '{{ remote_tmp_dir }}/files/roots/'
register: cert2_root
- name: Verify root for cert 2
assert:
that:
- cert2_root.complete_chain | join('') == (fullchain ~ root)
- cert2_root.root == root
vars:
fullchain: "{{ lookup('file', 'cert2-fullchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-root.pem', rstrip=False) }}"
- block:
- name: Find rootchain for cert 2 using intermediate and root PEM
certificate_complete_chain:
input_chain: '{{ cert }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert2-chain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_rootchain
- name: Verify rootchain for cert 2
assert:
that:
- cert2_rootchain.complete_chain | join('') == (cert ~ chain ~ root)
- cert2_rootchain.chain[:-1] | join('') == chain
- cert2_rootchain.root == root
vars:
cert: "{{ lookup('file', 'cert2.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert2-chain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-root.pem', rstrip=False) }}"
- block:
- name: Find alternate rootchain for cert 2 using intermediate and root PEM
certificate_complete_chain:
input_chain: '{{ cert }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert2-altchain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_rootchain_alt
- name: Verify rootchain for cert 2
assert:
that:
- cert2_rootchain_alt.complete_chain | join('') == (cert ~ chain ~ root)
- cert2_rootchain_alt.chain[:-1] | join('') == chain
- cert2_rootchain_alt.root == root
vars:
cert: "{{ lookup('file', 'cert2.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert2-altchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-altroot.pem', rstrip=False) }}"
- block:
- name: Find alternate rootchain for cert 2 when complete chain is already presented to the module
certificate_complete_chain:
input_chain: '{{ cert ~ chain ~ root }}'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_complete_chain
- name: Verify rootchain for cert 2
assert:
that:
- cert2_complete_chain.complete_chain | join('') == (cert ~ chain ~ root)
- cert2_complete_chain.chain == []
- cert2_complete_chain.root == root
vars:
cert: "{{ lookup('file', 'cert2.pem', rstrip=False) }}"
chain: "{{ lookup('file', 'cert2-altchain.pem', rstrip=False) }}"
root: "{{ lookup('file', 'cert2-altroot.pem', rstrip=False) }}"
- name: Check failure when no intermediate certificate can be found
certificate_complete_chain:
input_chain: '{{ lookup("file", "cert2.pem", rstrip=True) }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/cert1-chain.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
register: cert2_no_intermediate
ignore_errors: true
- name: Verify failure
assert:
that:
- cert2_no_intermediate is failed
- "cert2_no_intermediate.msg.startswith('Cannot complete chain. Stuck at certificate ')"
- name: Check failure when infinite loop is found
certificate_complete_chain:
input_chain: '{{ lookup("file", "cert2-fullchain.pem", rstrip=True) }}'
intermediate_certificates:
- '{{ remote_tmp_dir }}/files/roots.pem'
root_certificates:
- '{{ remote_tmp_dir }}/files/cert1-chain.pem'
register: cert2_infinite_loop
ignore_errors: true
- name: Verify failure
assert:
that:
- cert2_infinite_loop is failed
- "cert2_infinite_loop.msg == 'Found cycle while building certificate chain'"
- name: Run tests with created certificates
import_tasks: created.yml
when: cryptography_version.stdout is version('1.5', '>=')

View File

@@ -0,0 +1,103 @@
---
- name: Gather package facts
package_facts:
manager: auto
- name: On kernel >= 5.9 use performance flags
block:
- name: Create and open (check)
luks_device:
device: "{{ cryptfile_device }}"
state: opened
keyfile: "{{ remote_tmp_dir }}/keyfile1"
perf_same_cpu_crypt: true
perf_submit_from_crypt_cpus: true
perf_no_read_workqueue: true
perf_no_write_workqueue: true
persistent: true
pbkdf:
iteration_time: 0.1
check_mode: yes
become: yes
register: create_open_check
- name: Create and open
luks_device:
device: "{{ cryptfile_device }}"
state: opened
keyfile: "{{ remote_tmp_dir }}/keyfile1"
pbkdf:
iteration_time: 0.1
perf_same_cpu_crypt: true
perf_submit_from_crypt_cpus: true
perf_no_read_workqueue: true
perf_no_write_workqueue: true
persistent: true
become: yes
register: create_open
- name: Create and open (idempotent)
luks_device:
device: "{{ cryptfile_device }}"
state: opened
keyfile: "{{ remote_tmp_dir }}/keyfile1"
pbkdf:
iteration_time: 0.1
perf_same_cpu_crypt: true
perf_submit_from_crypt_cpus: true
perf_no_read_workqueue: true
perf_no_write_workqueue: true
persistent: true
become: yes
register: create_open_idem
- name: Create and open (idempotent, check)
luks_device:
device: "{{ cryptfile_device }}"
state: present
keyfile: "{{ remote_tmp_dir }}/keyfile1"
pbkdf:
iteration_time: 0.1
perf_same_cpu_crypt: true
perf_submit_from_crypt_cpus: true
perf_no_read_workqueue: true
perf_no_write_workqueue: true
persistent: true
check_mode: yes
become: yes
register: create_open_idem_check
- assert:
that:
- create_open_check is changed
- create_open is changed
- create_open_idem is not changed
- create_open_idem_check is not changed
- name: Dump LUKS Header
command: "cryptsetup luksDump {{ cryptfile_device }}"
become: yes
register: luks_header
- assert:
that:
- "'no-read-workqueue' in luks_header.stdout"
- "'no-write-workqueue' in luks_header.stdout"
- "'same-cpu-crypt' in luks_header.stdout"
- "'submit-from-crypt-cpus' in luks_header.stdout"
- name: Dump device mapper table
command: "dmsetup table {{ create_open.name }}"
become: yes
register: dm_table
- assert:
that:
- "'no_read_workqueue' in dm_table.stdout"
- "'no_write_workqueue' in dm_table.stdout"
- "'same_cpu_crypt' in dm_table.stdout"
- "'submit_from_crypt_cpus' in dm_table.stdout"
- name: Closed and Removed
luks_device:
name: "{{ cryptfile_device }}"
state: absent
become: yes
when:
- ansible_facts.kernel is version('5.9.0', '>=')
- ansible_facts.packages['cryptsetup'][0].version is version('2.3.4', '>=')

View File

@@ -53,21 +53,25 @@
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
- block:
- 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: Assert second signature algorithm update causes change
assert:
that:
- second_signature_algorithm is changed
# RHEL9 disables SHA-1 algorithms by default making this test fail with a 'libcrypt' error. Other systems which
# impose a similar restriction may also need to skip this block in the future.
when: not (ansible_facts['distribution'] == "RedHat" and (ansible_facts['distribution_major_version'] | int) >= 9)
- name: Omit signature algorithm
openssh_cert:

View File

@@ -86,6 +86,78 @@
regenerate: full_idempotence
register: default_options
- name: Generate cert with relative timestamp
openssh_cert:
type: user
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: +0s
valid_to: +32w
valid_at: +2w
regenerate: full_idempotence
register: relative_timestamp
- name: Generate cert with ignore_timestamp true
openssh_cert:
type: user
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: +0s
valid_to: +32w
valid_at: +2w
ignore_timestamps: true
regenerate: full_idempotence
register: relative_timestamp_true
- name: Generate cert with ignore_timestamp false
openssh_cert:
type: user
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: +0s
valid_to: +32w
valid_at: +2w
ignore_timestamps: false
regenerate: full_idempotence
register: relative_timestamp_false
- name: Generate cert with ignore_timestamp true
openssh_cert:
type: user
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: +0s
valid_to: +32w
valid_at: +50w
ignore_timestamps: true
regenerate: full_idempotence
register: relative_timestamp_invalid_at
- name: Generate host cert full_idempotence
openssh_cert:
type: host
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: always
valid_to: forever
regenerate: full_idempotence
- name: Generate host cert full_idempotence again
openssh_cert:
type: host
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: always
valid_to: forever
regenerate: full_idempotence
register: host_cert_full_idempotence
- name: Assert options results
assert:
that:
@@ -95,6 +167,11 @@
- explicit_extension_after is not changed
- explicit_extension_and_directive is changed
- default_options is not changed
- relative_timestamp is changed
- relative_timestamp_true is not changed
- relative_timestamp_false is changed
- relative_timestamp_invalid_at is changed
- host_cert_full_idempotence is not changed
- name: Remove certificate
openssh_cert:

View File

@@ -8,6 +8,20 @@
select_crypto_backend: '{{ select_crypto_backend }}'
register: result
- name: "({{ select_crypto_backend }}) Get CSR info (IDNA encoding)"
openssl_csr_info:
path: '{{ remote_tmp_dir }}/csr_1.csr'
name_encoding: idna
select_crypto_backend: '{{ select_crypto_backend }}'
register: result_idna
- name: "({{ select_crypto_backend }}) Get CSR info (Unicode encoding)"
openssl_csr_info:
path: '{{ remote_tmp_dir }}/csr_1.csr'
name_encoding: unicode
select_crypto_backend: '{{ select_crypto_backend }}'
register: result_unicode
- name: "({{ select_crypto_backend }}) Check whether subject and extensions behaves as expected"
assert:
that:
@@ -23,8 +37,11 @@
- result.extensions_by_oid['2.5.29.15'].critical == true
- result.extensions_by_oid['2.5.29.15'].value in ['AwMA/4A=', 'AwMH/4A=']
# Subject Alternative Names
- result.subject_alt_name[1] == ("DNS:âņsïbłè.com" if cryptography_version.stdout is version('2.1', '<') else "DNS:xn--sb-oia0a7a53bya.com")
- result_unicode.subject_alt_name[1] == "DNS:âņsïbłè.com"
- result_idna.subject_alt_name[1] == "DNS:xn--sb-oia0a7a53bya.com"
- result.extensions_by_oid['2.5.29.17'].critical == false
- result.extensions_by_oid['2.5.29.17'].value == 'MGCCD3d3dy5hbnNpYmxlLmNvbYcEAQIDBIcQAAAAAAAAAAAAAAAAAAAAAYEQdGVzdEBleGFtcGxlLm9yZ4YjaHR0cHM6Ly9leGFtcGxlLm9yZy90ZXN0L2luZGV4Lmh0bWw='
- result.extensions_by_oid['2.5.29.17'].value == 'MHmCD3d3dy5hbnNpYmxlLmNvbYIXeG4tLXNiLW9pYTBhN2E1M2J5YS5jb22HBAECAwSHEAAAAAAAAAAAAAAAAAAAAAGBEHRlc3RAZXhhbXBsZS5vcmeGI2h0dHBzOi8vZXhhbXBsZS5vcmcvdGVzdC9pbmRleC5odG1s'
# Basic Constraints
- result.extensions_by_oid['2.5.29.19'].critical == true
- result.extensions_by_oid['2.5.29.19'].value == 'MAYBAf8CARc='

View File

@@ -4,6 +4,11 @@
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: Make sure the Python idna library is installed
pip:
name: idna
state: present
- name: Generate privatekey
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey.pem'
@@ -67,6 +72,7 @@
- biometricInfo
subject_alt_name:
- "DNS:www.ansible.com"
- "DNS:âņsïbłè.com"
- "IP:1.2.3.4"
- "IP:::1"
- "email:test@example.org"

View File

@@ -45,6 +45,34 @@
return_content: true
register: p12_standard_idempotency
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file again, idempotency (empty other_certificates)"
openssl_pkcs12:
select_crypto_backend: '{{ select_crypto_backend }}'
path: '{{ remote_tmp_dir }}/ansible.p12'
friendly_name: abracadabra
privatekey_path: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
state: present
return_content: true
other_certificates: []
register: p12_standard_idempotency_no_certs
- name: "({{ select_crypto_backend }}) Read ansible_pkey1.pem"
slurp:
src: '{{ remote_tmp_dir }}/ansible_pkey1.pem'
register: ansible_pkey_content
- name: "({{ select_crypto_backend }}) Generate PKCS#12 file again, idempotency (private key from file)"
openssl_pkcs12:
select_crypto_backend: '{{ select_crypto_backend }}'
path: '{{ remote_tmp_dir }}/ansible.p12'
friendly_name: abracadabra
privatekey_content: '{{ ansible_pkey_content.content | b64decode }}'
certificate_path: '{{ remote_tmp_dir }}/ansible1.crt'
state: present
return_content: true
register: p12_standard_idempotency_2
- name: "({{ select_crypto_backend }}) Read ansible.p12"
slurp:
src: '{{ remote_tmp_dir }}/ansible.p12'

View File

@@ -65,7 +65,7 @@
vars:
select_crypto_backend: pyopenssl
when: pyopenssl_version.stdout is version('0.15', '>=')
when: (pyopenssl_version.stdout | default('0.0')) is version('0.15', '>=')
- block:
- name: Running tests with cryptography backend
@@ -75,4 +75,4 @@
when: cryptography_version.stdout is version('3.0', '>=')
when: pyopenssl_version.stdout is version('0.15', '>=') or cryptography_version.stdout is version('3.0', '>=')
when: (pyopenssl_version.stdout | default('0.0')) is version('0.15', '>=') or cryptography_version.stdout is version('3.0', '>=')

View File

@@ -25,6 +25,8 @@
- p12_dumped is changed
- p12_standard_idempotency is not changed
- p12_standard_idempotency_check is not changed
- p12_standard_idempotency_no_certs is not changed
- p12_standard_idempotency_2 is not changed
- p12_multiple_certs_idempotency is not changed
- p12_dumped_idempotency is not changed
- p12_dumped_check_mode is not changed
@@ -83,4 +85,4 @@
- p12_empty is changed
- p12_empty_idem is not changed
- p12_empty_concat_idem is not changed
- empty_contents == (empty_expected_pyopenssl if select_crypto_backend == 'pyopenssl' else empty_expected_cryptography)
- (empty_contents == empty_expected_cryptography) or (empty_contents == empty_expected_pyopenssl and select_crypto_backend == 'pyopenssl')

View File

@@ -0,0 +1,4 @@
---
openssl_package_name: openssl
cryptography_package_name: py-cryptography
cryptography_package_name_python3: py3-cryptography

View File

@@ -0,0 +1,4 @@
---
openssl_package_name: openssl
cryptography_package_name: python-cryptography
cryptography_package_name_python3: python-cryptography

View File

@@ -0,0 +1 @@
has_pyopenssl: true

View File

@@ -9,19 +9,31 @@
block:
- name: Include OS-specific variables
include_vars: '{{ ansible_os_family }}.yml'
include_vars: '{{ lookup("first_found", search) }}'
vars:
search:
files:
- '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml'
- '{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml'
- '{{ ansible_distribution }}.yml'
- '{{ ansible_os_family }}.yml'
paths:
- vars
- name: Install pyOpenSSL (Python 3 from system packages)
become: true
package:
name: '{{ pyopenssl_package_name_python3 }}'
when: ansible_python_version is version('3.0', '>=')
- when: has_pyopenssl
block:
- name: Install pyOpenSSL (Python 2 from system packages)
become: true
package:
name: '{{ pyopenssl_package_name }}'
when: ansible_python_version is version('3.0', '<')
- name: Install pyOpenSSL (Python 3 from system packages)
become: true
package:
name: '{{ pyopenssl_package_name_python3 }}'
when: ansible_python_version is version('3.0', '>=')
- name: Install pyOpenSSL (Python 2 from system packages)
become: true
package:
name: '{{ pyopenssl_package_name }}'
when: ansible_python_version is version('3.0', '<')
- name: Install from PyPi
when: ansible_os_family == "Darwin" or not target_system_python
@@ -34,14 +46,17 @@
state: "{{ 'latest' if not target_system_python_cannot_upgrade_cryptography else omit }}"
extra_args: "-c {{ remote_constraints }}"
- name: Register pyOpenSSL version
command: "{{ ansible_python.executable }} -c 'import OpenSSL; print(OpenSSL.__version__)'"
register: pyopenssl_version
- when: has_pyopenssl
block:
- name: Register pyOpenSSL debug details
command: "{{ ansible_python.executable }} -m OpenSSL.debug"
register: pyopenssl_debug_version
ignore_errors: yes
- name: Register pyOpenSSL version
command: "{{ ansible_python.executable }} -c 'import OpenSSL; print(OpenSSL.__version__)'"
register: pyopenssl_version
- name: Register pyOpenSSL debug details
command: "{{ ansible_python.executable }} -m OpenSSL.debug"
register: pyopenssl_debug_version
ignore_errors: yes
# Depending on which pyOpenSSL version has been installed, it could be that cryptography has
# been upgraded to a newer version. Make sure to register cryptography_version another time here

View File

@@ -0,0 +1,3 @@
---
pyopenssl_package_name: py-openssl
pyopenssl_package_name_python3: py3-openssl

View File

@@ -0,0 +1,3 @@
---
pyopenssl_package_name: python-pyopenssl
pyopenssl_package_name_python3: python-pyopenssl

View File

@@ -0,0 +1,2 @@
---
has_pyopenssl: false

View File

@@ -1,19 +1,5 @@
# (c) 2021, Felix Fontein <felix@fontein.de>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -32,22 +32,41 @@ system_python_version_data:
- '3.8'
'11.1':
- '3.9'
'12.0':
- '3.10'
FreeBSD:
'12.1':
- '3.6'
'12.2':
- '3.7'
'12.3':
- '3.8'
'13.0':
- '3.7'
'13.1':
- '3.8'
RedHat:
'7':
- '2.7'
'8':
- '3.6'
'9.0':
- '3.9'
Suse:
'15':
- '2.7'
- '3.6'
Archlinux:
'NA':
- '3.10'
Debian:
'11':
- '3.9'
Alpine:
'3.15':
- '3.9'
'3.12':
- '3.8'
cannot_upgrade_cryptography:
FreeBSD:
@@ -55,3 +74,6 @@ cannot_upgrade_cryptography:
- '3.8' # on the VMs in CI, system packages are used for this version as well
'13.0':
- '3.8' # on the VMs in CI, system packages are used for this version as well
Ubuntu:
'18':
- '3.9' # this is the default container for ansible-core 2.12; upgrading cryptography wrecks pyOpenSSL

View File

@@ -0,0 +1 @@
openssh_client_package_name: openssh

View File

@@ -0,0 +1 @@
openssh_client_package_name: openssh

View File

@@ -1,14 +1,10 @@
shippable/cloud/group1
shippable/posix/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
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel

Some files were not shown because too many files have changed in this diff Show More