Compare commits

...

26 Commits
3.0.1 ... 3.0.4

Author SHA1 Message Date
Felix Fontein
520e7c6278 Release 3.0.4. 2025-10-01 06:43:56 +02:00
Felix Fontein
1da1fdc3b0 Prepare 3.0.4. 2025-09-30 22:10:18 +02:00
Felix Fontein
c5135496c8 Add repo configuration to antsibull-nox.toml. 2025-09-26 06:55:46 +02:00
Felix Fontein
05864d366c Fix EE test names. 2025-09-06 22:33:34 +02:00
Felix Fontein
43ba69e495 Remove dead code. (#956) 2025-09-06 21:30:20 +02:00
dependabot[bot]
62b4535465 Bump actions/checkout from 4 to 5 in the ci group (#954)
Bumps the ci group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 4 to 5
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 06:15:55 +02:00
Felix Fontein
c0072d29f5 ansible-core 2.20: avoid deprecated functionality (#953)
* Avoid deprecated functionality.

* Lint.

* Fix typing.

* Python 3.7/3.8 compat.
2025-08-17 22:30:10 +02:00
Felix Fontein
1bfee3c23b 2.19.0 has been released. 2025-08-17 21:15:32 +02:00
Felix Fontein
7f7704ece8 CI: Add Debian 13 Trixie (#952)
* Add Debian 13 Trixie to CI.

* Cannot uninstall cryptography on Debian 13.
2025-08-10 18:54:16 +02:00
Felix Fontein
7cc52204a8 Build docs with ansible-core devel.
Needed for https://github.com/ansible-collections/community.crypto/pull/951.
2025-08-10 14:55:37 +02:00
Felix Fontein
8e76660e80 The next expected release will be 3.1.0. 2025-08-04 19:50:10 +02:00
Felix Fontein
114c98928d Release 3.0.3. 2025-08-04 19:18:38 +02:00
Felix Fontein
ba5c551a29 Increase number of retries from 10 to 20. (#949) 2025-08-03 10:29:55 +02:00
Felix Fontein
09c45551fe Prepare 3.0.3. 2025-08-02 21:02:29 +02:00
Felix Fontein
75413d0b08 Also retry on HTTP statuses 502 and 504. (#947) 2025-08-02 18:25:28 +02:00
Felix Fontein
dfff658f34 Disable another unsuitable ansible-lint rule. 2025-07-30 23:46:17 +02:00
Felix Fontein
1dd771c0c4 Replace Python 3.8 with 3.14 for devel; bump AZP container. (#944) 2025-07-29 17:38:43 +02:00
Felix Fontein
bc16487882 Normalize changelog configs. 2025-07-27 16:35:32 +02:00
Felix Fontein
ec2d662320 The next expected release will be 3.1.0. 2025-07-26 15:35:06 +02:00
Felix Fontein
690561ecd9 Release 3.0.2. 2025-07-26 14:40:11 +02:00
Felix Fontein
1aa313ab96 Bump Alpine 3.21 to 3.22, Fedora 41 to 42, RHEL 9.5 to 9.6, and FreeBSD 14.2 to 14.3. (#943)
Add old versions to stable-2.19 if not present yet.
2025-07-26 12:31:25 +02:00
Felix Fontein
0636123f56 Move EE tests to nox. (#941) 2025-07-25 19:04:30 +02:00
Felix Fontein
05c9e09d20 Prepare 3.0.2. 2025-07-25 14:40:38 +02:00
Felix Fontein
f219cac94c Improve error message when lodaing corrupt private key or private key with wrong passphrase. (#939) 2025-07-25 14:36:54 +02:00
Felix Fontein
b4303b3a32 Replace FreeBSD 13.3 with 13.5. (#937) 2025-07-24 17:43:13 +02:00
Felix Fontein
84f0c7f163 Next expected release is 3.1.0. 2025-07-17 22:29:30 +02:00
19 changed files with 573 additions and 505 deletions

View File

@@ -24,5 +24,6 @@ skip_list:
- risky-file-permissions - risky-file-permissions
- risky-shell-pipe - risky-shell-pipe
- var-naming[no-reserved] - var-naming[no-reserved]
- var-naming[no-role-prefix]
- var-naming[pattern] - var-naming[pattern]
- var-naming[read-only] - var-naming[read-only]

View File

@@ -44,7 +44,7 @@ variables:
resources: resources:
containers: containers:
- container: default - container: default
image: quay.io/ansible/azure-pipelines-test-container:6.0.0 image: quay.io/ansible/azure-pipelines-test-container:7.0.0
pool: Standard pool: Standard
@@ -103,12 +103,12 @@ stages:
parameters: parameters:
testFormat: devel/linux/{0} testFormat: devel/linux/{0}
targets: targets:
- name: Fedora 41 - name: Fedora 42
test: fedora41 test: fedora42
- name: Ubuntu 24.04 - name: Ubuntu 24.04
test: ubuntu2404 test: ubuntu2404
- name: Alpine 3.21 - name: Alpine 3.22
test: alpine321 test: alpine322
groups: groups:
- 1 - 1
- 2 - 2
@@ -122,6 +122,8 @@ stages:
targets: targets:
- name: Fedora 41 - name: Fedora 41
test: fedora41 test: fedora41
- name: Alpine 3.21
test: alpine321
groups: groups:
- 1 - 1
- 2 - 2
@@ -169,9 +171,11 @@ stages:
parameters: parameters:
testFormat: devel/linux-community/{0} testFormat: devel/linux-community/{0}
targets: targets:
- name: Debian Bookworm - name: Debian 13 Trixie
test: debian-13-trixie/3.13
- name: Debian 12 Bookworm
test: debian-bookworm/3.11 test: debian-bookworm/3.11
- name: Debian Bullseye - name: Debian 11 Bullseye
test: debian-bullseye/3.9 test: debian-bullseye/3.9
- name: ArchLinux - name: ArchLinux
test: archlinux/3.13 test: archlinux/3.13
@@ -188,10 +192,10 @@ stages:
parameters: parameters:
testFormat: devel/{0} testFormat: devel/{0}
targets: targets:
- name: Alpine 3.21 - name: Alpine 3.22
test: alpine/3.21 test: alpine/3.22
- name: Fedora 41 - name: Fedora 42
test: fedora/41 test: fedora/42
- name: Ubuntu 22.04 - name: Ubuntu 22.04
test: ubuntu/22.04 test: ubuntu/22.04
- name: Ubuntu 24.04 - name: Ubuntu 24.04
@@ -210,10 +214,10 @@ stages:
test: macos/15.3 test: macos/15.3
- name: RHEL 10.0 - name: RHEL 10.0
test: rhel/10.0 test: rhel/10.0
- name: RHEL 9.5 - name: RHEL 9.6
test: rhel/9.5 test: rhel/9.6
- name: FreeBSD 14.2 - name: FreeBSD 14.3
test: freebsd/14.2 test: freebsd/14.3
- name: FreeBSD 13.5 - name: FreeBSD 13.5
test: freebsd/13.5 test: freebsd/13.5
groups: groups:
@@ -227,8 +231,12 @@ stages:
parameters: parameters:
testFormat: 2.19/{0} testFormat: 2.19/{0}
targets: targets:
- name: RHEL 9.5
test: rhel/9.5
- name: RHEL 10.0 - name: RHEL 10.0
test: rhel/10.0 test: rhel/10.0
- name: FreeBSD 14.2
test: freebsd/14.2
groups: groups:
- 1 - 1
- 2 - 2
@@ -259,8 +267,8 @@ stages:
targets: targets:
- name: RHEL 9.3 - name: RHEL 9.3
test: rhel/9.3 test: rhel/9.3
- name: FreeBSD 13.3 - name: FreeBSD 13.5
test: freebsd/13.3 test: freebsd/13.5
groups: groups:
- 1 - 1
- 2 - 2
@@ -274,11 +282,11 @@ stages:
nameFormat: Python {0} nameFormat: Python {0}
testFormat: devel/generic/{0} testFormat: devel/generic/{0}
targets: targets:
- test: "3.8"
- test: "3.9" - test: "3.9"
- test: "3.10" - test: "3.10"
- test: "3.11" - test: "3.11"
- test: "3.13" - test: "3.13"
- test: "3.14"
groups: groups:
- 1 - 1
- 2 - 2

View File

@@ -21,6 +21,7 @@ jobs:
name: Build Ansible Docs name: Build Ansible Docs
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main
with: with:
ansible-ref: devel
collection-name: community.crypto collection-name: community.crypto
init-lenient: false init-lenient: false
init-fail-on-error: true init-fail-on-error: true

View File

@@ -27,6 +27,7 @@ jobs:
name: Build Ansible Docs name: Build Ansible Docs
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main
with: with:
ansible-ref: devel
collection-name: community.crypto collection-name: community.crypto
init-lenient: false init-lenient: false
init-fail-on-error: true init-fail-on-error: true

View File

@@ -1,172 +0,0 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
name: execution environment
'on':
# Run CI against all pushes (direct commits, also merged PRs), Pull Requests
push:
branches:
- main
- stable-*
pull_request:
# Run CI once per day (at 09:00 UTC)
# This ensures that even if there haven't been commits that we are still testing against latest version of ansible-builder
schedule:
- cron: '0 9 * * *'
env:
NAMESPACE: community
COLLECTION_NAME: crypto
jobs:
build:
name: Build and test EE (${{ matrix.name }})
strategy:
fail-fast: false
matrix:
name:
- ''
ansible_core:
- ''
ansible_runner:
- ''
base_image:
- ''
pre_base:
- ''
extra_vars:
- ''
other_deps:
- ''
exclude:
- ansible_core: ''
include:
- name: ansible-core devel @ RHEL UBI 9
ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz
ansible_runner: ansible-runner
other_deps: |2
python_interpreter:
package_system: python3.12 python3.12-pip python3.12-wheel python3.12-cryptography
python_path: "/usr/bin/python3.12"
base_image: docker.io/redhat/ubi9:latest
pre_base: '"#"'
- name: ansible-core 2.17 @ Rocky Linux 9
ansible_core: https://github.com/ansible/ansible/archive/stable-2.17.tar.gz
ansible_runner: ansible-runner
other_deps: |2
python_interpreter:
package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography
python_path: "/usr/bin/python3.11"
base_image: quay.io/rockylinux/rockylinux:9
pre_base: RUN dnf install -y epel-release
- name: ansible-core 2.18 @ CentOS Stream 9
ansible_core: https://github.com/ansible/ansible/archive/stable-2.18.tar.gz
ansible_runner: ansible-runner
other_deps: |2
python_interpreter:
package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography
python_path: "/usr/bin/python3.11"
base_image: quay.io/centos/centos:stream9
pre_base: '"#"'
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install ansible-builder and ansible-navigator
run: pip install ansible-builder ansible-navigator
- name: Verify requirements
run: ansible-builder introspect --sanitize .
- name: Make sure galaxy.yml has version entry
run: >-
python -c
'import yaml ;
f = open("galaxy.yml", "rb") ;
data = yaml.safe_load(f) ;
f.close() ;
data["version"] = data.get("version") or "0.0.1" ;
f = open("galaxy.yml", "wb") ;
f.write(yaml.dump(data).encode("utf-8")) ;
f.close() ;
'
working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
- name: Build collection
run: |
ansible-galaxy collection build --output-path ../../../
working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
- name: Create files for building execution environment
run: |
COLLECTION_FILENAME="$(ls "${NAMESPACE}-${COLLECTION_NAME}"-*.tar.gz)"
# EE config
cat > execution-environment.yml <<EOF
---
version: 3
dependencies:
ansible_core:
package_pip: ${{ matrix.ansible_core }}
ansible_runner:
package_pip: ${{ matrix.ansible_runner }}
galaxy: requirements.yml
${{ matrix.other_deps }}
images:
base_image:
name: ${{ matrix.base_image }}
additional_build_files:
- src: ${COLLECTION_FILENAME}
dest: src
additional_build_steps:
prepend_base:
- ${{ matrix.pre_base }}
EOF
echo "::group::execution-environment.yml"
cat execution-environment.yml
echo "::endgroup::"
# Requirements
cat > requirements.yml <<EOF
---
collections:
- name: src/${COLLECTION_FILENAME}
type: file
EOF
echo "::group::requirements.yml"
cat requirements.yml
echo "::endgroup::"
- name: Build image based on ${{ matrix.base_image }}
run: |
ansible-builder build --verbosity 3 --tag test-ee:latest --container-runtime podman
- name: Show images
run: podman image ls
- name: Run basic tests
run: >
ansible-navigator run
--mode stdout
--container-engine podman
--pull-policy never
--set-environment-variable ANSIBLE_PRIVATE_ROLE_VARS=true
--execution-environment-image test-ee:latest
-v
all.yml
${{ matrix.extra_vars }}
working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}/tests/ee

View File

@@ -21,8 +21,11 @@ jobs:
name: "Run extra sanity tests" name: "Run extra sanity tests"
steps: steps:
- name: Check out collection - name: Check out collection
uses: actions/checkout@v4 uses: actions/checkout@v5
with: with:
persist-credentials: false persist-credentials: false
- name: Run nox - name: Run nox
uses: ansible-community/antsibull-nox@main uses: ansible-community/antsibull-nox@main
ansible-test:
uses: ansible-community/antsibull-nox/.github/workflows/reusable-nox-matrix.yml@main

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,46 @@ Community Crypto Release Notes
.. contents:: Topics .. contents:: Topics
v3.0.4
======
Release Summary
---------------
Maintenance release.
Bugfixes
--------
- Avoid deprecated functionality in ansible-core 2.20 (https://github.com/ansible-collections/community.crypto/pull/953).
v3.0.3
======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- acme_* modules - also retry on HTTP responses 502 Bad Gateway and 504 Gateway Timeout. The latter is needed for ZeroSSL, which seems to have a lot of 504s (https://github.com/ansible-collections/community.crypto/issues/945, https://github.com/ansible-collections/community.crypto/pull/947).
- acme_* modules - increase the maximum amount of retries from 10 to 20 to accomodate ZeroSSL's buggy implementation (https://github.com/ansible-collections/community.crypto/pull/949).
v3.0.2
======
Release Summary
---------------
Bugfix release.
Bugfixes
--------
- Improve error message when loading a private key fails due to correct private key files or wrong passwords. Also include the original cryptography error since it likely contains more helpful information (https://github.com/ansible-collections/community.crypto/issues/936, https://github.com/ansible-collections/community.crypto/pull/939).
v3.0.1 v3.0.1
====== ======

View File

@@ -5,6 +5,11 @@
[collection_sources] [collection_sources]
"community.internal_test_tools" = "git+https://github.com/ansible-collections/community.internal_test_tools.git,main" "community.internal_test_tools" = "git+https://github.com/ansible-collections/community.internal_test_tools.git,main"
[vcs]
vcs = "git"
development_branch = "main"
stable_branches = [ "stable-*" ]
[sessions] [sessions]
[sessions.lint] [sessions.lint]
@@ -15,14 +20,14 @@ run_flake8 = true
flake8_config = ".flake8" flake8_config = ".flake8"
run_pylint = true run_pylint = true
pylint_rcfile = ".pylintrc" pylint_rcfile = ".pylintrc"
pylint_ansible_core_package = "ansible-core>=2.19.0b4" pylint_ansible_core_package = "ansible-core>=2.19.0"
run_yamllint = true run_yamllint = true
yamllint_config = ".yamllint" yamllint_config = ".yamllint"
yamllint_config_plugins = ".yamllint-docs" yamllint_config_plugins = ".yamllint-docs"
yamllint_config_plugins_examples = ".yamllint-examples" yamllint_config_plugins_examples = ".yamllint-examples"
yamllint_config_extra_docs = ".yamllint-extra-docs" yamllint_config_extra_docs = ".yamllint-extra-docs"
run_mypy = true run_mypy = true
mypy_ansible_core_package = "ansible-core>=2.19.0b4" mypy_ansible_core_package = "ansible-core>=2.19.0"
mypy_config = ".mypy.ini" mypy_config = ".mypy.ini"
mypy_extra_deps = [ mypy_extra_deps = [
"cryptography", "cryptography",
@@ -79,3 +84,36 @@ skip_paths = [
run_galaxy_importer = true run_galaxy_importer = true
[sessions.ansible_lint] [sessions.ansible_lint]
[[sessions.ee_check.execution_environments]]
name = "devel-ubi-9"
description = "ansible-core devel @ RHEL UBI 9"
test_playbooks = ["tests/ee/all.yml"]
config.images.base_image.name = "docker.io/redhat/ubi9:latest"
config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/devel.tar.gz"
config.dependencies.ansible_runner.package_pip = "ansible-runner"
config.dependencies.python_interpreter.package_system = "python3.12 python3.12-pip python3.12-wheel python3.12-cryptography"
config.dependencies.python_interpreter.python_path = "/usr/bin/python3.12"
runtime_environment = {"ANSIBLE_PRIVATE_ROLE_VARS" = "true"}
[[sessions.ee_check.execution_environments]]
name = "2.17-rocky-9"
description = "ansible-core 2.17 @ Rocky Linux 9"
test_playbooks = ["tests/ee/all.yml"]
config.images.base_image.name = "quay.io/rockylinux/rockylinux:9"
config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/stable-2.17.tar.gz"
config.dependencies.ansible_runner.package_pip = "ansible-runner"
config.dependencies.python_interpreter.package_system = "python3.11 python3.11-pip python3.11-wheel python3.11-cryptography"
config.dependencies.python_interpreter.python_path = "/usr/bin/python3.11"
runtime_environment = {"ANSIBLE_PRIVATE_ROLE_VARS" = "true"}
[[sessions.ee_check.execution_environments]]
name = "2.18-centos-stream-9"
description = "ansible-core 2.18 @ CentOS Stream 9"
test_playbooks = ["tests/ee/all.yml"]
config.images.base_image.name = "quay.io/centos/centos:stream9"
config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/stable-2.18.tar.gz"
config.dependencies.ansible_runner.package_pip = "ansible-runner"
config.dependencies.python_interpreter.package_system = "python3.11 python3.11-pip python3.11-wheel python3.11-cryptography"
config.dependencies.python_interpreter.python_path = "/usr/bin/python3.11"
runtime_environment = {"ANSIBLE_PRIVATE_ROLE_VARS" = "true"}

View File

@@ -1841,3 +1841,39 @@ releases:
- 3.0.1.yml - 3.0.1.yml
- 395-csr-key_usage.yml - 395-csr-key_usage.yml
release_date: '2025-07-17' release_date: '2025-07-17'
3.0.2:
changes:
bugfixes:
- Improve error message when loading a private key fails due to correct private
key files or wrong passwords. Also include the original cryptography error
since it likely contains more helpful information (https://github.com/ansible-collections/community.crypto/issues/936,
https://github.com/ansible-collections/community.crypto/pull/939).
release_summary: Bugfix release.
fragments:
- 3.0.2.yml
- 939-private-key-errors.yml
release_date: '2025-07-26'
3.0.3:
changes:
bugfixes:
- acme_* modules - also retry on HTTP responses 502 Bad Gateway and 504 Gateway
Timeout. The latter is needed for ZeroSSL, which seems to have a lot of
504s (https://github.com/ansible-collections/community.crypto/issues/945,
https://github.com/ansible-collections/community.crypto/pull/947).
- acme_* modules - increase the maximum amount of retries from 10 to 20 to
accomodate ZeroSSL's buggy implementation (https://github.com/ansible-collections/community.crypto/pull/949).
release_summary: Bugfix release.
fragments:
- 3.0.3.yml
- 947-acme-retry.yml
- 949-acme-retry.yml
release_date: '2025-08-04'
3.0.4:
changes:
bugfixes:
- Avoid deprecated functionality in ansible-core 2.20 (https://github.com/ansible-collections/community.crypto/pull/953).
release_summary: Maintenance release.
fragments:
- 3.0.4.yml
- 953-deprecations.yml
release_date: '2025-10-01'

View File

@@ -7,6 +7,7 @@ changelog_filename_template: ../CHANGELOG.rst
changelog_filename_version_depth: 0 changelog_filename_version_depth: 0
changes_file: changelog.yaml changes_file: changelog.yaml
changes_format: combined changes_format: combined
ignore_other_fragment_extensions: true
keep_fragments: false keep_fragments: false
mention_ancestor: true mention_ancestor: true
new_plugins_after_name: removed_features new_plugins_after_name: removed_features
@@ -39,3 +40,4 @@ use_fqcn: true
add_plugin_period: true add_plugin_period: true
changelog_nice_yaml: true changelog_nice_yaml: true
changelog_sort: version changelog_sort: version
vcs: auto

View File

@@ -5,7 +5,7 @@
namespace: community namespace: community
name: crypto name: crypto
version: 3.0.1 version: 3.0.4
readme: README.md readme: README.md
authors: authors:
- Ansible (github.com/ansible) - Ansible (github.com/ansible)

View File

@@ -9,8 +9,8 @@
from __future__ import annotations from __future__ import annotations
import typing as t import typing as t
from collections.abc import Mapping
from ansible.module_utils.common._collections_compat import Mapping
from ansible_collections.community.crypto.plugins.module_utils._acme.errors import ( from ansible_collections.community.crypto.plugins.module_utils._acme.errors import (
ACMEProtocolException, ACMEProtocolException,
ModuleFailException, ModuleFailException,
@@ -22,6 +22,11 @@ if t.TYPE_CHECKING:
ACMEClient, ACMEClient,
) )
_JsonMapping = Mapping[str, t.Any]
else:
# Since we need to pass this to t.cast(), we need a version that doesn't break with Python 3.7 and 3.8
_JsonMapping = Mapping
class ACMEAccount: class ACMEAccount:
""" """
@@ -42,7 +47,7 @@ class ACMEAccount:
terms_agreed: bool = False, terms_agreed: bool = False,
allow_creation: bool = True, allow_creation: bool = True,
external_account_binding: dict[str, t.Any] | None = None, external_account_binding: dict[str, t.Any] | None = None,
) -> tuple[bool, dict[str, t.Any] | None]: ) -> tuple[bool, Mapping[str, t.Any] | None]:
""" """
Registers a new ACME account. Returns a pair ``(created, data)``. Registers a new ACME account. Returns a pair ``(created, data)``.
Here, ``created`` is ``True`` if the account was created and Here, ``created`` is ``True`` if the account was created and
@@ -132,7 +137,7 @@ class ACMEAccount:
# Account did not exist # Account did not exist
if "location" in info: if "location" in info:
self.client.set_account_uri(info["location"]) self.client.set_account_uri(info["location"])
return True, result return True, t.cast(_JsonMapping, result)
if info["status"] == 200: if info["status"] == 200:
# Account did exist # Account did exist
if result.get("status") == "deactivated": if result.get("status") == "deactivated":
@@ -147,7 +152,7 @@ class ACMEAccount:
raise ModuleFailException("Account is deactivated") raise ModuleFailException("Account is deactivated")
if "location" in info: if "location" in info:
self.client.set_account_uri(info["location"]) self.client.set_account_uri(info["location"])
return False, result return False, t.cast(_JsonMapping, result)
if ( if (
info["status"] in (400, 404) info["status"] in (400, 404)
and result["type"] == "urn:ietf:params:acme:error:accountDoesNotExist" and result["type"] == "urn:ietf:params:acme:error:accountDoesNotExist"
@@ -236,7 +241,7 @@ class ACMEAccount:
allow_creation: t.Literal[True] = True, allow_creation: t.Literal[True] = True,
remove_account_uri_if_not_exists: bool = False, remove_account_uri_if_not_exists: bool = False,
external_account_binding: dict[str, t.Any] | None = None, external_account_binding: dict[str, t.Any] | None = None,
) -> tuple[bool, dict[str, t.Any]]: ... ) -> tuple[bool, Mapping[str, t.Any]]: ...
@t.overload @t.overload
def setup_account( def setup_account(
@@ -247,7 +252,7 @@ class ACMEAccount:
allow_creation: bool = True, allow_creation: bool = True,
remove_account_uri_if_not_exists: bool = False, remove_account_uri_if_not_exists: bool = False,
external_account_binding: dict[str, t.Any] | None = None, external_account_binding: dict[str, t.Any] | None = None,
) -> tuple[bool, dict[str, t.Any] | None]: ... ) -> tuple[bool, Mapping[str, t.Any] | None]: ...
def setup_account( def setup_account(
self, self,
@@ -257,7 +262,7 @@ class ACMEAccount:
allow_creation: bool = True, allow_creation: bool = True,
remove_account_uri_if_not_exists: bool = False, remove_account_uri_if_not_exists: bool = False,
external_account_binding: dict[str, t.Any] | None = None, external_account_binding: dict[str, t.Any] | None = None,
) -> tuple[bool, dict[str, t.Any] | None]: ) -> tuple[bool, Mapping[str, t.Any] | None]:
""" """
Detect or create an account on the ACME server. For ACME v1, Detect or create an account on the ACME server. For ACME v1,
as the only way (without knowing an account URI) to test if an as the only way (without knowing an account URI) to test if an
@@ -288,7 +293,7 @@ class ACMEAccount:
created = False created = False
# Verify that the account key belongs to the URI. # Verify that the account key belongs to the URI.
# (If update_contact is True, this will be done below.) # (If update_contact is True, this will be done below.)
account_data = self.get_account_data() account_data: Mapping[str, t.Any] | None = self.get_account_data()
if account_data is None: if account_data is None:
if remove_account_uri_if_not_exists and not allow_creation: if remove_account_uri_if_not_exists and not allow_creation:
self.client.account_uri = None self.client.account_uri = None
@@ -314,7 +319,7 @@ class ACMEAccount:
def update_account( def update_account(
self, *, account_data: dict[str, t.Any], contact: list[str] | None = None self, *, account_data: dict[str, t.Any], contact: list[str] | None = None
) -> tuple[bool, dict[str, t.Any]]: ) -> tuple[bool, Mapping[str, t.Any]]:
""" """
Update an account on the ACME server. Check mode is fully respected. Update an account on the ACME server. Check mode is fully respected.
@@ -340,9 +345,11 @@ class ACMEAccount:
return False, dict(account_data) return False, dict(account_data)
# Apply change # Apply change
account_data_res: Mapping[str, t.Any]
if self.client.module.check_mode: if self.client.module.check_mode:
account_data = dict(account_data) account_data_dict = dict(account_data)
account_data.update(update_request) account_data_dict.update(update_request)
account_data_res = account_data_dict
else: else:
raw_account_data, info = self.client.send_signed_request( raw_account_data, info = self.client.send_signed_request(
self.client.account_uri, update_request self.client.account_uri, update_request
@@ -354,9 +361,9 @@ class ACMEAccount:
info=info, info=info,
content_json=account_data, content_json=account_data,
) )
account_data = raw_account_data account_data_res = raw_account_data
return True, account_data return True, account_data_res
__all__ = ("ACMEAccount",) __all__ = ("ACMEAccount",)

View File

@@ -64,9 +64,9 @@ if t.TYPE_CHECKING:
# -1 usually means connection problems # -1 usually means connection problems
RETRY_STATUS_CODES = (-1, 408, 429, 503) RETRY_STATUS_CODES = (-1, 408, 429, 502, 503, 504)
RETRY_COUNT = 10 RETRY_COUNT = 20
def _decode_retry( def _decode_retry(

View File

@@ -25,6 +25,7 @@ from ansible_collections.community.crypto.plugins.module_utils._crypto.pem impor
try: try:
from cryptography import x509 from cryptography import x509
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.hazmat.primitives.serialization import load_pem_private_key
except ImportError: except ImportError:
@@ -168,13 +169,15 @@ def load_privatekey(
priv_key_detail, priv_key_detail,
None if passphrase is None else to_bytes(passphrase), None if passphrase is None else to_bytes(passphrase),
) )
except UnsupportedAlgorithm as exc:
raise OpenSSLBadPassphraseError(f"Unsupported private key type: {exc}") from exc
except TypeError as exc: except TypeError as exc:
raise OpenSSLBadPassphraseError( raise OpenSSLBadPassphraseError(
"Wrong or empty passphrase provided for private key" "Wrong or empty passphrase provided for private key"
) from exc ) from exc
except ValueError as exc: except ValueError as exc:
raise OpenSSLBadPassphraseError( raise OpenSSLBadPassphraseError(
"Wrong passphrase provided for private key" f"Wrong passphrase provided for private key, or private key cannot be parsed: {exc}"
) from exc ) from exc

View File

@@ -320,11 +320,12 @@ def main() -> t.NoReturn:
result["account_uri"] = client.account_uri result["account_uri"] = client.account_uri
result["exists"] = True result["exists"] = True
# Make sure promised data is there # Make sure promised data is there
account_data_dict = dict(account_data)
if "contact" not in account_data: if "contact" not in account_data:
account_data["contact"] = [] account_data_dict["contact"] = []
if client.account_key_data: if client.account_key_data:
account_data["public_account_key"] = client.account_key_data["jwk"] account_data_dict["public_account_key"] = client.account_key_data["jwk"]
result["account"] = account_data result["account"] = account_data_dict
# Retrieve orders list # Retrieve orders list
if ( if (
account_data.get("orders") account_data.get("orders")

View File

@@ -21,8 +21,7 @@ import traceback
import typing as t import typing as t
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.module_utils.basic import SEQUENCETYPE, remove_values from ansible.module_utils.basic import remove_values
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.common.arg_spec import ArgumentSpecValidator from ansible.module_utils.common.arg_spec import ArgumentSpecValidator
from ansible.module_utils.errors import UnsupportedError from ansible.module_utils.errors import UnsupportedError
from ansible.plugins.action import ActionBase from ansible.plugins.action import ActionBase
@@ -164,39 +163,9 @@ class AnsibleActionModule:
if "invocation" not in kwargs: if "invocation" not in kwargs:
kwargs["invocation"] = {"module_args": self.params} kwargs["invocation"] = {"module_args": self.params}
if "warnings" in kwargs:
if isinstance(kwargs["warnings"], list):
for w in kwargs["warnings"]:
self.warn(w)
else:
self.warn(kwargs["warnings"])
if self.__warnings: if self.__warnings:
kwargs["warnings"] = self.__warnings kwargs["warnings"] = self.__warnings
if "deprecations" in kwargs:
if isinstance(kwargs["deprecations"], list):
for d in kwargs["deprecations"]:
if isinstance(d, SEQUENCETYPE) and len(d) == 2:
self.deprecate(d[0], version=d[1])
elif isinstance(d, Mapping):
self.deprecate(
d["msg"],
version=d.get("version"),
date=d.get("date"),
collection_name=d.get("collection_name"),
)
else:
# pylint: disable-next=unknown-option-value
self.deprecate( # pylint: disable=ansible-deprecated-no-version
d
)
else:
# pylint: disable-next=unknown-option-value
self.deprecate( # pylint: disable=ansible-deprecated-no-version
kwargs["deprecations"]
)
if self.__deprecations: if self.__deprecations:
kwargs["deprecations"] = self.__deprecations kwargs["deprecations"] = self.__deprecations

View File

@@ -90,6 +90,32 @@
- "'public_data' not in result" - "'public_data' not in result"
- "'private_data' not in result" - "'private_data' not in result"
- name: ({{ select_crypto_backend }}) Get key 3 info (with wrong passphrase)
community.crypto.openssl_privatekey_info:
path: '{{ remote_tmp_dir }}/privatekey_3.pem'
return_private_key_data: true
select_crypto_backend: '{{ select_crypto_backend }}'
passphrase: blabla
ignore_errors: true
register: result
- name: Check that loading passphrase protected key with wrong passphrase failed
ansible.builtin.assert:
that:
- result is failed
# Check that return values are there
- result.can_load_key is defined
- result.can_parse_key is defined
# Check that return values are correct
- result.can_load_key
- not result.can_parse_key
# Check that additional data isn't there
- "'pulic_key' not in result"
- "'pulic_key_fingerprints' not in result"
- "'type' not in result"
- "'public_data' not in result"
- "'private_data' not in result"
- name: ({{ select_crypto_backend }}) Get key 3 info (with passphrase) - name: ({{ select_crypto_backend }}) Get key 3 info (with passphrase)
community.crypto.openssl_privatekey_info: community.crypto.openssl_privatekey_info:
path: '{{ remote_tmp_dir }}/privatekey_3.pem' path: '{{ remote_tmp_dir }}/privatekey_3.pem'
@@ -155,3 +181,53 @@
- "result.public_data.y > 2" - "result.public_data.y > 2"
- "'private_data' in result" - "'private_data' in result"
- "result.private_data.x > 2" - "result.private_data.x > 2"
- name: ({{ select_crypto_backend }}) Get empty key info
community.crypto.openssl_privatekey_info:
content: ''
return_private_key_data: true
select_crypto_backend: '{{ select_crypto_backend }}'
register: result
ignore_errors: true
- name: Check that empty key loading failed
ansible.builtin.assert:
that:
- result is failed
# Check that return values are there
- result.can_load_key is defined
- result.can_parse_key is defined
# Check that return values are correct
- result.can_load_key
- not result.can_parse_key
# Check that additional data isn't there
- "'pulic_key' not in result"
- "'pulic_key_fingerprints' not in result"
- "'type' not in result"
- "'public_data' not in result"
- "'private_data' not in result"
- name: ({{ select_crypto_backend }}) Get corrupt key info
community.crypto.openssl_privatekey_info:
content: C0RRUPT
return_private_key_data: true
select_crypto_backend: '{{ select_crypto_backend }}'
register: result
ignore_errors: true
- name: Check that corrupt key loading failed
ansible.builtin.assert:
that:
- result is failed
# Check that return values are there
- result.can_load_key is defined
- result.can_parse_key is defined
# Check that return values are correct
- result.can_load_key
- not result.can_parse_key
# Check that additional data isn't there
- "'pulic_key' not in result"
- "'pulic_key_fingerprints' not in result"
- "'type' not in result"
- "'public_data' not in result"
- "'private_data' not in result"

View File

@@ -76,6 +76,8 @@ system_python_version_data:
- '3.9' - '3.9'
'12': '12':
- '3.11' - '3.11'
'13':
- '3.13'
Alpine: Alpine:
'3.16': '3.16':
- '3.10' - '3.10'
@@ -95,3 +97,6 @@ cannot_upgrade_cryptography:
- '3.9' # this is the default container for ansible-core 2.12; upgrading cryptography wrecks pyOpenSSL - '3.9' # this is the default container for ansible-core 2.12; upgrading cryptography wrecks pyOpenSSL
'24': '24':
- '3.12' # ERROR: Cannot uninstall cryptography 41.0.7, RECORD file not found. Hint: The package was installed by debian. - '3.12' # ERROR: Cannot uninstall cryptography 41.0.7, RECORD file not found. Hint: The package was installed by debian.
Debian:
'13':
- '3.13' # ERROR: Cannot uninstall cryptography 43.0.0, RECORD file not found. Hint: The package was installed by debian.