Compare commits

...

65 Commits

Author SHA1 Message Date
Felix Fontein
d4509bce5f Release 2.11.0. 2023-02-23 09:28:13 +01:00
Austin Lane
ced0e30506 EL9 - Retrieve python3-pyOpenSSL from epel (#575)
* EL9 - pull python3-pyOpenSSL from epel

* Incorporate bindep changes from felixfontein

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

* Add changelog fragment for PR #575

* Update changelog fragment.

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-02-22 23:16:26 +01:00
Felix Fontein
2fb543b144 Normalize bools in tests. (#577) 2023-02-15 22:23:36 +01:00
Felix Fontein
b08f6eefe8 Remove unnecessary test imports. (#576) 2023-02-12 20:59:55 +01:00
Felix Fontein
65d1881f12 Prepare 2.11.0 release. 2023-02-10 21:02:11 +01:00
dlehrman
b000491514 Support Custom Cipher Selection (#571)
* Enable custom cipher selection for get_certificate

* get_certificate ciphers desc grammar fix

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

* get_certificate ciphers desc grammar fix

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

* get_certificate ciphers include version_added

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

* Add changelog fragment

* Fail if ciphers is set and Python < 2.7.9

* Standardize ciphers conditionals in get_certificate

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

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-02-10 21:01:13 +01:00
Felix Fontein
70c4585b88 Fix deprecation handling. (#572) 2023-02-09 15:36:23 +01:00
Felix Fontein
aea3713484 Remove unneccessary imports (#569)
* Remove unneccessary imports.

* Add noqas.

* Add comment which name is actually ignored.
2023-02-09 11:57:54 +01:00
Felix Fontein
7f040011f0 Document PSF-2.0 license in galaxy.yml. (#567) 2023-01-31 21:31:30 +01:00
Felix Fontein
c6429eae4f Fix acme_inspect tests. (#565) 2023-01-22 22:41:12 +01:00
Felix Fontein
d2a30d2801 Update CI matrix. (#562) 2023-01-07 12:46:05 +01:00
Felix Fontein
a122be7942 Update CI matrix. (#562) 2023-01-07 12:45:52 +01:00
Felix Fontein
61f431dff3 Next expected release is 2.11.0. 2023-01-02 20:20:50 +01:00
Felix Fontein
b19c83578d Release 2.10.0. 2023-01-02 19:54:30 +01:00
Felix Fontein
ddfb18b609 openssl_csr: fix bad tests, avoid accepting invalid crl_distribution_points records (#560)
* Improve error handling.

* Remove invalid tests.

* Add changelog fragment.

* Fix tests.

* Improve exception catching.

Co-authored-by: Kristian Heljas <11139388+kristianheljas@users.noreply.github.com>

* Prevent empty full_name.

* Fix condition. Make sure errors are caught.

* Add more checks.

Co-authored-by: Kristian Heljas <11139388+kristianheljas@users.noreply.github.com>
2023-01-02 14:52:59 +00:00
Felix Fontein
095434a4c1 Prepare 2.10.0 release. 2022-12-31 18:05:12 +01:00
Felix Fontein
8a80ced4b8 Add openssl_privatekey_info filter (#555)
* Add openssl_privatekey_info filter.

* Update description.
2022-12-31 17:45:45 +01:00
Felix Fontein
ef2bb6d510 Add openssl_csr_info ilter. (#554) 2022-12-31 07:58:37 +01:00
Felix Fontein
889cfdf47e Add openssl_publickey_info filter. (#556) 2022-12-31 07:56:54 +01:00
Felix Fontein
c173449c46 Add x509_crl_info filter (#558)
* Add x509_crl_info filter.

* Work around bugs in Ansible 2.9 and ansible-base 2.10.
2022-12-31 07:56:34 +01:00
Felix Fontein
c08bae8308 Add x509_certificate_info filter. (#557) 2022-12-31 07:56:11 +01:00
Felix Fontein
80f7b084c0 Add filter module base, prepare adding filters (#553)
* Improve string handling.

* Cleanup tests.

* Add filter module mock.
2022-12-30 20:44:13 +01:00
Felix Fontein
5d24d04adf Fix crash when public key cannot be parsed. (#551) 2022-12-28 18:28:50 +01:00
Felix Fontein
7cc9a70e43 Add split_pem filter (#549)
* Add split_pem filter.

* Fix documentation.

* Python 2.7.

* Improve error message matching.

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>
2022-12-27 21:57:20 +01:00
Felix Fontein
5ddfb2c2ca CI: balance groups (#548)
* Show timings with devel, and skip everything else.

* Move to other group.

* Try smaller SSH key size (i.e. make tests run faster).

* Add implicit size that now must be explicit.

* Change group of luks_device.

* Revert "Show timings with devel, and skip everything else."

This reverts commit 7b73f7e4d7.
2022-12-21 08:12:53 +01:00
Felix Fontein
242c15bf4c Make sure that iteration_count=1000 is not used with algorithm=argon* (which is SLOW and takes around 10 minutes). (#546) 2022-12-20 20:01:26 +01:00
Felix Fontein
867f407401 CI: improve CI matrix, split into two groups (#544)
* Prepare having more than one group.

* Remove duplicates; add CentOS Stream 8 with Python 3.6.

* Split up tests into two groups.
2022-12-20 12:57:53 +01:00
Felix Fontein
54f49f38f2 Improve docsite build. 2022-12-18 21:50:28 +01:00
Felix Fontein
83d2a782f6 Switch to my fork of ansible-test-gh-action. 2022-12-18 09:53:58 +01:00
Felix Fontein
d6dd8e0d45 The ansible-test patch has been backported to stable-2.12. 2022-12-17 19:39:06 +01:00
Felix Fontein
9029f8ce34 Fix CI name. 2022-12-12 21:28:19 +01:00
Felix Fontein
ca23b2ed9a Improve CI (#539)
* Update CI scripts to be more close to the ones in ansible-core.

* Extend CI matrix.

* Mark more VMs.

* Revert "Mark more VMs."

This reverts commit 8bc79af636.

* Disable alpine VMs for get_certificate due to httptester problems.

* Improve retrieval of cryptsetup version.

* ACME 'emulator' won't work on Alpine either.

* Improve luks test setup.

* Make sure wipefs is installed on Alpine.

* dmsetup (from device-mapper) is used by the tests.

* Fix bcrypt install failure handling.

* String, not float.

* openssl_privatekey_convert is not an action module.

* Update Python info.

* Try out which VMs can be used by now.

* Enable ACME tests on all VMs but Alpine; update comment.

* Adjust acme-tiny shebang.

* Remove new entries from CI matrix.
2022-12-11 19:55:47 +01:00
Felix Fontein
664f34f2ac Mark x509_certificate-acme test as target test. 2022-12-09 23:10:26 +01:00
Felix Fontein
1c2c404ca9 Bump CentOS Stream 8 Python from 3.8 to 3.9. (#540) 2022-12-09 14:58:03 +01:00
Felix Fontein
eef4df9063 Allow triggering docs workflow manually. 2022-12-07 19:54:22 +01:00
Felix Fontein
176da44faf Backports to stable-2.13 and stable-2.14 have been merged. (#537)
https://github.com/ansible/ansible/pull/79538
https://github.com/ansible/ansible/pull/79507
2022-12-07 08:59:00 +01:00
Felix Fontein
619d7d1dfe Improve CI image selection. (#536) 2022-12-03 15:31:03 +01:00
Felix Fontein
2eab4ec19c Switch CI from ubuntu-latest to ubuntu-20.04 to avoid problems with ansible-test from ansible-core 2.12, 2.13, 2.14. (#535) 2022-12-01 23:01:49 +01:00
Felix Fontein
05eff13ec8 ansible-core 2.11 is EOL. Move CI runs to GHA. (#534) 2022-11-27 22:44:07 +01:00
Felix Fontein
4d28266eba Use proposed new options for ansible-test-gh-action. (#533) 2022-11-27 21:04:52 +01:00
Felix Fontein
ba9c50c358 Next expected release is 2.10.0. 2022-11-27 18:55:12 +01:00
Felix Fontein
e1e5dfccc1 Release 2.9.0. 2022-11-27 18:15:33 +01:00
Felix Fontein
1097371cf4 Be more precise about which private keys are supported in openssl_publickey. (#532) 2022-11-27 18:13:59 +01:00
Felix Fontein
0b08d6bc52 Include collection name into docs workflows. 2022-11-27 17:44:19 +01:00
Felix Fontein
72ed39a481 Reference documentation in README. 2022-11-26 09:53:59 +01:00
Felix Fontein
d4683d941f Add GH Pages publishing. 2022-11-26 09:38:36 +01:00
Felix Fontein
f853108d69 Prepare 2.9.0 release. 2022-11-17 12:43:40 +01:00
Felix Fontein
045ff10826 Allow changelog fragments with .yaml ending. 2022-11-17 12:41:33 +01:00
Katze
2a746115ca fix #529 issuer_uri in x509_certificate_info (#530)
The issuer_uri is retrieved from the Authority Information Access field the same way as the OCSP responder URI is.
Handling is exactly the same since they reside in the same OID space and have the same data type.
Tests have also been added based on the integration test certificates.

Signed-off-by: benaryorg <binary@benary.org>

Signed-off-by: benaryorg <binary@benary.org>
2022-11-17 12:40:44 +01:00
Christoph
37fddc61d8 openssl_privatekey: fix example for cipher (#527)
the cipher parameter required for encrypted private keys only accepts the value "auto" 
as described in /plugins/doc_fragments/module_privatekey.py.

The previously documented value of "aes256" is invalid here.
2022-11-10 20:25:56 +01:00
Felix Fontein
a050250153 Next expected release is 2.9.0. 2022-11-06 22:31:21 +01:00
Felix Fontein
42e27a360d Release 2.8.1 2022-11-06 22:02:07 +01:00
Felix Fontein
95b9df187f Prepare 2.8.1 release. 2022-11-06 21:13:02 +01:00
Felix Fontein
7bbe8f467c Document attributes (#526)
* Add 'acme' action group attribute.

* Compatibility with older ansible-core releases.

* Fix typo.

* Document standard attributes.

* Improve docs.

* Add shortcuts for common combinations.
2022-11-06 21:10:56 +01:00
Felix Fontein
0c67afb6c3 Next expected release is 2.9.0. 2022-11-02 13:33:30 +01:00
Felix Fontein
68b7c0d38c Release 2.8.0. 2022-11-02 12:56:08 +01:00
Felix Fontein
9ba0e25bfe Handle new nonce call more gracefully when it does not return nonce. (#525) 2022-11-02 08:32:01 +00:00
Felix Fontein
9a64347ea6 Prepare 2.8.0 release. 2022-11-01 19:52:23 +01:00
Felix Fontein
e4e2b804bc Allow to configure encryption level. (#523) 2022-11-01 19:51:28 +01:00
Felix Fontein
4533b3e934 Include symbolic HTTP status codes in error and log messages when available. (#524) 2022-10-31 21:33:27 +01:00
Felix Fontein
fd71773668 Add badge for EOL CI. (#522) 2022-10-30 09:21:12 +01:00
Felix Fontein
b17d57f737 CI: drop remote CI targets for EoL Ansible/ansible-base versions; move docker CI targets for EoL Ansible/ansible-base versions to GHA (#520)
* Drop remote CI targets for EoL Ansible/ansible-base versions; move docker CI targets for EoL Ansible/ansible-base versions to GHA.

* Add target.

* Use change detection.
2022-10-29 21:23:33 +02:00
Felix Fontein
f5d98e3148 Use dependabot to update GHAs. 2022-10-17 22:57:28 +02:00
Felix Fontein
5f9536af06 Next expected elease is 2.8.0. 2022-10-17 22:47:26 +02:00
Felix Fontein
7c41b31c37 Bump GHA actions. 2022-10-17 22:47:26 +02:00
180 changed files with 4890 additions and 1177 deletions

View File

@@ -98,39 +98,6 @@ stages:
test: '2.12/sanity/1'
- name: Units
test: '2.12/units/1'
- stage: Ansible_2_11
displayName: Sanity & Units 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
targets:
- name: Sanity
test: '2.11/sanity/1'
- name: Units
test: '2.11/units/1'
- stage: Ansible_2_10
displayName: Sanity & Units 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
targets:
- name: Sanity
test: '2.10/sanity/1'
- name: Units
test: '2.10/units/1'
- stage: Ansible_2_9
displayName: Sanity & Units 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
targets:
- name: Sanity
test: '2.9/sanity/1'
- name: Units
test: '2.9/units/1'
### Docker
- stage: Docker_devel
displayName: Docker devel
@@ -138,12 +105,12 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux/{0}/1
testFormat: devel/linux/{0}
targets:
- name: CentOS 7
test: centos7
- name: Fedora 36
test: fedora36
- name: Fedora 37
test: fedora37
- name: openSUSE 15
test: opensuse15
- name: Ubuntu 20.04
@@ -152,23 +119,29 @@ stages:
test: ubuntu2204
- name: Alpine 3
test: alpine3
groups:
- 1
- 2
- stage: Docker_2_14
displayName: Docker 2.14
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.14/linux/{0}/1
testFormat: 2.14/linux/{0}
targets:
- name: Ubuntu 22.04
test: ubuntu2204
- name: Fedora 36
test: fedora36
groups:
- 1
- 2
- stage: Docker_2_13
displayName: Docker 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/linux/{0}/1
testFormat: 2.13/linux/{0}
targets:
- name: openSUSE 15 py2
test: opensuse15py2
@@ -180,54 +153,24 @@ stages:
test: ubuntu1804
- name: Alpine 3
test: alpine3
groups:
- 1
- 2
- stage: Docker_2_12
displayName: Docker 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.12/linux/{0}/1
testFormat: 2.12/linux/{0}
targets:
- name: CentOS 6
test: centos6
- name: Fedora 33
test: fedora33
- stage: Docker_2_11
displayName: Docker 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.11/linux/{0}/1
targets:
- name: CentOS 7
test: centos7
- name: Fedora 32
test: fedora32
- name: Alpine 3
test: alpine3
- stage: Docker_2_10
displayName: Docker 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.10/linux/{0}/1
targets:
- name: CentOS 6
test: centos6
- stage: Docker_2_9
displayName: Docker 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.9/linux/{0}/1
targets:
- name: Fedora 31
test: fedora31
- name: Ubuntu 18.04
test: ubuntu1804
groups:
- 1
- 2
### Community Docker
- stage: Docker_community_devel
@@ -236,14 +179,19 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux-community/{0}/1
testFormat: devel/linux-community/{0}
targets:
- name: Debian Bullseye
test: debian-bullseye/3.9
- name: ArchLinux
test: archlinux/3.10
- name: CentOS Stream 8
test: centos-stream8/3.8
- name: CentOS Stream 8 with Python 3.9
test: centos-stream8/3.9
- name: CentOS Stream 8 with Python 3.6
test: centos-stream8/3.6
groups:
- 1
- 2
### Remote
- stage: Remote_devel
@@ -252,88 +200,71 @@ stages:
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/{0}/1
testFormat: devel/{0}
targets:
- 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: RHEL 9.1
test: rhel/9.1
- name: FreeBSD 12.4
test: freebsd/12.4
- name: FreeBSD 13.1
test: freebsd/13.1
groups:
- 1
- 2
- stage: Remote_2_14
displayName: Remote 2.14
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.14/{0}/1
testFormat: 2.14/{0}
targets:
- name: RHEL 9.0
test: rhel/9.0
- name: FreeBSD 12.3
test: freebsd/12.3
groups:
- 1
- 2
- stage: Remote_2_13
displayName: Remote 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/{0}/1
testFormat: 2.13/{0}
targets:
- name: macOS 12.0
test: macos/12.0
# - name: macOS 12.0
# test: macos/12.0
- name: RHEL 8.5
test: rhel/8.5
- name: FreeBSD 13.0
test: freebsd/13.0
groups:
- 1
- 2
- stage: Remote_2_12
displayName: Remote 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.12/{0}/1
testFormat: 2.12/{0}
targets:
# Not working anymore:
# - name: macOS 11.1
# test: macos/11.1
- name: RHEL 8.4
test: rhel/8.4
- stage: Remote_2_11
displayName: Remote 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.11/{0}/1
targets:
- name: RHEL 8.3
test: rhel/8.3
- name: FreeBSD 12.2
test: freebsd/12.2
- stage: Remote_2_10
displayName: Remote 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.10/{0}/1
targets:
- name: OS X 10.11
test: osx/10.11
# - name: macOS 10.15
# test: macos/10.15
- stage: Remote_2_9
displayName: Remote 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.9/{0}/1
targets:
- name: 'RHEL 7.8'
test: 'rhel/7.8'
groups:
- 1
- 2
### Generic
- stage: Generic_devel
displayName: Generic devel
@@ -342,16 +273,19 @@ stages:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: devel/generic/{0}/1
testFormat: devel/generic/{0}
targets:
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9
# - test: 3.8
# - test: 3.9
- test: "3.10"
- test: "3.11"
groups:
- 1
- 2
- stage: Generic_2_14
displayName: Generic 2.14
dependsOn: []
@@ -359,9 +293,12 @@ stages:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.14/generic/{0}/1
testFormat: 2.14/generic/{0}
targets:
- test: 3.9
groups:
- 1
- 2
- stage: Generic_2_13
displayName: Generic 2.13
dependsOn: []
@@ -369,9 +306,12 @@ stages:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.13/generic/{0}/1
testFormat: 2.13/generic/{0}
targets:
- test: 3.8
groups:
- 1
- 2
- stage: Generic_2_12
displayName: Generic 2.12
dependsOn: []
@@ -379,40 +319,13 @@ stages:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.12/generic/{0}/1
testFormat: 2.12/generic/{0}
targets:
- test: 2.6
- test: 3.9
- stage: Generic_2_11
displayName: Generic 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.11/generic/{0}/1
targets:
- test: 3.8
- stage: Generic_2_10
displayName: Generic 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.10/generic/{0}/1
targets:
- test: 3.6
- stage: Generic_2_9
displayName: Generic 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.9/generic/{0}/1
targets:
- test: 2.7
groups:
- 1
- 2
## Finally
@@ -423,30 +336,18 @@ stages:
- Ansible_2_14
- Ansible_2_13
- Ansible_2_12
- Ansible_2_11
- Ansible_2_10
- Ansible_2_9
- Remote_devel
- Remote_2_14
- Remote_2_13
- Remote_2_12
- Remote_2_11
- Remote_2_10
- Remote_2_9
- Docker_devel
- Docker_2_14
- Docker_2_13
- Docker_2_12
- Docker_2_11
- Docker_2_10
- Docker_2_9
- Docker_community_devel
- Generic_devel
- Generic_2_14
- Generic_2_13
- Generic_2_12
- Generic_2_11
- Generic_2_10
- Generic_2_9
jobs:
- template: templates/coverage.yml

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

192
.github/workflows/ansible-test.yml vendored Normal file
View File

@@ -0,0 +1,192 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# For the comprehensive list of the inputs supported by the ansible-community/ansible-test-gh-action GitHub Action, see
# https://github.com/marketplace/actions/ansible-test
name: EOL CI
on:
# Run EOL CI against all pushes (direct commits, also merged PRs), Pull Requests
push:
branches:
- main
- stable-*
pull_request:
# Run EOL CI once per day (at 09:00 UTC)
schedule:
- cron: '0 9 * * *'
jobs:
sanity:
name: EOL Sanity (Ⓐ${{ matrix.ansible }})
strategy:
matrix:
ansible:
- '2.9'
- '2.10'
- '2.11'
# Ansible-test on various stable branches does not yet work well with cgroups v2.
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
# image for these stable branches. The list of branches where this is necessary will
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
# for the latest list.
runs-on: >-
${{ contains(fromJson(
'["2.9", "2.10", "2.11"]'
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
steps:
- name: Perform sanity testing
uses: felixfontein/ansible-test-gh-action@main
with:
ansible-core-version: stable-${{ matrix.ansible }}
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
pull-request-change-detection: 'true'
testing-type: sanity
units:
# Ansible-test on various stable branches does not yet work well with cgroups v2.
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
# image for these stable branches. The list of branches where this is necessary will
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
# for the latest list.
runs-on: >-
${{ contains(fromJson(
'["2.9", "2.10", "2.11"]'
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
name: EOL Units (Ⓐ${{ matrix.ansible }})
strategy:
# As soon as the first unit test fails, cancel the others to free up the CI queue
fail-fast: true
matrix:
ansible:
- '2.9'
- '2.10'
- '2.11'
steps:
- name: >-
Perform unit testing against
Ansible version ${{ matrix.ansible }}
uses: felixfontein/ansible-test-gh-action@main
with:
ansible-core-version: stable-${{ matrix.ansible }}
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
pull-request-change-detection: 'true'
testing-type: units
integration:
# Ansible-test on various stable branches does not yet work well with cgroups v2.
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
# image for these stable branches. The list of branches where this is necessary will
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
# for the latest list.
runs-on: >-
${{ contains(fromJson(
'["2.9", "2.10", "2.11"]'
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
name: EOL I (Ⓐ${{ matrix.ansible }}+${{ matrix.docker }}+py${{ matrix.python }}:${{ matrix.target }})
strategy:
fail-fast: false
matrix:
ansible:
- ''
docker:
- ''
python:
- ''
target:
- ''
exclude:
- ansible: ''
include:
# 2.9
- ansible: '2.9'
docker: fedora31
python: ''
target: azp/posix/1/
- ansible: '2.9'
docker: fedora31
python: ''
target: azp/posix/2/
- ansible: '2.9'
docker: ubuntu1804
python: ''
target: azp/posix/1/
- ansible: '2.9'
docker: ubuntu1804
python: ''
target: azp/posix/2/
- ansible: '2.9'
docker: default
python: '2.7'
target: azp/generic/1/
- ansible: '2.9'
docker: default
python: '2.7'
target: azp/generic/2/
# 2.10
- ansible: '2.10'
docker: centos6
python: ''
target: azp/posix/1/
- ansible: '2.10'
docker: centos6
python: ''
target: azp/posix/2/
- ansible: '2.10'
docker: default
python: '3.6'
target: azp/generic/1/
- ansible: '2.10'
docker: default
python: '3.6'
target: azp/generic/2/
# 2.11
- ansible: '2.11'
docker: fedora32
python: ''
target: azp/posix/1/
- ansible: '2.11'
docker: fedora32
python: ''
target: azp/posix/2/
- ansible: '2.11'
docker: alpine3
python: ''
target: azp/posix/1/
- ansible: '2.11'
docker: alpine3
python: ''
target: azp/posix/2/
- ansible: '2.11'
docker: default
python: '3.8'
target: azp/generic/1/
- ansible: '2.11'
docker: default
python: '3.8'
target: azp/generic/2/
steps:
- name: >-
Perform integration testing against
Ansible version ${{ matrix.ansible }}
under Python ${{ matrix.python }}
uses: felixfontein/ansible-test-gh-action@main
with:
ansible-core-version: stable-${{ matrix.ansible }}
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
docker-image: ${{ matrix.docker }}
integration-continue-on-error: 'false'
integration-diff: 'false'
integration-retry-on-error: 'true'
pre-test-cmd: >-
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
;
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git ../../community/general
pull-request-change-detection: 'true'
target: ${{ matrix.target }}
target-python-version: ${{ matrix.python }}
testing-type: integration

View File

@@ -5,12 +5,15 @@
name: Collection Docs
concurrency:
group: docs-${{ github.head_ref }}
group: docs-pr-${{ github.head_ref }}
cancel-in-progress: true
on:
pull_request_target:
types: [opened, synchronize, reopened, closed]
env:
GHP_BASE_URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
jobs:
build-docs:
permissions:
@@ -18,13 +21,37 @@ jobs:
name: Build Ansible Docs
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main
with:
collection-name: community.crypto
init-lenient: false
init-fail-on-error: true
squash-hierarchy: true
init-project: Community.Crypto Collection
init-copyright: Community.Crypto Contributors
init-title: Community.Crypto Collection Documentation
init-html-short-title: Community.Crypto Collection Docs
init-extra-html-theme-options: |
documentation_home_url=https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/branch/main/
render-file-line: '> * `$<status>` [$<path_tail>](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr/${{ github.event.number }}/$<path_tail>)'
publish-docs-gh-pages:
# for now we won't run this on forks
if: github.repository == 'ansible-collections/community.crypto'
permissions:
contents: write
needs: [build-docs]
name: Publish Ansible Docs
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main
with:
artifact-name: ${{ needs.build-docs.outputs.artifact-name }}
action: ${{ (github.event.action == 'closed' || needs.build-docs.outputs.changed != 'true') && 'teardown' || 'publish' }}
secrets:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
comment:
permissions:
pull-requests: write
runs-on: ubuntu-latest
needs: build-docs
needs: [build-docs, publish-docs-gh-pages]
name: PR comments
steps:
- name: PR comment
@@ -42,13 +69,20 @@ jobs:
Thank you for contribution!✨
This PR has been merged and your docs changes will be incorporated when they are next published.
This PR has been merged and the docs are now incorporated into `main`:
${{ env.GHP_BASE_URL }}/branch/main
body: |
## Docs Build 📝
Thank you for contribution!✨
The docsite for **this PR** is available for download as an artifact from this run:
The docs for **this PR** have been published here:
${{ env.GHP_BASE_URL }}/pr/${{ github.event.number }}
You can compare to the docs for the `main` branch here:
${{ env.GHP_BASE_URL }}/branch/main
The docsite for **this PR** is also available for download as an artifact from this run:
${{ needs.build-docs.outputs.artifact-url }}
File changes:

52
.github/workflows/docs-push.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
name: Collection Docs
concurrency:
group: docs-push-${{ github.sha }}
cancel-in-progress: true
on:
push:
branches:
- main
- stable-*
tags:
- '*'
# Run CI once per day (at 09:00 UTC)
schedule:
- cron: '0 9 * * *'
# Allow manual trigger (for newer antsibull-docs, sphinx-ansible-theme, ... versions)
workflow_dispatch:
jobs:
build-docs:
permissions:
contents: read
name: Build Ansible Docs
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main
with:
collection-name: community.crypto
init-lenient: false
init-fail-on-error: true
squash-hierarchy: true
init-project: Community.Crypto Collection
init-copyright: Community.Crypto Contributors
init-title: Community.Crypto Collection Documentation
init-html-short-title: Community.Crypto Collection Docs
init-extra-html-theme-options: |
documentation_home_url=https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/branch/main/
publish-docs-gh-pages:
# for now we won't run this on forks
if: github.repository == 'ansible-collections/community.crypto'
permissions:
contents: write
needs: [build-docs]
name: Publish Ansible Docs
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main
with:
artifact-name: ${{ needs.build-docs.outputs.artifact-name }}
secrets:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -38,7 +38,7 @@ jobs:
path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: '3.10'

View File

@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install dependencies
run: |

View File

@@ -5,6 +5,89 @@ Community Crypto Release Notes
.. contents:: Topics
v2.11.0
=======
Release Summary
---------------
Feature and bugfix release.
Minor Changes
-------------
- get_certificate - adds ``ciphers`` option for custom cipher selection (https://github.com/ansible-collections/community.crypto/pull/571).
Bugfixes
--------
- action plugin helper - fix handling of deprecations for ansible-core 2.14.2 (https://github.com/ansible-collections/community.crypto/pull/572).
- execution environment binary dependencies (bindep.txt) - fix ``python3-pyOpenSSL`` dependency resolution on RHEL 9+ / CentOS Stream 9+ platforms (https://github.com/ansible-collections/community.crypto/pull/575).
- various plugins - remove unnecessary imports (https://github.com/ansible-collections/community.crypto/pull/569).
v2.10.0
=======
Release Summary
---------------
Bugfix and feature release.
Bugfixes
--------
- openssl_csr, openssl_csr_pipe - prevent invalid values for ``crl_distribution_points`` that do not have one of ``full_name``, ``relative_name``, and ``crl_issuer`` (https://github.com/ansible-collections/community.crypto/pull/560).
- openssl_publickey_info - do not crash with internal error when public key cannot be parsed (https://github.com/ansible-collections/community.crypto/pull/551).
New Plugins
-----------
Filter
~~~~~~
- openssl_csr_info - Retrieve information from OpenSSL Certificate Signing Requests (CSR)
- openssl_privatekey_info - Retrieve information from OpenSSL private keys
- openssl_publickey_info - Retrieve information from OpenSSL public keys in PEM format
- split_pem - Split PEM file contents into multiple objects
- x509_certificate_info - Retrieve information from X.509 certificates in PEM format
- x509_crl_info - Retrieve information from X.509 CRLs in PEM format
v2.9.0
======
Release Summary
---------------
Regular feature release.
Minor Changes
-------------
- x509_certificate_info - adds ``issuer_uri`` field in return value based on Authority Information Access data (https://github.com/ansible-collections/community.crypto/pull/530).
v2.8.1
======
Release Summary
---------------
Maintenance release with improved documentation.
v2.8.0
======
Release Summary
---------------
Feature release.
Minor Changes
-------------
- acme_* modules - handle more gracefully if CA's new nonce call does not return a nonce (https://github.com/ansible-collections/community.crypto/pull/525).
- acme_* modules - include symbolic HTTP status codes in error and log messages when available (https://github.com/ansible-collections/community.crypto/pull/524).
- openssl_pkcs12 - add option ``encryption_level`` which allows to chose ``compatibility2022`` when cryptography >= 38.0.0 is used to enable a more backwards compatible encryption algorithm. If cryptography uses OpenSSL 3.0.0 or newer, the default algorithm is not compatible with older software (https://github.com/ansible-collections/community.crypto/pull/523).
v2.7.1
======

View File

@@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
# Ansible Community Crypto Collection
[![Build Status](https://dev.azure.com/ansible/community.crypto/_apis/build/status/CI?branchName=main)](https://dev.azure.com/ansible/community.crypto/_build?definitionId=21)
[![EOL CI](https://github.com/ansible-collections/community.crypto/workflows/EOL%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.crypto/actions)
[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.crypto)](https://codecov.io/gh/ansible-collections/community.crypto)
Provides modules for [Ansible](https://www.ansible.com/community) for various cryptographic operations.
@@ -25,6 +26,16 @@ The exact requirements for every module are listed in the module documentation.
Most modules require a recent enough version of [the Python cryptography library](https://pypi.org/project/cryptography/). See the module documentations for the minimal version supported for each module.
## Collection Documentation
Browsing the [**latest** collection documentation](https://docs.ansible.com/ansible/latest/collections/community/crypto) will show docs for the _latest version released in the Ansible package_, not the latest version of the collection released on Galaxy.
Browsing the [**devel** collection documentation](https://docs.ansible.com/ansible/devel/collections/community/crypto) shows docs for the _latest version released on Galaxy_.
We also separately publish [**latest commit** collection documentation](https://ansible-collections.github.io/community.crypto/branch/main/) which shows docs for the _latest commit in the `main` branch_.
If you use the Ansible package and do not update collections independently, use **latest**. If you install or update this collection directly from Galaxy, use **devel**. If you are looking to contribute, use **latest commit**.
## Included content
- OpenSSL / PKI modules:

View File

@@ -737,6 +737,59 @@ releases:
name: openssl_privatekey_convert
namespace: ''
release_date: '2022-01-10'
2.10.0:
changes:
bugfixes:
- openssl_csr, openssl_csr_pipe - prevent invalid values for ``crl_distribution_points``
that do not have one of ``full_name``, ``relative_name``, and ``crl_issuer``
(https://github.com/ansible-collections/community.crypto/pull/560).
- openssl_publickey_info - do not crash with internal error when public key
cannot be parsed (https://github.com/ansible-collections/community.crypto/pull/551).
release_summary: Bugfix and feature release.
fragments:
- 2.10.0.yml
- 551-publickey-info.yml
- 560-openssl_csr-crl_distribution_points.yml
plugins:
filter:
- description: Retrieve information from OpenSSL Certificate Signing Requests
(CSR)
name: openssl_csr_info
namespace: null
- description: Retrieve information from OpenSSL private keys
name: openssl_privatekey_info
namespace: null
- description: Retrieve information from OpenSSL public keys in PEM format
name: openssl_publickey_info
namespace: null
- description: Split PEM file contents into multiple objects
name: split_pem
namespace: null
- description: Retrieve information from X.509 certificates in PEM format
name: x509_certificate_info
namespace: null
- description: Retrieve information from X.509 CRLs in PEM format
name: x509_crl_info
namespace: null
release_date: '2023-01-02'
2.11.0:
changes:
bugfixes:
- action plugin helper - fix handling of deprecations for ansible-core 2.14.2
(https://github.com/ansible-collections/community.crypto/pull/572).
- execution environment binary dependencies (bindep.txt) - fix ``python3-pyOpenSSL``
dependency resolution on RHEL 9+ / CentOS Stream 9+ platforms (https://github.com/ansible-collections/community.crypto/pull/575).
- various plugins - remove unnecessary imports (https://github.com/ansible-collections/community.crypto/pull/569).
minor_changes:
- get_certificate - adds ``ciphers`` option for custom cipher selection (https://github.com/ansible-collections/community.crypto/pull/571).
release_summary: Feature and bugfix release.
fragments:
- 2.11.0.yml
- 571_get_certificate_ciphers.yaml
- 572-action-module.yml
- 575-bindep-python3-pyOpenSSL.yml
- remove-unneeded-imports.yml
release_date: '2023-02-23'
2.2.0:
changes:
bugfixes:
@@ -990,3 +1043,37 @@ releases:
- 2.7.1.yml
- 519-acme-cryptography.yml
release_date: '2022-10-17'
2.8.0:
changes:
minor_changes:
- acme_* modules - handle more gracefully if CA's new nonce call does not return
a nonce (https://github.com/ansible-collections/community.crypto/pull/525).
- acme_* modules - include symbolic HTTP status codes in error and log messages
when available (https://github.com/ansible-collections/community.crypto/pull/524).
- openssl_pkcs12 - add option ``encryption_level`` which allows to chose ``compatibility2022``
when cryptography >= 38.0.0 is used to enable a more backwards compatible
encryption algorithm. If cryptography uses OpenSSL 3.0.0 or newer, the default
algorithm is not compatible with older software (https://github.com/ansible-collections/community.crypto/pull/523).
release_summary: Feature release.
fragments:
- 2.8.0.yml
- 523-pkcs12-compat.yml
- 524-acme-http-errors.yml
- 525-acme-no-nonce.yml
release_date: '2022-11-02'
2.8.1:
changes:
release_summary: Maintenance release with improved documentation.
fragments:
- 2.8.1.yml
release_date: '2022-11-06'
2.9.0:
changes:
minor_changes:
- x509_certificate_info - adds ``issuer_uri`` field in return value based on
Authority Information Access data (https://github.com/ansible-collections/community.crypto/pull/530).
release_summary: Regular feature release.
fragments:
- 2.9.0.yml
- aia_issuer.yaml
release_date: '2022-11-27'

View File

@@ -5,7 +5,7 @@
namespace: community
name: crypto
version: 2.7.1
version: 2.11.0
readme: README.md
authors:
- Ansible (github.com/ansible)
@@ -15,9 +15,7 @@ license:
- Apache-2.0
- BSD-2-Clause
- BSD-3-Clause
# TODO: galaxy-importer does not support this license type yet. Uncomment once this has been
# fixed and the fix deployed (https://github.com/ansible/galaxy-importer/pull/175).
# - PSF-2.0
- PSF-2.0
#license_file: COPYING
tags:
- acme

View File

@@ -11,4 +11,7 @@ openssl [platform:rpm]
python3-cryptography [platform:dpkg]
python3-cryptography [platform:rpm]
python3-openssl [platform:dpkg]
python3-pyOpenSSL [platform:rpm]
# On RHEL 9+ and CentOS Stream 9+, python3-pyOpenSSL is part of EPEL
python3-pyOpenSSL [platform:rpm !platform:rhel !platform:centos]
python3-pyOpenSSL [platform:rhel-6 platform:centos-6 platform:rhel-7 platform:centos-7 platform:rhel-8 platform:centos-8]
python3-pyOpenSSL [platform:rhel platform:centos !platform:rhel-6 !platform:centos-6 !platform:rhel-7 !platform:centos-7 !platform:rhel-8 !platform:centos-8 epel]

View File

@@ -7,12 +7,11 @@ requires_ansible: '>=2.9.10'
action_groups:
acme:
- acme_inspect
- acme_certificate_revoke
- acme_certificate
- acme_account
- acme_account_facts
- acme_account_info
- acme_inspect
- acme_certificate_revoke
- acme_certificate
- acme_account
- acme_account_info
plugin_routing:
modules:

View File

@@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
# Standard documentation fragment
DOCUMENTATION = r'''
options: {}
attributes:
check_mode:
description: Can run in C(check_mode) and return changed status prediction without modifying target.
diff_mode:
description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode.
'''
# Should be used together with the standard fragment
INFO_MODULE = r'''
options: {}
attributes:
check_mode:
support: full
details:
- This action does not modify state.
diff_mode:
support: N/A
details:
- This action does not modify state.
'''
ACTIONGROUP_ACME = r'''
options: {}
attributes:
action_group:
description: Use C(group/acme) or C(group/community.crypto.acme) in C(module_defaults) to set defaults for this module.
support: full
membership:
- community.crypto.acme
- acme
'''
FACTS = r'''
options: {}
attributes:
facts:
description: Action returns an C(ansible_facts) dictionary that will update existing host facts.
'''
# Should be used together with the standard fragment and the FACTS fragment
FACTS_MODULE = r'''
options: {}
attributes:
check_mode:
support: full
details:
- This action does not modify state.
diff_mode:
support: N/A
details:
- This action does not modify state.
facts:
support: full
'''
FILES = r'''
options: {}
attributes:
safe_file_operations:
description: Uses Ansible's strict file operation functions to ensure proper permissions and avoid data corruption.
'''
FLOW = r'''
options: {}
attributes:
action:
description: Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller.
async:
description: Supports being used with the C(async) keyword.
'''

View File

@@ -0,0 +1,313 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
name: openssl_csr_info
short_description: Retrieve information from OpenSSL Certificate Signing Requests (CSR)
version_added: 2.10.0
author:
- Felix Fontein (@felixfontein)
description:
- Provided an OpenSSL Certificate Signing Requests (CSR), retrieve information.
- This is a filter version of the M(community.crypto.openssl_csr_info) module.
options:
_input:
description:
- The content of the OpenSSL CSR.
type: string
required: true
extends_documentation_fragment:
- community.crypto.name_encoding
seealso:
- module: community.crypto.openssl_csr_info
'''
EXAMPLES = '''
- name: Show the Subject Alt Names of the CSR
ansible.builtin.debug:
msg: >-
{{
(
lookup('ansible.builtin.file', '/path/to/cert.csr')
| community.crypto.openssl_csr_info
).subject_alt_name | join(', ')
}}
'''
RETURN = '''
_value:
description:
- Information on the certificate.
type: dict
contains:
signature_valid:
description:
- Whether the CSR's signature is valid.
- In case the check returns C(false), the module will fail.
returned: success
type: bool
basic_constraints:
description: Entries in the C(basic_constraints) extension, or C(none) if extension is not present.
returned: success
type: list
elements: str
sample: ['CA:TRUE', 'pathlen:1']
basic_constraints_critical:
description: Whether the C(basic_constraints) extension is critical.
returned: success
type: bool
extended_key_usage:
description: Entries in the C(extended_key_usage) extension, or C(none) if extension is not present.
returned: success
type: list
elements: str
sample: [Biometric Info, DVCS, Time Stamping]
extended_key_usage_critical:
description: Whether the C(extended_key_usage) extension is critical.
returned: success
type: bool
extensions_by_oid:
description: Returns a dictionary for every extension OID
returned: success
type: dict
contains:
critical:
description: Whether the extension is critical.
returned: success
type: bool
value:
description:
- The Base64 encoded value (in DER format) of the extension.
- B(Note) that depending on the C(cryptography) version used, it is
not possible to extract the ASN.1 content of the extension, but only
to provide the re-encoded content of the extension in case it was
parsed by C(cryptography). This should usually result in exactly the
same value, except if the original extension value was malformed.
returned: success
type: str
sample: "MAMCAQU="
sample: {"1.3.6.1.5.5.7.1.24": { "critical": false, "value": "MAMCAQU="}}
key_usage:
description: Entries in the C(key_usage) extension, or C(none) if extension is not present.
returned: success
type: str
sample: [Key Agreement, Data Encipherment]
key_usage_critical:
description: Whether the C(key_usage) extension is 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.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: list
elements: str
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
subject_alt_name_critical:
description: Whether the C(subject_alt_name) extension is critical.
returned: success
type: bool
ocsp_must_staple:
description: C(true) if the OCSP Must Staple extension is present, C(none) otherwise.
returned: success
type: bool
ocsp_must_staple_critical:
description: Whether the C(ocsp_must_staple) extension is critical.
returned: success
type: bool
name_constraints_permitted:
description: List of permitted subtrees to sign certificates for.
returned: success
type: list
elements: str
sample: ['email:.somedomain.com']
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
sample: ['email:.com']
name_constraints_critical:
description:
- Whether the C(name_constraints) extension is critical.
- Is C(none) if extension is not present.
returned: success
type: bool
subject:
description:
- The CSR's subject as a dictionary.
- Note that for repeated values, only the last one will be returned.
returned: success
type: dict
sample: {"commonName": "www.example.com", "emailAddress": "test@example.com"}
subject_ordered:
description: The CSR's subject as an ordered list of tuples.
returned: success
type: list
elements: list
sample: [["commonName", "www.example.com"], ["emailAddress": "test@example.com"]]
public_key:
description: CSR's public key in PEM format
returned: success
type: str
sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."
public_key_type:
description:
- The CSR's public key's type.
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
- Will start with C(unknown) if the key type cannot be determined.
returned: success
type: str
sample: RSA
public_key_data:
description:
- Public key data. Depends on the public key's type.
returned: success
type: dict
contains:
size:
description:
- Bit size of modulus (RSA) or prime number (DSA).
type: int
returned: When C(public_key_type=RSA) or C(public_key_type=DSA)
modulus:
description:
- The RSA key's modulus.
type: int
returned: When C(public_key_type=RSA)
exponent:
description:
- The RSA key's public exponent.
type: int
returned: When C(public_key_type=RSA)
p:
description:
- The C(p) value for DSA.
- This is the prime modulus upon which arithmetic takes place.
type: int
returned: When C(public_key_type=DSA)
q:
description:
- The C(q) value for DSA.
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
multiplicative group of the prime field used.
type: int
returned: When C(public_key_type=DSA)
g:
description:
- The C(g) value for DSA.
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
type: int
returned: When C(public_key_type=DSA)
curve:
description:
- The curve's name for ECC.
type: str
returned: When C(public_key_type=ECC)
exponent_size:
description:
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
type: int
returned: When C(public_key_type=ECC)
x:
description:
- The C(x) coordinate for the public point on the elliptic curve.
type: int
returned: When C(public_key_type=ECC)
y:
description:
- For C(public_key_type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
- For C(public_key_type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
type: int
returned: When C(public_key_type=DSA) or C(public_key_type=ECC)
public_key_fingerprints:
description:
- Fingerprints of CSR's public key.
- For every hash algorithm available, the fingerprint is computed.
returned: success
type: dict
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
subject_key_identifier:
description:
- The CSR's subject key identifier.
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
- Is C(none) if the C(SubjectKeyIdentifier) extension is not present.
returned: success
type: str
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
authority_key_identifier:
description:
- The CSR's authority key identifier.
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
returned: success
type: str
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
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
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
authority_cert_serial_number:
description:
- The CSR's authority cert serial number.
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
returned: success
type: int
sample: 12345
'''
from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
OpenSSLObjectError,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.csr_info import (
get_csr_info,
)
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
def openssl_csr_info_filter(data, name_encoding='ignore'):
'''Extract information from X.509 PEM certificate.'''
if not isinstance(data, string_types):
raise AnsibleFilterError('The community.crypto.openssl_csr_info input must be a text type, not %s' % type(data))
if not isinstance(name_encoding, string_types):
raise AnsibleFilterError('The name_encoding option must be of a text type, not %s' % type(name_encoding))
name_encoding = to_native(name_encoding)
if name_encoding not in ('ignore', 'idna', 'unicode'):
raise AnsibleFilterError('The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' % name_encoding)
module = FilterModuleMock({'name_encoding': name_encoding})
try:
return get_csr_info(module, 'cryptography', content=to_bytes(data), validate_signature=True)
except OpenSSLObjectError as exc:
raise AnsibleFilterError(to_native(exc))
class FilterModule(object):
'''Ansible jinja2 filters'''
def filters(self):
return {
'openssl_csr_info': openssl_csr_info_filter,
}

View File

@@ -0,0 +1,193 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
name: openssl_privatekey_info
short_description: Retrieve information from OpenSSL private keys
version_added: 2.10.0
author:
- Felix Fontein (@felixfontein)
description:
- Provided an OpenSSL private keys, retrieve information.
- This is a filter version of the M(community.crypto.openssl_privatekey_info) module.
options:
_input:
description:
- The content of the OpenSSL private key.
type: string
required: true
passphrase:
description:
- The passphrase for the private key.
type: str
return_private_key_data:
description:
- Whether to return private key data.
- Only set this to C(true) when you want private information about this key to
be extracted.
- "B(WARNING:) you have to make sure that private key data is not accidentally logged!"
type: bool
default: false
extends_documentation_fragment:
- community.crypto.name_encoding
seealso:
- module: community.crypto.openssl_privatekey_info
'''
EXAMPLES = '''
- name: Show the Subject Alt Names of the CSR
ansible.builtin.debug:
msg: >-
{{
(
lookup('ansible.builtin.file', '/path/to/cert.csr')
| community.crypto.openssl_privatekey_info
).subject_alt_name | join(', ')
}}
'''
RETURN = '''
_value:
description:
- Information on the certificate.
type: dict
contains:
public_key:
description: Private key's public key in PEM format.
returned: success
type: str
sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."
public_key_fingerprints:
description:
- Fingerprints of private key's public key.
- For every hash algorithm available, the fingerprint is computed.
returned: success
type: dict
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
type:
description:
- The key's type.
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
- Will start with C(unknown) if the key type cannot be determined.
returned: success
type: str
sample: RSA
public_data:
description:
- Public key data. Depends on key type.
returned: success
type: dict
contains:
size:
description:
- Bit size of modulus (RSA) or prime number (DSA).
type: int
returned: When C(type=RSA) or C(type=DSA)
modulus:
description:
- The RSA key's modulus.
type: int
returned: When C(type=RSA)
exponent:
description:
- The RSA key's public exponent.
type: int
returned: When C(type=RSA)
p:
description:
- The C(p) value for DSA.
- This is the prime modulus upon which arithmetic takes place.
type: int
returned: When C(type=DSA)
q:
description:
- The C(q) value for DSA.
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
multiplicative group of the prime field used.
type: int
returned: When C(type=DSA)
g:
description:
- The C(g) value for DSA.
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
type: int
returned: When C(type=DSA)
curve:
description:
- The curve's name for ECC.
type: str
returned: When C(type=ECC)
exponent_size:
description:
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
type: int
returned: When C(type=ECC)
x:
description:
- The C(x) coordinate for the public point on the elliptic curve.
type: int
returned: When C(type=ECC)
y:
description:
- For C(type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
- For C(type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
type: int
returned: When C(type=DSA) or C(type=ECC)
private_data:
description:
- Private key data. Depends on key type.
returned: success and when I(return_private_key_data) is set to C(true)
type: dict
'''
from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
OpenSSLObjectError,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.privatekey_info import (
PrivateKeyParseError,
get_privatekey_info,
)
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
def openssl_privatekey_info_filter(data, passphrase=None, return_private_key_data=False):
'''Extract information from X.509 PEM certificate.'''
if not isinstance(data, string_types):
raise AnsibleFilterError('The community.crypto.openssl_privatekey_info input must be a text type, not %s' % type(data))
if passphrase is not None and not isinstance(passphrase, string_types):
raise AnsibleFilterError('The passphrase option must be a text type, not %s' % type(passphrase))
if not isinstance(return_private_key_data, bool):
raise AnsibleFilterError('The return_private_key_data option must be a boolean, not %s' % type(return_private_key_data))
module = FilterModuleMock({})
try:
result = get_privatekey_info(module, 'cryptography', content=to_bytes(data), passphrase=passphrase, return_private_key_data=return_private_key_data)
result.pop('can_parse_key', None)
result.pop('key_is_consistent', None)
return result
except PrivateKeyParseError as exc:
raise AnsibleFilterError(exc.error_message)
except OpenSSLObjectError as exc:
raise AnsibleFilterError(to_native(exc))
class FilterModule(object):
'''Ansible jinja2 filters'''
def filters(self):
return {
'openssl_privatekey_info': openssl_privatekey_info_filter,
}

View File

@@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
name: openssl_publickey_info
short_description: Retrieve information from OpenSSL public keys in PEM format
version_added: 2.10.0
author:
- Felix Fontein (@felixfontein)
description:
- Provided a public key in OpenSSL PEM format, retrieve information.
- This is a filter version of the M(community.crypto.openssl_publickey_info) module.
options:
_input:
description:
- The content of the OpenSSL PEM public key.
type: string
required: true
seealso:
- module: community.crypto.openssl_publickey_info
'''
EXAMPLES = '''
- name: Show the type of a public key
ansible.builtin.debug:
msg: >-
{{
(
lookup('ansible.builtin.file', '/path/to/public-key.pem')
| community.crypto.openssl_publickey_info
).type
}}
'''
RETURN = '''
_value:
description:
- Information on the public key.
type: dict
contains:
fingerprints:
description:
- Fingerprints of public key.
- For every hash algorithm available, the fingerprint is computed.
returned: success
type: dict
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
type:
description:
- The key's type.
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
- Will start with C(unknown) if the key type cannot be determined.
returned: success
type: str
sample: RSA
public_data:
description:
- Public key data. Depends on key type.
returned: success
type: dict
contains:
size:
description:
- Bit size of modulus (RSA) or prime number (DSA).
type: int
returned: When C(type=RSA) or C(type=DSA)
modulus:
description:
- The RSA key's modulus.
type: int
returned: When C(type=RSA)
exponent:
description:
- The RSA key's public exponent.
type: int
returned: When C(type=RSA)
p:
description:
- The C(p) value for DSA.
- This is the prime modulus upon which arithmetic takes place.
type: int
returned: When C(type=DSA)
q:
description:
- The C(q) value for DSA.
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
multiplicative group of the prime field used.
type: int
returned: When C(type=DSA)
g:
description:
- The C(g) value for DSA.
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
type: int
returned: When C(type=DSA)
curve:
description:
- The curve's name for ECC.
type: str
returned: When C(type=ECC)
exponent_size:
description:
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
type: int
returned: When C(type=ECC)
x:
description:
- The C(x) coordinate for the public point on the elliptic curve.
type: int
returned: When C(type=ECC)
y:
description:
- For C(type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
- For C(type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
type: int
returned: When C(type=DSA) or C(type=ECC)
'''
from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
OpenSSLObjectError,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.publickey_info import (
PublicKeyParseError,
get_publickey_info,
)
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
def openssl_publickey_info_filter(data):
'''Extract information from OpenSSL PEM public key.'''
if not isinstance(data, string_types):
raise AnsibleFilterError('The community.crypto.openssl_publickey_info input must be a text type, not %s' % type(data))
module = FilterModuleMock({})
try:
return get_publickey_info(module, 'cryptography', content=to_bytes(data))
except PublicKeyParseError as exc:
raise AnsibleFilterError(exc.error_message)
except OpenSSLObjectError as exc:
raise AnsibleFilterError(to_native(exc))
class FilterModule(object):
'''Ansible jinja2 filters'''
def filters(self):
return {
'openssl_publickey_info': openssl_publickey_info_filter,
}

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
name: split_pem
short_description: Split PEM file contents into multiple objects
version_added: 2.10.0
author:
- Felix Fontein (@felixfontein)
description:
- Split PEM file contents into multiple PEM objects. Comments or invalid parts are ignored.
options:
_input:
description:
- The PEM contents to split.
type: string
required: true
'''
EXAMPLES = '''
- name: Print all CA certificates
ansible.builtin.debug:
msg: '{{ item }}'
loop: >-
{{ lookup('ansible.builtin.file', '/path/to/ca-bundle.pem') | community.crypto.split_pem }}
'''
RETURN = '''
_value:
description:
- A list of PEM file contents.
type: list
elements: string
'''
from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.text.converters import to_text
from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import split_pem_list
def split_pem_filter(data):
'''Split PEM file.'''
if not isinstance(data, string_types):
raise AnsibleFilterError('The community.crypto.split_pem input must be a text type, not %s' % type(data))
data = to_text(data)
return split_pem_list(data)
class FilterModule(object):
'''Ansible jinja2 filters'''
def filters(self):
return {
'split_pem': split_pem_filter,
}

View File

@@ -0,0 +1,346 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
name: x509_certificate_info
short_description: Retrieve information from X.509 certificates in PEM format
version_added: 2.10.0
author:
- Felix Fontein (@felixfontein)
description:
- Provided a X.509 certificate in PEM format, retrieve information.
- This is a filter version of the M(community.crypto.x509_certificate_info) module.
options:
_input:
description:
- The content of the X.509 certificate in PEM format.
type: string
required: true
extends_documentation_fragment:
- community.crypto.name_encoding
seealso:
- module: community.crypto.x509_certificate_info
'''
EXAMPLES = '''
- name: Show the Subject Alt Names of the certificate
ansible.builtin.debug:
msg: >-
{{
(
lookup('ansible.builtin.file', '/path/to/cert.pem')
| community.crypto.x509_certificate_info
).subject_alt_name | join(', ')
}}
'''
RETURN = '''
_value:
description:
- Information on the certificate.
type: dict
contains:
expired:
description: Whether the certificate is expired (in other words, C(notAfter) is in the past).
returned: success
type: bool
basic_constraints:
description: Entries in the C(basic_constraints) extension, or C(none) if extension is not present.
returned: success
type: list
elements: str
sample: ["CA:TRUE", "pathlen:1"]
basic_constraints_critical:
description: Whether the C(basic_constraints) extension is critical.
returned: success
type: bool
extended_key_usage:
description: Entries in the C(extended_key_usage) extension, or C(none) if extension is not present.
returned: success
type: list
elements: str
sample: [Biometric Info, DVCS, Time Stamping]
extended_key_usage_critical:
description: Whether the C(extended_key_usage) extension is critical.
returned: success
type: bool
extensions_by_oid:
description: Returns a dictionary for every extension OID.
returned: success
type: dict
contains:
critical:
description: Whether the extension is critical.
returned: success
type: bool
value:
description:
- The Base64 encoded value (in DER format) of the extension.
- B(Note) that depending on the C(cryptography) version used, it is
not possible to extract the ASN.1 content of the extension, but only
to provide the re-encoded content of the extension in case it was
parsed by C(cryptography). This should usually result in exactly the
same value, except if the original extension value was malformed.
returned: success
type: str
sample: "MAMCAQU="
sample: {"1.3.6.1.5.5.7.1.24": { "critical": false, "value": "MAMCAQU="}}
key_usage:
description: Entries in the C(key_usage) extension, or C(none) if extension is not present.
returned: success
type: str
sample: [Key Agreement, Data Encipherment]
key_usage_critical:
description: Whether the C(key_usage) extension is 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.
- See I(name_encoding) for how IDNs are handled.
returned: success
type: list
elements: str
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
subject_alt_name_critical:
description: Whether the C(subject_alt_name) extension is critical.
returned: success
type: bool
ocsp_must_staple:
description: C(true) if the OCSP Must Staple extension is present, C(none) otherwise.
returned: success
type: bool
ocsp_must_staple_critical:
description: Whether the C(ocsp_must_staple) extension is critical.
returned: success
type: bool
issuer:
description:
- The certificate's issuer.
- Note that for repeated values, only the last one will be returned.
returned: success
type: dict
sample: {"organizationName": "Ansible", "commonName": "ca.example.com"}
issuer_ordered:
description: The certificate's issuer as an ordered list of tuples.
returned: success
type: list
elements: list
sample: [["organizationName", "Ansible"], ["commonName": "ca.example.com"]]
subject:
description:
- The certificate's subject as a dictionary.
- Note that for repeated values, only the last one will be returned.
returned: success
type: dict
sample: {"commonName": "www.example.com", "emailAddress": "test@example.com"}
subject_ordered:
description: The certificate's subject as an ordered list of tuples.
returned: success
type: list
elements: list
sample: [["commonName", "www.example.com"], ["emailAddress": "test@example.com"]]
not_after:
description: C(notAfter) date as ASN.1 TIME.
returned: success
type: str
sample: '20190413202428Z'
not_before:
description: C(notBefore) date as ASN.1 TIME.
returned: success
type: str
sample: '20190331202428Z'
public_key:
description: Certificate's public key in PEM format.
returned: success
type: str
sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."
public_key_type:
description:
- The certificate's public key's type.
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
- Will start with C(unknown) if the key type cannot be determined.
returned: success
type: str
sample: RSA
public_key_data:
description:
- Public key data. Depends on the public key's type.
returned: success
type: dict
contains:
size:
description:
- Bit size of modulus (RSA) or prime number (DSA).
type: int
returned: When C(public_key_type=RSA) or C(public_key_type=DSA)
modulus:
description:
- The RSA key's modulus.
type: int
returned: When C(public_key_type=RSA)
exponent:
description:
- The RSA key's public exponent.
type: int
returned: When C(public_key_type=RSA)
p:
description:
- The C(p) value for DSA.
- This is the prime modulus upon which arithmetic takes place.
type: int
returned: When C(public_key_type=DSA)
q:
description:
- The C(q) value for DSA.
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
multiplicative group of the prime field used.
type: int
returned: When C(public_key_type=DSA)
g:
description:
- The C(g) value for DSA.
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
type: int
returned: When C(public_key_type=DSA)
curve:
description:
- The curve's name for ECC.
type: str
returned: When C(public_key_type=ECC)
exponent_size:
description:
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
type: int
returned: When C(public_key_type=ECC)
x:
description:
- The C(x) coordinate for the public point on the elliptic curve.
type: int
returned: When C(public_key_type=ECC)
y:
description:
- For C(public_key_type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
- For C(public_key_type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
type: int
returned: When C(public_key_type=DSA) or C(public_key_type=ECC)
public_key_fingerprints:
description:
- Fingerprints of certificate's public key.
- For every hash algorithm available, the fingerprint is computed.
returned: success
type: dict
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
fingerprints:
description:
- Fingerprints of the DER-encoded form of the whole certificate.
- For every hash algorithm available, the fingerprint is computed.
returned: success
type: dict
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
signature_algorithm:
description: The signature algorithm used to sign the certificate.
returned: success
type: str
sample: sha256WithRSAEncryption
serial_number:
description: The certificate's serial number.
returned: success
type: int
sample: 1234
version:
description: The certificate version.
returned: success
type: int
sample: 3
subject_key_identifier:
description:
- The certificate's subject key identifier.
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
- Is C(none) if the C(SubjectKeyIdentifier) extension is not present.
returned: success
type: str
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
authority_key_identifier:
description:
- The certificate's authority key identifier.
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
returned: success
type: str
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
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
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
authority_cert_serial_number:
description:
- The certificate's authority cert serial number.
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
returned: success
type: int
sample: 12345
ocsp_uri:
description: The OCSP responder URI, if included in the certificate. Will be
C(none) if no OCSP responder URI is included.
returned: success
type: str
issuer_uri:
description: The Issuer URI, if included in the certificate. Will be
C(none) if no issuer URI is included.
returned: success
type: str
'''
from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
OpenSSLObjectError,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.certificate_info import (
get_certificate_info,
)
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
def x509_certificate_info_filter(data, name_encoding='ignore'):
'''Extract information from X.509 PEM certificate.'''
if not isinstance(data, string_types):
raise AnsibleFilterError('The community.crypto.x509_certificate_info input must be a text type, not %s' % type(data))
if not isinstance(name_encoding, string_types):
raise AnsibleFilterError('The name_encoding option must be of a text type, not %s' % type(name_encoding))
name_encoding = to_native(name_encoding)
if name_encoding not in ('ignore', 'idna', 'unicode'):
raise AnsibleFilterError('The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' % name_encoding)
module = FilterModuleMock({'name_encoding': name_encoding})
try:
return get_certificate_info(module, 'cryptography', content=to_bytes(data))
except OpenSSLObjectError as exc:
raise AnsibleFilterError(to_native(exc))
class FilterModule(object):
'''Ansible jinja2 filters'''
def filters(self):
return {
'x509_certificate_info': x509_certificate_info_filter,
}

View File

@@ -0,0 +1,196 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
name: x509_crl_info
short_description: Retrieve information from X.509 CRLs in PEM format
version_added: 2.10.0
author:
- Felix Fontein (@felixfontein)
description:
- Provided a X.509 crl in PEM format, retrieve information.
- This is a filter version of the M(community.crypto.x509_crl_info) module.
options:
_input:
description:
- The content of the X.509 CRL in PEM format.
type: string
required: true
list_revoked_certificates:
description:
- If set to C(false), the list of revoked certificates is not included in the result.
- This is useful when retrieving information on large CRL files. Enumerating all revoked
certificates can take some time, including serializing the result as JSON, sending it to
the Ansible controller, and decoding it again.
type: bool
default: true
version_added: 1.7.0
extends_documentation_fragment:
- community.crypto.name_encoding
seealso:
- module: community.crypto.x509_crl_info
'''
EXAMPLES = '''
- name: Show the Organization Name of the CRL's subject
ansible.builtin.debug:
msg: >-
{{
(
lookup('ansible.builtin.file', '/path/to/cert.pem')
| community.crypto.x509_crl_info
).issuer.organizationName
}}
'''
RETURN = '''
_value:
description:
- Information on the CRL.
type: dict
contains:
format:
description:
- Whether the CRL is in PEM format (C(pem)) or in DER format (C(der)).
returned: success
type: str
sample: pem
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"}
issuer_ordered:
description: The CRL's issuer as an ordered list of tuples.
returned: success
type: list
elements: list
sample: [["organizationName", "Ansible"], ["commonName": "ca.example.com"]]
last_update:
description: The point in time from which this CRL can be trusted as ASN.1 TIME.
returned: success
type: str
sample: '20190413202428Z'
next_update:
description: The point in time from which a new CRL will be issued and the client has to check for it as ASN.1 TIME.
returned: success
type: str
sample: '20190413202428Z'
digest:
description: The signature algorithm used to sign the CRL.
returned: success
type: str
sample: sha256WithRSAEncryption
revoked_certificates:
description: List of certificates to be revoked.
returned: success if I(list_revoked_certificates=true)
type: list
elements: dict
contains:
serial_number:
description: Serial number of the certificate.
type: int
sample: 1234
revocation_date:
description: The point in time the certificate was revoked as ASN.1 TIME.
type: str
sample: '20190413202428Z'
issuer:
description:
- The certificate's issuer.
- See I(name_encoding) for how IDNs are handled.
type: list
elements: str
sample: ["DNS:ca.example.org"]
issuer_critical:
description: Whether the certificate issuer extension is critical.
type: bool
sample: false
reason:
description:
- The value for the revocation reason extension.
- One of C(unspecified), C(key_compromise), C(ca_compromise), C(affiliation_changed), C(superseded),
C(cessation_of_operation), C(certificate_hold), C(privilege_withdrawn), C(aa_compromise), and
C(remove_from_crl).
type: str
sample: key_compromise
reason_critical:
description: Whether the revocation reason extension is critical.
type: bool
sample: false
invalidity_date:
description: |
The point in time it was known/suspected that the private key was compromised
or that the certificate otherwise became invalid as ASN.1 TIME.
type: str
sample: '20190413202428Z'
invalidity_date_critical:
description: Whether the invalidity date extension is critical.
type: bool
sample: false
'''
import base64
import binascii
from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
OpenSSLObjectError,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import (
identify_pem_format,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.crl_info import (
get_crl_info,
)
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
def x509_crl_info_filter(data, name_encoding='ignore', list_revoked_certificates=True):
'''Extract information from X.509 PEM certificate.'''
if not isinstance(data, string_types):
raise AnsibleFilterError('The community.crypto.x509_crl_info input must be a text type, not %s' % type(data))
if not isinstance(name_encoding, string_types):
raise AnsibleFilterError('The name_encoding option must be of a text type, not %s' % type(name_encoding))
if not isinstance(list_revoked_certificates, bool):
raise AnsibleFilterError('The list_revoked_certificates option must be a boolean, not %s' % type(list_revoked_certificates))
name_encoding = to_native(name_encoding)
if name_encoding not in ('ignore', 'idna', 'unicode'):
raise AnsibleFilterError('The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' % name_encoding)
data = to_bytes(data)
if not identify_pem_format(data):
try:
data = base64.b64decode(to_native(data))
except (binascii.Error, TypeError, ValueError, UnicodeEncodeError) as e:
pass
module = FilterModuleMock({'name_encoding': name_encoding})
try:
return get_crl_info(module, content=data, list_revoked_certificates=list_revoked_certificates)
except OpenSSLObjectError as exc:
raise AnsibleFilterError(to_native(exc))
class FilterModule(object):
'''Ansible jinja2 filters'''
def filters(self):
return {
'x509_crl_info': x509_crl_info_filter,
}

View File

@@ -38,6 +38,7 @@ from ansible_collections.community.crypto.plugins.module_utils.acme.errors impor
NetworkException,
ModuleFailException,
KeyParsingError,
format_http_status,
)
from ansible_collections.community.crypto.plugins.module_utils.acme.utils import (
@@ -45,7 +46,7 @@ from ansible_collections.community.crypto.plugins.module_utils.acme.utils import
)
try:
import ipaddress
import ipaddress # noqa: F401, pylint: disable=unused-import
except ImportError:
HAS_IPADDRESS = False
IPADDRESS_IMPORT_ERROR = traceback.format_exc()
@@ -69,7 +70,7 @@ def _decode_retry(module, response, info, retry_count):
retry_after = min(max(1, int(info.get('retry-after'))), 60)
except (TypeError, ValueError) as dummy:
retry_after = 10
module.log('Retrieved a %d HTTP status on %s, retrying in %s seconds' % (info['status'], info['url'], retry_after))
module.log('Retrieved a %s HTTP status on %s, retrying in %s seconds' % (format_http_status(info['status']), info['url'], retry_after))
time.sleep(retry_after)
return True
@@ -138,8 +139,15 @@ class ACMEDirectory(object):
retry_count += 1
continue
if info['status'] not in (200, 204):
raise NetworkException("Failed to get replay-nonce, got status {0}".format(info['status']))
return info['replay-nonce']
raise NetworkException("Failed to get replay-nonce, got status {0}".format(format_http_status(info['status'])))
if 'replay-nonce' in info:
return info['replay-nonce']
self.module.log(
'HEAD to {0} did return status {1}, but no replay-nonce header!'.format(url, format_http_status(info['status'])))
if retry_count >= 5:
raise ACMEProtocolException(
self.module, msg='Was not able to obtain nonce, giving up after 5 retries', info=info, response=response)
retry_count += 1
class ACMEClient(object):

View File

@@ -10,6 +10,14 @@ __metaclass__ = type
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.six import binary_type, PY3
from ansible.module_utils.six.moves.http_client import responses as http_responses
def format_http_status(status_code):
expl = http_responses.get(status_code)
if not expl:
return str(status_code)
return '%d %s' % (status_code, expl)
def format_error_problem(problem, subproblem_prefix=''):
@@ -87,9 +95,10 @@ class ACMEProtocolException(ModuleFailException):
extras['http_status'] = code
if code is not None and code >= 400 and content_json is not None and 'type' in content_json:
if 'status' in content_json and content_json['status'] != code:
code = 'status {problem_code} (HTTP status: {http_code})'.format(http_code=code, problem_code=content_json['status'])
code = 'status {problem_code} (HTTP status: {http_code})'.format(
http_code=format_http_status(code), problem_code=content_json['status'])
else:
code = 'status {problem_code}'.format(problem_code=code)
code = 'status {problem_code}'.format(problem_code=format_http_status(code))
subproblems = content_json.pop('subproblems', None)
add_msg = ' {problem}.'.format(problem=format_error_problem(content_json))
extras['problem'] = content_json
@@ -103,12 +112,12 @@ class ACMEProtocolException(ModuleFailException):
problem=format_error_problem(problem, subproblem_prefix='{0}.'.format(index)),
)
else:
code = 'HTTP status {code}'.format(code=code)
code = 'HTTP status {code}'.format(code=format_http_status(code))
if content_json is not None:
add_msg = ' The JSON error result: {content}'.format(content=content_json)
elif content is not None:
add_msg = ' The raw error result: {content}'.format(content=to_text(content))
msg = '{msg} for {url} with {code}'.format(msg=msg, url=url, code=code)
msg = '{msg} for {url} with {code}'.format(msg=msg, url=url, code=format_http_status(code))
elif content_json is not None:
add_msg = ' The JSON result: {content}'.format(content=content_json)
elif content is not None:

View File

@@ -14,7 +14,7 @@ import re
import sys
import traceback
from ansible.module_utils.common.text.converters import to_text, to_bytes
from ansible.module_utils.common.text.converters import to_text, to_bytes, to_native
from ansible.module_utils.six.moves.urllib.parse import urlparse, urlunparse, ParseResult
from ._asn1 import serialize_asn1_string_as_der
@@ -138,7 +138,7 @@ def cryptography_get_extensions_from_cert(cert):
der = backend._ffi.buffer(data.data, data.length)[:]
entry = dict(
critical=(crit == 1),
value=base64.b64encode(der),
value=to_native(base64.b64encode(der)),
)
try:
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
@@ -155,7 +155,7 @@ def cryptography_get_extensions_from_cert(cert):
for ext in cert.extensions:
result[ext.oid.dotted_string] = dict(
critical=ext.critical,
value=base64.b64encode(ext.value.public_bytes()),
value=to_native(base64.b64encode(ext.value.public_bytes())),
)
return result
@@ -198,7 +198,7 @@ def cryptography_get_extensions_from_csr(csr):
der = backend._ffi.buffer(data.data, data.length)[:]
entry = dict(
critical=(crit == 1),
value=base64.b64encode(der),
value=to_native(base64.b64encode(der)),
)
try:
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
@@ -215,7 +215,7 @@ def cryptography_get_extensions_from_csr(csr):
for ext in csr.extensions:
result[ext.oid.dotted_string] = dict(
critical=ext.critical,
value=base64.b64encode(ext.value.public_bytes()),
value=to_native(base64.b64encode(ext.value.public_bytes())),
)
return result

View File

@@ -139,6 +139,10 @@ class CertificateInfoRetrieval(object):
def _get_ocsp_uri(self):
pass
@abc.abstractmethod
def _get_issuer_uri(self):
pass
def get_info(self, prefer_one_fingerprint=False):
result = dict()
self.cert = load_certificate(None, content=self.content, backend=self.backend)
@@ -167,7 +171,7 @@ class CertificateInfoRetrieval(object):
result['not_after'] = not_after.strftime(TIMESTAMP_FORMAT)
result['expired'] = not_after < datetime.datetime.utcnow()
result['public_key'] = self._get_public_key_pem()
result['public_key'] = to_native(self._get_public_key_pem())
public_key_info = get_publickey_info(
self.module,
@@ -200,6 +204,7 @@ class CertificateInfoRetrieval(object):
result['serial_number'] = self._get_serial_number()
result['extensions_by_oid'] = self._get_all_extensions()
result['ocsp_uri'] = self._get_ocsp_uri()
result['issuer_uri'] = self._get_issuer_uri()
return result
@@ -365,6 +370,17 @@ class CertificateInfoRetrievalCryptography(CertificateInfoRetrieval):
pass
return None
def _get_issuer_uri(self):
try:
ext = self.cert.extensions.get_extension_for_class(x509.AuthorityInformationAccess)
for desc in ext.value:
if desc.access_method == x509.oid.AuthorityInformationAccessOID.CA_ISSUERS:
if isinstance(desc.access_location, x509.UniformResourceIdentifier):
return desc.access_location.value
except x509.ExtensionNotFound as dummy:
pass
return None
def get_certificate_info(module, backend, content, prefer_one_fingerprint=False):
if backend == 'cryptography':

View File

@@ -270,8 +270,12 @@ def parse_crl_distribution_points(module, crl_distribution_points):
reasons=None,
)
if parse_crl_distribution_point['full_name'] is not None:
if not parse_crl_distribution_point['full_name']:
raise OpenSSLObjectError('full_name must not be empty')
params['full_name'] = [cryptography_get_name(name, 'full name') for name in parse_crl_distribution_point['full_name']]
if parse_crl_distribution_point['relative_name'] is not None:
if not parse_crl_distribution_point['relative_name']:
raise OpenSSLObjectError('relative_name must not be empty')
try:
params['relative_name'] = cryptography_parse_relative_distinguished_name(parse_crl_distribution_point['relative_name'])
except Exception:
@@ -280,6 +284,8 @@ def parse_crl_distribution_points(module, crl_distribution_points):
raise OpenSSLObjectError('Cannot specify relative_name for cryptography < 1.6')
raise
if parse_crl_distribution_point['crl_issuer'] is not None:
if not parse_crl_distribution_point['crl_issuer']:
raise OpenSSLObjectError('crl_issuer must not be empty')
params['crl_issuer'] = [cryptography_get_name(name, 'CRL issuer') for name in parse_crl_distribution_point['crl_issuer']]
if parse_crl_distribution_point['reasons'] is not None:
reasons = []
@@ -287,7 +293,7 @@ def parse_crl_distribution_points(module, crl_distribution_points):
reasons.append(REVOCATION_REASON_MAP[reason])
params['reasons'] = frozenset(reasons)
result.append(cryptography.x509.DistributionPoint(**params))
except OpenSSLObjectError as e:
except (OpenSSLObjectError, ValueError) as e:
raise OpenSSLObjectError('Error while parsing CRL distribution point #{index}: {error}'.format(index=index, error=e))
return result
@@ -651,7 +657,8 @@ def get_csr_argument_spec():
'aa_compromise',
]),
),
mutually_exclusive=[('full_name', 'relative_name')]
mutually_exclusive=[('full_name', 'relative_name')],
required_one_of=[('full_name', 'relative_name', 'crl_issuer')],
),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography']),
),

View File

@@ -133,7 +133,7 @@ class CSRInfoRetrieval(object):
result['name_constraints_critical'],
) = self._get_name_constraints()
result['public_key'] = self._get_public_key_pem()
result['public_key'] = to_native(self._get_public_key_pem())
public_key_info = get_publickey_info(
self.module,

View File

@@ -214,7 +214,7 @@ class PrivateKeyInfoRetrieval(object):
except OpenSSLObjectError as exc:
raise PrivateKeyParseError(to_native(exc), result)
result['public_key'] = self._get_public_key(binary=False)
result['public_key'] = to_native(self._get_public_key(binary=False))
pk = self._get_public_key(binary=True)
result['public_key_fingerprints'] = get_fingerprint_of_bytes(
pk, prefer_one=prefer_one_fingerprint) if pk is not None else dict()

View File

@@ -112,7 +112,7 @@ class PublicKeyInfoRetrieval(object):
try:
self.key = load_publickey(content=self.content, backend=self.backend)
except OpenSSLObjectError as e:
raise PublicKeyParseError(to_native(e))
raise PublicKeyParseError(to_native(e), {})
pk = self._get_public_key(binary=True)
result['fingerprints'] = get_fingerprint_of_bytes(

View File

@@ -8,6 +8,6 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
# This import is only to maintain backwards compatibility
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import (
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import ( # noqa: F401, pylint: disable=unused-import
parse_openssh_version
)

View File

@@ -15,4 +15,4 @@ __metaclass__ = type
#
# from ansible.module_utils.compat.version import LooseVersion
from ._version import LooseVersion
from ._version import LooseVersion # noqa: F401, pylint: disable=unused-import

View File

@@ -15,15 +15,15 @@ module: acme_account
author: "Felix Fontein (@felixfontein)"
short_description: Create, modify or delete ACME accounts
description:
- "Allows to create, modify or delete accounts with a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/)."
- "This module only works with the ACME v2 protocol."
- "Allows to create, modify or delete accounts with a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/)."
- "This module only works with the ACME v2 protocol."
notes:
- "The M(community.crypto.acme_certificate) module also allows to do basic account management.
When using both modules, it is recommended to disable account management
for M(community.crypto.acme_certificate). For that, use the C(modify_account) option of
M(community.crypto.acme_certificate)."
- "The M(community.crypto.acme_certificate) module also allows to do basic account management.
When using both modules, it is recommended to disable account management
for M(community.crypto.acme_certificate). For that, use the C(modify_account) option of
M(community.crypto.acme_certificate)."
seealso:
- name: Automatic Certificate Management Environment (ACME)
description: The specification of the ACME protocol (RFC 8555).
@@ -37,8 +37,14 @@ seealso:
- module: community.crypto.acme_inspect
description: Allows to debug problems.
extends_documentation_fragment:
- community.crypto.acme
- community.crypto.acme
- community.crypto.attributes
- community.crypto.attributes.actiongroup_acme
attributes:
check_mode:
support: full
diff_mode:
support: full
options:
state:
description:

View File

@@ -15,16 +15,20 @@ module: acme_account_info
author: "Felix Fontein (@felixfontein)"
short_description: Retrieves information on ACME accounts
description:
- "Allows to retrieve information on accounts a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/)."
- "This module only works with the ACME v2 protocol."
- "Allows to retrieve information on accounts a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/)."
- "This module only works with the ACME v2 protocol."
notes:
- "The M(community.crypto.acme_account) module allows to modify, create and delete ACME
accounts."
- "This module was called C(acme_account_facts) before Ansible 2.8. The usage
did not change."
- Supports C(check_mode).
- "The M(community.crypto.acme_account) module allows to modify, create and delete ACME
accounts."
- "This module was called C(acme_account_facts) before Ansible 2.8. The usage
did not change."
extends_documentation_fragment:
- community.crypto.acme
- community.crypto.attributes
- community.crypto.attributes.actiongroup_acme
- community.crypto.attributes.info_module
options:
retrieve_orders:
description:
@@ -45,8 +49,6 @@ options:
seealso:
- module: community.crypto.acme_account
description: Allows to create, modify or delete an ACME account.
extends_documentation_fragment:
- community.crypto.acme
'''

View File

@@ -15,35 +15,35 @@ module: acme_certificate
author: "Michael Gruener (@mgruener)"
short_description: Create SSL/TLS certificates with the ACME protocol
description:
- "Create and renew SSL/TLS certificates with a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/) or
L(Buypass,https://www.buypass.com/). The current implementation
supports the C(http-01), C(dns-01) and C(tls-alpn-01) challenges."
- "To use this module, it has to be executed twice. Either as two
different tasks in the same run or during two runs. Note that the output
of the first run needs to be recorded and passed to the second run as the
module argument C(data)."
- "Between these two tasks you have to fulfill the required steps for the
chosen challenge by whatever means necessary. For C(http-01) that means
creating the necessary challenge file on the destination webserver. For
C(dns-01) the necessary dns record has to be created. For C(tls-alpn-01)
the necessary certificate has to be created and served.
It is I(not) the responsibility of this module to perform these steps."
- "For details on how to fulfill these challenges, you might have to read through
L(the main ACME specification,https://tools.ietf.org/html/rfc8555#section-8)
and the L(TLS-ALPN-01 specification,https://www.rfc-editor.org/rfc/rfc8737.html#section-3).
Also, consider the examples provided for this module."
- "The module includes experimental support for IP identifiers according to
the L(RFC 8738,https://www.rfc-editor.org/rfc/rfc8738.html)."
- "Create and renew SSL/TLS certificates with a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/) or
L(Buypass,https://www.buypass.com/). The current implementation
supports the C(http-01), C(dns-01) and C(tls-alpn-01) challenges."
- "To use this module, it has to be executed twice. Either as two
different tasks in the same run or during two runs. Note that the output
of the first run needs to be recorded and passed to the second run as the
module argument C(data)."
- "Between these two tasks you have to fulfill the required steps for the
chosen challenge by whatever means necessary. For C(http-01) that means
creating the necessary challenge file on the destination webserver. For
C(dns-01) the necessary dns record has to be created. For C(tls-alpn-01)
the necessary certificate has to be created and served.
It is I(not) the responsibility of this module to perform these steps."
- "For details on how to fulfill these challenges, you might have to read through
L(the main ACME specification,https://tools.ietf.org/html/rfc8555#section-8)
and the L(TLS-ALPN-01 specification,https://www.rfc-editor.org/rfc/rfc8737.html#section-3).
Also, consider the examples provided for this module."
- "The module includes experimental support for IP identifiers according to
the L(RFC 8738,https://www.rfc-editor.org/rfc/rfc8738.html)."
notes:
- "At least one of C(dest) and C(fullchain_dest) must be specified."
- "This module includes basic account management functionality.
If you want to have more control over your ACME account, use the
M(community.crypto.acme_account) module and disable account management
for this module using the C(modify_account) option."
- "This module was called C(letsencrypt) before Ansible 2.6. The usage
did not change."
- "At least one of C(dest) and C(fullchain_dest) must be specified."
- "This module includes basic account management functionality.
If you want to have more control over your ACME account, use the
M(community.crypto.acme_account) module and disable account management
for this module using the C(modify_account) option."
- "This module was called C(letsencrypt) before Ansible 2.6. The usage
did not change."
seealso:
- name: The Let's Encrypt documentation
description: Documentation for the Let's Encrypt Certification Authority.
@@ -78,8 +78,17 @@ seealso:
- module: community.crypto.acme_inspect
description: Allows to debug problems.
extends_documentation_fragment:
- community.crypto.acme
- community.crypto.acme
- community.crypto.attributes
- community.crypto.attributes.files
- community.crypto.attributes.actiongroup_acme
attributes:
check_mode:
support: full
diff_mode:
support: none
safe_file_operations:
support: full
options:
account_email:
description:

View File

@@ -15,18 +15,17 @@ module: acme_certificate_revoke
author: "Felix Fontein (@felixfontein)"
short_description: Revoke certificates with the ACME protocol
description:
- "Allows to revoke certificates issued by a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/)."
- "Allows to revoke certificates issued by a CA supporting the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
such as L(Let's Encrypt,https://letsencrypt.org/)."
notes:
- "Exactly one of C(account_key_src), C(account_key_content),
C(private_key_src) or C(private_key_content) must be specified."
- "Trying to revoke an already revoked certificate
should result in an unchanged status, even if the revocation reason
was different than the one specified here. Also, depending on the
server, it can happen that some other error is returned if the
certificate has already been revoked."
- Does not support C(check_mode).
- "Exactly one of C(account_key_src), C(account_key_content),
C(private_key_src) or C(private_key_content) must be specified."
- "Trying to revoke an already revoked certificate
should result in an unchanged status, even if the revocation reason
was different than the one specified here. Also, depending on the
server, it can happen that some other error is returned if the
certificate has already been revoked."
seealso:
- name: The Let's Encrypt documentation
description: Documentation for the Let's Encrypt Certification Authority.
@@ -38,8 +37,14 @@ seealso:
- module: community.crypto.acme_inspect
description: Allows to debug problems.
extends_documentation_fragment:
- community.crypto.acme
- community.crypto.acme
- community.crypto.attributes
- community.crypto.attributes.actiongroup_acme
attributes:
check_mode:
support: none
diff_mode:
support: none
options:
certificate:
description:

View File

@@ -15,10 +15,10 @@ module: acme_challenge_cert_helper
author: "Felix Fontein (@felixfontein)"
short_description: Prepare certificates required for ACME challenges such as C(tls-alpn-01)
description:
- "Prepares certificates for ACME challenges such as C(tls-alpn-01)."
- "The raw data is provided by the M(community.crypto.acme_certificate) module, and needs to be
converted to a certificate to be used for challenge validation. This module
provides a simple way to generate the required certificates."
- "Prepares certificates for ACME challenges such as C(tls-alpn-01)."
- "The raw data is provided by the M(community.crypto.acme_certificate) module, and needs to be
converted to a certificate to be used for challenge validation. This module
provides a simple way to generate the required certificates."
seealso:
- name: Automatic Certificate Management Environment (ACME)
description: The specification of the ACME protocol (RFC 8555).
@@ -27,7 +27,18 @@ seealso:
description: The specification of the C(tls-alpn-01) challenge (RFC 8737).
link: https://www.rfc-editor.org/rfc/rfc8737.html
requirements:
- "cryptography >= 1.3"
- "cryptography >= 1.3"
extends_documentation_fragment:
- community.crypto.attributes
attributes:
check_mode:
support: none
details:
- This action does not modify state.
diff_mode:
support: N/A
details:
- This action does not modify state.
options:
challenge:
description:
@@ -58,8 +69,6 @@ options:
- Phassphrase to use to decode the private key.
type: str
version_added: 1.6.0
notes:
- Does not support C(check_mode).
'''
EXAMPLES = '''

View File

@@ -15,25 +15,25 @@ module: acme_inspect
author: "Felix Fontein (@felixfontein)"
short_description: Send direct requests to an ACME server
description:
- "Allows to send direct requests to an ACME server with the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
which is supported by CAs such as L(Let's Encrypt,https://letsencrypt.org/)."
- "This module can be used to debug failed certificate request attempts,
for example when M(community.crypto.acme_certificate) fails or encounters a problem which
you wish to investigate."
- "The module can also be used to directly access features of an ACME servers
which are not yet supported by the Ansible ACME modules."
- "Allows to send direct requests to an ACME server with the
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
which is supported by CAs such as L(Let's Encrypt,https://letsencrypt.org/)."
- "This module can be used to debug failed certificate request attempts,
for example when M(community.crypto.acme_certificate) fails or encounters a problem which
you wish to investigate."
- "The module can also be used to directly access features of an ACME servers
which are not yet supported by the Ansible ACME modules."
notes:
- "The I(account_uri) option must be specified for properly authenticated
ACME v2 requests (except a C(new-account) request)."
- "Using the C(ansible) tool, M(community.crypto.acme_inspect) can be used to directly execute
ACME requests without the need of writing a playbook. For example, the
following command retrieves the ACME account with ID 1 from Let's Encrypt
(assuming C(/path/to/key) is the correct private account key):
C(ansible localhost -m acme_inspect -a \"account_key_src=/path/to/key
acme_directory=https://acme-v02.api.letsencrypt.org/directory acme_version=2
account_uri=https://acme-v02.api.letsencrypt.org/acme/acct/1 method=get
url=https://acme-v02.api.letsencrypt.org/acme/acct/1\")"
- "The I(account_uri) option must be specified for properly authenticated
ACME v2 requests (except a C(new-account) request)."
- "Using the C(ansible) tool, M(community.crypto.acme_inspect) can be used to directly execute
ACME requests without the need of writing a playbook. For example, the
following command retrieves the ACME account with ID 1 from Let's Encrypt
(assuming C(/path/to/key) is the correct private account key):
C(ansible localhost -m acme_inspect -a \"account_key_src=/path/to/key
acme_directory=https://acme-v02.api.letsencrypt.org/directory acme_version=2
account_uri=https://acme-v02.api.letsencrypt.org/acme/acct/1 method=get
url=https://acme-v02.api.letsencrypt.org/acme/acct/1\")"
seealso:
- name: Automatic Certificate Management Environment (ACME)
description: The specification of the ACME protocol (RFC 8555).
@@ -42,8 +42,14 @@ seealso:
description: The specification of the C(tls-alpn-01) challenge (RFC 8737).
link: https://www.rfc-editor.org/rfc/rfc8737.html
extends_documentation_fragment:
- community.crypto.acme
- community.crypto.acme
- community.crypto.attributes
- community.crypto.attributes.actiongroup_acme
attributes:
check_mode:
support: none
diff_mode:
support: none
options:
url:
description:

View File

@@ -26,6 +26,17 @@ description:
generated chain is valid, please use C(openssl verify ...)."
requirements:
- "cryptography >= 1.5"
extends_documentation_fragment:
- community.crypto.attributes
attributes:
check_mode:
support: full
details:
- This action does not modify state.
diff_mode:
support: N/A
details:
- This action does not modify state.
options:
input_chain:
description:

View File

@@ -16,11 +16,12 @@ author: "Felix Fontein (@felixfontein)"
short_description: Retrieve cryptographic capabilities
version_added: 2.1.0
description:
- Retrieve information on cryptographic capabilities.
- The current version retrieves information on the L(Python cryptography library, https://cryptography.io/) available to
Ansible modules, and on the OpenSSL binary C(openssl) found in the path.
notes:
- Supports C(check_mode).
- Retrieve information on cryptographic capabilities.
- The current version retrieves information on the L(Python cryptography library, https://cryptography.io/) available to
Ansible modules, and on the OpenSSL binary C(openssl) found in the path.
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.info_module
options: {}
'''

View File

@@ -24,6 +24,19 @@ notes:
- C(path) must be specified as the output location of the certificate.
requirements:
- cryptography >= 1.6
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.files
- community.crypto.ecs_credential
attributes:
check_mode:
support: partial
details:
- Check mode is only supported if I(request_type=new).
diff_mode:
support: none
safe_file_operations:
support: full
options:
backup:
description:
@@ -337,9 +350,6 @@ seealso:
description: Can be used to create private keys (both for certificates and accounts).
- module: community.crypto.openssl_csr
description: Can be used to create a Certificate Signing Request (CSR).
extends_documentation_fragment:
- community.crypto.ecs_credential
'''
EXAMPLES = r'''

View File

@@ -33,6 +33,14 @@ description:
notes:
- There is a small delay (typically about 5 seconds, but can be as long as 60 seconds) before obtaining the random values when requesting a validation
while C(verification_method=dns) or C(verification_method=web_server). Be aware of that if doing many domain validation requests.
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.ecs_credential
attributes:
check_mode:
support: none
diff_mode:
support: none
options:
client_id:
description:
@@ -79,9 +87,6 @@ seealso:
description: Can be used to request certificates from ECS, with C(provider=entrust).
- module: community.crypto.ecs_certificate
description: Can be used to request a Certificate from ECS using a verified domain.
extends_documentation_fragment:
- community.crypto.ecs_credential
'''
EXAMPLES = r'''

View File

@@ -18,6 +18,17 @@ description:
- Makes a secure connection and returns information about the presented certificate
- The module uses the cryptography Python library.
- Support SNI (L(Server Name Indication,https://en.wikipedia.org/wiki/Server_Name_Indication)) only with python >= 2.7.
extends_documentation_fragment:
- community.crypto.attributes
attributes:
check_mode:
support: none
details:
- This action does not modify state.
diff_mode:
support: N/A
details:
- This action does not modify state.
options:
host:
description:
@@ -70,13 +81,23 @@ options:
type: str
default: auto
choices: [ auto, cryptography ]
ciphers:
description:
- SSL/TLS Ciphers to use for the request.
- 'When a list is provided, all ciphers are joined in order with C(:).'
- See the L(OpenSSL Cipher List Format,https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html#CIPHER-LIST-FORMAT)
for more details.
- The available ciphers is dependent on the Python and OpenSSL/LibreSSL versions.
type: list
elements: str
version_added: 2.11.0
notes:
- When using ca_cert on OS X it has been reported that in some conditions the validate will always succeed.
- When using ca_cert on OS X it has been reported that in some conditions the validate will always succeed.
requirements:
- "python >= 2.7 when using C(proxy_host)"
- "cryptography >= 1.6"
- "python >= 2.7 when using C(proxy_host)"
- "cryptography >= 1.6"
'''
RETURN = '''
@@ -236,6 +257,7 @@ def main():
timeout=dict(type='int', default=10),
select_crypto_backend=dict(type='str', choices=['auto', 'cryptography'], default='auto'),
starttls=dict(type='str', choices=['mysql']),
ciphers=dict(type='list', elements='str'),
),
)
@@ -247,6 +269,7 @@ def main():
timeout = module.params.get('timeout')
server_name = module.params.get('server_name')
start_tls_server_type = module.params.get('starttls')
ciphers = module.params.get('ciphers')
backend = module.params.get('select_crypto_backend')
if backend == 'auto':
@@ -283,6 +306,9 @@ def main():
if proxy_host:
module.fail_json(msg='To use proxy_host, you must run the get_certificate module with Python 2.7 or newer.',
exception=CREATE_DEFAULT_CONTEXT_IMP_ERR)
if ciphers is not None:
module.fail_json(msg='To use ciphers, you must run the get_certificate module with Python 2.7 or newer.',
exception=CREATE_DEFAULT_CONTEXT_IMP_ERR)
try:
# Note: get_server_certificate does not support SNI!
cert = get_server_certificate((host, port), ca_certs=ca_cert)
@@ -314,6 +340,10 @@ def main():
if start_tls_server_type is not None:
send_starttls_packet(sock, start_tls_server_type)
if ciphers is not None:
ciphers_joined = ":".join(ciphers)
ctx.set_ciphers(ciphers_joined)
cert = ctx.wrap_socket(sock, server_hostname=server_name or host).getpeercert(True)
cert = DER_cert_to_PEM_cert(cert)
except Exception as e:

View File

@@ -13,12 +13,20 @@ module: luks_device
short_description: Manage encrypted (LUKS) devices
description:
- "Module manages L(LUKS,https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup)
on given device. Supports creating, destroying, opening and closing of
LUKS container and adding or removing new keys and passphrases."
extends_documentation_fragment:
- community.crypto.attributes
attributes:
check_mode:
support: full
diff_mode:
support: none
options:
device:
description:

View File

@@ -18,6 +18,17 @@ description:
- Generate and regenerate OpenSSH host or user certificates.
requirements:
- "ssh-keygen"
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
attributes:
check_mode:
support: full
diff_mode:
support: full
safe_file_operations:
support: full
options:
state:
description:
@@ -180,8 +191,6 @@ options:
The serial number may be omitted for checks, but must be specified again for a new certificate.
Note: The default value set by ssh-keygen is 0."
type: int
extends_documentation_fragment: files
'''
EXAMPLES = '''

View File

@@ -21,6 +21,17 @@ requirements:
- ssh-keygen (if I(backend=openssh))
- cryptography >= 2.6 (if I(backend=cryptography) and OpenSSH < 7.8 is installed)
- cryptography >= 3.0 (if I(backend=cryptography) and OpenSSH >= 7.8 is installed)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
attributes:
check_mode:
support: full
diff_mode:
support: full
safe_file_operations:
support: full
options:
state:
description:
@@ -128,10 +139,7 @@ options:
notes:
- In case the ssh key is broken or password protected, the module will fail.
Set the I(force) option to C(true) if you want to regenerate the keypair.
- Supports C(check_mode).
- In the case a custom C(mode), C(group), C(owner), or other file attribute is provided it will be applied to both key files.
extends_documentation_fragment: files
'''
EXAMPLES = '''

View File

@@ -19,8 +19,20 @@ description:
options, or if it seems to be corrupt. If you are concerned that this could overwrite
your existing CSR, consider using the I(backup) option."
author:
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
- community.crypto.module_csr
attributes:
check_mode:
support: full
diff_mode:
support: full
safe_file_operations:
support: full
options:
state:
description:
@@ -58,11 +70,8 @@ options:
version_added: 1.1.0
name_constraints_critical:
version_added: 1.1.0
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.module_csr
seealso:
- module: community.crypto.openssl_csr_pipe
- module: community.crypto.openssl_csr_pipe
'''
EXAMPLES = r'''
@@ -330,9 +339,10 @@ def main():
if not os.path.isdir(base_dir):
module.fail_json(name=base_dir, msg='The directory %s does not exist or the file is not a directory' % base_dir)
backend = module.params['select_crypto_backend']
backend, module_backend = select_backend(module, backend)
try:
backend = module.params['select_crypto_backend']
backend, module_backend = select_backend(module, backend)
csr = CertificateSigningRequestModule(module, module_backend)
if module.params['state'] == 'present':
csr.generate(module)

View File

@@ -22,8 +22,12 @@ description:
requirements:
- cryptography >= 1.3
author:
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.info_module
- community.crypto.name_encoding
options:
path:
description:
@@ -45,12 +49,13 @@ 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
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_csr_pipe
- ref: community.crypto.openssl_csr_info filter <ansible_collections.community.crypto.openssl_csr_info_filter>
# - plugin: community.crypto.openssl_csr_info
# plugin_type: filter
description: A filter variant of this module.
'''
EXAMPLES = r'''

View File

@@ -19,15 +19,21 @@ description:
- "Please note that the module regenerates an existing CSR if it does not match the module's
options, or if it seems to be corrupt."
author:
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.module_csr
attributes:
check_mode:
support: full
diff_mode:
support: full
options:
content:
description:
- The existing CSR.
type: str
extends_documentation_fragment:
- community.crypto.module_csr
seealso:
- module: community.crypto.openssl_csr
'''
@@ -161,9 +167,10 @@ def main():
supports_check_mode=True,
)
backend = module.params['select_crypto_backend']
backend, module_backend = select_backend(module, backend)
try:
backend = module.params['select_crypto_backend']
backend, module_backend = select_backend(module, backend)
csr = CertificateSigningRequestModule(module, module_backend)
csr.generate(module)
result = csr.dump()

View File

@@ -27,6 +27,17 @@ requirements:
- Or OpenSSL binary C(openssl)
author:
- Thom Wiggers (@thomwiggers)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
attributes:
check_mode:
support: full
diff_mode:
support: none
safe_file_operations:
support: full
options:
state:
description:
@@ -72,16 +83,12 @@ options:
type: bool
default: false
version_added: "1.0.0"
notes:
- Supports C(check_mode).
extends_documentation_fragment:
- files
seealso:
- module: community.crypto.x509_certificate
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_pkcs12
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_publickey
- module: community.crypto.x509_certificate
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_pkcs12
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_publickey
'''
EXAMPLES = r'''

View File

@@ -25,6 +25,17 @@ description:
# and will be removed in community.crypto (x+1).0.0.
requirements:
- PyOpenSSL >= 0.15 or cryptography >= 3.0
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
attributes:
check_mode:
support: full
diff_mode:
support: none
safe_file_operations:
support: full
options:
action:
description:
@@ -65,15 +76,30 @@ options:
iter_size:
description:
- Number of times to repeat the encryption step.
- This is not considered during idempotency checks.
- This is only used by the C(pyopenssl) backend. When using it, the default is C(2048).
- This is B(not considered during idempotency checks).
- This is only used by the C(pyopenssl) backend, or when I(encryption_level=compatibility2022).
- When using it, the default is C(2048) for C(pyopenssl) and C(50000) for C(cryptography).
type: int
maciter_size:
description:
- Number of times to repeat the MAC step.
- This is not considered during idempotency checks.
- This is B(not considered during idempotency checks).
- This is only used by the C(pyopenssl) backend. When using it, the default is C(1).
type: int
encryption_level:
description:
- Determines the encryption level used.
- C(auto) uses the default of the selected backend. For C(cryptography), this is what the
cryptography library's specific version considers the best available encryption.
- C(compatibility2022) uses compatibility settings for older software in 2022.
This is only supported by the C(cryptography) backend if cryptography >= 38.0.0 is available.
- B(Note) that this option is B(not used for idempotency).
choices:
- auto
- compatibility2022
default: auto
type: str
version_added: 2.8.0
passphrase:
description:
- The PKCS#12 password.
@@ -128,8 +154,8 @@ options:
description:
- Determines which crypto backend to use.
- The default choice is C(auto), which tries to use C(cryptography) if available, and falls back to C(pyopenssl).
If one of I(iter_size) or I(maciter_size) is used, C(auto) will always result in C(pyopenssl) to be chosen
for backwards compatibility.
If I(iter_size) is used together with I(encryption_level != compatibility2022), or if I(maciter_size) is used,
C(auto) will always result in C(pyopenssl) to be chosen for backwards compatibility.
- If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) library.
- If set to C(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
# - Please note that the C(pyopenssl) backend has been deprecated in community.crypto x.y.0, and will be
@@ -139,14 +165,12 @@ options:
default: auto
choices: [ auto, cryptography, pyopenssl ]
version_added: 1.7.0
extends_documentation_fragment:
- files
seealso:
- module: community.crypto.x509_certificate
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_dhparam
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_publickey
- module: community.crypto.x509_certificate
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_dhparam
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_publickey
'''
EXAMPLES = r'''
@@ -302,6 +326,18 @@ except ImportError:
else:
CRYPTOGRAPHY_FOUND = True
CRYPTOGRAPHY_COMPATIBILITY2022_ERR = None
try:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.serialization.pkcs12 import PBES
# Try to build encryption builder for compatibility2022
serialization.PrivateFormat.PKCS12.encryption_builder().key_cert_algorithm(PBES.PBESv1SHA1And3KeyTripleDESCBC).hmac_hash(hashes.SHA1())
except Exception:
CRYPTOGRAPHY_COMPATIBILITY2022_ERR = traceback.format_exc()
CRYPTOGRAPHY_HAS_COMPATIBILITY2022 = False
else:
CRYPTOGRAPHY_HAS_COMPATIBILITY2022 = True
def load_certificate_set(filename, backend):
'''
@@ -317,7 +353,7 @@ class PkcsError(OpenSSLObjectError):
class Pkcs(OpenSSLObject):
def __init__(self, module, backend):
def __init__(self, module, backend, iter_size_default=2048):
super(Pkcs, self).__init__(
module.params['path'],
module.params['state'],
@@ -330,8 +366,9 @@ class Pkcs(OpenSSLObject):
self.other_certificates_parse_all = module.params['other_certificates_parse_all']
self.certificate_path = module.params['certificate_path']
self.friendly_name = module.params['friendly_name']
self.iter_size = module.params['iter_size'] or 2048
self.iter_size = module.params['iter_size'] or iter_size_default
self.maciter_size = module.params['maciter_size'] or 1
self.encryption_level = module.params['encryption_level']
self.passphrase = module.params['passphrase']
self.pkcs12 = None
self.privatekey_passphrase = module.params['privatekey_passphrase']
@@ -508,6 +545,8 @@ class Pkcs(OpenSSLObject):
class PkcsPyOpenSSL(Pkcs):
def __init__(self, module):
super(PkcsPyOpenSSL, self).__init__(module, 'pyopenssl')
if self.encryption_level != 'auto':
module.fail_json(msg='The PyOpenSSL backend only supports encryption_level = auto')
def generate_bytes(self, module):
"""Generate PKCS#12 file archive."""
@@ -573,7 +612,12 @@ class PkcsPyOpenSSL(Pkcs):
class PkcsCryptography(Pkcs):
def __init__(self, module):
super(PkcsCryptography, self).__init__(module, 'cryptography')
super(PkcsCryptography, self).__init__(module, 'cryptography', iter_size_default=50000)
if self.encryption_level == 'compatibility2022' and not CRYPTOGRAPHY_HAS_COMPATIBILITY2022:
module.fail_json(
msg='The installed cryptography version does not support encryption_level = compatibility2022.'
' You need cryptography >= 38.0.0 and support for SHA1',
exception=CRYPTOGRAPHY_COMPATIBILITY2022_ERR)
def generate_bytes(self, module):
"""Generate PKCS#12 file archive."""
@@ -593,13 +637,25 @@ class PkcsCryptography(Pkcs):
# Store fake object which can be used to retrieve the components back
self.pkcs12 = (pkey, cert, self.other_certificates, friendly_name)
if not self.passphrase:
encryption = serialization.NoEncryption()
elif self.encryption_level == 'compatibility2022':
encryption = (
serialization.PrivateFormat.PKCS12.encryption_builder().
kdf_rounds(self.iter_size).
key_cert_algorithm(PBES.PBESv1SHA1And3KeyTripleDESCBC).
hmac_hash(hashes.SHA1()).
build(to_bytes(self.passphrase))
)
else:
encryption = serialization.BestAvailableEncryption(to_bytes(self.passphrase))
return serialize_key_and_certificates(
friendly_name,
pkey,
cert,
self.other_certificates,
serialization.BestAvailableEncryption(to_bytes(self.passphrase))
if self.passphrase else serialization.NoEncryption(),
encryption,
)
def parse_bytes(self, pkcs12_content):
@@ -658,8 +714,11 @@ def select_backend(module, backend):
can_use_pyopenssl = PYOPENSSL_FOUND and PYOPENSSL_VERSION >= LooseVersion(MINIMAL_PYOPENSSL_VERSION)
# If no restrictions are provided, first try cryptography, then pyOpenSSL
if module.params['iter_size'] is not None or module.params['maciter_size'] is not None:
# If iter_size or maciter_size is specified, use pyOpenSSL backend
if (
(module.params['iter_size'] is not None and module.params['encryption_level'] != 'compatibility2022')
or module.params['maciter_size'] is not None
):
# If iter_size (for encryption_level != compatibility2022) or maciter_size is specified, use pyOpenSSL backend
backend = 'pyopenssl'
elif can_use_cryptography:
backend = 'cryptography'
@@ -697,6 +756,7 @@ def main():
certificate_path=dict(type='path'),
force=dict(type='bool', default=False),
friendly_name=dict(type='str', aliases=['name']),
encryption_level=dict(type='str', choices=['auto', 'compatibility2022'], default='auto'),
iter_size=dict(type='int'),
maciter_size=dict(type='int'),
passphrase=dict(type='str', no_log=True),

View File

@@ -19,6 +19,18 @@ description:
author:
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
- community.crypto.module_privatekey
attributes:
check_mode:
support: full
diff_mode:
support: full
safe_file_operations:
support: full
options:
state:
description:
@@ -59,12 +71,9 @@ options:
version_added: '1.0.0'
regenerate:
version_added: '1.0.0'
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.module_privatekey
seealso:
- module: community.crypto.openssl_privatekey_pipe
- module: community.crypto.openssl_privatekey_info
- module: community.crypto.openssl_privatekey_pipe
- module: community.crypto.openssl_privatekey_info
'''
EXAMPLES = r'''
@@ -76,7 +85,7 @@ EXAMPLES = r'''
community.crypto.openssl_privatekey:
path: /etc/ssl/private/ansible.com.pem
passphrase: ansible
cipher: aes256
cipher: auto
- name: Generate an OpenSSL private key with a different size (2048 bits)
community.crypto.openssl_privatekey:

View File

@@ -19,6 +19,18 @@ description:
- The default mode for the private key file will be C(0600) if I(mode) is not explicitly set.
author:
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
- community.crypto.module_privatekey_convert
attributes:
check_mode:
support: full
diff_mode:
support: none
safe_file_operations:
support: full
options:
dest_path:
description:
@@ -32,9 +44,6 @@ options:
the original private key back if you overwrote it with a new one by accident.
type: bool
default: false
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.module_privatekey_convert
seealso: []
'''

View File

@@ -24,8 +24,11 @@ description:
requirements:
- cryptography >= 1.2.3
author:
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.info_module
options:
path:
description:
@@ -70,12 +73,13 @@ options:
default: auto
choices: [ auto, cryptography ]
notes:
- Supports C(check_mode).
seealso:
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_privatekey_pipe
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_privatekey_pipe
- ref: community.crypto.openssl_privatekey_info filter <ansible_collections.community.crypto.openssl_privatekey_info_filter>
# - plugin: community.crypto.openssl_privatekey_info
# plugin_type: filter
description: A filter variant of this module.
'''
EXAMPLES = r'''

View File

@@ -23,6 +23,21 @@ description:
author:
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.flow
- community.crypto.module_privatekey
attributes:
action:
support: full
async:
support: none
details:
- This action runs completely on the controller.
check_mode:
support: full
diff_mode:
support: full
options:
content:
description:
@@ -42,11 +57,9 @@ options:
current key (if it was provided) and Ansible will replace it by C(VALUE_SPECIFIED_IN_NO_LOG_PARAMETER).
type: bool
default: false
extends_documentation_fragment:
- community.crypto.module_privatekey
seealso:
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_privatekey_info
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_privatekey_info
'''
EXAMPLES = r'''

View File

@@ -14,8 +14,9 @@ DOCUMENTATION = r'''
module: openssl_publickey
short_description: Generate an OpenSSL public key from its private key.
description:
- This module allows one to (re)generate OpenSSL public keys from their private keys.
- Keys are generated in PEM or OpenSSH format.
- This module allows one to (re)generate public keys from their private keys.
- Public keys are generated in PEM or OpenSSH format. Private keys must be OpenSSL PEM keys.
OpenSSH private keys are not supported, use the M(community.crypto.openssh_keypair) module to manage these.
- The module uses the cryptography Python library.
requirements:
- cryptography >= 1.2.3 (older versions might work as well)
@@ -23,6 +24,17 @@ requirements:
author:
- Yanis Guenane (@Spredzy)
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
attributes:
check_mode:
support: full
diff_mode:
support: full
safe_file_operations:
support: full
options:
state:
description:
@@ -83,17 +95,15 @@ options:
type: bool
default: false
version_added: '1.0.0'
extends_documentation_fragment:
- files
seealso:
- module: community.crypto.x509_certificate
- module: community.crypto.x509_certificate_pipe
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_csr_pipe
- module: community.crypto.openssl_dhparam
- module: community.crypto.openssl_pkcs12
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_privatekey_pipe
- module: community.crypto.x509_certificate
- module: community.crypto.x509_certificate_pipe
- module: community.crypto.openssl_csr
- module: community.crypto.openssl_csr_pipe
- module: community.crypto.openssl_dhparam
- module: community.crypto.openssl_pkcs12
- module: community.crypto.openssl_privatekey
- module: community.crypto.openssl_privatekey_pipe
'''
EXAMPLES = r'''

View File

@@ -21,6 +21,9 @@ requirements:
- cryptography >= 1.2.3
author:
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.info_module
options:
path:
description:
@@ -41,12 +44,13 @@ options:
default: auto
choices: [ auto, cryptography ]
notes:
- Supports C(check_mode).
seealso:
- module: community.crypto.openssl_publickey
- module: community.crypto.openssl_privatekey_info
- module: community.crypto.openssl_publickey
- module: community.crypto.openssl_privatekey_info
- ref: community.crypto.openssl_publickey_info filter <ansible_collections.community.crypto.openssl_publickey_info_filter>
# - plugin: community.crypto.openssl_publickey_info
# plugin_type: filter
description: A filter variant of this module.
'''
EXAMPLES = r'''

View File

@@ -22,6 +22,15 @@ requirements:
author:
- Patrick Pichler (@aveexy)
- Markus Teufelberger (@MarkusTeufelberger)
extends_documentation_fragment:
- community.crypto.attributes
attributes:
check_mode:
support: full
details:
- This action does not modify state.
diff_mode:
support: none
options:
privatekey_path:
description:

View File

@@ -22,6 +22,9 @@ requirements:
author:
- Patrick Pichler (@aveexy)
- Markus Teufelberger (@MarkusTeufelberger)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.info_module
options:
path:
description:
@@ -57,7 +60,6 @@ notes:
RSA keys: C(cryptography) >= 1.4
DSA and ECDSA keys: C(cryptography) >= 1.5
ed448 and ed25519 keys: C(cryptography) >= 2.6
- Supports C(check_mode).
seealso:
- module: community.crypto.openssl_signature
- module: community.crypto.x509_certificate

View File

@@ -29,8 +29,24 @@ description:
keyword, the new name M(community.crypto.x509_certificate) should be used to avoid
a deprecation warning.
author:
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
- community.crypto.module_certificate
- community.crypto.module_certificate.backend_acme_documentation
- community.crypto.module_certificate.backend_entrust_documentation
- community.crypto.module_certificate.backend_ownca_documentation
- community.crypto.module_certificate.backend_selfsigned_documentation
attributes:
check_mode:
support: full
diff_mode:
support: full
safe_file_operations:
support: full
options:
state:
description:
@@ -82,19 +98,8 @@ options:
ownca_privatekey_content:
version_added: '1.0.0'
notes:
- Supports C(check_mode).
seealso:
- module: community.crypto.x509_certificate_pipe
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.module_certificate
- community.crypto.module_certificate.backend_acme_documentation
- community.crypto.module_certificate.backend_entrust_documentation
- community.crypto.module_certificate.backend_ownca_documentation
- community.crypto.module_certificate.backend_selfsigned_documentation
- module: community.crypto.x509_certificate_pipe
'''
EXAMPLES = r'''

View File

@@ -28,9 +28,13 @@ description:
requirements:
- cryptography >= 1.6
author:
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.info_module
- community.crypto.name_encoding
options:
path:
description:
@@ -63,16 +67,16 @@ 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.
- Supports C(check_mode).
seealso:
- module: community.crypto.x509_certificate
- module: community.crypto.x509_certificate_pipe
- module: community.crypto.x509_certificate
- module: community.crypto.x509_certificate_pipe
- ref: community.crypto.x509_certificate_info filter <ansible_collections.community.crypto.x509_certificate_info_filter>
# - plugin: community.crypto.x509_certificate_info
# plugin_type: filter
description: A filter variant of this module.
'''
EXAMPLES = r'''
@@ -378,6 +382,12 @@ ocsp_uri:
C(none) if no OCSP responder URI is included.
returned: success
type: str
issuer_uri:
description: The Issuer URI, if included in the certificate. Will be
C(none) if no issuer URI is included.
returned: success
type: str
version_added: 2.9.0
'''

View File

@@ -23,9 +23,20 @@ description:
options, or if it seems to be corrupt. If you are concerned that this could overwrite
your existing certificate, consider using the I(backup) option."
author:
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
- Felix Fontein (@felixfontein)
- Yanis Guenane (@Spredzy)
- Markus Teufelberger (@MarkusTeufelberger)
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.module_certificate
- community.crypto.module_certificate.backend_entrust_documentation
- community.crypto.module_certificate.backend_ownca_documentation
- community.crypto.module_certificate.backend_selfsigned_documentation
attributes:
check_mode:
support: full
diff_mode:
support: full
options:
provider:
description:
@@ -42,16 +53,7 @@ options:
type: str
seealso:
- module: community.crypto.x509_certificate
notes:
- Supports C(check_mode).
extends_documentation_fragment:
- community.crypto.module_certificate
- community.crypto.module_certificate.backend_entrust_documentation
- community.crypto.module_certificate.backend_ownca_documentation
- community.crypto.module_certificate.backend_selfsigned_documentation
- module: community.crypto.x509_certificate
'''
EXAMPLES = r'''

View File

@@ -22,6 +22,18 @@ requirements:
- cryptography >= 1.2
author:
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- ansible.builtin.files
- community.crypto.attributes
- community.crypto.attributes.files
- community.crypto.name_encoding
attributes:
check_mode:
support: full
diff_mode:
support: full
safe_file_operations:
support: full
options:
state:
description:
@@ -241,14 +253,9 @@ options:
type: bool
default: false
extends_documentation_fragment:
- files
- community.crypto.name_encoding
notes:
- All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.
- Date specified should be UTC. Minutes and seconds are mandatory.
- Supports C(check_mode).
'''
EXAMPLES = r'''

View File

@@ -20,6 +20,10 @@ requirements:
- cryptography >= 1.2
author:
- Felix Fontein (@felixfontein)
extends_documentation_fragment:
- community.crypto.attributes
- community.crypto.attributes.info_module
- community.crypto.name_encoding
options:
path:
description:
@@ -41,15 +45,15 @@ 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.
- Supports C(check_mode).
seealso:
- module: community.crypto.x509_crl
- ref: community.crypto.x509_crl_info filter <ansible_collections.community.crypto.x509_crl_info_filter>
# - plugin: community.crypto.x509_crl_info
# plugin_type: filter
description: A filter variant of this module.
'''
EXAMPLES = r'''

View File

@@ -69,9 +69,9 @@ try:
# For ansible-core 2.11, we can use the ArgumentSpecValidator. We also import
# ModuleArgumentSpecValidator since that indicates that the 'classical' approach
# will no longer work.
from ansible.module_utils.common.arg_spec import (
from ansible.module_utils.common.arg_spec import ( # noqa: F401, pylint: disable=unused-import
ArgumentSpecValidator,
ModuleArgumentSpecValidator, # noqa
ModuleArgumentSpecValidator, # ModuleArgumentSpecValidator is not used
)
from ansible.module_utils.errors import UnsupportedError
HAS_ARGSPEC_VALIDATOR = True
@@ -145,9 +145,14 @@ class AnsibleActionModule(object):
# warnings and deprecations that do not work in plugins. This is a copy of that code adjusted
# for our use-case:
for d in self._validation_result._deprecations:
self.deprecate(
"Alias '{name}' is deprecated. See the module docs for more information".format(name=d['name']),
version=d.get('version'), date=d.get('date'), collection_name=d.get('collection_name'))
# Before ansible-core 2.14.2, deprecations were always for aliases:
if 'name' in d:
self.deprecate(
"Alias '{name}' is deprecated. See the module docs for more information".format(name=d['name']),
version=d.get('version'), date=d.get('date'), collection_name=d.get('collection_name'))
# Since ansible-core 2.14.2, a message is present that can be directly printed:
if 'msg' in d:
self.deprecate(d['msg'], version=d.get('version'), date=d.get('date'), collection_name=d.get('collection_name'))
for w in self._validation_result._warnings:
self.warn('Both option {option} and its alias {alias} are set.'.format(option=w['option'], alias=w['alias']))

View File

@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# NOTE: THIS IS ONLY FOR FILTER PLUGINS!
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.errors import AnsibleFilterError
class FilterModuleMock(object):
def __init__(self, params):
self.check_mode = True
self.params = params
self._diff = False
def fail_json(self, msg, **kwargs):
raise AnsibleFilterError(msg)

View File

@@ -29,7 +29,7 @@ import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
import ipaddress
import ipaddress # noqa: F401, pylint: disable=unused-import
HAS_IPADDRESS = True
IPADDRESS_IMP_ERR = None
except ImportError as exc:

View File

@@ -29,7 +29,7 @@ import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
try:
import yaml
import yaml # noqa: F401, pylint: disable=unused-import
HAS_PYYAML = True
PYYAML_IMP_ERR = None
except ImportError as exc:

View File

@@ -6,9 +6,5 @@ azp/generic/1
azp/posix/1
cloud/acme
# Skip all VMs, since we cannot talk to the ACME simulator from these:
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel
# For some reason connecting to helper containers does not work on the Alpine VMs
skip/alpine

View File

@@ -36,10 +36,10 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: no
ignore_errors: yes
allow_creation: false
ignore_errors: true
register: account_not_created
- name: Create it now (check mode, diff)
@@ -48,14 +48,14 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: yes
terms_agreed: yes
allow_creation: true
terms_agreed: true
contact:
- mailto:example@example.org
check_mode: yes
diff: yes
check_mode: true
diff: true
register: account_created_check
- name: Create it now
@@ -64,10 +64,10 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: yes
terms_agreed: yes
allow_creation: true
terms_agreed: true
contact:
- mailto:example@example.org
register: account_created
@@ -78,10 +78,10 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: yes
terms_agreed: yes
allow_creation: true
terms_agreed: true
contact:
- mailto:example@example.org
register: account_created_idempotent
@@ -97,13 +97,13 @@
account_key_content: "{{ slurp.content | b64decode }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
# allow_creation: no
# allow_creation: false
contact:
- mailto:example@example.com
check_mode: yes
diff: yes
check_mode: true
diff: true
register: account_modified_check
- name: Change email address
@@ -112,9 +112,9 @@
account_key_content: "{{ slurp.content | b64decode }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
# allow_creation: no
# allow_creation: false
contact:
- mailto:example@example.com
register: account_modified
@@ -126,9 +126,9 @@
account_uri: "{{ account_created.account_uri }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
# allow_creation: no
# allow_creation: false
contact:
- mailto:example@example.com
register: account_modified_idempotent
@@ -140,10 +140,10 @@
account_uri: "{{ account_created.account_uri ~ '12345thisdoesnotexist' }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
contact: []
ignore_errors: yes
ignore_errors: true
register: account_modified_wrong_uri
- name: Clear contact email addresses (check mode, diff)
@@ -152,12 +152,12 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
# allow_creation: no
# allow_creation: false
contact: []
check_mode: yes
diff: yes
check_mode: true
diff: true
register: account_modified_2_check
- name: Clear contact email addresses
@@ -166,9 +166,9 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
# allow_creation: no
# allow_creation: false
contact: []
register: account_modified_2
@@ -178,9 +178,9 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
# allow_creation: no
# allow_creation: false
contact: []
register: account_modified_2_idempotent
@@ -190,14 +190,14 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
new_account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
new_account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
state: changed_key
contact:
- mailto:example@example.com
check_mode: yes
diff: yes
check_mode: true
diff: true
register: account_change_key_check
- name: Change account key
@@ -206,7 +206,7 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
new_account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
new_account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
state: changed_key
@@ -221,10 +221,10 @@
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: absent
check_mode: yes
diff: yes
check_mode: true
diff: true
register: account_deactivate_check
- name: Deactivate account
@@ -234,7 +234,7 @@
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: absent
register: account_deactivate
@@ -245,7 +245,7 @@
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: absent
register: account_deactivate_idempotent
@@ -256,10 +256,10 @@
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: no
ignore_errors: yes
allow_creation: false
ignore_errors: true
register: account_not_created_2
- name: Do not try to create account III
@@ -268,10 +268,10 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: no
ignore_errors: yes
allow_creation: false
ignore_errors: true
register: account_not_created_3
- name: Create account with External Account Binding
@@ -280,10 +280,10 @@
account_key_src: "{{ remote_tmp_dir }}/{{ item.account }}.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: yes
terms_agreed: yes
allow_creation: true
terms_agreed: true
contact:
- mailto:example@example.org
external_account_binding:
@@ -291,7 +291,7 @@
alg: "{{ item.alg }}"
key: "{{ item.key }}"
register: account_created_eab
ignore_errors: yes
ignore_errors: true
loop:
- account: accountkey3
kid: kid-1

View File

@@ -6,9 +6,5 @@ azp/generic/1
azp/posix/1
cloud/acme
# Skip all VMs, since we cannot talk to the ACME simulator from these:
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel
# For some reason connecting to helper containers does not work on the Alpine VMs
skip/alpine

View File

@@ -29,7 +29,7 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
register: account_not_created
- name: Create it now
@@ -38,10 +38,10 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: yes
terms_agreed: yes
allow_creation: true
terms_agreed: true
contact:
- mailto:example@example.org
@@ -51,7 +51,7 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
register: account_created
- name: Read account key
@@ -65,9 +65,9 @@
account_key_content: "{{ slurp.content | b64decode }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
state: present
allow_creation: no
allow_creation: false
contact: []
- name: Check that account was modified
@@ -76,7 +76,7 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
account_uri: "{{ account_created.account_uri }}"
register: account_modified
@@ -86,7 +86,7 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
account_uri: "{{ account_created.account_uri }}test1234doesnotexists"
register: account_not_exist
@@ -96,7 +96,7 @@
account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
account_uri: "{{ account_created.account_uri }}"
ignore_errors: yes
ignore_errors: true
register: account_wrong_key

View File

@@ -6,9 +6,5 @@ azp/generic/1
azp/posix/1
cloud/acme
# Skip all VMs, since we cannot talk to the ACME simulator from these:
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel
# For some reason connecting to helper containers does not work on the Alpine VMs
skip/alpine

View File

@@ -31,7 +31,7 @@
select_crypto_backend: "{{ select_crypto_backend }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
state: absent
- name: Read account key (EC384)
@@ -43,11 +43,11 @@
select_crypto_backend: "{{ select_crypto_backend }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
account_key_content: "{{ slurp.content | b64decode }}"
state: present
allow_creation: yes
terms_agreed: yes
allow_creation: true
terms_agreed: true
contact:
- mailto:example@example.org
- mailto:example@example.com
@@ -56,11 +56,11 @@
select_crypto_backend: "{{ select_crypto_backend }}"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/account-rsa.pem"
state: present
allow_creation: yes
terms_agreed: yes
allow_creation: true
terms_agreed: true
contact: []
## OBTAIN CERTIFICATES ########################################################################
- name: Obtain cert 1
@@ -71,16 +71,16 @@
key_type: rsa
rsa_bits: "{{ default_rsa_key_size }}"
subject_alt_name: "DNS:example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec256
challenge: http-01
modify_account: yes
deactivate_authzs: no
force: no
modify_account: true
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
retrieve_all_alternates: yes
retrieve_all_alternates: true
acme_expected_root_number: 1
select_chain:
- test_certificates: last
@@ -98,17 +98,17 @@
certificate_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else '' }}"
key_type: ec256
subject_alt_name: "DNS:*.example.com,DNS:example.com"
subject_alt_name_critical: yes
subject_alt_name_critical: true
account_key: account-ec384
challenge: dns-01
modify_account: no
deactivate_authzs: yes
force: no
modify_account: false
deactivate_authzs: true
force: false
remaining_days: 10
terms_agreed: no
terms_agreed: false
account_email: ""
acme_expected_root_number: 0
retrieve_all_alternates: yes
retrieve_all_alternates: true
select_chain:
# All intermediates have the same subject, so always the first
# chain will be found, and we need a second condition to make sure
@@ -134,17 +134,17 @@
certificate_name: cert-3
key_type: ec384
subject_alt_name: "DNS:*.example.com,DNS:example.org,DNS:t1.example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key_content: "{{ slurp_account_key.content | b64decode }}"
challenge: dns-01
modify_account: no
deactivate_authzs: no
force: no
modify_account: false
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: no
terms_agreed: false
account_email: ""
acme_expected_root_number: 0
retrieve_all_alternates: yes
retrieve_all_alternates: true
select_chain:
- test_certificates: last
subject: "{{ acme_roots[1].subject }}"
@@ -161,14 +161,14 @@
key_type: rsa
rsa_bits: "{{ default_rsa_key_size }}"
subject_alt_name: "DNS:example.com,DNS:t1.example.com,DNS:test.t2.example.com,DNS:example.org,DNS:test.example.org"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-rsa
challenge: http-01
modify_account: no
deactivate_authzs: yes
force: yes
modify_account: false
deactivate_authzs: true
force: true
remaining_days: 10
terms_agreed: no
terms_agreed: false
account_email: ""
acme_expected_root_number: 2
select_chain:
@@ -188,14 +188,14 @@
certificate_name: cert-5
key_type: ec521
subject_alt_name: "DNS:t2.example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec384
challenge: http-01
modify_account: no
deactivate_authzs: yes
force: yes
modify_account: false
deactivate_authzs: true
force: true
remaining_days: 10
terms_agreed: no
terms_agreed: false
account_email: ""
use_csr_content: true
- name: Store obtain results for cert 5a
@@ -209,14 +209,14 @@
certificate_name: cert-5
key_type: ec521
subject_alt_name: "DNS:t2.example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec384
challenge: http-01
modify_account: no
deactivate_authzs: yes
force: no
modify_account: false
deactivate_authzs: true
force: false
remaining_days: 10
terms_agreed: no
terms_agreed: false
account_email: ""
use_csr_content: false
- name: Store obtain results for cert 5b
@@ -229,14 +229,14 @@
certificate_name: cert-5
key_type: ec521
subject_alt_name: "DNS:t2.example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec384
challenge: http-01
modify_account: no
deactivate_authzs: yes
force: yes
modify_account: false
deactivate_authzs: true
force: true
remaining_days: 1000
terms_agreed: no
terms_agreed: false
account_email: ""
use_csr_content: true
- name: Store obtain results for cert 5c
@@ -254,14 +254,14 @@
certificate_name: cert-5
key_type: ec521
subject_alt_name: "DNS:t2.example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key_content: "{{ slurp_account_key.content | b64decode }}"
challenge: http-01
modify_account: no
deactivate_authzs: yes
force: yes
modify_account: false
deactivate_authzs: true
force: true
remaining_days: 10
terms_agreed: no
terms_agreed: false
account_email: ""
use_csr_content: false
- name: Store obtain results for cert 5d
@@ -277,14 +277,14 @@
key_type: rsa
rsa_bits: "{{ default_rsa_key_size }}"
subject_alt_name: "DNS:example.org"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec256
challenge: tls-alpn-01
modify_account: yes
deactivate_authzs: no
force: no
modify_account: true
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
acme_expected_root_number: 0
select_chain:
@@ -313,14 +313,14 @@
subject_alt_name:
- "IP:127.0.0.1"
# - "IP:::1"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec256
challenge: http-01
modify_account: yes
deactivate_authzs: no
force: no
modify_account: true
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
acme_expected_root_number: 2
select_chain:
@@ -344,15 +344,15 @@
- "IP:127.0.0.1"
# IPv4 only since our test validation server doesn't work
# with IPv6 (thanks to Python's socketserver).
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec256
challenge: tls-alpn-01
challenge_alpn_tls: acme_challenge_cert_helper
modify_account: yes
deactivate_authzs: no
force: no
modify_account: true
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
use_csr_content: true
- name: Store obtain results for cert 8
@@ -364,37 +364,37 @@
# Make sure certificates are valid. Root certificate for Pebble equals the chain certificate.
- name: Verifying cert 1
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-1-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-1-chain.pem" "{{ remote_tmp_dir }}/cert-1.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_1_valid
- name: Verifying cert 2
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-2-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-2-chain.pem" "{{ remote_tmp_dir }}/cert-2.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_2_valid
- name: Verifying cert 3
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-3-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-3-chain.pem" "{{ remote_tmp_dir }}/cert-3.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_3_valid
- name: Verifying cert 4
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-4-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-4-chain.pem" "{{ remote_tmp_dir }}/cert-4.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_4_valid
- name: Verifying cert 5
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-5-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-5-chain.pem" "{{ remote_tmp_dir }}/cert-5.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_5_valid
- name: Verifying cert 6
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-6-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-6-chain.pem" "{{ remote_tmp_dir }}/cert-6.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_6_valid
when: acme_intermediates[0].subject_key_identifier is defined
- name: Verifying cert 7
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-7-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-7-chain.pem" "{{ remote_tmp_dir }}/cert-7.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_7_valid
when: acme_roots[2].subject_key_identifier is defined
- name: Verifying cert 8
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-8-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-8-chain.pem" "{{ remote_tmp_dir }}/cert-8.pem"'
ignore_errors: yes
ignore_errors: true
register: cert_8_valid
when: cryptography_version.stdout is version('1.3', '>=')
# Dump certificate info
@@ -468,7 +468,7 @@
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
retrieve_orders: ignore
register: account_orders_not
- name: Retrieve orders as URL list (1/2)
@@ -477,7 +477,7 @@
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
retrieve_orders: url_list
register: account_orders_urls
- name: Retrieve orders as URL list (2/2)
@@ -486,7 +486,7 @@
account_key_src: "{{ remote_tmp_dir }}/account-ec384.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
retrieve_orders: url_list
register: account_orders_urls2
- name: Retrieve orders as object list (1/2)
@@ -495,7 +495,7 @@
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
retrieve_orders: object_list
register: account_orders_full
- name: Retrieve orders as object list (2/2)
@@ -504,6 +504,6 @@
account_key_src: "{{ remote_tmp_dir }}/account-ec384.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
validate_certs: false
retrieve_orders: object_list
register: account_orders_full2

View File

@@ -6,9 +6,5 @@ azp/generic/1
azp/posix/1
cloud/acme
# Skip all VMs, since we cannot talk to the ACME simulator from these:
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel
# For some reason connecting to helper containers does not work on the Alpine VMs
skip/alpine

View File

@@ -38,14 +38,14 @@
key_type: rsa
rsa_bits: "{{ default_rsa_key_size }}"
subject_alt_name: "DNS:example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key_content: "{{ slurp_account_key.content | b64decode }}"
challenge: http-01
modify_account: yes
deactivate_authzs: no
force: no
modify_account: true
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
- name: Obtain cert 2
include_tasks: obtain-cert.yml
@@ -55,14 +55,14 @@
certificate_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else '' }}"
key_type: ec256
subject_alt_name: "DNS:*.example.com"
subject_alt_name_critical: yes
subject_alt_name_critical: true
account_key: account-ec384
challenge: dns-01
modify_account: yes
deactivate_authzs: yes
force: no
modify_account: true
deactivate_authzs: true
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
- name: Obtain cert 3
include_tasks: obtain-cert.yml
@@ -71,14 +71,14 @@
certificate_name: cert-3
key_type: ec384
subject_alt_name: "DNS:t1.example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-rsa
challenge: dns-01
modify_account: yes
deactivate_authzs: no
force: no
modify_account: true
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
## REVOKE CERTIFICATES ########################################################################
- name: Revoke certificate 1 via account key
@@ -88,8 +88,8 @@
certificate: "{{ remote_tmp_dir }}/cert-1.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
ignore_errors: yes
validate_certs: false
ignore_errors: true
register: cert_1_revoke
- name: Revoke certificate 2 via certificate private key
acme_certificate_revoke:
@@ -99,8 +99,8 @@
certificate: "{{ remote_tmp_dir }}/cert-2.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
ignore_errors: yes
validate_certs: false
ignore_errors: true
register: cert_2_revoke
- name: Read account key (RSA)
slurp:
@@ -113,6 +113,6 @@
certificate: "{{ remote_tmp_dir }}/cert-3-fullchain.pem"
acme_version: 2
acme_directory: https://{{ acme_host }}:14000/dir
validate_certs: no
ignore_errors: yes
validate_certs: false
ignore_errors: true
register: cert_3_revoke

View File

@@ -6,9 +6,5 @@ azp/generic/1
azp/posix/1
cloud/acme
# Skip all VMs, since we cannot talk to the ACME simulator from these:
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel
# For some reason connecting to helper containers does not work on the Alpine VMs
skip/alpine

View File

@@ -24,15 +24,15 @@
key_type: rsa
rsa_bits: "{{ default_rsa_key_size }}"
subject_alt_name: "DNS:example.com"
subject_alt_name_critical: no
subject_alt_name_critical: false
account_key: account-ec256
challenge: tls-alpn-01
challenge_alpn_tls: acme_challenge_cert_helper
modify_account: yes
deactivate_authzs: no
force: no
modify_account: true
deactivate_authzs: false
force: false
remaining_days: 10
terms_agreed: yes
terms_agreed: true
account_email: "example@example.org"
when: cryptography_version.stdout is version('1.5', '>=')

View File

@@ -6,9 +6,5 @@ azp/generic/1
azp/posix/1
cloud/acme
# Skip all VMs, since we cannot talk to the ACME simulator from these:
skip/aix
skip/freebsd
skip/macos
skip/osx
skip/rhel
# For some reason connecting to helper containers does not work on the Alpine VMs
skip/alpine

View File

@@ -26,7 +26,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
method: directory-only
register: directory
- debug: var=directory
@@ -35,7 +35,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
url: "{{ directory.directory.newAccount}}"
method: post
@@ -49,7 +49,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ account_creation.headers.location }}"
@@ -61,7 +61,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ account_creation.headers.location }}"
@@ -80,7 +80,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ directory.directory.newOrder }}"
@@ -103,7 +103,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ new_order.headers.location }}"
@@ -115,7 +115,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ item }}"
@@ -128,7 +128,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ (item.challenges | selectattr('type', 'equalto', 'http-01') | list)[0].url }}"
@@ -141,7 +141,7 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ item.url }}"
@@ -155,14 +155,14 @@
acme_inspect:
acme_directory: https://{{ acme_host }}:14000/dir
acme_version: 2
validate_certs: no
validate_certs: false
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
account_uri: "{{ account_creation.headers.location }}"
url: "{{ item.url }}"
method: get
register: validation_result
loop: "{{ http01challenge.results | map(attribute='output_json') | list }}"
until: "validation_result.output_json.status != 'pending'"
until: "validation_result.output_json.status not in ['pending', 'processing']"
retries: 20
delay: 1
- debug: var=validation_result

View File

@@ -111,7 +111,7 @@
- "'headers' in item"
- "'output_text' in item"
- "'output_json' in item"
- item.output_json.status == 'pending'
- item.output_json.status in ['pending', 'processing']
- item.output_json.type == 'http-01'
- item.output_json.url == item.invocation.module_args.url
- "'token' in item.output_json"

View File

@@ -2,5 +2,5 @@
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
azp/generic/1
azp/posix/1
azp/generic/2
azp/posix/2

View File

@@ -17,7 +17,7 @@
- '{{ remote_tmp_dir }}/a-root.pem'
- name: Case B => doesn't work, but this is expected
failed_when: no
failed_when: false
register: caseb
certificate_complete_chain:
input_chain: "{{ read_certificates['d-leaf'] }}"

View File

@@ -3,6 +3,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
context/controller
azp/generic/1
azp/posix/1
azp/generic/2
azp/posix/2
destructive

View File

@@ -0,0 +1,7 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
azp/generic/2
azp/posix/2
destructive

View File

@@ -0,0 +1,9 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
dependencies:
- setup_openssl
- setup_remote_tmp_dir
- prepare_jinja2_compat

View File

@@ -0,0 +1,144 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: "Get CSR info"
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/csr_1.csr') | community.crypto.openssl_csr_info }}
result_idna: >-
{{ lookup('file', remote_tmp_dir ~ '/csr_1.csr') | community.crypto.openssl_csr_info(name_encoding='idna') }}
result_unicode: >-
{{ lookup('file', remote_tmp_dir ~ '/csr_1.csr') | community.crypto.openssl_csr_info(name_encoding='unicode') }}
- name: "Check whether subject and extensions behaves as expected"
assert:
that:
- result.subject.organizationalUnitName == 'ACME Department'
- "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
- "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
- result.public_key_type == 'RSA'
- result.public_key_data.size == default_rsa_key_size
# TLS Feature
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].critical == false
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].value == 'MAMCAQU='
# Key Usage
- 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 == 'MHmCD3d3dy5hbnNpYmxlLmNvbYIXeG4tLXNiLW9pYTBhN2E1M2J5YS5jb22HBAECAwSHEAAAAAAAAAAAAAAAAAAAAAGBEHRlc3RAZXhhbXBsZS5vcmeGI2h0dHBzOi8vZXhhbXBsZS5vcmcvdGVzdC9pbmRleC5odG1s'
# Basic Constraints
- result.extensions_by_oid['2.5.29.19'].critical == true
- result.extensions_by_oid['2.5.29.19'].value == 'MAYBAf8CARc='
# Extended Key Usage
- result.extensions_by_oid['2.5.29.37'].critical == false
- result.extensions_by_oid['2.5.29.37'].value == 'MHQGCCsGAQUFBwMBBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgGCCsGAQUFBwMJBgRVHSUABggrBgEFBQcBAwYIKwYBBQUHAwoGCCsGAQUFBwMHBggrBgEFBQcBAg=='
- name: "Check SubjectKeyIdentifier and AuthorityKeyIdentifier"
assert:
that:
- result.subject_key_identifier == "00:11:22:33"
- result.authority_key_identifier == "44:55:66:77"
- result.authority_cert_issuer == expected_authority_cert_issuer
- result.authority_cert_serial_number == 12345
# Subject Key Identifier
- result.extensions_by_oid['2.5.29.14'].critical == false
# Authority Key Identifier
- result.extensions_by_oid['2.5.29.35'].critical == false
vars:
expected_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
when: cryptography_version.stdout is version('1.3', '>=')
- name: "Get CSR info"
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/csr_2.csr') | community.crypto.openssl_csr_info }}
- name: "Get CSR info"
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/csr_3.csr') | community.crypto.openssl_csr_info }}
- name: "Check AuthorityKeyIdentifier"
assert:
that:
- result.authority_key_identifier is none
- result.authority_cert_issuer == expected_authority_cert_issuer
- result.authority_cert_serial_number == 12345
vars:
expected_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
when: cryptography_version.stdout is version('1.3', '>=')
- name: "Get CSR info"
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/csr_4.csr') | community.crypto.openssl_csr_info }}
- name: "Check AuthorityKeyIdentifier"
assert:
that:
- result.authority_key_identifier == "44:55:66:77"
- result.authority_cert_issuer is none
- result.authority_cert_serial_number is none
when: cryptography_version.stdout is version('1.3', '>=')
- name: Get invalid certificate info
set_fact:
result: >-
{{ [] | community.crypto.openssl_csr_info }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^The community.crypto.openssl_csr_info input must be a text type, not <(?:class|type) 'list'>$")
- name: Get invalid certificate info
set_fact:
result: >-
{{ 'foo' | community.crypto.openssl_csr_info }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^Unable to load (?:request|PEM file)(?:\.|$)")
- name: Get invalid certificate info
set_fact:
result: >-
{{ 'foo' | community.crypto.openssl_csr_info(name_encoding=[]) }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^The name_encoding option must be of a text type, not <(?:class|type) 'list'>$")
- name: Get invalid name_encoding parameter
set_fact:
result: >-
{{ 'bar' | community.crypto.openssl_csr_info(name_encoding='foo') }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^The name_encoding option must be one of the values \"ignore\", \"idna\", or \"unicode\", not \"foo\"$")

View File

@@ -0,0 +1,133 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# 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'
size: '{{ default_rsa_key_size }}'
- name: Generate privatekey with password
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
passphrase: hunter2
cipher: auto
size: '{{ default_rsa_key_size }}'
- name: Generate CSR 1
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_1.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
subject:
commonName: www.example.com
C: de
L: Somewhere
ST: Zurich
streetAddress: Welcome Street
O: Ansible
organizationalUnitName:
- Crypto Department
- ACME Department
serialNumber: "1234"
SN: Last Name
GN: First Name
title: Chief
pseudonym: test
UID: asdf
emailAddress: test@example.com
postalAddress: 1234 Somewhere
postalCode: "1234"
useCommonNameForSAN: false
key_usage:
- digitalSignature
- keyAgreement
- Non Repudiation
- Key Encipherment
- dataEncipherment
- Certificate Sign
- cRLSign
- Encipher Only
- decipherOnly
key_usage_critical: true
extended_key_usage:
- serverAuth # the same as "TLS Web Server Authentication"
- TLS Web Server Authentication
- TLS Web Client Authentication
- Code Signing
- E-mail Protection
- timeStamping
- OCSPSigning
- Any Extended Key Usage
- qcStatements
- DVCS
- IPSec User
- biometricInfo
subject_alt_name:
- "DNS:www.ansible.com"
- "DNS:âņsïbłè.com"
- "IP:1.2.3.4"
- "IP:::1"
- "email:test@example.org"
- "URI:https://example.org/test/index.html"
basic_constraints:
- "CA:TRUE"
- "pathlen:23"
basic_constraints_critical: true
ocsp_must_staple: true
subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
vars:
value_for_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
- name: Generate CSR 2
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_2.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
privatekey_passphrase: hunter2
useCommonNameForSAN: false
basic_constraints:
- "CA:TRUE"
- name: Generate CSR 3
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_3.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
useCommonNameForSAN: false
subject_alt_name:
- "DNS:*.ansible.com"
- "DNS:*.example.org"
- "IP:DEAD:BEEF::1"
basic_constraints:
- "CA:FALSE"
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
vars:
value_for_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
- name: Generate CSR 4
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_4.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
useCommonNameForSAN: false
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
- name: Running tests
include_tasks: impl.yml
when: cryptography_version.stdout is version('1.3', '>=')

View File

@@ -0,0 +1,7 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
azp/generic/2
azp/posix/2
destructive

View File

@@ -0,0 +1,9 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
dependencies:
- setup_openssl
- setup_remote_tmp_dir
- prepare_jinja2_compat

View File

@@ -0,0 +1,113 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Get key 1 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/privatekey_1.pem') | community.crypto.openssl_privatekey_info }}
- name: Check that RSA key info is ok
assert:
that:
- "'public_key' in result"
- "'public_key_fingerprints' in result"
- "'type' in result"
- "result.type == 'RSA'"
- "'public_data' in result"
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
- "result.public_data.exponent > 5"
- "'private_data' not in result"
- name: Get key 2 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/privatekey_2.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
- name: Check that RSA key info is ok
assert:
that:
- "'public_key' in result"
- "'public_key_fingerprints' in result"
- "'type' in result"
- "result.type == 'RSA'"
- "'public_data' in result"
- "result.public_data.size == default_rsa_key_size"
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
- "result.public_data.exponent > 5"
- "'private_data' in result"
- "result.public_data.modulus == result.private_data.p * result.private_data.q"
- "result.private_data.exponent > 5"
- name: Get key 3 info (without passphrase)
set_fact:
result_: >-
{{ lookup('file', remote_tmp_dir ~ '/privatekey_3.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
ignore_errors: true
register: result
- name: Check that loading passphrase protected key without passphrase failed
assert:
that:
- result is failed
- result.msg == 'Wrong or empty passphrase provided for private key'
- name: Get key 3 info (with passphrase)
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/privatekey_3.pem') | community.crypto.openssl_privatekey_info(passphrase='hunter2', return_private_key_data=true) }}
- name: Check that RSA key info is ok
assert:
that:
- "'public_key' in result"
- "'public_key_fingerprints' in result"
- "'type' in result"
- "result.type == 'RSA'"
- "'public_data' in result"
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
- "result.public_data.exponent > 5"
- "'private_data' in result"
- "result.public_data.modulus == result.private_data.p * result.private_data.q"
- "result.private_data.exponent > 5"
- name: Get key 4 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/privatekey_4.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
- name: Check that ECC key info is ok
assert:
that:
- "'public_key' in result"
- "'public_key_fingerprints' in result"
- "'type' in result"
- "result.type == 'ECC'"
- "'public_data' in result"
- "result.public_data.curve is string"
- "result.public_data.x != 0"
- "result.public_data.y != 0"
- "result.public_data.exponent_size == (521 if (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') else 256)"
- "'private_data' in result"
- "result.private_data.multiplier > 1024"
- name: Get key 5 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/privatekey_5.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
- name: Check that DSA key info is ok
assert:
that:
- "'public_key' in result"
- "'public_key_fingerprints' in result"
- "'type' in result"
- "result.type == 'DSA'"
- "'public_data' in result"
- "result.public_data.p > 2"
- "result.public_data.q > 2"
- "result.public_data.g >= 2"
- "result.public_data.y > 2"
- "'private_data' in result"
- "result.private_data.x > 2"

View File

@@ -0,0 +1,43 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: Generate privatekey 1
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_1.pem'
- name: Generate privatekey 2 (less bits)
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_2.pem'
type: RSA
size: '{{ default_rsa_key_size }}'
- name: Generate privatekey 3 (with password)
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_3.pem'
passphrase: hunter2
cipher: auto
size: '{{ default_rsa_key_size }}'
- name: Generate privatekey 4 (ECC)
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_4.pem'
type: ECC
curve: "{{ (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') | ternary('secp521r1', 'secp256k1') }}"
# ^ cryptography on CentOS6 doesn't support secp256k1, so we use secp521r1 instead
- name: Generate privatekey 5 (DSA)
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_5.pem'
type: DSA
size: 1024
- name: Running tests
include_tasks: impl.yml
when: cryptography_version.stdout is version('1.2.3', '>=')

View File

@@ -0,0 +1,7 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
azp/generic/2
azp/posix/2
destructive

View File

@@ -0,0 +1,9 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
dependencies:
- setup_openssl
- setup_remote_tmp_dir
- prepare_jinja2_compat

View File

@@ -0,0 +1,95 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Get key 1 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/publickey_1.pem') | community.crypto.openssl_publickey_info }}
- name: Check that RSA key info is ok
assert:
that:
- "'fingerprints' in result"
- "'type' in result"
- "result.type == 'RSA'"
- "'public_data' in result"
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
- "result.public_data.exponent > 5"
- name: Get key 2 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/publickey_2.pem') | community.crypto.openssl_publickey_info }}
- name: Check that RSA key info is ok
assert:
that:
- "'fingerprints' in result"
- "'type' in result"
- "result.type == 'RSA'"
- "'public_data' in result"
- "result.public_data.size == default_rsa_key_size"
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
- "result.public_data.exponent > 5"
- name: Get key 3 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/publickey_3.pem') | community.crypto.openssl_publickey_info }}
- name: Check that ECC key info is ok
assert:
that:
- "'fingerprints' in result"
- "'type' in result"
- "result.type == 'ECC'"
- "'public_data' in result"
- "result.public_data.curve is string"
- "result.public_data.x != 0"
- "result.public_data.y != 0"
- "result.public_data.exponent_size == (521 if (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') else 256)"
- name: Get key 4 info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/publickey_4.pem') | community.crypto.openssl_publickey_info }}
- name: Check that DSA key info is ok
assert:
that:
- "'fingerprints' in result"
- "'type' in result"
- "result.type == 'DSA'"
- "'public_data' in result"
- "result.public_data.p > 2"
- "result.public_data.q > 2"
- "result.public_data.g >= 2"
- "result.public_data.y > 2"
- name: Get invalid key info
set_fact:
result: >-
{{ [] | community.crypto.openssl_publickey_info }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^The community.crypto.openssl_publickey_info input must be a text type, not <(?:class|type) 'list'>$")
- name: Get invalid key info
set_fact:
result: >-
{{ 'foo' | community.crypto.openssl_publickey_info }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- 'output.msg is search("^Error while deserializing key: ")'

View File

@@ -0,0 +1,47 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: Generate privatekey 1
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_1.pem'
- name: Generate privatekey 2 (less bits)
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_2.pem'
type: RSA
size: '{{ default_rsa_key_size }}'
- name: Generate privatekey 3 (ECC)
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_3.pem'
type: ECC
curve: "{{ (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') | ternary('secp521r1', 'secp256k1') }}"
# ^ cryptography on CentOS6 doesn't support secp256k1, so we use secp521r1 instead
select_crypto_backend: cryptography
- name: Generate privatekey 4 (DSA)
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekey_4.pem'
type: DSA
size: 1024
- name: Generate public keys
openssl_publickey:
privatekey_path: '{{ remote_tmp_dir }}/privatekey_{{ item }}.pem'
path: '{{ remote_tmp_dir }}/publickey_{{ item }}.pem'
loop:
- 1
- 2
- 3
- 4
- name: Running tests
include_tasks: impl.yml
when: cryptography_version.stdout is version('1.2.3', '>=')

View File

@@ -0,0 +1,6 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
azp/generic/2
azp/posix/2

View File

@@ -0,0 +1,64 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: Run tests that raise no errors
assert:
that:
- >-
'' | community.crypto.split_pem == []
- >-
(pem_1 + pem_2 + pem_3) | community.crypto.split_pem == [pem_1, pem_2, pem_3]
- >-
(pem_3 + pem_2 + pem_1) | community.crypto.split_pem == [pem_3, pem_2, pem_1]
- >-
(crap_1 + pem_3 + crap_2 + pem_2 + crap_3 + pem_1 + crap_2) | community.crypto.split_pem == [pem_3, pem_2, pem_1]
- >-
(crap_1 + pem_1 + crap_2 + pem_1 + crap_3 + crap_4 + crap_4) | community.crypto.split_pem == [pem_1, pem_1]
vars:
pem_1: |
-----BEGIN CERTIFICATE-----
AAb=
-----END CERTIFICATE-----
pem_2: |
-----BEGIN PRIVATE KEY-----
Foo
Bar
Baz
Bam
-----END PRIVATE KEY-----
pem_3: |
-----BEGIN
foo
-----END
crap_1: |
# Comment
crap_2: |
Random text
In multiple
Lines
crap_3: |
----BEGIN CERTIFICATE----
Certificate with too few dashes
----END CERTIFICATE----
crap_4: |
-----BEGIN CERTIFICATE-----
AAb=
- name: Invalid input
debug:
msg: "{{ [] | community.crypto.split_pem }}"
ignore_errors: true
register: output
- name: Validate error
assert:
that:
- output is failed
- output.msg is search("^The community.crypto.split_pem input must be a text type, not <(?:class|type) 'list'>$")

View File

@@ -0,0 +1,8 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
azp/generic/2
azp/posix/2
needs/target/x509_certificate_info
destructive

View File

@@ -0,0 +1,9 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
dependencies:
- setup_openssl
- setup_remote_tmp_dir
- prepare_jinja2_compat

View File

@@ -0,0 +1,221 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Get certificate info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/cert_1.pem') | community.crypto.x509_certificate_info }}
result_idna: >-
{{ lookup('file', remote_tmp_dir ~ '/cert_1.pem') | community.crypto.x509_certificate_info(name_encoding='idna') }}
result_unicode: >-
{{ lookup('file', remote_tmp_dir ~ '/cert_1.pem') | community.crypto.x509_certificate_info(name_encoding='unicode') }}
- name: Check whether issuer and subject and extensions behave as expected
assert:
that:
- result.issuer.organizationalUnitName == 'ACME Department'
- "['organizationalUnitName', 'Crypto Department'] in result.issuer_ordered"
- "['organizationalUnitName', 'ACME Department'] in result.issuer_ordered"
- result.subject.organizationalUnitName == 'ACME Department'
- "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
- "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
- result.public_key_type == 'RSA'
- result.public_key_data.size == (default_rsa_key_size_certifiates | int)
- "result.subject_alt_name == [
'DNS:www.ansible.com',
'DNS:' ~ ('öç' if cryptography_version.stdout is version('2.1', '<') else 'xn--7ca3a') ~ '.com',
'DNS:' ~ ('www.öç' if cryptography_version.stdout is version('2.1', '<') else 'xn--74h') ~ '.com',
'IP:1.2.3.4',
'IP:::1',
'email:test@example.org',
'URI:https://example.org/test/index.html'
]"
- "result_idna.subject_alt_name == [
'DNS:www.ansible.com',
'DNS:xn--7ca3a.com',
'DNS:' ~ ('www.xn--7ca3a' if cryptography_version.stdout is version('2.1', '<') else 'xn--74h') ~ '.com',
'IP:1.2.3.4',
'IP:::1',
'email:test@example.org',
'URI:https://example.org/test/index.html'
]"
- "result_unicode.subject_alt_name == [
'DNS:www.ansible.com',
'DNS:öç.com',
'DNS:' ~ ('www.öç' if cryptography_version.stdout is version('2.1', '<') else '☺') ~ '.com',
'IP:1.2.3.4',
'IP:::1',
'email:test@example.org',
'URI:https://example.org/test/index.html'
]"
# TLS Feature
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].critical == false
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].value == 'MAMCAQU='
# Key Usage
- 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.extensions_by_oid['2.5.29.17'].critical == false
- >
result.extensions_by_oid['2.5.29.17'].value == (
'MIGCgg93d3cuYW5zaWJsZS5jb22CDXhuLS03Y2EzYS5jb22CEXd3dy54bi0tN2NhM2EuY29thwQBAgMEhxAAAAAAAAAAAAAAAAAAAAABgRB0ZXN0QGV4YW1wbGUub3JnhiNodHRwczovL2V4YW1wbGUub3JnL3Rlc3QvaW5kZXguaHRtbA=='
if cryptography_version.stdout is version('2.1', '<') else
'MHyCD3d3dy5hbnNpYmxlLmNvbYINeG4tLTdjYTNhLmNvbYILeG4tLTc0aC5jb22HBAECAwSHEAAAAAAAAAAAAAAAAAAAAAGBEHRlc3RAZXhhbXBsZS5vcmeGI2h0dHBzOi8vZXhhbXBsZS5vcmcvdGVzdC9pbmRleC5odG1s'
)
# Basic Constraints
- result.extensions_by_oid['2.5.29.19'].critical == true
- result.extensions_by_oid['2.5.29.19'].value == 'MAYBAf8CARc='
# Extended Key Usage
- result.extensions_by_oid['2.5.29.37'].critical == false
- result.extensions_by_oid['2.5.29.37'].value == 'MHQGCCsGAQUFBwMBBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgGCCsGAQUFBwMJBgRVHSUABggrBgEFBQcBAwYIKwYBBQUHAwoGCCsGAQUFBwMHBggrBgEFBQcBAg=='
- name: Check SubjectKeyIdentifier and AuthorityKeyIdentifier
assert:
that:
- result.subject_key_identifier == "00:11:22:33"
- result.authority_key_identifier == "44:55:66:77"
- result.authority_cert_issuer == expected_authority_cert_issuer
- result.authority_cert_serial_number == 12345
# Subject Key Identifier
- result.extensions_by_oid['2.5.29.14'].critical == false
# Authority Key Identifier
- result.extensions_by_oid['2.5.29.35'].critical == false
vars:
expected_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
when: cryptography_version.stdout is version('1.3', '>=')
- name: Get certificate info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/cert_2.pem') | community.crypto.x509_certificate_info }}
- name: Get certificate info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/cert_3.pem') | community.crypto.x509_certificate_info }}
- name: Check AuthorityKeyIdentifier
assert:
that:
- result.authority_key_identifier is none
- result.authority_cert_issuer == expected_authority_cert_issuer
- result.authority_cert_serial_number == 12345
vars:
expected_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
when: cryptography_version.stdout is version('1.3', '>=')
- name: Get certificate info
set_fact:
result: >-
{{ lookup('file', remote_tmp_dir ~ '/cert_4.pem') | community.crypto.x509_certificate_info }}
- name: Check AuthorityKeyIdentifier
assert:
that:
- result.authority_key_identifier == "44:55:66:77"
- result.authority_cert_issuer is none
- result.authority_cert_serial_number is none
when: cryptography_version.stdout is version('1.3', '>=')
- name: Get certificate info for packaged cert 1
set_fact:
result: >-
{{ lookup('file', role_path ~ '/../x509_certificate_info/files/cert1.pem') | community.crypto.x509_certificate_info }}
- name: Check extensions
assert:
that:
- "'ocsp_uri' in result"
- "result.ocsp_uri == 'http://ocsp.int-x3.letsencrypt.org'"
- "'issuer_uri' in result"
- "result.issuer_uri == 'http://cert.int-x3.letsencrypt.org/'"
- result.extensions_by_oid | length == 9
# Precert Signed Certificate Timestamps
- result.extensions_by_oid['1.3.6.1.4.1.11129.2.4.2'].critical == false
- result.extensions_by_oid['1.3.6.1.4.1.11129.2.4.2'].value == 'BIHyAPAAdgDBFkrgp3LS1DktyArBB3DU8MSb3pkaSEDB+gdRZPYzYAAAAWTdAoU6AAAEAwBHMEUCIG5WpfKF536KKa9fnVlYbwcfrKh09Hi2MSRwU2kad49UAiEA4RUKjJOgw11IHFNdit+sy1RcCU3QCSOEQYrJ1/oPltAAdgApPFGWVMg5ZbqqUPxYB9S3b79Yeily3KTDDPTlRUf0eAAAAWTdAoc+AAAEAwBHMEUCIQCJjo75K4rVDSiWQe3XFLY6MiG3zcHQrKb0YhM17r1UKAIgGa8qMoN03DLp+Rm9nRJ9XLbTJz1vbuu9PyXUY741P8E='
# Authority Information Access
- result.extensions_by_oid['1.3.6.1.5.5.7.1.1'].critical == false
- result.extensions_by_oid['1.3.6.1.5.5.7.1.1'].value == 'MGEwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcv'
# Subject Key Identifier
- result.extensions_by_oid['2.5.29.14'].critical == false
- result.extensions_by_oid['2.5.29.14'].value == 'BBRtcOI/yg62Ehbu5vQzxMUUdBOYMw=='
# Key Usage (The certificate has 'AwIFoA==', while de-serializing and re-serializing yields 'AwIAoA=='!)
- result.extensions_by_oid['2.5.29.15'].critical == true
- result.extensions_by_oid['2.5.29.15'].value in ['AwIFoA==', 'AwIAoA==']
# Subject Alternative Names
- result.extensions_by_oid['2.5.29.17'].critical == false
- result.extensions_by_oid['2.5.29.17'].value == 'MIIB5IIbY2VydC5pbnQteDEubGV0c2VuY3J5cHQub3JnghtjZXJ0LmludC14Mi5sZXRzZW5jcnlwdC5vcmeCG2NlcnQuaW50LXgzLmxldHNlbmNyeXB0Lm9yZ4IbY2VydC5pbnQteDQubGV0c2VuY3J5cHQub3JnghxjZXJ0LnJvb3QteDEubGV0c2VuY3J5cHQub3Jngh9jZXJ0LnN0YWdpbmcteDEubGV0c2VuY3J5cHQub3Jngh9jZXJ0LnN0Zy1pbnQteDEubGV0c2VuY3J5cHQub3JngiBjZXJ0LnN0Zy1yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ISY3AubGV0c2VuY3J5cHQub3JnghpjcC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ITY3BzLmxldHNlbmNyeXB0Lm9yZ4IbY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3Jnghtjcmwucm9vdC14MS5sZXRzZW5jcnlwdC5vcmeCD2xldHNlbmNyeXB0Lm9yZ4IWb3JpZ2luLmxldHNlbmNyeXB0Lm9yZ4IXb3JpZ2luMi5sZXRzZW5jcnlwdC5vcmeCFnN0YXR1cy5sZXRzZW5jcnlwdC5vcmeCE3d3dy5sZXRzZW5jcnlwdC5vcmc='
# Basic Constraints
- result.extensions_by_oid['2.5.29.19'].critical == true
- result.extensions_by_oid['2.5.29.19'].value == 'MAA='
# Certificate Policies
- result.extensions_by_oid['2.5.29.32'].critical == false
- result.extensions_by_oid['2.5.29.32'].value == 'MIHzMAgGBmeBDAECATCB5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5kIGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkv'
# Authority Key Identifier
- result.extensions_by_oid['2.5.29.35'].critical == false
- result.extensions_by_oid['2.5.29.35'].value == 'MBaAFKhKamMEfd265tE5t6ZFZe/zqOyh'
# Extended Key Usage
- result.extensions_by_oid['2.5.29.37'].critical == false
- result.extensions_by_oid['2.5.29.37'].value == 'MBQGCCsGAQUFBwMBBggrBgEFBQcDAg=='
- name: Check fingerprints
assert:
that:
- (result.fingerprints.sha256 == '57:7c:f1:f5:dd:cc:6e:e9:f3:17:28:73:17:e4:25:c7:69:74:3e:f7:9a:df:58:20:7a:5a:e4:aa:de:bf:24:5b' if result.fingerprints.sha256 is defined else true)
- (result.fingerprints.sha1 == 'b7:79:64:f4:2b:e0:ae:45:74:d4:f3:08:f6:53:cb:39:26:fa:52:6b' if result.fingerprints.sha1 is defined else true)
- name: Get invalid certificate info
set_fact:
result: >-
{{ [] | community.crypto.x509_certificate_info }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^The community.crypto.x509_certificate_info input must be a text type, not <(?:class|type) 'list'>$")
- name: Get invalid certificate info
set_fact:
result: >-
{{ 'foo' | community.crypto.x509_certificate_info }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^Unable to load (?:certificate|PEM file)(?:\.|$)")
- name: Get invalid certificate info
set_fact:
result: >-
{{ 'foo' | community.crypto.x509_certificate_info(name_encoding=[]) }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^The name_encoding option must be of a text type, not <(?:class|type) 'list'>$")
- name: Get invalid name_encoding parameter
set_fact:
result: >-
{{ 'bar' | community.crypto.x509_certificate_info(name_encoding='foo') }}
ignore_errors: true
register: output
- name: Check that task failed and error message is OK
assert:
that:
- output is failed
- output.msg is search("^The name_encoding option must be one of the values \"ignore\", \"idna\", or \"unicode\", not \"foo\"$")

View File

@@ -0,0 +1,151 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# 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'
size: '{{ default_rsa_key_size_certifiates }}'
- name: Generate privatekey with password
openssl_privatekey:
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
passphrase: hunter2
cipher: auto
select_crypto_backend: cryptography
size: '{{ default_rsa_key_size_certifiates }}'
- name: Generate CSR 1
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_1.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
subject:
commonName: www.example.com
C: de
L: Somewhere
ST: Zurich
streetAddress: Welcome Street
O: Ansible
organizationalUnitName:
- Crypto Department
- ACME Department
serialNumber: "1234"
SN: Last Name
GN: First Name
title: Chief
pseudonym: test
UID: asdf
emailAddress: test@example.com
postalAddress: 1234 Somewhere
postalCode: "1234"
useCommonNameForSAN: false
key_usage:
- digitalSignature
- keyAgreement
- Non Repudiation
- Key Encipherment
- dataEncipherment
- Certificate Sign
- cRLSign
- Encipher Only
- decipherOnly
key_usage_critical: true
extended_key_usage:
- serverAuth # the same as "TLS Web Server Authentication"
- TLS Web Server Authentication
- TLS Web Client Authentication
- Code Signing
- E-mail Protection
- timeStamping
- OCSPSigning
- Any Extended Key Usage
- qcStatements
- DVCS
- IPSec User
- biometricInfo
subject_alt_name:
- "DNS:www.ansible.com"
- "DNS:öç.com"
# cryptography < 2.1 cannot handle certain Unicode characters
- "DNS:{{ 'www.öç' if cryptography_version.stdout is version('2.1', '<') else '☺' }}.com"
- "IP:1.2.3.4"
- "IP:::1"
- "email:test@example.org"
- "URI:https://example.org/test/index.html"
basic_constraints:
- "CA:TRUE"
- "pathlen:23"
basic_constraints_critical: true
ocsp_must_staple: true
subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
vars:
value_for_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
- name: Generate CSR 2
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_2.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
privatekey_passphrase: hunter2
useCommonNameForSAN: false
basic_constraints:
- "CA:TRUE"
- name: Generate CSR 3
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_3.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
useCommonNameForSAN: false
subject_alt_name:
- "DNS:*.ansible.com"
- "DNS:*.example.org"
- "IP:DEAD:BEEF::1"
basic_constraints:
- "CA:FALSE"
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
vars:
value_for_authority_cert_issuer:
- "DNS:ca.example.org"
- "IP:1.2.3.4"
- name: Generate CSR 4
openssl_csr:
path: '{{ remote_tmp_dir }}/csr_4.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
useCommonNameForSAN: false
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
- name: Generate selfsigned certificates
x509_certificate:
path: '{{ remote_tmp_dir }}/cert_{{ item }}.pem'
csr_path: '{{ remote_tmp_dir }}/csr_{{ item }}.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
provider: selfsigned
selfsigned_digest: sha256
selfsigned_not_after: "+10d"
selfsigned_not_before: "-3d"
loop:
- 1
- 2
- 3
- 4
- name: Running tests
include_tasks: impl.yml
when: cryptography_version.stdout is version('1.6', '>=')

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