Compare commits

...

59 Commits

Author SHA1 Message Date
Felix Fontein
c57822b3b3 Release 1.9.19. 2022-11-01 20:53:52 +01:00
patchback[bot]
c313bbd83d Action plugin support code: ensure compatibility with newer versions of ansible-core (#515) (#516)
* Only access C.STRING_CONVERSION_ACTION for old ansible-base / Ansible versions.

* Always use self.__xxx instead of xxx directly.

(cherry picked from commit b3f589df62)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-09-23 07:33:48 +02:00
patchback[bot]
b9e8bb70eb Fix docs (#497) (#498)
* Fix docs.

* Fix YAML.

* Prevent crashes with older pyyaml versions.

(cherry picked from commit 2dafef1fab)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-08-04 20:17:55 +02:00
patchback[bot]
62da550c6c Fix ssh-agent tests (#493) (#494)
* Work around stupid ssh-agent output format.

* Workaround for Ansible 2.9.

* Old jinja2...

* Jinja2 on CentOS 6 is really annoying.

(cherry picked from commit e4ebca0945)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-07-22 14:00:53 +02:00
Felix Fontein
3d9fb17d17 Fix typo. 2022-07-09 13:54:52 +02:00
Felix Fontein
2fd7aa6de7 Prepare 1.9.19. 2022-07-09 13:51:12 +02:00
Felix Fontein
b78dd8d542 Release 1.9.18. 2022-07-09 13:17:40 +02:00
Felix Fontein
1df51621fa openssl_pkcs12: fix crash when trying to get non-existing other certificates (#487) (#488)
* Fix crash when trying to get non-existing other certificates.

* Add test.

(cherry picked from commit 9ed4526fee)
2022-07-07 22:53:36 +02:00
Felix Fontein
33703d15e2 Prepare 1.9.18 release. 2022-06-17 09:26:09 +02:00
Felix Fontein
b682c7a281 Release 1.9.17. 2022-06-17 08:23:20 +02:00
Felix Fontein
d393ea233e Add Apache 2.0 license for Apache 2.0 licensed parts. (#479) 2022-06-17 08:21:08 +02:00
patchback[bot]
563e3a2791 Fix ValueError: excluded_subtrees must be a non-empty list or None (#481) (#482)
(cherry picked from commit b29f238083)

Co-authored-by: Songmin Li <lisongmin@protonmail.com>
2022-06-17 08:02:49 +02:00
Felix Fontein
651f2b8f5d x509_crl: do not crash when signing with Ed25519 or Ed448 (#475) (#480)
* Do not crash when signing with Ed25519 or Ed448.

* Forgot replace.

(cherry picked from commit 297b44f24b)
2022-06-15 22:29:34 +02:00
patchback[bot]
077bcba377 Skip Ansible 2.9 coverage reporting with new AZP container. (#476) (#477)
ci_coverage

(cherry picked from commit 429ed5faa5)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-06-14 20:32:32 +00:00
patchback[bot]
9084df1e5c Bump AZP container version. (#472) (#474)
(cherry picked from commit b3029f75cd)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-06-13 21:58:14 +02:00
patchback[bot]
2bb6d7f49d Disable broken CI platforms. (#469) (#470)
(cherry picked from commit f7bc3aa77c)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-06-06 09:36:44 +02:00
Felix Fontein
83cf13a483 Next expected release is 1.9.17. 2022-06-02 12:46:50 +02:00
Felix Fontein
1b22a88b80 Release 1.9.16. 2022-06-02 12:27:44 +02:00
patchback[bot]
252c1a7236 Add simplified_bsd.txt license file (#467) (#468)
* Add simplified_bsd.txt and adjust references.

* Add changelog.

(cherry picked from commit ccd66419f4)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-06-02 08:14:26 +02:00
Felix Fontein
7f371f6915 Update release summary for 1.9.16. 2022-06-02 07:48:31 +02:00
patchback[bot]
1ccd48efba Remove FreeBSD 12.1 from CI. The remote seems to be no longer working. (#459) (#461)
(cherry picked from commit fd0048827d)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-05-20 15:33:08 +00:00
patchback[bot]
a4c077c388 certificate_complete_chain: do not stop execution on unsupported algorithm (#457) (#458)
* Do not stop execution on unsupported algorithm.

* Fix typo.

(cherry picked from commit c49102d688)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-05-20 12:47:59 +02:00
Felix Fontein
2b1e85c86c Next expected release is 1.9.16. 2022-05-16 12:52:21 +02:00
Felix Fontein
a68f119afe Release 1.9.15. 2022-05-16 12:26:27 +02:00
Felix Fontein
9ebf7d668f [stable-1] Add PSF-license.txt file (#455)
* Add PSF-license.txt file. (#453)

(cherry picked from commit 5664bfe4b6)

* Update with actual CPython 3.9.5 license. (#454)

(cherry picked from commit 7183596586)
2022-05-16 09:02:58 +02:00
Felix Fontein
4570c481ef Prepare 1.9.15 release. 2022-05-16 07:14:00 +02:00
Felix Fontein
5d56629d10 Prepare 1.9.15 release. 2022-05-09 20:52:41 +02:00
Felix Fontein
37c7100c8b Release 1.9.14. 2022-05-09 20:29:24 +02:00
Felix Fontein
35266bda0e Prepare 1.9.14 release. 2022-05-03 19:25:24 +02:00
Felix Fontein
6a90a43995 Fix stable-1 for new cryptography 37.0.0 release (#446)
* Fix empty check for openssl_pkcs12 tests.

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

* Add changelog fragment.

* Fix constraints file.

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

* Prevent upgrading cryptography on ansible-core 2.12's default container with Python 3.9.
2022-04-26 22:33:13 +02:00
Felix Fontein
096262b6f1 Fix crash in x509_crl when certificate issuer is specified (#441) (#442)
* Fix x509_crl certificate issuer issue.

* Add tests.

* Add changelog fragment.

(cherry picked from commit 9d03178b00)
2022-04-18 10:19:27 +02:00
patchback[bot]
03df636e5e Switch from antsibull to antsibull-docs. (#438) (#439)
(cherry picked from commit c7f581daad)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-04-10 10:58:54 +02:00
Felix Fontein
02bc9de560 On the 'default' image with Python 3.8, cryptography 2.8 is installed from the
system packages, but cryptography 36.0.1 is already present and shadows the
one from the system packages. Since PyOpenSSL is also installed from the system
packages, there is a version mismatch between the two. Temporarily disable the
Python 3.8 tests with the 'default' image on ansible-core 2.13 until this is
resolved, or the stable-1 branch is EOL (whatever comes first).
2022-04-03 15:08:55 +02:00
patchback[bot]
8fe0a2450e Replace antsibull-lint collection-docs with antsibull-docs lint-collection-docs. (#432) (#433)
(cherry picked from commit bc00c30faf)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-03-30 08:13:40 +02:00
Felix Fontein
d8bb99d547 Replace devel with stable-2.13 in stable-1 CI. (#424) 2022-03-29 06:19:54 +02:00
patchback[bot]
79f9ce437a openssh_* - catch and report top-level exceptions via fail_json (#417) (#418)
* ensure exceptions are properly reported

* adding changelog fragment

* applying review suggestions

* typo

* adding back exception msg

(cherry picked from commit 033bab7db1)

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>
2022-03-08 20:25:38 +01:00
Felix Fontein
6cb02818ef Next expected release is 1.9.14. 2022-03-04 08:06:24 +01:00
Felix Fontein
e94fb2dff2 Release 1.9.13. 2022-03-04 07:38:05 +01:00
Felix Fontein
14c39b1f99 Prepare 1.9.13 release. 2022-03-03 21:17:36 +01:00
patchback[bot]
6dafa5954e fixing public key return value docs (#412) (#414)
(cherry picked from commit 010f1a4d2d)

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>
2022-03-02 14:09:20 +01:00
patchback[bot]
da1dd21a9e Fix parsing of lsblk output. (#410) (#413)
(cherry picked from commit 0d4b3ed991)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-03-02 14:05:07 +01:00
Felix Fontein
011036b87f Next expected release is 1.9.13. 2022-02-21 22:22:36 +01:00
Felix Fontein
35ef2edb3f Release 1.9.12. 2022-02-21 21:48:14 +01:00
Felix Fontein
ebcf866891 Prepare 1.9.12 release. 2022-02-19 18:53:26 +01:00
Felix Fontein
60c6d87b05 [stable-1] x509_certificate: regenerate certificate on CA's subject change (#406)
* Regenerate certificate on CA's subject change. (#402)

(cherry picked from commit 3ebc132c03)

* Add fix for PyOpenSSL backend.

* x509_certificate: check existing certificate's signature for selfsigned and ownca provider (#407)

* Verify whether signature matches.

* Add changelog fragment.

* Forgot imports.

* Fix wrong name.

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

* Refactor code.

(cherry picked from commit 28729657ac)

* There doesn't seem a way to do this with pyOpenSSL.
2022-02-19 17:51:28 +00:00
patchback[bot]
2aa38fe247 certificate_complete_chain: handle duplicate intermediate subjects (#403) (#405)
* Allow multiple intermediate CAs to have same subject.

* Add tests.

* Fix test name.

* Don't use CN for SAN.

* Make a bit more compatible.

* Include jinja2 compat for CentOS 6.

(cherry picked from commit 11a14543c8)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-02-14 18:04:54 +01:00
Felix Fontein
d19faa1627 Next expected release is 1.9.12. 2022-02-05 21:45:27 +01:00
Felix Fontein
e910f299b9 Release 1.9.11. 2022-02-05 21:28:22 +01:00
Felix Fontein
2ebf26854e Prepare 1.9.11 release. 2022-02-05 20:19:18 +01:00
Andrew Pantuso
7ff067937a openssh_cert - fix full_idempotence for host certificates (#396) (#397)
* fixing host cert idempotence

* adding changelog fragment

(cherry picked from commit a307618872)
2022-02-05 10:00:07 +01:00
Felix Fontein
2727b74cc7 Next expected release is 1.9.11. 2022-02-01 06:18:36 +01:00
Felix Fontein
3bb9c5f9a7 Release 1.9.10. 2022-02-01 05:49:00 +01:00
patchback[bot]
5623590c77 Drop CentOS 8 from CI. (#393) (#394)
(cherry picked from commit 23226dce8f)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-02-01 05:24:21 +01:00
Felix Fontein
29050913b3 Prepare 1.9.10 release. 2022-01-31 06:03:15 +01:00
patchback[bot]
aead2bf783 Set LANG and similar env variables to prevent translated cryptsetup output. (#388) (#390)
(cherry picked from commit ea2e45d63f)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-30 21:57:31 +01:00
patchback[bot]
2aaae70372 [PR #387/5abfe8fc backport][stable-1] PyOpenSSL 22.0.0 no longer supports Python 2.7 (#389)
* PyOpenSSL 22.0.0 no longer supports Python 2.7. (#387)

(cherry picked from commit 5abfe8fca9)

* Do not install PyOpenSSL from PyPi if cryptography cannot be updated - at least on FreeBSD 13.0, latest PyOpenSSL requires a cryptography upgrade, which breaks CI.

* Revert "Do not install PyOpenSSL from PyPi if cryptography cannot be updated - at least on FreeBSD 13.0, latest PyOpenSSL requires a cryptography upgrade, which breaks CI."

This reverts commit 16f9145653.

* Try another approach.

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-30 15:23:29 +01:00
patchback[bot]
de29a258c6 Fix indentation of when in example. (#382) (#383)
(cherry picked from commit a467f036b1)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-19 04:54:17 +00:00
patchback[bot]
8ca5b480e4 Update CI matrix for Remote Devel (#377) (#378)
* Update CI matrix for Remote Devel.

* Add Python info entries.

(cherry picked from commit cd5ed011a5)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-13 09:52:59 +01:00
Felix Fontein
f6ec785b0d Next expected release is 1.9.10. 2022-01-11 07:28:54 +01:00
68 changed files with 1352 additions and 291 deletions

View File

@@ -41,25 +41,25 @@ variables:
resources:
containers:
- container: default
image: quay.io/ansible/azure-pipelines-test-container:1.9.0
image: quay.io/ansible/azure-pipelines-test-container:3.0.0
pool: Standard
stages:
### Sanity & units
- stage: Ansible_devel
displayName: Sanity & Units devel
- stage: Ansible_2_13
displayName: Sanity & Units 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
targets:
- name: Sanity
test: 'devel/sanity/1'
test: '2.13/sanity/1'
- name: Sanity Extra # Only on devel
test: 'devel/sanity/extra'
test: '2.13/sanity/extra'
- name: Units
test: 'devel/units/1'
test: '2.13/units/1'
- stage: Ansible_2_12
displayName: Sanity & Units 2.12
dependsOn: []
@@ -105,13 +105,13 @@ stages:
- name: Units
test: '2.9/units/1'
### Docker
- stage: Docker_devel
displayName: Docker devel
- stage: Docker_2_13
displayName: Docker 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux/{0}/1
testFormat: 2.13/linux/{0}/1
targets:
- name: CentOS 7
test: centos7
@@ -137,8 +137,6 @@ stages:
targets:
- name: CentOS 6
test: centos6
- name: CentOS 8
test: centos8
- name: Fedora 33
test: fedora33
- name: openSUSE 15 py3
@@ -155,8 +153,6 @@ stages:
targets:
- name: CentOS 7
test: centos7
- name: CentOS 8
test: centos8
- name: Fedora 32
test: fedora32
- name: openSUSE 15 py2
@@ -197,22 +193,22 @@ stages:
test: ubuntu1804
### Remote
- stage: Remote_devel
displayName: Remote devel
- stage: Remote_2_13
displayName: Remote 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/{0}/1
testFormat: 2.13/{0}/1
targets:
- name: macOS 11.1
test: macos/11.1
- name: macOS 12.0
test: macos/12.0
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.5
test: rhel/8.5
- name: FreeBSD 12.2
test: freebsd/12.2
- name: FreeBSD 12.3
test: freebsd/12.3
- name: FreeBSD 13.0
test: freebsd/13.0
- stage: Remote_2_12
@@ -223,8 +219,8 @@ stages:
parameters:
testFormat: 2.12/{0}/1
targets:
- name: macOS 11.1
test: macos/11.1
# - name: macOS 11.1
# test: macos/11.1
- name: RHEL 8.4
test: rhel/8.4
- name: FreeBSD 13.0
@@ -253,10 +249,8 @@ stages:
targets:
- name: OS X 10.11
test: osx/10.11
- name: macOS 10.15
test: macos/10.15
- name: FreeBSD 12.1
test: freebsd/12.1
# - name: macOS 10.15
# test: macos/10.15
- stage: Remote_2_9
displayName: Remote 2.9
dependsOn: []
@@ -268,20 +262,20 @@ stages:
- name: 'RHEL 7.8'
test: 'rhel/7.8'
### cloud
- stage: Cloud_devel
displayName: Cloud devel
- stage: Cloud_2_13
displayName: Cloud 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: devel/cloud/{0}/1
testFormat: 2.13/cloud/{0}/1
targets:
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
# - test: 3.8
- test: 3.9
- test: "3.10"
- stage: Cloud_2_12
@@ -324,29 +318,29 @@ stages:
nameFormat: Python {0}
testFormat: 2.9/cloud/{0}/1
targets:
- test: 3.5
- test: 2.7
## Finally
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- Ansible_devel
- Ansible_2_13
- Ansible_2_12
- Ansible_2_11
- Ansible_2_10
- Ansible_2_9
- Remote_devel
- Remote_2_13
- Remote_2_12
- Remote_2_11
- Remote_2_10
- Remote_2_9
- Docker_devel
- Docker_2_13
- Docker_2_12
- Docker_2_11
- Docker_2_10
- Docker_2_9
- Cloud_devel
- Cloud_2_13
- Cloud_2_12
- Cloud_2_11
- Cloud_2_10

View File

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

View File

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

202
Apache-2.0.txt Normal file
View File

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

View File

@@ -5,6 +5,152 @@ Community Crypto Release Notes
.. contents:: Topics
v1.9.19
=======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- openssl_privatekey_pipe - ensure compatibility with newer versions of ansible-core (https://github.com/ansible-collections/community.crypto/pull/515).
v1.9.18
=======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- openssl_pkcs12 - when using the pyOpenSSL backend, do not crash when trying to read non-existing other certificates (https://github.com/ansible-collections/community.crypto/issues/486, https://github.com/ansible-collections/community.crypto/pull/487).
v1.9.17
=======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- Include ``Apache-2.0.txt`` file for ``plugins/module_utils/crypto/_obj2txt.py`` and ``plugins/module_utils/crypto/_objects_data.py``.
- openssl_csr - the module no longer crashes with 'permitted_subtrees/excluded_subtrees must be a non-empty list or None' if only one of ``name_constraints_permitted`` and ``name_constraints_excluded`` is provided (https://github.com/ansible-collections/community.crypto/issues/481).
- x509_crl - do not crash when signing CRL with Ed25519 or Ed448 keys (https://github.com/ansible-collections/community.crypto/issues/473, https://github.com/ansible-collections/community.crypto/pull/474).
v1.9.16
=======
Release Summary
---------------
Maintenance and bugfix release.
Bugfixes
--------
- Include ``simplified_bsd.txt`` license file for the ECS module utils.
- certificate_complete_chain - do not stop execution if an unsupported signature algorithm is encountered; warn instead (https://github.com/ansible-collections/community.crypto/pull/457).
v1.9.15
=======
Release Summary
---------------
Maintenance release.
Bugfixes
--------
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
v1.9.14
=======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- Make collection more robust when PyOpenSSL is used with an incompatible cryptography version (https://github.com/ansible-collections/community.crypto/pull/446).
- openssh_* modules - fix exception handling to report traceback to users for enhanced traceability (https://github.com/ansible-collections/community.crypto/pull/417).
- x509_crl - fix crash when ``issuer`` for a revoked certificate is specified (https://github.com/ansible-collections/community.crypto/pull/441).
v1.9.13
=======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- luks_device - fix parsing of ``lsblk`` output when device name ends with ``crypt`` (https://github.com/ansible-collections/community.crypto/issues/409, https://github.com/ansible-collections/community.crypto/pull/410).
v1.9.12
=======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- certificate_complete_chain - allow multiple potential intermediate certificates to have the same subject (https://github.com/ansible-collections/community.crypto/issues/399, https://github.com/ansible-collections/community.crypto/pull/403).
- x509_certificate - for the ``ownca`` provider, check whether the CA private key actually belongs to the CA certificate. This fix only covers the ``cryptography`` backend, not the ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's public key changes for ``provider=ownca``. This fix only covers the ``cryptography`` backend, not the ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's subject changes for ``provider=ownca`` (https://github.com/ansible-collections/community.crypto/issues/400, https://github.com/ansible-collections/community.crypto/pull/402).
- x509_certificate - regenerate certificate when the private key changes for ``provider=selfsigned``. This fix only covers the ``cryptography`` backend, not the ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/407).
Known Issues
------------
- x509_certificate - when using the ``ownca`` provider with the ``pyopenssl`` backend, changing the CA's public key does not cause regeneration of the certificate (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - when using the ``ownca`` provider with the ``pyopenssl`` backend, it is possible to specify a CA private key which is not related to the CA certificate (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - when using the ``selfsigned`` provider with the ``pyopenssl`` backend, changing the private key does not cause regeneration of the certificate (https://github.com/ansible-collections/community.crypto/pull/407).
v1.9.11
=======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- openssh_cert - fixed false ``changed`` status for ``host`` certificates when using ``full_idempotence`` (https://github.com/ansible-collections/community.crypto/issues/395, https://github.com/ansible-collections/community.crypto/pull/396).
v1.9.10
=======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- luks_devices - set ``LANG`` and similar environment variables to avoid translated output, which can break some of the module's functionality like key management (https://github.com/ansible-collections/community.crypto/pull/388, https://github.com/ansible-collections/community.crypto/issues/385).
v1.9.9
======

48
PSF-license.txt Normal file
View File

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

View File

@@ -11,7 +11,7 @@ Please note that this collection does **not** support Windows targets.
## Tested with Ansible
Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11 and ansible-core 2.12 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported.
Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12 and ansible-core 2.13 releases. Ansible versions before 2.9.10 are not supported.
## External requirements

View File

@@ -528,6 +528,148 @@ releases:
changes:
release_summary: Accidental 1.9.1 release. Identical to 1.9.0.
release_date: '2021-08-30'
1.9.10:
changes:
bugfixes:
- luks_devices - set ``LANG`` and similar environment variables to avoid translated
output, which can break some of the module's functionality like key management
(https://github.com/ansible-collections/community.crypto/pull/388, https://github.com/ansible-collections/community.crypto/issues/385).
release_summary: Regular bugfix release.
fragments:
- 1.9.10.yml
- 388-luks_device-i18n.yml
release_date: '2022-02-01'
1.9.11:
changes:
bugfixes:
- openssh_cert - fixed false ``changed`` status for ``host`` certificates when
using ``full_idempotence`` (https://github.com/ansible-collections/community.crypto/issues/395,
https://github.com/ansible-collections/community.crypto/pull/396).
release_summary: Bugfix release.
fragments:
- 1.9.11.yml
- 396-openssh_cert-host-cert-idempotence-fix.yml
release_date: '2022-02-05'
1.9.12:
changes:
bugfixes:
- certificate_complete_chain - allow multiple potential intermediate certificates
to have the same subject (https://github.com/ansible-collections/community.crypto/issues/399,
https://github.com/ansible-collections/community.crypto/pull/403).
- x509_certificate - for the ``ownca`` provider, check whether the CA private
key actually belongs to the CA certificate. This fix only covers the ``cryptography``
backend, not the ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's public key changes
for ``provider=ownca``. This fix only covers the ``cryptography`` backend,
not the ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - regenerate certificate when the CA's subject changes for
``provider=ownca`` (https://github.com/ansible-collections/community.crypto/issues/400,
https://github.com/ansible-collections/community.crypto/pull/402).
- x509_certificate - regenerate certificate when the private key changes for
``provider=selfsigned``. This fix only covers the ``cryptography`` backend,
not the ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/407).
known_issues:
- x509_certificate - when using the ``ownca`` provider with the ``pyopenssl``
backend, changing the CA's public key does not cause regeneration of the certificate
(https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - when using the ``ownca`` provider with the ``pyopenssl``
backend, it is possible to specify a CA private key which is not related to
the CA certificate (https://github.com/ansible-collections/community.crypto/pull/407).
- x509_certificate - when using the ``selfsigned`` provider with the ``pyopenssl``
backend, changing the private key does not cause regeneration of the certificate
(https://github.com/ansible-collections/community.crypto/pull/407).
release_summary: Regular bugfix release.
fragments:
- 1.9.12.yml
- 402-x509_certificate-ownca-subject.yml
- 403-certificate_complete_chain-same-subject.yml
- 407-x509_certificate-signature.yml
release_date: '2022-02-21'
1.9.13:
changes:
bugfixes:
- luks_device - fix parsing of ``lsblk`` output when device name ends with ``crypt``
(https://github.com/ansible-collections/community.crypto/issues/409, https://github.com/ansible-collections/community.crypto/pull/410).
release_summary: Regular bugfix release.
fragments:
- 1.9.13.yml
- 410-luks_device-lsblk-parsing.yml
release_date: '2022-03-04'
1.9.14:
changes:
bugfixes:
- Make collection more robust when PyOpenSSL is used with an incompatible cryptography
version (https://github.com/ansible-collections/community.crypto/pull/446).
- openssh_* modules - fix exception handling to report traceback to users for
enhanced traceability (https://github.com/ansible-collections/community.crypto/pull/417).
- x509_crl - fix crash when ``issuer`` for a revoked certificate is specified
(https://github.com/ansible-collections/community.crypto/pull/441).
release_summary: Regular bugfix release.
fragments:
- 1.9.14.yml
- 417-openssh_modules-fix-exception-reporting.yml
- 441-x509-crl-cert-issuer.yml
- 446-fix.yml
release_date: '2022-05-09'
1.9.15:
changes:
bugfixes:
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
release_summary: Maintenance release.
fragments:
- 1.9.15.yml
- psf-license.yml
release_date: '2022-05-16'
1.9.16:
changes:
bugfixes:
- Include ``simplified_bsd.txt`` license file for the ECS module utils.
- certificate_complete_chain - do not stop execution if an unsupported signature
algorithm is encountered; warn instead (https://github.com/ansible-collections/community.crypto/pull/457).
release_summary: Maintenance and bugfix release.
fragments:
- 1.9.16.yml
- 457-certificate_complete_chain-unsupported-algorithm.yml
- simplified-bsd-license.yml
release_date: '2022-06-02'
1.9.17:
changes:
bugfixes:
- Include ``Apache-2.0.txt`` file for ``plugins/module_utils/crypto/_obj2txt.py``
and ``plugins/module_utils/crypto/_objects_data.py``.
- openssl_csr - the module no longer crashes with 'permitted_subtrees/excluded_subtrees
must be a non-empty list or None' if only one of ``name_constraints_permitted``
and ``name_constraints_excluded`` is provided (https://github.com/ansible-collections/community.crypto/issues/481).
- x509_crl - do not crash when signing CRL with Ed25519 or Ed448 keys (https://github.com/ansible-collections/community.crypto/issues/473,
https://github.com/ansible-collections/community.crypto/pull/474).
release_summary: Bugfix release.
fragments:
- 1.9.17.yml
- 474-x509_crl-ed25519-ed448.yml
- 481-fix-excluded_subtrees-must-be-a-non-empty-list-or-None.yml
- apache-license.yml
release_date: '2022-06-17'
1.9.18:
changes:
bugfixes:
- openssl_pkcs12 - when using the pyOpenSSL backend, do not crash when trying
to read non-existing other certificates (https://github.com/ansible-collections/community.crypto/issues/486,
https://github.com/ansible-collections/community.crypto/pull/487).
release_summary: Bugfix release.
fragments:
- 1.9.18.yml
- 487-openssl_pkcs12-other-certs-crash.yml
release_date: '2022-07-09'
1.9.19:
changes:
bugfixes:
- openssl_privatekey_pipe - ensure compatibility with newer versions of ansible-core
(https://github.com/ansible-collections/community.crypto/pull/515).
release_summary: Bugfix release.
fragments:
- 1.9.19.yml
- 515-action-module-compat.yml
release_date: '2022-11-01'
1.9.2:
changes:
release_summary: Bugfix release to fix the changelog. No other change compared

View File

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

View File

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

View File

@@ -2,6 +2,8 @@
# 2.0, and the BSD License. See the LICENSE file at
# https://github.com/pyca/cryptography/blob/master/LICENSE for complete details.
#
# The Apache 2.0 license has been included as Apache-2.0.txt in this collection.
#
# Adapted from cryptography's hazmat/backends/openssl/decode_asn1.py
#
# Copyright (c) 2015, 2016 Paul Kehrer (@reaperhulk)

View File

@@ -5,7 +5,7 @@
# In case the following data structure has any copyrightable content, note that it is licensed as follows:
# Copyright (c) the OpenSSL contributors
# Licensed under the Apache License 2.0
# https://github.com/openssl/openssl/blob/master/LICENSE
# https://github.com/openssl/openssl/blob/master/LICENSE.txt or Apache-2.0.txt
from __future__ import absolute_import, division, print_function
__metaclass__ = type

View File

@@ -26,7 +26,7 @@ try:
import OpenSSL # noqa
from OpenSSL import crypto # noqa
HAS_PYOPENSSL = True
except ImportError:
except (ImportError, AttributeError):
# Error handled in the calling module.
HAS_PYOPENSSL = False

View File

@@ -31,13 +31,36 @@ from ansible_collections.community.crypto.plugins.module_utils.version import Lo
try:
import cryptography
from cryptography import x509
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
import ipaddress
except ImportError:
# Error handled in the calling module.
pass
try:
import cryptography.hazmat.primitives.asymmetric.rsa
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.ec
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.dsa
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.ed25519
except ImportError:
pass
try:
import cryptography.hazmat.primitives.asymmetric.ed448
except ImportError:
pass
try:
# This is a separate try/except since this is only present in cryptography 2.5 or newer
from cryptography.hazmat.primitives.serialization.pkcs12 import (
@@ -57,8 +80,13 @@ except ImportError:
_load_pkcs12 = None
from .basic import (
CRYPTOGRAPHY_HAS_DSA_SIGN,
CRYPTOGRAPHY_HAS_EC_SIGN,
CRYPTOGRAPHY_HAS_ED25519,
CRYPTOGRAPHY_HAS_ED25519_SIGN,
CRYPTOGRAPHY_HAS_ED448,
CRYPTOGRAPHY_HAS_ED448_SIGN,
CRYPTOGRAPHY_HAS_RSA_SIGN,
OpenSSLObjectError,
)
@@ -579,3 +607,40 @@ def _parse_pkcs12_legacy(pkcs12_bytes, passphrase=None):
if maybe_name != backend._ffi.NULL:
friendly_name = backend._ffi.string(maybe_name)
return private_key, certificate, additional_certificates, friendly_name
def cryptography_verify_signature(signature, data, hash_algorithm, signer_public_key):
'''
Check whether the given signature of the given data was signed by the given public key object.
'''
try:
if CRYPTOGRAPHY_HAS_RSA_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey):
signer_public_key.verify(signature, data, padding.PKCS1v15(), hash_algorithm)
return True
if CRYPTOGRAPHY_HAS_EC_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey):
signer_public_key.verify(signature, data, cryptography.hazmat.primitives.asymmetric.ec.ECDSA(hash_algorithm))
return True
if CRYPTOGRAPHY_HAS_DSA_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey):
signer_public_key.verify(signature, data, hash_algorithm)
return True
if CRYPTOGRAPHY_HAS_ED25519_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey):
signer_public_key.verify(signature, data)
return True
if CRYPTOGRAPHY_HAS_ED448_SIGN and isinstance(signer_public_key, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey):
signer_public_key.verify(signature, data)
return True
raise OpenSSLObjectError(u'Unsupported public key type {0}'.format(type(signer_public_key)))
except InvalidSignature:
return False
def cryptography_verify_certificate_signature(certificate, signer_public_key):
'''
Check whether the given X509 certificate object was signed by the given public key object.
'''
return cryptography_verify_signature(
certificate.signature,
certificate.tbs_certificate_bytes,
certificate.signature_hash_algorithm,
signer_public_key
)

View File

@@ -45,7 +45,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -37,7 +37,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.module_bac
try:
import OpenSSL
from OpenSSL import crypto
except ImportError:
except (ImportError, AttributeError):
pass
try:

View File

@@ -59,7 +59,7 @@ try:
# OpenSSL 1.0.x or older
OPENSSL_MUST_STAPLE_NAME = b"1.3.6.1.5.5.7.1.24"
OPENSSL_MUST_STAPLE_VALUE = b"DER:30:03:02:01:05"
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -28,8 +28,10 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
cryptography_compare_public_keys,
cryptography_key_needs_digest_for_signing,
cryptography_serial_number_of_cert,
cryptography_verify_certificate_signature,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.certificate import (
@@ -41,7 +43,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.module_bac
try:
from OpenSSL import crypto
except ImportError:
except (ImportError, AttributeError):
pass
try:
@@ -107,6 +109,9 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
except OpenSSLBadPassphraseError as exc:
module.fail_json(msg=str(exc))
if not cryptography_compare_public_keys(self.ca_cert.public_key(), self.ca_private_key.public_key()):
raise CertificateError('The CA private key does not belong to the CA certificate')
if cryptography_key_needs_digest_for_signing(self.ca_private_key):
if self.digest is None:
raise CertificateError(
@@ -173,6 +178,16 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
if super(OwnCACertificateBackendCryptography, self).needs_regeneration():
return True
self._ensure_existing_certificate_loaded()
# Check whether certificate is signed by CA certificate
if not cryptography_verify_certificate_signature(self.existing_certificate, self.ca_cert.public_key()):
return True
# Check subject
if self.ca_cert.subject != self.existing_certificate.issuer:
return True
# Check AuthorityKeyIdentifier
if self.create_authority_key_identifier:
try:
@@ -185,7 +200,6 @@ class OwnCACertificateBackendCryptography(CertificateBackend):
except cryptography.x509.ExtensionNotFound:
expected_ext = x509.AuthorityKeyIdentifier.from_issuer_public_key(self.ca_cert.public_key())
self._ensure_existing_certificate_loaded()
try:
ext = self.existing_certificate.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier)
if ext.value != expected_ext:
@@ -297,6 +311,18 @@ class OwnCACertificateBackendPyOpenSSL(CertificateBackend):
"""Return bytes for self.cert."""
return crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert)
def needs_regeneration(self):
if super(OwnCACertificateBackendPyOpenSSL, self).needs_regeneration():
return True
self._ensure_existing_certificate_loaded()
# Check subject
if self.ca_cert.get_subject() != self.existing_certificate.get_issuer():
return True
return False
def dump(self, include_certificate):
result = super(OwnCACertificateBackendPyOpenSSL, self).dump(include_certificate)
result.update({

View File

@@ -22,6 +22,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
cryptography_key_needs_digest_for_signing,
cryptography_serial_number_of_cert,
cryptography_verify_certificate_signature,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.certificate import (
@@ -32,7 +33,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.module_bac
try:
from OpenSSL import crypto
except ImportError:
except (ImportError, AttributeError):
pass
try:
@@ -134,6 +135,18 @@ class SelfSignedCertificateBackendCryptography(CertificateBackend):
"""Return bytes for self.cert."""
return self.cert.public_bytes(Encoding.PEM)
def needs_regeneration(self):
if super(SelfSignedCertificateBackendCryptography, self).needs_regeneration():
return True
self._ensure_existing_certificate_loaded()
# Check whether certificate is signed by private key
if not cryptography_verify_certificate_signature(self.existing_certificate, self.privatekey.public_key()):
return True
return False
def dump(self, include_certificate):
result = super(SelfSignedCertificateBackendCryptography, self).dump(include_certificate)

View File

@@ -63,7 +63,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:
@@ -528,8 +528,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
if self.name_constraints_permitted or self.name_constraints_excluded:
try:
csr = csr.add_extension(cryptography.x509.NameConstraints(
[cryptography_get_name(name, 'name constraints permitted') for name in self.name_constraints_permitted],
[cryptography_get_name(name, 'name constraints excluded') for name in self.name_constraints_excluded],
[cryptography_get_name(name, 'name constraints permitted') for name in self.name_constraints_permitted] or None,
[cryptography_get_name(name, 'name constraints excluded') for name in self.name_constraints_excluded] or None,
), critical=self.name_constraints_critical)
except TypeError as e:
raise OpenSSLObjectError('Error while parsing name constraint: {0}'.format(e))
@@ -678,8 +678,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
def _check_nameConstraints(extensions):
current_nc_ext = _find_extension(extensions, cryptography.x509.NameConstraints)
current_nc_perm = [to_text(altname) for altname in current_nc_ext.value.permitted_subtrees] if current_nc_ext else []
current_nc_excl = [to_text(altname) for altname in current_nc_ext.value.excluded_subtrees] if current_nc_ext else []
current_nc_perm = [to_text(altname) for altname in current_nc_ext.value.permitted_subtrees or []] if current_nc_ext else []
current_nc_excl = [to_text(altname) for altname in current_nc_ext.value.excluded_subtrees or []] if current_nc_ext else []
nc_perm = [to_text(cryptography_get_name(altname, 'name constraints permitted')) for altname in self.name_constraints_permitted]
nc_excl = [to_text(cryptography_get_name(altname, 'name constraints excluded')) for altname in self.name_constraints_excluded]
if set(nc_perm) != set(current_nc_perm) or set(nc_excl) != set(current_nc_excl):

View File

@@ -57,7 +57,7 @@ try:
# OpenSSL 1.0.x or older
OPENSSL_MUST_STAPLE_NAME = b"1.3.6.1.5.5.7.1.24"
OPENSSL_MUST_STAPLE_VALUE = b"DER:30:03:02:01:05"
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -54,7 +54,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -49,7 +49,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -38,7 +38,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -29,7 +29,7 @@ from ._objects import OID_LOOKUP
try:
import OpenSSL
except ImportError:
except (ImportError, AttributeError):
# Error handled in the calling module.
pass

View File

@@ -32,7 +32,7 @@ from ansible.module_utils.common.text.converters import to_native, to_bytes
try:
from OpenSSL import crypto
HAS_PYOPENSSL = True
except ImportError:
except (ImportError, AttributeError):
# Error handled in the calling module.
HAS_PYOPENSSL = False

View File

@@ -7,7 +7,7 @@
# their own license to the complete work.
#
# Copyright (c), Entrust Datacard Corporation, 2019
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
# Simplified BSD License (see simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:

View File

@@ -21,9 +21,11 @@ __metaclass__ = type
import abc
import os
import stat
import traceback
from ansible.module_utils import six
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import (
parse_openssh_version,
)
@@ -75,7 +77,14 @@ class OpensshModule(object):
self.check_mode = self.module.check_mode
def execute(self):
self._execute()
try:
self._execute()
except Exception as e:
self.module.fail_json(
msg="unexpected error occurred: %s" % to_native(e),
exception=traceback.format_exc(),
)
self.module.exit_json(**self.result)
@abc.abstractmethod

View File

@@ -101,7 +101,7 @@ account:
returned: always
type: list
elements: str
sample: "['mailto:me@example.com', 'tel:00123456789']"
sample: ['mailto:me@example.com', 'tel:00123456789']
status:
description: the account's status
returned: always

View File

@@ -308,7 +308,7 @@ EXAMPLES = r'''
# - copy:
# dest: /var/www/html/{{ sample_com_challenge['challenge_data']['sample.com']['http-01']['resource'] }}
# content: "{{ sample_com_challenge['challenge_data']['sample.com']['http-01']['resource_value'] }}"
# when: sample_com_challenge is changed and 'sample.com' in sample_com_challenge['challenge_data']
# when: sample_com_challenge is changed and 'sample.com' in sample_com_challenge['challenge_data']
#
# Alternative way:
#
@@ -467,7 +467,20 @@ authorizations:
- Maps an identifier to ACME authorization objects. See U(https://tools.ietf.org/html/rfc8555#section-7.1.4).
returned: changed
type: dict
sample: '{"example.com":{...}}'
sample:
example.com:
identifier:
type: dns
value: example.com
status: valid
expires: '2022-08-04T01:02:03.45Z'
challenges:
- url: https://example.org/acme/challenge/12345
type: http-01
status: valid
token: A5b1C3d2E9f8G7h6
validated: '2022-08-01T01:01:02.34Z'
wildcard: false
order_uri:
description: ACME order URI.
returned: changed

View File

@@ -183,7 +183,7 @@ directory:
description: The ACME directory's content
returned: always
type: dict
sample: |
sample:
{
"a85k3x9f91A4": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
"keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
@@ -203,7 +203,7 @@ headers:
description: The request's HTTP headers (with lowercase keys)
returned: always
type: dict
sample: |
sample:
{
"boulder-requester": "12345",
"cache-control": "max-age=0, no-cache, no-store",
@@ -214,7 +214,7 @@ headers:
"cookies_string": "",
"date": "Wed, 07 Nov 2018 12:34:56 GMT",
"expires": "Wed, 07 Nov 2018 12:44:56 GMT",
"link": "<https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf>;rel=\"terms-of-service\"",
"link": '<https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf>;rel="terms-of-service"',
"msg": "OK (904 bytes)",
"pragma": "no-cache",
"replay-nonce": "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGH",

View File

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

View File

@@ -198,7 +198,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -350,7 +350,7 @@ STDERR = 2
# used to get <luks-name> out of lsblk output in format 'crypt <luks-name>'
# regex takes care of any possible blank characters
LUKS_NAME_REGEX = re.compile(r'\s*crypt\s+([^\s]*)\s*')
LUKS_NAME_REGEX = re.compile(r'^crypt\s+([^\s]*)\s*$')
# used to get </luks/device> out of lsblk output
# in format 'device: </luks/device>'
LUKS_DEVICE_REGEX = re.compile(r'\s*device:\s+([^\s]*)\s*')
@@ -446,13 +446,11 @@ class CryptHandler(Handler):
raise ValueError('Error while obtaining LUKS name for %s: %s'
% (device, result[STDERR]))
m = LUKS_NAME_REGEX.search(result[STDOUT])
try:
name = m.group(1)
except AttributeError:
name = None
return name
for line in result[STDOUT].splitlines(False):
m = LUKS_NAME_REGEX.match(line)
if m:
return m.group(1)
return None
def get_container_device_by_name(self, name):
''' obtain device name based on the LUKS container name
@@ -821,6 +819,7 @@ def run_module():
module = AnsibleModule(argument_spec=module_args,
supports_check_mode=True,
mutually_exclusive=mutually_exclusive)
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
if module.params['device'] is not None:
try:

View File

@@ -379,7 +379,7 @@ class Certificate(OpensshModule):
def _is_fully_valid(self):
return self._is_partially_valid() and all([
self._compare_options(),
self._compare_options() if self.original_data.type == 'user' else True,
self.original_data.key_id == self.identifier,
self.original_data.public_key == self._get_key_fingerprint(self.public_key),
self.original_data.signing_key == self._get_key_fingerprint(self.signing_key),

View File

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

View File

@@ -177,7 +177,7 @@ subject:
returned: changed or success
type: list
elements: list
sample: "[('CN', 'www.ansible.com'), ('O', 'Ansible')]"
sample: [['CN', 'www.ansible.com'], ['O', 'Ansible']]
subjectAltName:
description: The alternative names this CSR is valid for
returned: changed or success

View File

@@ -85,7 +85,7 @@ basic_constraints:
returned: success
type: list
elements: str
sample: "[CA:TRUE, pathlen:1]"
sample: ['CA:TRUE', 'pathlen:1']
basic_constraints_critical:
description: Whether the C(basic_constraints) extension is critical.
returned: success
@@ -95,7 +95,7 @@ extended_key_usage:
returned: success
type: list
elements: str
sample: "[Biometric Info, DVCS, Time Stamping]"
sample: [Biometric Info, DVCS, Time Stamping]
extended_key_usage_critical:
description: Whether the C(extended_key_usage) extension is critical.
returned: success
@@ -114,12 +114,12 @@ extensions_by_oid:
returned: success
type: str
sample: "MAMCAQU="
sample: '{"1.3.6.1.5.5.7.1.24": { "critical": false, "value": "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]"
sample: [Key Agreement, Data Encipherment]
key_usage_critical:
description: Whether the C(key_usage) extension is critical.
returned: success
@@ -129,7 +129,7 @@ subject_alt_name:
returned: success
type: list
elements: str
sample: "[DNS:www.ansible.com, IP:1.2.3.4]"
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
@@ -171,13 +171,13 @@ subject:
- 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"}'
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"]]'
sample: [["commonName", "www.example.com"], ["emailAddress": "test@example.com"]]
public_key:
description: CSR's public key in PEM format
returned: success
@@ -285,14 +285,14 @@ authority_cert_issuer:
returned: success and if the pyOpenSSL backend is I(not) used
type: list
elements: str
sample: "[DNS:www.ansible.com, IP:1.2.3.4]"
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 and if the pyOpenSSL backend is I(not) used
type: int
sample: '12345'
sample: 12345
'''

View File

@@ -66,7 +66,7 @@ subject:
returned: changed or success
type: list
elements: list
sample: "[('CN', 'www.ansible.com'), ('O', 'Ansible')]"
sample: [['CN', 'www.ansible.com'], ['O', 'Ansible']]
subjectAltName:
description: The alternative names this CSR is valid for
returned: changed or success

View File

@@ -276,7 +276,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:
@@ -542,6 +542,8 @@ class PkcsPyOpenSSL(Pkcs):
return crypto.dump_certificate(crypto.FILETYPE_PEM, cert) if cert else None
def _dump_other_certificates(self, pkcs12):
if pkcs12.get_ca_certificates() is None:
return []
return [
crypto.dump_certificate(crypto.FILETYPE_PEM, other_cert)
for other_cert in pkcs12.get_ca_certificates()

View File

@@ -217,7 +217,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -108,7 +108,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -108,7 +108,7 @@ try:
import OpenSSL
from OpenSSL import crypto
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
except ImportError:
except (ImportError, AttributeError):
PYOPENSSL_IMP_ERR = traceback.format_exc()
PYOPENSSL_FOUND = False
else:

View File

@@ -129,7 +129,7 @@ basic_constraints:
returned: success
type: list
elements: str
sample: "[CA:TRUE, pathlen:1]"
sample: ["CA:TRUE", "pathlen:1"]
basic_constraints_critical:
description: Whether the C(basic_constraints) extension is critical.
returned: success
@@ -139,7 +139,7 @@ extended_key_usage:
returned: success
type: list
elements: str
sample: "[Biometric Info, DVCS, Time Stamping]"
sample: [Biometric Info, DVCS, Time Stamping]
extended_key_usage_critical:
description: Whether the C(extended_key_usage) extension is critical.
returned: success
@@ -158,12 +158,12 @@ extensions_by_oid:
returned: success
type: str
sample: "MAMCAQU="
sample: '{"1.3.6.1.5.5.7.1.24": { "critical": false, "value": "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]"
sample: [Key Agreement, Data Encipherment]
key_usage_critical:
description: Whether the C(key_usage) extension is critical.
returned: success
@@ -173,7 +173,7 @@ subject_alt_name:
returned: success
type: list
elements: str
sample: "[DNS:www.ansible.com, IP:1.2.3.4]"
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
@@ -192,36 +192,36 @@ issuer:
- Note that for repeated values, only the last one will be returned.
returned: success
type: dict
sample: '{"organizationName": "Ansible", "commonName": "ca.example.com"}'
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"]]'
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"}'
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"]]'
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
sample: '20190413202428Z'
not_before:
description: C(notBefore) date as ASN.1 TIME.
returned: success
type: str
sample: 20190331202428Z
sample: '20190331202428Z'
public_key:
description: Certificate's public key in PEM format.
returned: success
@@ -359,14 +359,14 @@ authority_cert_issuer:
returned: success and if the pyOpenSSL backend is I(not) used
type: list
elements: str
sample: "[DNS:www.ansible.com, IP:1.2.3.4]"
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 and if the pyOpenSSL backend is I(not) used
type: int
sample: '12345'
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.

View File

@@ -286,13 +286,13 @@ issuer:
- Note that for repeated values, only the last one will be returned.
returned: success
type: dict
sample: '{"organizationName": "Ansible", "commonName": "ca.example.com"}'
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"]]'
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
@@ -326,7 +326,7 @@ revoked_certificates:
description: The certificate's issuer.
type: list
elements: str
sample: '["DNS:ca.example.org"]'
sample: ["DNS:ca.example.org"]
issuer_critical:
description: Whether the certificate issuer extension is critical.
type: bool
@@ -392,6 +392,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
cryptography_get_name,
cryptography_key_needs_digest_for_signing,
cryptography_name_to_oid,
cryptography_oid_to_name,
cryptography_serial_number_of_cert,
@@ -612,8 +613,12 @@ class CRL(OpenSSLObject):
return False
if self.next_update != self.crl.next_update and not self.ignore_timestamps:
return False
if self.digest.name != self.crl.signature_hash_algorithm.name:
return False
if cryptography_key_needs_digest_for_signing(self.privatekey):
if self.crl.signature_hash_algorithm is None or self.digest.name != self.crl.signature_hash_algorithm.name:
return False
else:
if self.crl.signature_hash_algorithm is not None:
return False
want_issuer = [(cryptography_name_to_oid(entry[0]), entry[1]) for entry in self.issuer]
if want_issuer != [(sub.oid, sub.value) for sub in self.crl.issuer]:
@@ -664,9 +669,7 @@ class CRL(OpenSSLObject):
revoked_cert = revoked_cert.revocation_date(entry['revocation_date'])
if entry['issuer'] is not None:
revoked_cert = revoked_cert.add_extension(
x509.CertificateIssuer([
cryptography_get_name(name, 'issuer') for name in entry['issuer']
]),
x509.CertificateIssuer(entry['issuer']),
entry['issuer_critical']
)
if entry['reason'] is not None:
@@ -681,7 +684,10 @@ class CRL(OpenSSLObject):
)
crl = crl.add_revoked_certificate(revoked_cert.build(backend))
self.crl = crl.sign(self.privatekey, self.digest, backend=backend)
digest = None
if cryptography_key_needs_digest_for_signing(self.privatekey):
digest = self.digest
self.crl = crl.sign(self.privatekey, digest, backend=backend)
if self.format == 'pem':
return self.crl.public_bytes(Encoding.PEM)
else:

View File

@@ -78,23 +78,23 @@ issuer:
- Note that for repeated values, only the last one will be returned.
returned: success
type: dict
sample: '{"organizationName": "Ansible", "commonName": "ca.example.com"}'
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"]]'
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
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
sample: '20190413202428Z'
digest:
description: The signature algorithm used to sign the CRL.
returned: success
@@ -113,12 +113,12 @@ revoked_certificates:
revocation_date:
description: The point in time the certificate was revoked as ASN.1 TIME.
type: str
sample: 20190413202428Z
sample: '20190413202428Z'
issuer:
description: The certificate's issuer.
type: list
elements: str
sample: '["DNS:ca.example.org"]'
sample: ["DNS:ca.example.org"]
issuer_critical:
description: Whether the certificate issuer extension is critical.
type: bool
@@ -140,7 +140,7 @@ revoked_certificates:
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
sample: '20190413202428Z'
invalidity_date_critical:
description: Whether the invalidity date extension is critical.
type: bool

View File

@@ -115,13 +115,12 @@ class AnsibleActionModule(object):
self.required_by = required_by
self._diff = self.__action_plugin._play_context.diff
self._verbosity = self.__action_plugin._display.verbosity
self._string_conversion_action = C.STRING_CONVERSION_ACTION
self.aliases = {}
self._legal_inputs = []
self._options_context = list()
self.params = copy.deepcopy(action_plugin._task.args)
self.params = copy.deepcopy(self.__action_plugin._task.args)
self.no_log_values = set()
if HAS_ARGSPEC_VALIDATOR:
self._validator = ArgumentSpecValidator(
@@ -444,7 +443,7 @@ class AnsibleActionModule(object):
}
# Ignore, warn, or error when converting to a string.
allow_conversion = opts.get(self._string_conversion_action, True)
allow_conversion = opts.get(C.STRING_CONVERSION_ACTION, True)
try:
return check_type_str(value, allow_conversion)
except TypeError:
@@ -459,10 +458,10 @@ class AnsibleActionModule(object):
from_msg = '{0}: {1!r}'.format(param, value)
to_msg = '{0}: {1!r}'.format(param, to_text(value))
if self._string_conversion_action == 'error':
if C.STRING_CONVERSION_ACTION == 'error':
msg = common_msg.capitalize()
raise TypeError(to_native(msg))
elif self._string_conversion_action == 'warn':
elif C.STRING_CONVERSION_ACTION == 'warn':
msg = ('The value "{0}" (type {1.__class__.__name__}) was converted to "{2}" (type string). '
'If this does not look like what you expect, {3}').format(from_msg, value, to_msg, common_msg)
self.warn(to_native(msg))

8
simplified_bsd.txt Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -86,6 +86,27 @@
regenerate: full_idempotence
register: default_options
- name: Generate host cert full_idempotence
openssh_cert:
type: host
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: always
valid_to: forever
regenerate: full_idempotence
- name: Generate host cert full_idempotence again
openssh_cert:
type: host
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: always
valid_to: forever
regenerate: full_idempotence
register: host_cert_full_idempotence
- name: Assert options results
assert:
that:
@@ -95,6 +116,7 @@
- explicit_extension_after is not changed
- explicit_extension_and_directive is changed
- default_options is not changed
- host_cert_full_idempotence is not changed
- name: Remove certificate
openssh_cert:

View File

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

View File

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

View File

@@ -32,11 +32,15 @@ system_python_version_data:
- '3.8'
'11.1':
- '3.9'
'12.0':
- '3.10'
FreeBSD:
'12.1':
- '3.6'
'12.2':
- '3.7'
'12.3':
- '3.8'
'13.0':
- '3.7'
RedHat:
@@ -55,3 +59,6 @@ cannot_upgrade_cryptography:
- '3.8' # on the VMs in CI, system packages are used for this version as well
'13.0':
- '3.8' # on the VMs in CI, system packages are used for this version as well
Ubuntu:
'18':
- '3.9' # this is the default container for ansible-core 2.12; upgrading cryptography wrecks pyOpenSSL

View File

@@ -1,2 +1,3 @@
dependencies:
- setup_ssh_keygen
- prepare_jinja2_compat

View File

@@ -5,13 +5,22 @@
####################################################################
- name: Start an ssh agent to use for tests
shell: eval $(ssh-agent)>/dev/null&&echo "${SSH_AGENT_PID};${SSH_AUTH_SOCK}"
register: openssh_agent_env_vars
shell: ssh-agent -c | grep "^setenv"
register: openssh_agent_stdout
- name: Convert output to dictionary
set_fact:
openssh_agent_env: >-
{{
openssh_agent_stdout.stdout_lines | map('regex_replace', '^setenv ([^ ]+) ([^ ]+);', '\1')
| zip(openssh_agent_stdout.stdout_lines | map('regex_replace', '^setenv ([^ ]+) ([^ ]+);', '\2'))
| list | items2dict(key_name=0, value_name=1)
}}
- name: Register ssh agent facts
set_fact:
openssh_agent_pid: "{{ openssh_agent_env_vars.stdout.split(';')[0] }}"
openssh_agent_sock: "{{ openssh_agent_env_vars.stdout.split(';')[1] }}"
openssh_agent_pid: "{{ openssh_agent_env.SSH_AGENT_PID }}"
openssh_agent_sock: "{{ openssh_agent_env.SSH_AUTH_SOCK }}"
- name: stat agent socket
stat:

View File

@@ -14,14 +14,20 @@
- name: (OwnCA, {{select_crypto_backend}}) Generate CA CSR
openssl_csr:
path: '{{ remote_tmp_dir }}/ca_csr.csr'
path: '{{ item.path }}'
privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
subject:
commonName: Example CA
subject: '{{ item.subject }}'
useCommonNameForSAN: no
basic_constraints:
- 'CA:TRUE'
basic_constraints_critical: yes
loop:
- path: '{{ remote_tmp_dir }}/ca_csr.csr'
subject:
commonName: Example CA
- path: '{{ remote_tmp_dir }}/ca_csr2.csr'
subject:
commonName: Example CA 2
- name: (OwnCA, {{select_crypto_backend}}) Generate CA CSR (privatekey passphrase)
openssl_csr:
@@ -62,6 +68,15 @@
- result_check_mode is changed
- result is changed
- name: (OwnCA, {{select_crypto_backend}}) Generate selfsigned CA certificate with different commonName
x509_certificate:
path: '{{ remote_tmp_dir }}/ca_cert2.pem'
csr_path: '{{ remote_tmp_dir }}/ca_csr2.csr'
privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: selfsigned
selfsigned_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}'
- name: (OwnCA, {{select_crypto_backend}}) Generate selfsigned CA certificate (privatekey passphrase)
x509_certificate:
path: '{{ remote_tmp_dir }}/ca_cert_pw.pem'
@@ -110,6 +125,54 @@
select_crypto_backend: '{{ select_crypto_backend }}'
check_mode: yes
- name: (OwnCA, {{select_crypto_backend}}) Copy ownca certificate to new file to check regeneration
copy:
src: '{{ remote_tmp_dir }}/ownca_cert.pem'
dest: '{{ item }}'
remote_src: true
loop:
- '{{ remote_tmp_dir }}/ownca_cert_ca_cn.pem'
- '{{ remote_tmp_dir }}/ownca_cert_ca_key.pem'
- name: (OwnCA, {{select_crypto_backend}}) Regenerate ownca certificate with different CA subject
x509_certificate:
path: '{{ remote_tmp_dir }}/ownca_cert_ca_cn.pem'
csr_path: '{{ remote_tmp_dir }}/csr.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_path: '{{ remote_tmp_dir }}/ca_cert2.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: ownca_certificate_ca_subject_changed
- name: (OwnCA, {{select_crypto_backend}}) Regenerate ownca certificate with different CA key
x509_certificate:
path: '{{ remote_tmp_dir }}/ownca_cert_ca_key.pem'
csr_path: '{{ remote_tmp_dir }}/csr.csr'
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_path: '{{ remote_tmp_dir }}/ca_cert_pw.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey_pw.pem'
ownca_privatekey_passphrase: hunter2
provider: ownca
ownca_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: ownca_certificate_ca_key_changed
- name: (OwnCA, {{select_crypto_backend}}) Get certificate information
community.crypto.x509_certificate_info:
path: '{{ remote_tmp_dir }}/ownca_cert.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
register: result
- name: (OwnCA, {{select_crypto_backend}}) Get private key information
community.crypto.openssl_privatekey_info:
path: '{{ remote_tmp_dir }}/privatekey.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
register: result_privatekey
- name: (OwnCA, {{select_crypto_backend}}) Check ownca certificate
x509_certificate:
path: '{{ remote_tmp_dir }}/ownca_cert.pem'
@@ -285,7 +348,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_backup.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
backup: yes
@@ -296,7 +359,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_backup.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
backup: yes
@@ -307,7 +370,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_backup.pem'
csr_path: '{{ remote_tmp_dir }}/csr.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
backup: yes
@@ -335,7 +398,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_ski.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_subject_key_identifier: always_create
@@ -348,7 +411,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_ski.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_subject_key_identifier: always_create
@@ -361,7 +424,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_ski.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_subject_key_identifier: never_create
@@ -374,7 +437,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_ski.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_subject_key_identifier: never_create
@@ -387,7 +450,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_ski.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_subject_key_identifier: always_create
@@ -400,7 +463,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_aki.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_authority_key_identifier: yes
@@ -413,7 +476,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_aki.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_authority_key_identifier: yes
@@ -426,7 +489,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_aki.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_authority_key_identifier: no
@@ -439,7 +502,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_aki.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_authority_key_identifier: no
@@ -452,7 +515,7 @@
path: '{{ remote_tmp_dir }}/ownca_cert_aki.pem'
csr_path: '{{ remote_tmp_dir }}/csr_ecc.csr'
ownca_path: '{{ remote_tmp_dir }}/ca_cert.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
ownca_privatekey_path: '{{ remote_tmp_dir }}/ca_privatekey.pem'
provider: ownca
ownca_digest: sha256
ownca_create_authority_key_identifier: yes

View File

@@ -31,6 +31,14 @@
- ownca_certificate.notBefore == ownca_certificate_idempotence.notBefore
- ownca_certificate.notAfter == ownca_certificate_idempotence.notAfter
- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate regeneration
assert:
that:
- ownca_certificate_ca_subject_changed is changed
# ownca_certificate_ca_key_changed is not changed for the pyopenssl backend,
# see https://github.com/ansible-collections/community.crypto/pull/406
- ownca_certificate_ca_key_changed is changed or select_crypto_backend == 'pyopenssl'
- name: (OwnCA validation, {{select_crypto_backend}}) Read certificate
slurp:
src: '{{ remote_tmp_dir }}/ownca_cert.pem'

View File

@@ -456,3 +456,90 @@
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
list_revoked_certificates: false
register: crl_2_info_1
- name: Create CRL 3
x509_crl:
path: '{{ remote_tmp_dir }}/ca-crl3.crl'
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
issuer:
CN: Ansible
last_update: +0d
next_update: +0d
revoked_certificates:
- serial_number: 1234
revocation_date: 20191001000000Z
issuer:
- "DNS:ca.example.org"
issuer_critical: true
register: crl_3
- name: Retrieve CRL 3 infos
x509_crl_info:
path: '{{ remote_tmp_dir }}/ca-crl3.crl'
list_revoked_certificates: true
register: crl_3_info
- name: Ed25519 and Ed448 tests (for cryptography >= 2.6)
block:
- name: Generate private keys
openssl_privatekey:
path: '{{ remote_tmp_dir }}/ca-{{ item }}.key'
type: '{{ item }}'
loop:
- Ed25519
- Ed448
register: ed25519_ed448_privatekey
ignore_errors: yes
- when: ed25519_ed448_privatekey is not failed
block:
- name: Create CRL
x509_crl:
path: '{{ remote_tmp_dir }}/ca-crl-{{ item }}.crl'
privatekey_path: '{{ remote_tmp_dir }}/ca-{{ item }}.key'
issuer:
CN: Ansible
last_update: 20191013000000Z
next_update: 20191113000000Z
revoked_certificates:
- path: '{{ remote_tmp_dir }}/cert-1.pem'
revocation_date: 20191013000000Z
- path: '{{ remote_tmp_dir }}/cert-2.pem'
revocation_date: 20191013000000Z
reason: key_compromise
reason_critical: yes
invalidity_date: 20191012000000Z
- serial_number: 1234
revocation_date: 20191001000000Z
register: ed25519_ed448_crl
loop:
- Ed25519
- Ed448
ignore_errors: yes
- name: Create CRL (idempotence)
x509_crl:
path: '{{ remote_tmp_dir }}/ca-crl-{{ item }}.crl'
privatekey_path: '{{ remote_tmp_dir }}/ca-{{ item }}.key'
issuer:
CN: Ansible
last_update: 20191013000000Z
next_update: 20191113000000Z
revoked_certificates:
- path: '{{ remote_tmp_dir }}/cert-1.pem'
revocation_date: 20191013000000Z
- path: '{{ remote_tmp_dir }}/cert-2.pem'
revocation_date: 20191013000000Z
reason: key_compromise
reason_critical: yes
invalidity_date: 20191012000000Z
- serial_number: 1234
revocation_date: 20191001000000Z
register: ed25519_ed448_crl_idempotence
loop:
- Ed25519
- Ed448
ignore_errors: yes
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=')

View File

@@ -90,3 +90,31 @@
assert:
that:
- "'revoked_certificates' not in crl_2_info_1"
- name: Validate CRL 3 info
assert:
that:
- crl_3.revoked_certificates == crl_3_info.revoked_certificates
- crl_3.revoked_certificates[0].issuer == [
"DNS:ca.example.org",
]
- name: Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8)
assert:
that:
- ed25519_ed448_crl.results[0] is failed
- ed25519_ed448_crl.results[1] is failed
- ed25519_ed448_crl_idempotence.results[0] is failed
- ed25519_ed448_crl_idempotence.results[1] is failed
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') and cryptography_version.stdout is version('2.8', '<') and ed25519_ed448_privatekey is not failed
- name: Verify Ed25519 and Ed448 tests (for cryptography >= 2.8)
assert:
that:
- ed25519_ed448_crl is succeeded
- ed25519_ed448_crl.results[0] is changed
- ed25519_ed448_crl.results[1] is changed
- ed25519_ed448_crl_idempotence is succeeded
- ed25519_ed448_crl_idempotence.results[0] is not changed
- ed25519_ed448_crl_idempotence.results[1] is not changed
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') and ed25519_ed448_privatekey is not failed

View File

@@ -5,6 +5,6 @@
],
"output": "path-line-column-message",
"requirements": [
"antsibull"
"antsibull-docs"
]
}

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Check extra collection docs with antsibull-lint."""
"""Check extra collection docs with antsibull-docs."""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
@@ -14,7 +14,7 @@ def main():
"""Main entry point."""
if not os.path.isdir(os.path.join('docs', 'docsite')):
return
p = subprocess.run(['antsibull-lint', 'collection-docs', '.'], check=False)
p = subprocess.run(['antsibull-docs', 'lint-collection-docs', '.'], check=False)
if p.returncode not in (0, 3):
print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode))

View File

@@ -1,11 +1,13 @@
coverage >= 4.2, < 5.0.0, != 4.3.2 ; python_version <= '3.7' # features in 4.2+ required, avoid known bug in 4.3.2 on python 2.6, coverage 5.0+ incompatible
coverage >= 4.5.4, < 5.0.0 ; python_version > '3.7' # coverage had a bug in < 4.5.4 that would cause unit tests to hang in Python 3.8, coverage 5.0+ incompatible
cryptography < 2.2 ; python_version < '2.7' # cryptography 2.2 drops support for python 2.6
cryptography >= 3.0, < 3.4 ; python_version < '3.6' # cryptography 3.4 drops support for python 2.7
cryptography >= 3.0, < 3.4 ; python_version < '3.5' # cryptography 3.4 drops support for python 2.7
cryptography >= 3.0, < 3.3 ; python_version == '3.5' # cryptography 3.3 drops support for python 3.5
urllib3 < 1.24 ; python_version < '2.7' # urllib3 1.24 and later require python 2.7 or later
idna < 2.6, >= 2.5 # linode requires idna < 2.9, >= 2.5, requests requires idna < 2.6, but cryptography will cause the latest version to be installed instead
requests < 2.20.0 ; python_version < '2.7' # requests 2.20.0 drops support for python 2.6
virtualenv < 16.0.0 ; python_version < '2.7' # virtualenv 16.0.0 and later require python 2.7 or later
pyopenssl < 18.0.0 ; python_version < '2.7' # pyOpenSSL 18.0.0 and later require python 2.7 or later
pyopenssl < 22.0.0 ; python_version < '3.6' # pyOpenSSL 22.0.0 and later require python 3.6 or later
setuptools < 45 ; python_version <= '2.7' # setuptools 45 and later require python 3.5 or later
cffi >= 1.14.2, != 1.14.3 # Yanked version which older versions of pip will still install:

View File

@@ -17,6 +17,12 @@ fi
stage="${S:-prod}"
provider="${P:-default}"
if [ "${platform}/${version}" == "freebsd/13.0" ]; then
# On FreeBSD 13.0, installing PyOpenSSL 22.0.0 tries to upgrade cryptography, which
# will fail due to missing Rust compiler.
echo "pyopenssl < 22.0.0 ; python_version >= '3.8'" >> tests/utils/constraints.txt
fi
# shellcheck disable=SC2086
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
--remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}"