mirror of
https://github.com/ansible-collections/community.crypto.git
synced 2026-05-06 13:22:58 +00:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4509bce5f | ||
|
|
ced0e30506 | ||
|
|
2fb543b144 | ||
|
|
b08f6eefe8 | ||
|
|
65d1881f12 | ||
|
|
b000491514 | ||
|
|
70c4585b88 | ||
|
|
aea3713484 | ||
|
|
7f040011f0 | ||
|
|
c6429eae4f | ||
|
|
d2a30d2801 | ||
|
|
a122be7942 | ||
|
|
61f431dff3 | ||
|
|
b19c83578d | ||
|
|
ddfb18b609 | ||
|
|
095434a4c1 | ||
|
|
8a80ced4b8 | ||
|
|
ef2bb6d510 | ||
|
|
889cfdf47e | ||
|
|
c173449c46 | ||
|
|
c08bae8308 | ||
|
|
80f7b084c0 | ||
|
|
5d24d04adf | ||
|
|
7cc9a70e43 | ||
|
|
5ddfb2c2ca | ||
|
|
242c15bf4c | ||
|
|
867f407401 | ||
|
|
54f49f38f2 | ||
|
|
83d2a782f6 | ||
|
|
d6dd8e0d45 | ||
|
|
9029f8ce34 | ||
|
|
ca23b2ed9a | ||
|
|
664f34f2ac | ||
|
|
1c2c404ca9 | ||
|
|
eef4df9063 | ||
|
|
176da44faf | ||
|
|
619d7d1dfe | ||
|
|
2eab4ec19c | ||
|
|
05eff13ec8 | ||
|
|
4d28266eba | ||
|
|
ba9c50c358 | ||
|
|
e1e5dfccc1 | ||
|
|
1097371cf4 | ||
|
|
0b08d6bc52 | ||
|
|
72ed39a481 | ||
|
|
d4683d941f | ||
|
|
f853108d69 | ||
|
|
045ff10826 | ||
|
|
2a746115ca | ||
|
|
37fddc61d8 | ||
|
|
a050250153 | ||
|
|
42e27a360d | ||
|
|
95b9df187f | ||
|
|
7bbe8f467c | ||
|
|
0c67afb6c3 | ||
|
|
68b7c0d38c | ||
|
|
9ba0e25bfe | ||
|
|
9a64347ea6 | ||
|
|
e4e2b804bc | ||
|
|
4533b3e934 | ||
|
|
fd71773668 | ||
|
|
b17d57f737 | ||
|
|
f5d98e3148 | ||
|
|
5f9536af06 | ||
|
|
7c41b31c37 |
@@ -98,39 +98,6 @@ stages:
|
||||
test: '2.12/sanity/1'
|
||||
- name: Units
|
||||
test: '2.12/units/1'
|
||||
- stage: Ansible_2_11
|
||||
displayName: Sanity & Units 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: Sanity
|
||||
test: '2.11/sanity/1'
|
||||
- name: Units
|
||||
test: '2.11/units/1'
|
||||
- stage: Ansible_2_10
|
||||
displayName: Sanity & Units 2.10
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: Sanity
|
||||
test: '2.10/sanity/1'
|
||||
- name: Units
|
||||
test: '2.10/units/1'
|
||||
- stage: Ansible_2_9
|
||||
displayName: Sanity & Units 2.9
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
targets:
|
||||
- name: Sanity
|
||||
test: '2.9/sanity/1'
|
||||
- name: Units
|
||||
test: '2.9/units/1'
|
||||
### Docker
|
||||
- stage: Docker_devel
|
||||
displayName: Docker devel
|
||||
@@ -138,12 +105,12 @@ stages:
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/linux/{0}/1
|
||||
testFormat: devel/linux/{0}
|
||||
targets:
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
- name: Fedora 36
|
||||
test: fedora36
|
||||
- name: Fedora 37
|
||||
test: fedora37
|
||||
- name: openSUSE 15
|
||||
test: opensuse15
|
||||
- name: Ubuntu 20.04
|
||||
@@ -152,23 +119,29 @@ stages:
|
||||
test: ubuntu2204
|
||||
- name: Alpine 3
|
||||
test: alpine3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Docker_2_14
|
||||
displayName: Docker 2.14
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.14/linux/{0}/1
|
||||
testFormat: 2.14/linux/{0}
|
||||
targets:
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu2204
|
||||
- name: Fedora 36
|
||||
test: fedora36
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Docker_2_13
|
||||
displayName: Docker 2.13
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.13/linux/{0}/1
|
||||
testFormat: 2.13/linux/{0}
|
||||
targets:
|
||||
- name: openSUSE 15 py2
|
||||
test: opensuse15py2
|
||||
@@ -180,54 +153,24 @@ stages:
|
||||
test: ubuntu1804
|
||||
- name: Alpine 3
|
||||
test: alpine3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Docker_2_12
|
||||
displayName: Docker 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.12/linux/{0}/1
|
||||
testFormat: 2.12/linux/{0}
|
||||
targets:
|
||||
- name: CentOS 6
|
||||
test: centos6
|
||||
- name: Fedora 33
|
||||
test: fedora33
|
||||
- stage: Docker_2_11
|
||||
displayName: Docker 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.11/linux/{0}/1
|
||||
targets:
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
- name: Fedora 32
|
||||
test: fedora32
|
||||
- name: Alpine 3
|
||||
test: alpine3
|
||||
- stage: Docker_2_10
|
||||
displayName: Docker 2.10
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.10/linux/{0}/1
|
||||
targets:
|
||||
- name: CentOS 6
|
||||
test: centos6
|
||||
- stage: Docker_2_9
|
||||
displayName: Docker 2.9
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.9/linux/{0}/1
|
||||
targets:
|
||||
- name: Fedora 31
|
||||
test: fedora31
|
||||
- name: Ubuntu 18.04
|
||||
test: ubuntu1804
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
|
||||
### Community Docker
|
||||
- stage: Docker_community_devel
|
||||
@@ -236,14 +179,19 @@ stages:
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/linux-community/{0}/1
|
||||
testFormat: devel/linux-community/{0}
|
||||
targets:
|
||||
- name: Debian Bullseye
|
||||
test: debian-bullseye/3.9
|
||||
- name: ArchLinux
|
||||
test: archlinux/3.10
|
||||
- name: CentOS Stream 8
|
||||
test: centos-stream8/3.8
|
||||
- name: CentOS Stream 8 with Python 3.9
|
||||
test: centos-stream8/3.9
|
||||
- name: CentOS Stream 8 with Python 3.6
|
||||
test: centos-stream8/3.6
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
|
||||
### Remote
|
||||
- stage: Remote_devel
|
||||
@@ -252,88 +200,71 @@ stages:
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/{0}/1
|
||||
testFormat: devel/{0}
|
||||
targets:
|
||||
- name: macOS 12.0
|
||||
test: macos/12.0
|
||||
- name: RHEL 7.9
|
||||
test: rhel/7.9
|
||||
- name: RHEL 9.0
|
||||
test: rhel/9.0
|
||||
- name: FreeBSD 12.3
|
||||
test: freebsd/12.3
|
||||
- name: RHEL 9.1
|
||||
test: rhel/9.1
|
||||
- name: FreeBSD 12.4
|
||||
test: freebsd/12.4
|
||||
- name: FreeBSD 13.1
|
||||
test: freebsd/13.1
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Remote_2_14
|
||||
displayName: Remote 2.14
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.14/{0}/1
|
||||
testFormat: 2.14/{0}
|
||||
targets:
|
||||
- name: RHEL 9.0
|
||||
test: rhel/9.0
|
||||
- name: FreeBSD 12.3
|
||||
test: freebsd/12.3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Remote_2_13
|
||||
displayName: Remote 2.13
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.13/{0}/1
|
||||
testFormat: 2.13/{0}
|
||||
targets:
|
||||
- name: macOS 12.0
|
||||
test: macos/12.0
|
||||
# - name: macOS 12.0
|
||||
# test: macos/12.0
|
||||
- name: RHEL 8.5
|
||||
test: rhel/8.5
|
||||
- name: FreeBSD 13.0
|
||||
test: freebsd/13.0
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Remote_2_12
|
||||
displayName: Remote 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.12/{0}/1
|
||||
testFormat: 2.12/{0}
|
||||
targets:
|
||||
# Not working anymore:
|
||||
# - name: macOS 11.1
|
||||
# test: macos/11.1
|
||||
- name: RHEL 8.4
|
||||
test: rhel/8.4
|
||||
- stage: Remote_2_11
|
||||
displayName: Remote 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.11/{0}/1
|
||||
targets:
|
||||
- name: RHEL 8.3
|
||||
test: rhel/8.3
|
||||
- name: FreeBSD 12.2
|
||||
test: freebsd/12.2
|
||||
- stage: Remote_2_10
|
||||
displayName: Remote 2.10
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.10/{0}/1
|
||||
targets:
|
||||
- name: OS X 10.11
|
||||
test: osx/10.11
|
||||
# - name: macOS 10.15
|
||||
# test: macos/10.15
|
||||
- stage: Remote_2_9
|
||||
displayName: Remote 2.9
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.9/{0}/1
|
||||
targets:
|
||||
- name: 'RHEL 7.8'
|
||||
test: 'rhel/7.8'
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
### Generic
|
||||
- stage: Generic_devel
|
||||
displayName: Generic devel
|
||||
@@ -342,16 +273,19 @@ stages:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: devel/generic/{0}/1
|
||||
testFormat: devel/generic/{0}
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: 3.5
|
||||
- test: 3.6
|
||||
- test: 3.7
|
||||
- test: 3.8
|
||||
- test: 3.9
|
||||
# - test: 3.8
|
||||
# - test: 3.9
|
||||
- test: "3.10"
|
||||
- test: "3.11"
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Generic_2_14
|
||||
displayName: Generic 2.14
|
||||
dependsOn: []
|
||||
@@ -359,9 +293,12 @@ stages:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.14/generic/{0}/1
|
||||
testFormat: 2.14/generic/{0}
|
||||
targets:
|
||||
- test: 3.9
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Generic_2_13
|
||||
displayName: Generic 2.13
|
||||
dependsOn: []
|
||||
@@ -369,9 +306,12 @@ stages:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.13/generic/{0}/1
|
||||
testFormat: 2.13/generic/{0}
|
||||
targets:
|
||||
- test: 3.8
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- stage: Generic_2_12
|
||||
displayName: Generic 2.12
|
||||
dependsOn: []
|
||||
@@ -379,40 +319,13 @@ stages:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.12/generic/{0}/1
|
||||
testFormat: 2.12/generic/{0}
|
||||
targets:
|
||||
- test: 2.6
|
||||
- test: 3.9
|
||||
- stage: Generic_2_11
|
||||
displayName: Generic 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.11/generic/{0}/1
|
||||
targets:
|
||||
- test: 3.8
|
||||
- stage: Generic_2_10
|
||||
displayName: Generic 2.10
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.10/generic/{0}/1
|
||||
targets:
|
||||
- test: 3.6
|
||||
- stage: Generic_2_9
|
||||
displayName: Generic 2.9
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.9/generic/{0}/1
|
||||
targets:
|
||||
- test: 2.7
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
|
||||
## Finally
|
||||
|
||||
@@ -423,30 +336,18 @@ stages:
|
||||
- Ansible_2_14
|
||||
- Ansible_2_13
|
||||
- Ansible_2_12
|
||||
- Ansible_2_11
|
||||
- Ansible_2_10
|
||||
- Ansible_2_9
|
||||
- Remote_devel
|
||||
- Remote_2_14
|
||||
- Remote_2_13
|
||||
- Remote_2_12
|
||||
- Remote_2_11
|
||||
- Remote_2_10
|
||||
- Remote_2_9
|
||||
- Docker_devel
|
||||
- Docker_2_14
|
||||
- Docker_2_13
|
||||
- Docker_2_12
|
||||
- Docker_2_11
|
||||
- Docker_2_10
|
||||
- Docker_2_9
|
||||
- Docker_community_devel
|
||||
- Generic_devel
|
||||
- Generic_2_14
|
||||
- Generic_2_13
|
||||
- Generic_2_12
|
||||
- Generic_2_11
|
||||
- Generic_2_10
|
||||
- Generic_2_9
|
||||
jobs:
|
||||
- template: templates/coverage.yml
|
||||
|
||||
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
192
.github/workflows/ansible-test.yml
vendored
Normal file
192
.github/workflows/ansible-test.yml
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# For the comprehensive list of the inputs supported by the ansible-community/ansible-test-gh-action GitHub Action, see
|
||||
# https://github.com/marketplace/actions/ansible-test
|
||||
|
||||
name: EOL CI
|
||||
on:
|
||||
# Run EOL CI against all pushes (direct commits, also merged PRs), Pull Requests
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- stable-*
|
||||
pull_request:
|
||||
# Run EOL CI once per day (at 09:00 UTC)
|
||||
schedule:
|
||||
- cron: '0 9 * * *'
|
||||
|
||||
jobs:
|
||||
sanity:
|
||||
name: EOL Sanity (Ⓐ${{ matrix.ansible }})
|
||||
strategy:
|
||||
matrix:
|
||||
ansible:
|
||||
- '2.9'
|
||||
- '2.10'
|
||||
- '2.11'
|
||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
||||
# image for these stable branches. The list of branches where this is necessary will
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Perform sanity testing
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
pull-request-change-detection: 'true'
|
||||
testing-type: sanity
|
||||
|
||||
units:
|
||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
||||
# image for these stable branches. The list of branches where this is necessary will
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
name: EOL Units (Ⓐ${{ matrix.ansible }})
|
||||
strategy:
|
||||
# As soon as the first unit test fails, cancel the others to free up the CI queue
|
||||
fail-fast: true
|
||||
matrix:
|
||||
ansible:
|
||||
- '2.9'
|
||||
- '2.10'
|
||||
- '2.11'
|
||||
|
||||
steps:
|
||||
- name: >-
|
||||
Perform unit testing against
|
||||
Ansible version ${{ matrix.ansible }}
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
pull-request-change-detection: 'true'
|
||||
testing-type: units
|
||||
|
||||
integration:
|
||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
||||
# image for these stable branches. The list of branches where this is necessary will
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
name: EOL I (Ⓐ${{ matrix.ansible }}+${{ matrix.docker }}+py${{ matrix.python }}:${{ matrix.target }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ansible:
|
||||
- ''
|
||||
docker:
|
||||
- ''
|
||||
python:
|
||||
- ''
|
||||
target:
|
||||
- ''
|
||||
exclude:
|
||||
- ansible: ''
|
||||
include:
|
||||
# 2.9
|
||||
- ansible: '2.9'
|
||||
docker: fedora31
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.9'
|
||||
docker: fedora31
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.9'
|
||||
docker: ubuntu1804
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.9'
|
||||
docker: ubuntu1804
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.9'
|
||||
docker: default
|
||||
python: '2.7'
|
||||
target: azp/generic/1/
|
||||
- ansible: '2.9'
|
||||
docker: default
|
||||
python: '2.7'
|
||||
target: azp/generic/2/
|
||||
# 2.10
|
||||
- ansible: '2.10'
|
||||
docker: centos6
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.10'
|
||||
docker: centos6
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.10'
|
||||
docker: default
|
||||
python: '3.6'
|
||||
target: azp/generic/1/
|
||||
- ansible: '2.10'
|
||||
docker: default
|
||||
python: '3.6'
|
||||
target: azp/generic/2/
|
||||
# 2.11
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
docker: alpine3
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: alpine3
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
docker: default
|
||||
python: '3.8'
|
||||
target: azp/generic/1/
|
||||
- ansible: '2.11'
|
||||
docker: default
|
||||
python: '3.8'
|
||||
target: azp/generic/2/
|
||||
|
||||
steps:
|
||||
- name: >-
|
||||
Perform integration testing against
|
||||
Ansible version ${{ matrix.ansible }}
|
||||
under Python ${{ matrix.python }}
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
docker-image: ${{ matrix.docker }}
|
||||
integration-continue-on-error: 'false'
|
||||
integration-diff: 'false'
|
||||
integration-retry-on-error: 'true'
|
||||
pre-test-cmd: >-
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git ../../community/general
|
||||
pull-request-change-detection: 'true'
|
||||
target: ${{ matrix.target }}
|
||||
target-python-version: ${{ matrix.python }}
|
||||
testing-type: integration
|
||||
42
.github/workflows/docs-pr.yml
vendored
42
.github/workflows/docs-pr.yml
vendored
@@ -5,12 +5,15 @@
|
||||
|
||||
name: Collection Docs
|
||||
concurrency:
|
||||
group: docs-${{ github.head_ref }}
|
||||
group: docs-pr-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
|
||||
env:
|
||||
GHP_BASE_URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
|
||||
|
||||
jobs:
|
||||
build-docs:
|
||||
permissions:
|
||||
@@ -18,13 +21,37 @@ jobs:
|
||||
name: Build Ansible Docs
|
||||
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main
|
||||
with:
|
||||
collection-name: community.crypto
|
||||
init-lenient: false
|
||||
init-fail-on-error: true
|
||||
squash-hierarchy: true
|
||||
init-project: Community.Crypto Collection
|
||||
init-copyright: Community.Crypto Contributors
|
||||
init-title: Community.Crypto Collection Documentation
|
||||
init-html-short-title: Community.Crypto Collection Docs
|
||||
init-extra-html-theme-options: |
|
||||
documentation_home_url=https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/branch/main/
|
||||
render-file-line: '> * `$<status>` [$<path_tail>](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr/${{ github.event.number }}/$<path_tail>)'
|
||||
|
||||
publish-docs-gh-pages:
|
||||
# for now we won't run this on forks
|
||||
if: github.repository == 'ansible-collections/community.crypto'
|
||||
permissions:
|
||||
contents: write
|
||||
needs: [build-docs]
|
||||
name: Publish Ansible Docs
|
||||
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main
|
||||
with:
|
||||
artifact-name: ${{ needs.build-docs.outputs.artifact-name }}
|
||||
action: ${{ (github.event.action == 'closed' || needs.build-docs.outputs.changed != 'true') && 'teardown' || 'publish' }}
|
||||
secrets:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
comment:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-docs
|
||||
needs: [build-docs, publish-docs-gh-pages]
|
||||
name: PR comments
|
||||
steps:
|
||||
- name: PR comment
|
||||
@@ -42,13 +69,20 @@ jobs:
|
||||
|
||||
Thank you for contribution!✨
|
||||
|
||||
This PR has been merged and your docs changes will be incorporated when they are next published.
|
||||
This PR has been merged and the docs are now incorporated into `main`:
|
||||
${{ env.GHP_BASE_URL }}/branch/main
|
||||
body: |
|
||||
## Docs Build 📝
|
||||
|
||||
Thank you for contribution!✨
|
||||
|
||||
The docsite for **this PR** is available for download as an artifact from this run:
|
||||
The docs for **this PR** have been published here:
|
||||
${{ env.GHP_BASE_URL }}/pr/${{ github.event.number }}
|
||||
|
||||
You can compare to the docs for the `main` branch here:
|
||||
${{ env.GHP_BASE_URL }}/branch/main
|
||||
|
||||
The docsite for **this PR** is also available for download as an artifact from this run:
|
||||
${{ needs.build-docs.outputs.artifact-url }}
|
||||
|
||||
File changes:
|
||||
|
||||
52
.github/workflows/docs-push.yml
vendored
Normal file
52
.github/workflows/docs-push.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
name: Collection Docs
|
||||
concurrency:
|
||||
group: docs-push-${{ github.sha }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- stable-*
|
||||
tags:
|
||||
- '*'
|
||||
# Run CI once per day (at 09:00 UTC)
|
||||
schedule:
|
||||
- cron: '0 9 * * *'
|
||||
# Allow manual trigger (for newer antsibull-docs, sphinx-ansible-theme, ... versions)
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-docs:
|
||||
permissions:
|
||||
contents: read
|
||||
name: Build Ansible Docs
|
||||
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main
|
||||
with:
|
||||
collection-name: community.crypto
|
||||
init-lenient: false
|
||||
init-fail-on-error: true
|
||||
squash-hierarchy: true
|
||||
init-project: Community.Crypto Collection
|
||||
init-copyright: Community.Crypto Contributors
|
||||
init-title: Community.Crypto Collection Documentation
|
||||
init-html-short-title: Community.Crypto Collection Docs
|
||||
init-extra-html-theme-options: |
|
||||
documentation_home_url=https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/branch/main/
|
||||
|
||||
publish-docs-gh-pages:
|
||||
# for now we won't run this on forks
|
||||
if: github.repository == 'ansible-collections/community.crypto'
|
||||
permissions:
|
||||
contents: write
|
||||
needs: [build-docs]
|
||||
name: Publish Ansible Docs
|
||||
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main
|
||||
with:
|
||||
artifact-name: ${{ needs.build-docs.outputs.artifact-name }}
|
||||
secrets:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
2
.github/workflows/ee.yml
vendored
2
.github/workflows/ee.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v3
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
|
||||
2
.github/workflows/reuse.yml
vendored
2
.github/workflows/reuse.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
@@ -5,6 +5,89 @@ Community Crypto Release Notes
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v2.11.0
|
||||
=======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Feature and bugfix release.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- get_certificate - adds ``ciphers`` option for custom cipher selection (https://github.com/ansible-collections/community.crypto/pull/571).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- action plugin helper - fix handling of deprecations for ansible-core 2.14.2 (https://github.com/ansible-collections/community.crypto/pull/572).
|
||||
- execution environment binary dependencies (bindep.txt) - fix ``python3-pyOpenSSL`` dependency resolution on RHEL 9+ / CentOS Stream 9+ platforms (https://github.com/ansible-collections/community.crypto/pull/575).
|
||||
- various plugins - remove unnecessary imports (https://github.com/ansible-collections/community.crypto/pull/569).
|
||||
|
||||
v2.10.0
|
||||
=======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix and feature release.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- openssl_csr, openssl_csr_pipe - prevent invalid values for ``crl_distribution_points`` that do not have one of ``full_name``, ``relative_name``, and ``crl_issuer`` (https://github.com/ansible-collections/community.crypto/pull/560).
|
||||
- openssl_publickey_info - do not crash with internal error when public key cannot be parsed (https://github.com/ansible-collections/community.crypto/pull/551).
|
||||
|
||||
New Plugins
|
||||
-----------
|
||||
|
||||
Filter
|
||||
~~~~~~
|
||||
|
||||
- openssl_csr_info - Retrieve information from OpenSSL Certificate Signing Requests (CSR)
|
||||
- openssl_privatekey_info - Retrieve information from OpenSSL private keys
|
||||
- openssl_publickey_info - Retrieve information from OpenSSL public keys in PEM format
|
||||
- split_pem - Split PEM file contents into multiple objects
|
||||
- x509_certificate_info - Retrieve information from X.509 certificates in PEM format
|
||||
- x509_crl_info - Retrieve information from X.509 CRLs in PEM format
|
||||
|
||||
v2.9.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Regular feature release.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- x509_certificate_info - adds ``issuer_uri`` field in return value based on Authority Information Access data (https://github.com/ansible-collections/community.crypto/pull/530).
|
||||
|
||||
v2.8.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Maintenance release with improved documentation.
|
||||
|
||||
v2.8.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Feature release.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- acme_* modules - handle more gracefully if CA's new nonce call does not return a nonce (https://github.com/ansible-collections/community.crypto/pull/525).
|
||||
- acme_* modules - include symbolic HTTP status codes in error and log messages when available (https://github.com/ansible-collections/community.crypto/pull/524).
|
||||
- openssl_pkcs12 - add option ``encryption_level`` which allows to chose ``compatibility2022`` when cryptography >= 38.0.0 is used to enable a more backwards compatible encryption algorithm. If cryptography uses OpenSSL 3.0.0 or newer, the default algorithm is not compatible with older software (https://github.com/ansible-collections/community.crypto/pull/523).
|
||||
|
||||
v2.7.1
|
||||
======
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# Ansible Community Crypto Collection
|
||||
|
||||
[](https://dev.azure.com/ansible/community.crypto/_build?definitionId=21)
|
||||
[](https://github.com/ansible-collections/community.crypto/actions)
|
||||
[](https://codecov.io/gh/ansible-collections/community.crypto)
|
||||
|
||||
Provides modules for [Ansible](https://www.ansible.com/community) for various cryptographic operations.
|
||||
@@ -25,6 +26,16 @@ The exact requirements for every module are listed in the module documentation.
|
||||
|
||||
Most modules require a recent enough version of [the Python cryptography library](https://pypi.org/project/cryptography/). See the module documentations for the minimal version supported for each module.
|
||||
|
||||
## Collection Documentation
|
||||
|
||||
Browsing the [**latest** collection documentation](https://docs.ansible.com/ansible/latest/collections/community/crypto) will show docs for the _latest version released in the Ansible package_, not the latest version of the collection released on Galaxy.
|
||||
|
||||
Browsing the [**devel** collection documentation](https://docs.ansible.com/ansible/devel/collections/community/crypto) shows docs for the _latest version released on Galaxy_.
|
||||
|
||||
We also separately publish [**latest commit** collection documentation](https://ansible-collections.github.io/community.crypto/branch/main/) which shows docs for the _latest commit in the `main` branch_.
|
||||
|
||||
If you use the Ansible package and do not update collections independently, use **latest**. If you install or update this collection directly from Galaxy, use **devel**. If you are looking to contribute, use **latest commit**.
|
||||
|
||||
## Included content
|
||||
|
||||
- OpenSSL / PKI modules:
|
||||
|
||||
@@ -737,6 +737,59 @@ releases:
|
||||
name: openssl_privatekey_convert
|
||||
namespace: ''
|
||||
release_date: '2022-01-10'
|
||||
2.10.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- openssl_csr, openssl_csr_pipe - prevent invalid values for ``crl_distribution_points``
|
||||
that do not have one of ``full_name``, ``relative_name``, and ``crl_issuer``
|
||||
(https://github.com/ansible-collections/community.crypto/pull/560).
|
||||
- openssl_publickey_info - do not crash with internal error when public key
|
||||
cannot be parsed (https://github.com/ansible-collections/community.crypto/pull/551).
|
||||
release_summary: Bugfix and feature release.
|
||||
fragments:
|
||||
- 2.10.0.yml
|
||||
- 551-publickey-info.yml
|
||||
- 560-openssl_csr-crl_distribution_points.yml
|
||||
plugins:
|
||||
filter:
|
||||
- description: Retrieve information from OpenSSL Certificate Signing Requests
|
||||
(CSR)
|
||||
name: openssl_csr_info
|
||||
namespace: null
|
||||
- description: Retrieve information from OpenSSL private keys
|
||||
name: openssl_privatekey_info
|
||||
namespace: null
|
||||
- description: Retrieve information from OpenSSL public keys in PEM format
|
||||
name: openssl_publickey_info
|
||||
namespace: null
|
||||
- description: Split PEM file contents into multiple objects
|
||||
name: split_pem
|
||||
namespace: null
|
||||
- description: Retrieve information from X.509 certificates in PEM format
|
||||
name: x509_certificate_info
|
||||
namespace: null
|
||||
- description: Retrieve information from X.509 CRLs in PEM format
|
||||
name: x509_crl_info
|
||||
namespace: null
|
||||
release_date: '2023-01-02'
|
||||
2.11.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- action plugin helper - fix handling of deprecations for ansible-core 2.14.2
|
||||
(https://github.com/ansible-collections/community.crypto/pull/572).
|
||||
- execution environment binary dependencies (bindep.txt) - fix ``python3-pyOpenSSL``
|
||||
dependency resolution on RHEL 9+ / CentOS Stream 9+ platforms (https://github.com/ansible-collections/community.crypto/pull/575).
|
||||
- various plugins - remove unnecessary imports (https://github.com/ansible-collections/community.crypto/pull/569).
|
||||
minor_changes:
|
||||
- get_certificate - adds ``ciphers`` option for custom cipher selection (https://github.com/ansible-collections/community.crypto/pull/571).
|
||||
release_summary: Feature and bugfix release.
|
||||
fragments:
|
||||
- 2.11.0.yml
|
||||
- 571_get_certificate_ciphers.yaml
|
||||
- 572-action-module.yml
|
||||
- 575-bindep-python3-pyOpenSSL.yml
|
||||
- remove-unneeded-imports.yml
|
||||
release_date: '2023-02-23'
|
||||
2.2.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
@@ -990,3 +1043,37 @@ releases:
|
||||
- 2.7.1.yml
|
||||
- 519-acme-cryptography.yml
|
||||
release_date: '2022-10-17'
|
||||
2.8.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- acme_* modules - handle more gracefully if CA's new nonce call does not return
|
||||
a nonce (https://github.com/ansible-collections/community.crypto/pull/525).
|
||||
- acme_* modules - include symbolic HTTP status codes in error and log messages
|
||||
when available (https://github.com/ansible-collections/community.crypto/pull/524).
|
||||
- openssl_pkcs12 - add option ``encryption_level`` which allows to chose ``compatibility2022``
|
||||
when cryptography >= 38.0.0 is used to enable a more backwards compatible
|
||||
encryption algorithm. If cryptography uses OpenSSL 3.0.0 or newer, the default
|
||||
algorithm is not compatible with older software (https://github.com/ansible-collections/community.crypto/pull/523).
|
||||
release_summary: Feature release.
|
||||
fragments:
|
||||
- 2.8.0.yml
|
||||
- 523-pkcs12-compat.yml
|
||||
- 524-acme-http-errors.yml
|
||||
- 525-acme-no-nonce.yml
|
||||
release_date: '2022-11-02'
|
||||
2.8.1:
|
||||
changes:
|
||||
release_summary: Maintenance release with improved documentation.
|
||||
fragments:
|
||||
- 2.8.1.yml
|
||||
release_date: '2022-11-06'
|
||||
2.9.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- x509_certificate_info - adds ``issuer_uri`` field in return value based on
|
||||
Authority Information Access data (https://github.com/ansible-collections/community.crypto/pull/530).
|
||||
release_summary: Regular feature release.
|
||||
fragments:
|
||||
- 2.9.0.yml
|
||||
- aia_issuer.yaml
|
||||
release_date: '2022-11-27'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace: community
|
||||
name: crypto
|
||||
version: 2.7.1
|
||||
version: 2.11.0
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible (github.com/ansible)
|
||||
@@ -15,9 +15,7 @@ license:
|
||||
- Apache-2.0
|
||||
- BSD-2-Clause
|
||||
- BSD-3-Clause
|
||||
# TODO: galaxy-importer does not support this license type yet. Uncomment once this has been
|
||||
# fixed and the fix deployed (https://github.com/ansible/galaxy-importer/pull/175).
|
||||
# - PSF-2.0
|
||||
- PSF-2.0
|
||||
#license_file: COPYING
|
||||
tags:
|
||||
- acme
|
||||
|
||||
@@ -11,4 +11,7 @@ openssl [platform:rpm]
|
||||
python3-cryptography [platform:dpkg]
|
||||
python3-cryptography [platform:rpm]
|
||||
python3-openssl [platform:dpkg]
|
||||
python3-pyOpenSSL [platform:rpm]
|
||||
# On RHEL 9+ and CentOS Stream 9+, python3-pyOpenSSL is part of EPEL
|
||||
python3-pyOpenSSL [platform:rpm !platform:rhel !platform:centos]
|
||||
python3-pyOpenSSL [platform:rhel-6 platform:centos-6 platform:rhel-7 platform:centos-7 platform:rhel-8 platform:centos-8]
|
||||
python3-pyOpenSSL [platform:rhel platform:centos !platform:rhel-6 !platform:centos-6 !platform:rhel-7 !platform:centos-7 !platform:rhel-8 !platform:centos-8 epel]
|
||||
|
||||
@@ -7,12 +7,11 @@ requires_ansible: '>=2.9.10'
|
||||
|
||||
action_groups:
|
||||
acme:
|
||||
- acme_inspect
|
||||
- acme_certificate_revoke
|
||||
- acme_certificate
|
||||
- acme_account
|
||||
- acme_account_facts
|
||||
- acme_account_info
|
||||
- acme_inspect
|
||||
- acme_certificate_revoke
|
||||
- acme_certificate
|
||||
- acme_account
|
||||
- acme_account_info
|
||||
|
||||
plugin_routing:
|
||||
modules:
|
||||
|
||||
85
plugins/doc_fragments/attributes.py
Normal file
85
plugins/doc_fragments/attributes.py
Normal file
@@ -0,0 +1,85 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
# Standard documentation fragment
|
||||
DOCUMENTATION = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
check_mode:
|
||||
description: Can run in C(check_mode) and return changed status prediction without modifying target.
|
||||
diff_mode:
|
||||
description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode.
|
||||
'''
|
||||
|
||||
# Should be used together with the standard fragment
|
||||
INFO_MODULE = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
details:
|
||||
- This action does not modify state.
|
||||
diff_mode:
|
||||
support: N/A
|
||||
details:
|
||||
- This action does not modify state.
|
||||
'''
|
||||
|
||||
ACTIONGROUP_ACME = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
action_group:
|
||||
description: Use C(group/acme) or C(group/community.crypto.acme) in C(module_defaults) to set defaults for this module.
|
||||
support: full
|
||||
membership:
|
||||
- community.crypto.acme
|
||||
- acme
|
||||
'''
|
||||
|
||||
FACTS = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
facts:
|
||||
description: Action returns an C(ansible_facts) dictionary that will update existing host facts.
|
||||
'''
|
||||
|
||||
# Should be used together with the standard fragment and the FACTS fragment
|
||||
FACTS_MODULE = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
details:
|
||||
- This action does not modify state.
|
||||
diff_mode:
|
||||
support: N/A
|
||||
details:
|
||||
- This action does not modify state.
|
||||
facts:
|
||||
support: full
|
||||
'''
|
||||
|
||||
FILES = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
safe_file_operations:
|
||||
description: Uses Ansible's strict file operation functions to ensure proper permissions and avoid data corruption.
|
||||
'''
|
||||
|
||||
FLOW = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
action:
|
||||
description: Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller.
|
||||
async:
|
||||
description: Supports being used with the C(async) keyword.
|
||||
'''
|
||||
313
plugins/filter/openssl_csr_info.py
Normal file
313
plugins/filter/openssl_csr_info.py
Normal file
@@ -0,0 +1,313 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: openssl_csr_info
|
||||
short_description: Retrieve information from OpenSSL Certificate Signing Requests (CSR)
|
||||
version_added: 2.10.0
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
description:
|
||||
- Provided an OpenSSL Certificate Signing Requests (CSR), retrieve information.
|
||||
- This is a filter version of the M(community.crypto.openssl_csr_info) module.
|
||||
options:
|
||||
_input:
|
||||
description:
|
||||
- The content of the OpenSSL CSR.
|
||||
type: string
|
||||
required: true
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.name_encoding
|
||||
seealso:
|
||||
- module: community.crypto.openssl_csr_info
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Show the Subject Alt Names of the CSR
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{
|
||||
(
|
||||
lookup('ansible.builtin.file', '/path/to/cert.csr')
|
||||
| community.crypto.openssl_csr_info
|
||||
).subject_alt_name | join(', ')
|
||||
}}
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
_value:
|
||||
description:
|
||||
- Information on the certificate.
|
||||
type: dict
|
||||
contains:
|
||||
signature_valid:
|
||||
description:
|
||||
- Whether the CSR's signature is valid.
|
||||
- In case the check returns C(false), the module will fail.
|
||||
returned: success
|
||||
type: bool
|
||||
basic_constraints:
|
||||
description: Entries in the C(basic_constraints) extension, or C(none) if extension is not present.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ['CA:TRUE', 'pathlen:1']
|
||||
basic_constraints_critical:
|
||||
description: Whether the C(basic_constraints) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
extended_key_usage:
|
||||
description: Entries in the C(extended_key_usage) extension, or C(none) if extension is not present.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: [Biometric Info, DVCS, Time Stamping]
|
||||
extended_key_usage_critical:
|
||||
description: Whether the C(extended_key_usage) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
extensions_by_oid:
|
||||
description: Returns a dictionary for every extension OID
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
critical:
|
||||
description: Whether the extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
value:
|
||||
description:
|
||||
- The Base64 encoded value (in DER format) of the extension.
|
||||
- B(Note) that depending on the C(cryptography) version used, it is
|
||||
not possible to extract the ASN.1 content of the extension, but only
|
||||
to provide the re-encoded content of the extension in case it was
|
||||
parsed by C(cryptography). This should usually result in exactly the
|
||||
same value, except if the original extension value was malformed.
|
||||
returned: success
|
||||
type: str
|
||||
sample: "MAMCAQU="
|
||||
sample: {"1.3.6.1.5.5.7.1.24": { "critical": false, "value": "MAMCAQU="}}
|
||||
key_usage:
|
||||
description: Entries in the C(key_usage) extension, or C(none) if extension is not present.
|
||||
returned: success
|
||||
type: str
|
||||
sample: [Key Agreement, Data Encipherment]
|
||||
key_usage_critical:
|
||||
description: Whether the C(key_usage) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
subject_alt_name:
|
||||
description:
|
||||
- Entries in the C(subject_alt_name) extension, or C(none) if extension is not present.
|
||||
- See I(name_encoding) for how IDNs are handled.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
|
||||
subject_alt_name_critical:
|
||||
description: Whether the C(subject_alt_name) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
ocsp_must_staple:
|
||||
description: C(true) if the OCSP Must Staple extension is present, C(none) otherwise.
|
||||
returned: success
|
||||
type: bool
|
||||
ocsp_must_staple_critical:
|
||||
description: Whether the C(ocsp_must_staple) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
name_constraints_permitted:
|
||||
description: List of permitted subtrees to sign certificates for.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ['email:.somedomain.com']
|
||||
name_constraints_excluded:
|
||||
description:
|
||||
- List of excluded subtrees the CA cannot sign certificates for.
|
||||
- Is C(none) if extension is not present.
|
||||
- See I(name_encoding) for how IDNs are handled.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ['email:.com']
|
||||
name_constraints_critical:
|
||||
description:
|
||||
- Whether the C(name_constraints) extension is critical.
|
||||
- Is C(none) if extension is not present.
|
||||
returned: success
|
||||
type: bool
|
||||
subject:
|
||||
description:
|
||||
- The CSR's subject as a dictionary.
|
||||
- Note that for repeated values, only the last one will be returned.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: {"commonName": "www.example.com", "emailAddress": "test@example.com"}
|
||||
subject_ordered:
|
||||
description: The CSR's subject as an ordered list of tuples.
|
||||
returned: success
|
||||
type: list
|
||||
elements: list
|
||||
sample: [["commonName", "www.example.com"], ["emailAddress": "test@example.com"]]
|
||||
public_key:
|
||||
description: CSR's public key in PEM format
|
||||
returned: success
|
||||
type: str
|
||||
sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."
|
||||
public_key_type:
|
||||
description:
|
||||
- The CSR's public key's type.
|
||||
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
|
||||
- Will start with C(unknown) if the key type cannot be determined.
|
||||
returned: success
|
||||
type: str
|
||||
sample: RSA
|
||||
public_key_data:
|
||||
description:
|
||||
- Public key data. Depends on the public key's type.
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
size:
|
||||
description:
|
||||
- Bit size of modulus (RSA) or prime number (DSA).
|
||||
type: int
|
||||
returned: When C(public_key_type=RSA) or C(public_key_type=DSA)
|
||||
modulus:
|
||||
description:
|
||||
- The RSA key's modulus.
|
||||
type: int
|
||||
returned: When C(public_key_type=RSA)
|
||||
exponent:
|
||||
description:
|
||||
- The RSA key's public exponent.
|
||||
type: int
|
||||
returned: When C(public_key_type=RSA)
|
||||
p:
|
||||
description:
|
||||
- The C(p) value for DSA.
|
||||
- This is the prime modulus upon which arithmetic takes place.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA)
|
||||
q:
|
||||
description:
|
||||
- The C(q) value for DSA.
|
||||
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
|
||||
multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA)
|
||||
g:
|
||||
description:
|
||||
- The C(g) value for DSA.
|
||||
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA)
|
||||
curve:
|
||||
description:
|
||||
- The curve's name for ECC.
|
||||
type: str
|
||||
returned: When C(public_key_type=ECC)
|
||||
exponent_size:
|
||||
description:
|
||||
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
|
||||
type: int
|
||||
returned: When C(public_key_type=ECC)
|
||||
x:
|
||||
description:
|
||||
- The C(x) coordinate for the public point on the elliptic curve.
|
||||
type: int
|
||||
returned: When C(public_key_type=ECC)
|
||||
y:
|
||||
description:
|
||||
- For C(public_key_type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
|
||||
- For C(public_key_type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA) or C(public_key_type=ECC)
|
||||
public_key_fingerprints:
|
||||
description:
|
||||
- Fingerprints of CSR's public key.
|
||||
- For every hash algorithm available, the fingerprint is computed.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
|
||||
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
|
||||
subject_key_identifier:
|
||||
description:
|
||||
- The CSR's subject key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(SubjectKeyIdentifier) extension is not present.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
authority_key_identifier:
|
||||
description:
|
||||
- The CSR's authority key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
authority_cert_issuer:
|
||||
description:
|
||||
- The CSR's authority cert issuer as a list of general names.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
- See I(name_encoding) for how IDNs are handled.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
|
||||
authority_cert_serial_number:
|
||||
description:
|
||||
- The CSR's authority cert serial number.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 12345
|
||||
'''
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
OpenSSLObjectError,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.csr_info import (
|
||||
get_csr_info,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
|
||||
|
||||
|
||||
def openssl_csr_info_filter(data, name_encoding='ignore'):
|
||||
'''Extract information from X.509 PEM certificate.'''
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError('The community.crypto.openssl_csr_info input must be a text type, not %s' % type(data))
|
||||
if not isinstance(name_encoding, string_types):
|
||||
raise AnsibleFilterError('The name_encoding option must be of a text type, not %s' % type(name_encoding))
|
||||
name_encoding = to_native(name_encoding)
|
||||
if name_encoding not in ('ignore', 'idna', 'unicode'):
|
||||
raise AnsibleFilterError('The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' % name_encoding)
|
||||
|
||||
module = FilterModuleMock({'name_encoding': name_encoding})
|
||||
try:
|
||||
return get_csr_info(module, 'cryptography', content=to_bytes(data), validate_signature=True)
|
||||
except OpenSSLObjectError as exc:
|
||||
raise AnsibleFilterError(to_native(exc))
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
'''Ansible jinja2 filters'''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'openssl_csr_info': openssl_csr_info_filter,
|
||||
}
|
||||
193
plugins/filter/openssl_privatekey_info.py
Normal file
193
plugins/filter/openssl_privatekey_info.py
Normal file
@@ -0,0 +1,193 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: openssl_privatekey_info
|
||||
short_description: Retrieve information from OpenSSL private keys
|
||||
version_added: 2.10.0
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
description:
|
||||
- Provided an OpenSSL private keys, retrieve information.
|
||||
- This is a filter version of the M(community.crypto.openssl_privatekey_info) module.
|
||||
options:
|
||||
_input:
|
||||
description:
|
||||
- The content of the OpenSSL private key.
|
||||
type: string
|
||||
required: true
|
||||
passphrase:
|
||||
description:
|
||||
- The passphrase for the private key.
|
||||
type: str
|
||||
return_private_key_data:
|
||||
description:
|
||||
- Whether to return private key data.
|
||||
- Only set this to C(true) when you want private information about this key to
|
||||
be extracted.
|
||||
- "B(WARNING:) you have to make sure that private key data is not accidentally logged!"
|
||||
type: bool
|
||||
default: false
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.name_encoding
|
||||
seealso:
|
||||
- module: community.crypto.openssl_privatekey_info
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Show the Subject Alt Names of the CSR
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{
|
||||
(
|
||||
lookup('ansible.builtin.file', '/path/to/cert.csr')
|
||||
| community.crypto.openssl_privatekey_info
|
||||
).subject_alt_name | join(', ')
|
||||
}}
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
_value:
|
||||
description:
|
||||
- Information on the certificate.
|
||||
type: dict
|
||||
contains:
|
||||
public_key:
|
||||
description: Private key's public key in PEM format.
|
||||
returned: success
|
||||
type: str
|
||||
sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."
|
||||
public_key_fingerprints:
|
||||
description:
|
||||
- Fingerprints of private key's public key.
|
||||
- For every hash algorithm available, the fingerprint is computed.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
|
||||
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
|
||||
type:
|
||||
description:
|
||||
- The key's type.
|
||||
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
|
||||
- Will start with C(unknown) if the key type cannot be determined.
|
||||
returned: success
|
||||
type: str
|
||||
sample: RSA
|
||||
public_data:
|
||||
description:
|
||||
- Public key data. Depends on key type.
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
size:
|
||||
description:
|
||||
- Bit size of modulus (RSA) or prime number (DSA).
|
||||
type: int
|
||||
returned: When C(type=RSA) or C(type=DSA)
|
||||
modulus:
|
||||
description:
|
||||
- The RSA key's modulus.
|
||||
type: int
|
||||
returned: When C(type=RSA)
|
||||
exponent:
|
||||
description:
|
||||
- The RSA key's public exponent.
|
||||
type: int
|
||||
returned: When C(type=RSA)
|
||||
p:
|
||||
description:
|
||||
- The C(p) value for DSA.
|
||||
- This is the prime modulus upon which arithmetic takes place.
|
||||
type: int
|
||||
returned: When C(type=DSA)
|
||||
q:
|
||||
description:
|
||||
- The C(q) value for DSA.
|
||||
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
|
||||
multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(type=DSA)
|
||||
g:
|
||||
description:
|
||||
- The C(g) value for DSA.
|
||||
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(type=DSA)
|
||||
curve:
|
||||
description:
|
||||
- The curve's name for ECC.
|
||||
type: str
|
||||
returned: When C(type=ECC)
|
||||
exponent_size:
|
||||
description:
|
||||
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
|
||||
type: int
|
||||
returned: When C(type=ECC)
|
||||
x:
|
||||
description:
|
||||
- The C(x) coordinate for the public point on the elliptic curve.
|
||||
type: int
|
||||
returned: When C(type=ECC)
|
||||
y:
|
||||
description:
|
||||
- For C(type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
|
||||
- For C(type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
|
||||
type: int
|
||||
returned: When C(type=DSA) or C(type=ECC)
|
||||
private_data:
|
||||
description:
|
||||
- Private key data. Depends on key type.
|
||||
returned: success and when I(return_private_key_data) is set to C(true)
|
||||
type: dict
|
||||
'''
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
OpenSSLObjectError,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.privatekey_info import (
|
||||
PrivateKeyParseError,
|
||||
get_privatekey_info,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
|
||||
|
||||
|
||||
def openssl_privatekey_info_filter(data, passphrase=None, return_private_key_data=False):
|
||||
'''Extract information from X.509 PEM certificate.'''
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError('The community.crypto.openssl_privatekey_info input must be a text type, not %s' % type(data))
|
||||
if passphrase is not None and not isinstance(passphrase, string_types):
|
||||
raise AnsibleFilterError('The passphrase option must be a text type, not %s' % type(passphrase))
|
||||
if not isinstance(return_private_key_data, bool):
|
||||
raise AnsibleFilterError('The return_private_key_data option must be a boolean, not %s' % type(return_private_key_data))
|
||||
|
||||
module = FilterModuleMock({})
|
||||
try:
|
||||
result = get_privatekey_info(module, 'cryptography', content=to_bytes(data), passphrase=passphrase, return_private_key_data=return_private_key_data)
|
||||
result.pop('can_parse_key', None)
|
||||
result.pop('key_is_consistent', None)
|
||||
return result
|
||||
except PrivateKeyParseError as exc:
|
||||
raise AnsibleFilterError(exc.error_message)
|
||||
except OpenSSLObjectError as exc:
|
||||
raise AnsibleFilterError(to_native(exc))
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
'''Ansible jinja2 filters'''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'openssl_privatekey_info': openssl_privatekey_info_filter,
|
||||
}
|
||||
162
plugins/filter/openssl_publickey_info.py
Normal file
162
plugins/filter/openssl_publickey_info.py
Normal file
@@ -0,0 +1,162 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: openssl_publickey_info
|
||||
short_description: Retrieve information from OpenSSL public keys in PEM format
|
||||
version_added: 2.10.0
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
description:
|
||||
- Provided a public key in OpenSSL PEM format, retrieve information.
|
||||
- This is a filter version of the M(community.crypto.openssl_publickey_info) module.
|
||||
options:
|
||||
_input:
|
||||
description:
|
||||
- The content of the OpenSSL PEM public key.
|
||||
type: string
|
||||
required: true
|
||||
seealso:
|
||||
- module: community.crypto.openssl_publickey_info
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Show the type of a public key
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{
|
||||
(
|
||||
lookup('ansible.builtin.file', '/path/to/public-key.pem')
|
||||
| community.crypto.openssl_publickey_info
|
||||
).type
|
||||
}}
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
_value:
|
||||
description:
|
||||
- Information on the public key.
|
||||
type: dict
|
||||
contains:
|
||||
fingerprints:
|
||||
description:
|
||||
- Fingerprints of public key.
|
||||
- For every hash algorithm available, the fingerprint is computed.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
|
||||
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
|
||||
type:
|
||||
description:
|
||||
- The key's type.
|
||||
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
|
||||
- Will start with C(unknown) if the key type cannot be determined.
|
||||
returned: success
|
||||
type: str
|
||||
sample: RSA
|
||||
public_data:
|
||||
description:
|
||||
- Public key data. Depends on key type.
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
size:
|
||||
description:
|
||||
- Bit size of modulus (RSA) or prime number (DSA).
|
||||
type: int
|
||||
returned: When C(type=RSA) or C(type=DSA)
|
||||
modulus:
|
||||
description:
|
||||
- The RSA key's modulus.
|
||||
type: int
|
||||
returned: When C(type=RSA)
|
||||
exponent:
|
||||
description:
|
||||
- The RSA key's public exponent.
|
||||
type: int
|
||||
returned: When C(type=RSA)
|
||||
p:
|
||||
description:
|
||||
- The C(p) value for DSA.
|
||||
- This is the prime modulus upon which arithmetic takes place.
|
||||
type: int
|
||||
returned: When C(type=DSA)
|
||||
q:
|
||||
description:
|
||||
- The C(q) value for DSA.
|
||||
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
|
||||
multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(type=DSA)
|
||||
g:
|
||||
description:
|
||||
- The C(g) value for DSA.
|
||||
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(type=DSA)
|
||||
curve:
|
||||
description:
|
||||
- The curve's name for ECC.
|
||||
type: str
|
||||
returned: When C(type=ECC)
|
||||
exponent_size:
|
||||
description:
|
||||
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
|
||||
type: int
|
||||
returned: When C(type=ECC)
|
||||
x:
|
||||
description:
|
||||
- The C(x) coordinate for the public point on the elliptic curve.
|
||||
type: int
|
||||
returned: When C(type=ECC)
|
||||
y:
|
||||
description:
|
||||
- For C(type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
|
||||
- For C(type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
|
||||
type: int
|
||||
returned: When C(type=DSA) or C(type=ECC)
|
||||
'''
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
OpenSSLObjectError,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.publickey_info import (
|
||||
PublicKeyParseError,
|
||||
get_publickey_info,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
|
||||
|
||||
|
||||
def openssl_publickey_info_filter(data):
|
||||
'''Extract information from OpenSSL PEM public key.'''
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError('The community.crypto.openssl_publickey_info input must be a text type, not %s' % type(data))
|
||||
|
||||
module = FilterModuleMock({})
|
||||
try:
|
||||
return get_publickey_info(module, 'cryptography', content=to_bytes(data))
|
||||
except PublicKeyParseError as exc:
|
||||
raise AnsibleFilterError(exc.error_message)
|
||||
except OpenSSLObjectError as exc:
|
||||
raise AnsibleFilterError(to_native(exc))
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
'''Ansible jinja2 filters'''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'openssl_publickey_info': openssl_publickey_info_filter,
|
||||
}
|
||||
64
plugins/filter/split_pem.py
Normal file
64
plugins/filter/split_pem.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: split_pem
|
||||
short_description: Split PEM file contents into multiple objects
|
||||
version_added: 2.10.0
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
description:
|
||||
- Split PEM file contents into multiple PEM objects. Comments or invalid parts are ignored.
|
||||
options:
|
||||
_input:
|
||||
description:
|
||||
- The PEM contents to split.
|
||||
type: string
|
||||
required: true
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Print all CA certificates
|
||||
ansible.builtin.debug:
|
||||
msg: '{{ item }}'
|
||||
loop: >-
|
||||
{{ lookup('ansible.builtin.file', '/path/to/ca-bundle.pem') | community.crypto.split_pem }}
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
_value:
|
||||
description:
|
||||
- A list of PEM file contents.
|
||||
type: list
|
||||
elements: string
|
||||
'''
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import split_pem_list
|
||||
|
||||
|
||||
def split_pem_filter(data):
|
||||
'''Split PEM file.'''
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError('The community.crypto.split_pem input must be a text type, not %s' % type(data))
|
||||
|
||||
data = to_text(data)
|
||||
return split_pem_list(data)
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
'''Ansible jinja2 filters'''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'split_pem': split_pem_filter,
|
||||
}
|
||||
346
plugins/filter/x509_certificate_info.py
Normal file
346
plugins/filter/x509_certificate_info.py
Normal file
@@ -0,0 +1,346 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: x509_certificate_info
|
||||
short_description: Retrieve information from X.509 certificates in PEM format
|
||||
version_added: 2.10.0
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
description:
|
||||
- Provided a X.509 certificate in PEM format, retrieve information.
|
||||
- This is a filter version of the M(community.crypto.x509_certificate_info) module.
|
||||
options:
|
||||
_input:
|
||||
description:
|
||||
- The content of the X.509 certificate in PEM format.
|
||||
type: string
|
||||
required: true
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.name_encoding
|
||||
seealso:
|
||||
- module: community.crypto.x509_certificate_info
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Show the Subject Alt Names of the certificate
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{
|
||||
(
|
||||
lookup('ansible.builtin.file', '/path/to/cert.pem')
|
||||
| community.crypto.x509_certificate_info
|
||||
).subject_alt_name | join(', ')
|
||||
}}
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
_value:
|
||||
description:
|
||||
- Information on the certificate.
|
||||
type: dict
|
||||
contains:
|
||||
expired:
|
||||
description: Whether the certificate is expired (in other words, C(notAfter) is in the past).
|
||||
returned: success
|
||||
type: bool
|
||||
basic_constraints:
|
||||
description: Entries in the C(basic_constraints) extension, or C(none) if extension is not present.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ["CA:TRUE", "pathlen:1"]
|
||||
basic_constraints_critical:
|
||||
description: Whether the C(basic_constraints) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
extended_key_usage:
|
||||
description: Entries in the C(extended_key_usage) extension, or C(none) if extension is not present.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: [Biometric Info, DVCS, Time Stamping]
|
||||
extended_key_usage_critical:
|
||||
description: Whether the C(extended_key_usage) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
extensions_by_oid:
|
||||
description: Returns a dictionary for every extension OID.
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
critical:
|
||||
description: Whether the extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
value:
|
||||
description:
|
||||
- The Base64 encoded value (in DER format) of the extension.
|
||||
- B(Note) that depending on the C(cryptography) version used, it is
|
||||
not possible to extract the ASN.1 content of the extension, but only
|
||||
to provide the re-encoded content of the extension in case it was
|
||||
parsed by C(cryptography). This should usually result in exactly the
|
||||
same value, except if the original extension value was malformed.
|
||||
returned: success
|
||||
type: str
|
||||
sample: "MAMCAQU="
|
||||
sample: {"1.3.6.1.5.5.7.1.24": { "critical": false, "value": "MAMCAQU="}}
|
||||
key_usage:
|
||||
description: Entries in the C(key_usage) extension, or C(none) if extension is not present.
|
||||
returned: success
|
||||
type: str
|
||||
sample: [Key Agreement, Data Encipherment]
|
||||
key_usage_critical:
|
||||
description: Whether the C(key_usage) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
subject_alt_name:
|
||||
description:
|
||||
- Entries in the C(subject_alt_name) extension, or C(none) if extension is not present.
|
||||
- See I(name_encoding) for how IDNs are handled.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
|
||||
subject_alt_name_critical:
|
||||
description: Whether the C(subject_alt_name) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
ocsp_must_staple:
|
||||
description: C(true) if the OCSP Must Staple extension is present, C(none) otherwise.
|
||||
returned: success
|
||||
type: bool
|
||||
ocsp_must_staple_critical:
|
||||
description: Whether the C(ocsp_must_staple) extension is critical.
|
||||
returned: success
|
||||
type: bool
|
||||
issuer:
|
||||
description:
|
||||
- The certificate's issuer.
|
||||
- Note that for repeated values, only the last one will be returned.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: {"organizationName": "Ansible", "commonName": "ca.example.com"}
|
||||
issuer_ordered:
|
||||
description: The certificate's issuer as an ordered list of tuples.
|
||||
returned: success
|
||||
type: list
|
||||
elements: list
|
||||
sample: [["organizationName", "Ansible"], ["commonName": "ca.example.com"]]
|
||||
subject:
|
||||
description:
|
||||
- The certificate's subject as a dictionary.
|
||||
- Note that for repeated values, only the last one will be returned.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: {"commonName": "www.example.com", "emailAddress": "test@example.com"}
|
||||
subject_ordered:
|
||||
description: The certificate's subject as an ordered list of tuples.
|
||||
returned: success
|
||||
type: list
|
||||
elements: list
|
||||
sample: [["commonName", "www.example.com"], ["emailAddress": "test@example.com"]]
|
||||
not_after:
|
||||
description: C(notAfter) date as ASN.1 TIME.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '20190413202428Z'
|
||||
not_before:
|
||||
description: C(notBefore) date as ASN.1 TIME.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '20190331202428Z'
|
||||
public_key:
|
||||
description: Certificate's public key in PEM format.
|
||||
returned: success
|
||||
type: str
|
||||
sample: "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A..."
|
||||
public_key_type:
|
||||
description:
|
||||
- The certificate's public key's type.
|
||||
- One of C(RSA), C(DSA), C(ECC), C(Ed25519), C(X25519), C(Ed448), or C(X448).
|
||||
- Will start with C(unknown) if the key type cannot be determined.
|
||||
returned: success
|
||||
type: str
|
||||
sample: RSA
|
||||
public_key_data:
|
||||
description:
|
||||
- Public key data. Depends on the public key's type.
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
size:
|
||||
description:
|
||||
- Bit size of modulus (RSA) or prime number (DSA).
|
||||
type: int
|
||||
returned: When C(public_key_type=RSA) or C(public_key_type=DSA)
|
||||
modulus:
|
||||
description:
|
||||
- The RSA key's modulus.
|
||||
type: int
|
||||
returned: When C(public_key_type=RSA)
|
||||
exponent:
|
||||
description:
|
||||
- The RSA key's public exponent.
|
||||
type: int
|
||||
returned: When C(public_key_type=RSA)
|
||||
p:
|
||||
description:
|
||||
- The C(p) value for DSA.
|
||||
- This is the prime modulus upon which arithmetic takes place.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA)
|
||||
q:
|
||||
description:
|
||||
- The C(q) value for DSA.
|
||||
- This is a prime that divides C(p - 1), and at the same time the order of the subgroup of the
|
||||
multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA)
|
||||
g:
|
||||
description:
|
||||
- The C(g) value for DSA.
|
||||
- This is the element spanning the subgroup of the multiplicative group of the prime field used.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA)
|
||||
curve:
|
||||
description:
|
||||
- The curve's name for ECC.
|
||||
type: str
|
||||
returned: When C(public_key_type=ECC)
|
||||
exponent_size:
|
||||
description:
|
||||
- The maximum number of bits of a private key. This is basically the bit size of the subgroup used.
|
||||
type: int
|
||||
returned: When C(public_key_type=ECC)
|
||||
x:
|
||||
description:
|
||||
- The C(x) coordinate for the public point on the elliptic curve.
|
||||
type: int
|
||||
returned: When C(public_key_type=ECC)
|
||||
y:
|
||||
description:
|
||||
- For C(public_key_type=ECC), this is the C(y) coordinate for the public point on the elliptic curve.
|
||||
- For C(public_key_type=DSA), this is the publicly known group element whose discrete logarithm w.r.t. C(g) is the private key.
|
||||
type: int
|
||||
returned: When C(public_key_type=DSA) or C(public_key_type=ECC)
|
||||
public_key_fingerprints:
|
||||
description:
|
||||
- Fingerprints of certificate's public key.
|
||||
- For every hash algorithm available, the fingerprint is computed.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
|
||||
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
|
||||
fingerprints:
|
||||
description:
|
||||
- Fingerprints of the DER-encoded form of the whole certificate.
|
||||
- For every hash algorithm available, the fingerprint is computed.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
|
||||
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
|
||||
signature_algorithm:
|
||||
description: The signature algorithm used to sign the certificate.
|
||||
returned: success
|
||||
type: str
|
||||
sample: sha256WithRSAEncryption
|
||||
serial_number:
|
||||
description: The certificate's serial number.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1234
|
||||
version:
|
||||
description: The certificate version.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 3
|
||||
subject_key_identifier:
|
||||
description:
|
||||
- The certificate's subject key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(SubjectKeyIdentifier) extension is not present.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
authority_key_identifier:
|
||||
description:
|
||||
- The certificate's authority key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
authority_cert_issuer:
|
||||
description:
|
||||
- The certificate's authority cert issuer as a list of general names.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
- See I(name_encoding) for how IDNs are handled.
|
||||
returned: success
|
||||
type: list
|
||||
elements: str
|
||||
sample: ["DNS:www.ansible.com", "IP:1.2.3.4"]
|
||||
authority_cert_serial_number:
|
||||
description:
|
||||
- The certificate's authority cert serial number.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 12345
|
||||
ocsp_uri:
|
||||
description: The OCSP responder URI, if included in the certificate. Will be
|
||||
C(none) if no OCSP responder URI is included.
|
||||
returned: success
|
||||
type: str
|
||||
issuer_uri:
|
||||
description: The Issuer URI, if included in the certificate. Will be
|
||||
C(none) if no issuer URI is included.
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
OpenSSLObjectError,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.certificate_info import (
|
||||
get_certificate_info,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
|
||||
|
||||
|
||||
def x509_certificate_info_filter(data, name_encoding='ignore'):
|
||||
'''Extract information from X.509 PEM certificate.'''
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError('The community.crypto.x509_certificate_info input must be a text type, not %s' % type(data))
|
||||
if not isinstance(name_encoding, string_types):
|
||||
raise AnsibleFilterError('The name_encoding option must be of a text type, not %s' % type(name_encoding))
|
||||
name_encoding = to_native(name_encoding)
|
||||
if name_encoding not in ('ignore', 'idna', 'unicode'):
|
||||
raise AnsibleFilterError('The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' % name_encoding)
|
||||
|
||||
module = FilterModuleMock({'name_encoding': name_encoding})
|
||||
try:
|
||||
return get_certificate_info(module, 'cryptography', content=to_bytes(data))
|
||||
except OpenSSLObjectError as exc:
|
||||
raise AnsibleFilterError(to_native(exc))
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
'''Ansible jinja2 filters'''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'x509_certificate_info': x509_certificate_info_filter,
|
||||
}
|
||||
196
plugins/filter/x509_crl_info.py
Normal file
196
plugins/filter/x509_crl_info.py
Normal file
@@ -0,0 +1,196 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: x509_crl_info
|
||||
short_description: Retrieve information from X.509 CRLs in PEM format
|
||||
version_added: 2.10.0
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
description:
|
||||
- Provided a X.509 crl in PEM format, retrieve information.
|
||||
- This is a filter version of the M(community.crypto.x509_crl_info) module.
|
||||
options:
|
||||
_input:
|
||||
description:
|
||||
- The content of the X.509 CRL in PEM format.
|
||||
type: string
|
||||
required: true
|
||||
list_revoked_certificates:
|
||||
description:
|
||||
- If set to C(false), the list of revoked certificates is not included in the result.
|
||||
- This is useful when retrieving information on large CRL files. Enumerating all revoked
|
||||
certificates can take some time, including serializing the result as JSON, sending it to
|
||||
the Ansible controller, and decoding it again.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 1.7.0
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.name_encoding
|
||||
seealso:
|
||||
- module: community.crypto.x509_crl_info
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Show the Organization Name of the CRL's subject
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{
|
||||
(
|
||||
lookup('ansible.builtin.file', '/path/to/cert.pem')
|
||||
| community.crypto.x509_crl_info
|
||||
).issuer.organizationName
|
||||
}}
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
_value:
|
||||
description:
|
||||
- Information on the CRL.
|
||||
type: dict
|
||||
contains:
|
||||
format:
|
||||
description:
|
||||
- Whether the CRL is in PEM format (C(pem)) or in DER format (C(der)).
|
||||
returned: success
|
||||
type: str
|
||||
sample: pem
|
||||
issuer:
|
||||
description:
|
||||
- The CRL's issuer.
|
||||
- Note that for repeated values, only the last one will be returned.
|
||||
- See I(name_encoding) for how IDNs are handled.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: {"organizationName": "Ansible", "commonName": "ca.example.com"}
|
||||
issuer_ordered:
|
||||
description: The CRL's issuer as an ordered list of tuples.
|
||||
returned: success
|
||||
type: list
|
||||
elements: list
|
||||
sample: [["organizationName", "Ansible"], ["commonName": "ca.example.com"]]
|
||||
last_update:
|
||||
description: The point in time from which this CRL can be trusted as ASN.1 TIME.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '20190413202428Z'
|
||||
next_update:
|
||||
description: The point in time from which a new CRL will be issued and the client has to check for it as ASN.1 TIME.
|
||||
returned: success
|
||||
type: str
|
||||
sample: '20190413202428Z'
|
||||
digest:
|
||||
description: The signature algorithm used to sign the CRL.
|
||||
returned: success
|
||||
type: str
|
||||
sample: sha256WithRSAEncryption
|
||||
revoked_certificates:
|
||||
description: List of certificates to be revoked.
|
||||
returned: success if I(list_revoked_certificates=true)
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
serial_number:
|
||||
description: Serial number of the certificate.
|
||||
type: int
|
||||
sample: 1234
|
||||
revocation_date:
|
||||
description: The point in time the certificate was revoked as ASN.1 TIME.
|
||||
type: str
|
||||
sample: '20190413202428Z'
|
||||
issuer:
|
||||
description:
|
||||
- The certificate's issuer.
|
||||
- See I(name_encoding) for how IDNs are handled.
|
||||
type: list
|
||||
elements: str
|
||||
sample: ["DNS:ca.example.org"]
|
||||
issuer_critical:
|
||||
description: Whether the certificate issuer extension is critical.
|
||||
type: bool
|
||||
sample: false
|
||||
reason:
|
||||
description:
|
||||
- The value for the revocation reason extension.
|
||||
- One of C(unspecified), C(key_compromise), C(ca_compromise), C(affiliation_changed), C(superseded),
|
||||
C(cessation_of_operation), C(certificate_hold), C(privilege_withdrawn), C(aa_compromise), and
|
||||
C(remove_from_crl).
|
||||
type: str
|
||||
sample: key_compromise
|
||||
reason_critical:
|
||||
description: Whether the revocation reason extension is critical.
|
||||
type: bool
|
||||
sample: false
|
||||
invalidity_date:
|
||||
description: |
|
||||
The point in time it was known/suspected that the private key was compromised
|
||||
or that the certificate otherwise became invalid as ASN.1 TIME.
|
||||
type: str
|
||||
sample: '20190413202428Z'
|
||||
invalidity_date_critical:
|
||||
description: Whether the invalidity date extension is critical.
|
||||
type: bool
|
||||
sample: false
|
||||
'''
|
||||
|
||||
import base64
|
||||
import binascii
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
OpenSSLObjectError,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import (
|
||||
identify_pem_format,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.crl_info import (
|
||||
get_crl_info,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.plugin_utils.filter_module import FilterModuleMock
|
||||
|
||||
|
||||
def x509_crl_info_filter(data, name_encoding='ignore', list_revoked_certificates=True):
|
||||
'''Extract information from X.509 PEM certificate.'''
|
||||
if not isinstance(data, string_types):
|
||||
raise AnsibleFilterError('The community.crypto.x509_crl_info input must be a text type, not %s' % type(data))
|
||||
if not isinstance(name_encoding, string_types):
|
||||
raise AnsibleFilterError('The name_encoding option must be of a text type, not %s' % type(name_encoding))
|
||||
if not isinstance(list_revoked_certificates, bool):
|
||||
raise AnsibleFilterError('The list_revoked_certificates option must be a boolean, not %s' % type(list_revoked_certificates))
|
||||
name_encoding = to_native(name_encoding)
|
||||
if name_encoding not in ('ignore', 'idna', 'unicode'):
|
||||
raise AnsibleFilterError('The name_encoding option must be one of the values "ignore", "idna", or "unicode", not "%s"' % name_encoding)
|
||||
|
||||
data = to_bytes(data)
|
||||
if not identify_pem_format(data):
|
||||
try:
|
||||
data = base64.b64decode(to_native(data))
|
||||
except (binascii.Error, TypeError, ValueError, UnicodeEncodeError) as e:
|
||||
pass
|
||||
|
||||
module = FilterModuleMock({'name_encoding': name_encoding})
|
||||
try:
|
||||
return get_crl_info(module, content=data, list_revoked_certificates=list_revoked_certificates)
|
||||
except OpenSSLObjectError as exc:
|
||||
raise AnsibleFilterError(to_native(exc))
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
'''Ansible jinja2 filters'''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'x509_crl_info': x509_crl_info_filter,
|
||||
}
|
||||
@@ -38,6 +38,7 @@ from ansible_collections.community.crypto.plugins.module_utils.acme.errors impor
|
||||
NetworkException,
|
||||
ModuleFailException,
|
||||
KeyParsingError,
|
||||
format_http_status,
|
||||
)
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.acme.utils import (
|
||||
@@ -45,7 +46,7 @@ from ansible_collections.community.crypto.plugins.module_utils.acme.utils import
|
||||
)
|
||||
|
||||
try:
|
||||
import ipaddress
|
||||
import ipaddress # noqa: F401, pylint: disable=unused-import
|
||||
except ImportError:
|
||||
HAS_IPADDRESS = False
|
||||
IPADDRESS_IMPORT_ERROR = traceback.format_exc()
|
||||
@@ -69,7 +70,7 @@ def _decode_retry(module, response, info, retry_count):
|
||||
retry_after = min(max(1, int(info.get('retry-after'))), 60)
|
||||
except (TypeError, ValueError) as dummy:
|
||||
retry_after = 10
|
||||
module.log('Retrieved a %d HTTP status on %s, retrying in %s seconds' % (info['status'], info['url'], retry_after))
|
||||
module.log('Retrieved a %s HTTP status on %s, retrying in %s seconds' % (format_http_status(info['status']), info['url'], retry_after))
|
||||
|
||||
time.sleep(retry_after)
|
||||
return True
|
||||
@@ -138,8 +139,15 @@ class ACMEDirectory(object):
|
||||
retry_count += 1
|
||||
continue
|
||||
if info['status'] not in (200, 204):
|
||||
raise NetworkException("Failed to get replay-nonce, got status {0}".format(info['status']))
|
||||
return info['replay-nonce']
|
||||
raise NetworkException("Failed to get replay-nonce, got status {0}".format(format_http_status(info['status'])))
|
||||
if 'replay-nonce' in info:
|
||||
return info['replay-nonce']
|
||||
self.module.log(
|
||||
'HEAD to {0} did return status {1}, but no replay-nonce header!'.format(url, format_http_status(info['status'])))
|
||||
if retry_count >= 5:
|
||||
raise ACMEProtocolException(
|
||||
self.module, msg='Was not able to obtain nonce, giving up after 5 retries', info=info, response=response)
|
||||
retry_count += 1
|
||||
|
||||
|
||||
class ACMEClient(object):
|
||||
|
||||
@@ -10,6 +10,14 @@ __metaclass__ = type
|
||||
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
from ansible.module_utils.six import binary_type, PY3
|
||||
from ansible.module_utils.six.moves.http_client import responses as http_responses
|
||||
|
||||
|
||||
def format_http_status(status_code):
|
||||
expl = http_responses.get(status_code)
|
||||
if not expl:
|
||||
return str(status_code)
|
||||
return '%d %s' % (status_code, expl)
|
||||
|
||||
|
||||
def format_error_problem(problem, subproblem_prefix=''):
|
||||
@@ -87,9 +95,10 @@ class ACMEProtocolException(ModuleFailException):
|
||||
extras['http_status'] = code
|
||||
if code is not None and code >= 400 and content_json is not None and 'type' in content_json:
|
||||
if 'status' in content_json and content_json['status'] != code:
|
||||
code = 'status {problem_code} (HTTP status: {http_code})'.format(http_code=code, problem_code=content_json['status'])
|
||||
code = 'status {problem_code} (HTTP status: {http_code})'.format(
|
||||
http_code=format_http_status(code), problem_code=content_json['status'])
|
||||
else:
|
||||
code = 'status {problem_code}'.format(problem_code=code)
|
||||
code = 'status {problem_code}'.format(problem_code=format_http_status(code))
|
||||
subproblems = content_json.pop('subproblems', None)
|
||||
add_msg = ' {problem}.'.format(problem=format_error_problem(content_json))
|
||||
extras['problem'] = content_json
|
||||
@@ -103,12 +112,12 @@ class ACMEProtocolException(ModuleFailException):
|
||||
problem=format_error_problem(problem, subproblem_prefix='{0}.'.format(index)),
|
||||
)
|
||||
else:
|
||||
code = 'HTTP status {code}'.format(code=code)
|
||||
code = 'HTTP status {code}'.format(code=format_http_status(code))
|
||||
if content_json is not None:
|
||||
add_msg = ' The JSON error result: {content}'.format(content=content_json)
|
||||
elif content is not None:
|
||||
add_msg = ' The raw error result: {content}'.format(content=to_text(content))
|
||||
msg = '{msg} for {url} with {code}'.format(msg=msg, url=url, code=code)
|
||||
msg = '{msg} for {url} with {code}'.format(msg=msg, url=url, code=format_http_status(code))
|
||||
elif content_json is not None:
|
||||
add_msg = ' The JSON result: {content}'.format(content=content_json)
|
||||
elif content is not None:
|
||||
|
||||
@@ -14,7 +14,7 @@ import re
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.common.text.converters import to_text, to_bytes
|
||||
from ansible.module_utils.common.text.converters import to_text, to_bytes, to_native
|
||||
from ansible.module_utils.six.moves.urllib.parse import urlparse, urlunparse, ParseResult
|
||||
|
||||
from ._asn1 import serialize_asn1_string_as_der
|
||||
@@ -138,7 +138,7 @@ def cryptography_get_extensions_from_cert(cert):
|
||||
der = backend._ffi.buffer(data.data, data.length)[:]
|
||||
entry = dict(
|
||||
critical=(crit == 1),
|
||||
value=base64.b64encode(der),
|
||||
value=to_native(base64.b64encode(der)),
|
||||
)
|
||||
try:
|
||||
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
|
||||
@@ -155,7 +155,7 @@ def cryptography_get_extensions_from_cert(cert):
|
||||
for ext in cert.extensions:
|
||||
result[ext.oid.dotted_string] = dict(
|
||||
critical=ext.critical,
|
||||
value=base64.b64encode(ext.value.public_bytes()),
|
||||
value=to_native(base64.b64encode(ext.value.public_bytes())),
|
||||
)
|
||||
|
||||
return result
|
||||
@@ -198,7 +198,7 @@ def cryptography_get_extensions_from_csr(csr):
|
||||
der = backend._ffi.buffer(data.data, data.length)[:]
|
||||
entry = dict(
|
||||
critical=(crit == 1),
|
||||
value=base64.b64encode(der),
|
||||
value=to_native(base64.b64encode(der)),
|
||||
)
|
||||
try:
|
||||
oid = obj2txt(backend._lib, backend._ffi, backend._lib.X509_EXTENSION_get_object(ext))
|
||||
@@ -215,7 +215,7 @@ def cryptography_get_extensions_from_csr(csr):
|
||||
for ext in csr.extensions:
|
||||
result[ext.oid.dotted_string] = dict(
|
||||
critical=ext.critical,
|
||||
value=base64.b64encode(ext.value.public_bytes()),
|
||||
value=to_native(base64.b64encode(ext.value.public_bytes())),
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@@ -139,6 +139,10 @@ class CertificateInfoRetrieval(object):
|
||||
def _get_ocsp_uri(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_issuer_uri(self):
|
||||
pass
|
||||
|
||||
def get_info(self, prefer_one_fingerprint=False):
|
||||
result = dict()
|
||||
self.cert = load_certificate(None, content=self.content, backend=self.backend)
|
||||
@@ -167,7 +171,7 @@ class CertificateInfoRetrieval(object):
|
||||
result['not_after'] = not_after.strftime(TIMESTAMP_FORMAT)
|
||||
result['expired'] = not_after < datetime.datetime.utcnow()
|
||||
|
||||
result['public_key'] = self._get_public_key_pem()
|
||||
result['public_key'] = to_native(self._get_public_key_pem())
|
||||
|
||||
public_key_info = get_publickey_info(
|
||||
self.module,
|
||||
@@ -200,6 +204,7 @@ class CertificateInfoRetrieval(object):
|
||||
result['serial_number'] = self._get_serial_number()
|
||||
result['extensions_by_oid'] = self._get_all_extensions()
|
||||
result['ocsp_uri'] = self._get_ocsp_uri()
|
||||
result['issuer_uri'] = self._get_issuer_uri()
|
||||
|
||||
return result
|
||||
|
||||
@@ -365,6 +370,17 @@ class CertificateInfoRetrievalCryptography(CertificateInfoRetrieval):
|
||||
pass
|
||||
return None
|
||||
|
||||
def _get_issuer_uri(self):
|
||||
try:
|
||||
ext = self.cert.extensions.get_extension_for_class(x509.AuthorityInformationAccess)
|
||||
for desc in ext.value:
|
||||
if desc.access_method == x509.oid.AuthorityInformationAccessOID.CA_ISSUERS:
|
||||
if isinstance(desc.access_location, x509.UniformResourceIdentifier):
|
||||
return desc.access_location.value
|
||||
except x509.ExtensionNotFound as dummy:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def get_certificate_info(module, backend, content, prefer_one_fingerprint=False):
|
||||
if backend == 'cryptography':
|
||||
|
||||
@@ -270,8 +270,12 @@ def parse_crl_distribution_points(module, crl_distribution_points):
|
||||
reasons=None,
|
||||
)
|
||||
if parse_crl_distribution_point['full_name'] is not None:
|
||||
if not parse_crl_distribution_point['full_name']:
|
||||
raise OpenSSLObjectError('full_name must not be empty')
|
||||
params['full_name'] = [cryptography_get_name(name, 'full name') for name in parse_crl_distribution_point['full_name']]
|
||||
if parse_crl_distribution_point['relative_name'] is not None:
|
||||
if not parse_crl_distribution_point['relative_name']:
|
||||
raise OpenSSLObjectError('relative_name must not be empty')
|
||||
try:
|
||||
params['relative_name'] = cryptography_parse_relative_distinguished_name(parse_crl_distribution_point['relative_name'])
|
||||
except Exception:
|
||||
@@ -280,6 +284,8 @@ def parse_crl_distribution_points(module, crl_distribution_points):
|
||||
raise OpenSSLObjectError('Cannot specify relative_name for cryptography < 1.6')
|
||||
raise
|
||||
if parse_crl_distribution_point['crl_issuer'] is not None:
|
||||
if not parse_crl_distribution_point['crl_issuer']:
|
||||
raise OpenSSLObjectError('crl_issuer must not be empty')
|
||||
params['crl_issuer'] = [cryptography_get_name(name, 'CRL issuer') for name in parse_crl_distribution_point['crl_issuer']]
|
||||
if parse_crl_distribution_point['reasons'] is not None:
|
||||
reasons = []
|
||||
@@ -287,7 +293,7 @@ def parse_crl_distribution_points(module, crl_distribution_points):
|
||||
reasons.append(REVOCATION_REASON_MAP[reason])
|
||||
params['reasons'] = frozenset(reasons)
|
||||
result.append(cryptography.x509.DistributionPoint(**params))
|
||||
except OpenSSLObjectError as e:
|
||||
except (OpenSSLObjectError, ValueError) as e:
|
||||
raise OpenSSLObjectError('Error while parsing CRL distribution point #{index}: {error}'.format(index=index, error=e))
|
||||
return result
|
||||
|
||||
@@ -651,7 +657,8 @@ def get_csr_argument_spec():
|
||||
'aa_compromise',
|
||||
]),
|
||||
),
|
||||
mutually_exclusive=[('full_name', 'relative_name')]
|
||||
mutually_exclusive=[('full_name', 'relative_name')],
|
||||
required_one_of=[('full_name', 'relative_name', 'crl_issuer')],
|
||||
),
|
||||
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography']),
|
||||
),
|
||||
|
||||
@@ -133,7 +133,7 @@ class CSRInfoRetrieval(object):
|
||||
result['name_constraints_critical'],
|
||||
) = self._get_name_constraints()
|
||||
|
||||
result['public_key'] = self._get_public_key_pem()
|
||||
result['public_key'] = to_native(self._get_public_key_pem())
|
||||
|
||||
public_key_info = get_publickey_info(
|
||||
self.module,
|
||||
|
||||
@@ -214,7 +214,7 @@ class PrivateKeyInfoRetrieval(object):
|
||||
except OpenSSLObjectError as exc:
|
||||
raise PrivateKeyParseError(to_native(exc), result)
|
||||
|
||||
result['public_key'] = self._get_public_key(binary=False)
|
||||
result['public_key'] = to_native(self._get_public_key(binary=False))
|
||||
pk = self._get_public_key(binary=True)
|
||||
result['public_key_fingerprints'] = get_fingerprint_of_bytes(
|
||||
pk, prefer_one=prefer_one_fingerprint) if pk is not None else dict()
|
||||
|
||||
@@ -112,7 +112,7 @@ class PublicKeyInfoRetrieval(object):
|
||||
try:
|
||||
self.key = load_publickey(content=self.content, backend=self.backend)
|
||||
except OpenSSLObjectError as e:
|
||||
raise PublicKeyParseError(to_native(e))
|
||||
raise PublicKeyParseError(to_native(e), {})
|
||||
|
||||
pk = self._get_public_key(binary=True)
|
||||
result['fingerprints'] = get_fingerprint_of_bytes(
|
||||
|
||||
@@ -8,6 +8,6 @@ from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
# This import is only to maintain backwards compatibility
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import (
|
||||
from ansible_collections.community.crypto.plugins.module_utils.openssh.utils import ( # noqa: F401, pylint: disable=unused-import
|
||||
parse_openssh_version
|
||||
)
|
||||
|
||||
@@ -15,4 +15,4 @@ __metaclass__ = type
|
||||
#
|
||||
# from ansible.module_utils.compat.version import LooseVersion
|
||||
|
||||
from ._version import LooseVersion
|
||||
from ._version import LooseVersion # noqa: F401, pylint: disable=unused-import
|
||||
|
||||
@@ -15,15 +15,15 @@ module: acme_account
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
short_description: Create, modify or delete ACME accounts
|
||||
description:
|
||||
- "Allows to create, modify or delete accounts with a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module only works with the ACME v2 protocol."
|
||||
- "Allows to create, modify or delete accounts with a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module only works with the ACME v2 protocol."
|
||||
notes:
|
||||
- "The M(community.crypto.acme_certificate) module also allows to do basic account management.
|
||||
When using both modules, it is recommended to disable account management
|
||||
for M(community.crypto.acme_certificate). For that, use the C(modify_account) option of
|
||||
M(community.crypto.acme_certificate)."
|
||||
- "The M(community.crypto.acme_certificate) module also allows to do basic account management.
|
||||
When using both modules, it is recommended to disable account management
|
||||
for M(community.crypto.acme_certificate). For that, use the C(modify_account) option of
|
||||
M(community.crypto.acme_certificate)."
|
||||
seealso:
|
||||
- name: Automatic Certificate Management Environment (ACME)
|
||||
description: The specification of the ACME protocol (RFC 8555).
|
||||
@@ -37,8 +37,14 @@ seealso:
|
||||
- module: community.crypto.acme_inspect
|
||||
description: Allows to debug problems.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.acme
|
||||
|
||||
- community.crypto.acme
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.actiongroup_acme
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
|
||||
@@ -15,16 +15,20 @@ module: acme_account_info
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
short_description: Retrieves information on ACME accounts
|
||||
description:
|
||||
- "Allows to retrieve information on accounts a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module only works with the ACME v2 protocol."
|
||||
- "Allows to retrieve information on accounts a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module only works with the ACME v2 protocol."
|
||||
notes:
|
||||
- "The M(community.crypto.acme_account) module allows to modify, create and delete ACME
|
||||
accounts."
|
||||
- "This module was called C(acme_account_facts) before Ansible 2.8. The usage
|
||||
did not change."
|
||||
- Supports C(check_mode).
|
||||
- "The M(community.crypto.acme_account) module allows to modify, create and delete ACME
|
||||
accounts."
|
||||
- "This module was called C(acme_account_facts) before Ansible 2.8. The usage
|
||||
did not change."
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.acme
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.actiongroup_acme
|
||||
- community.crypto.attributes.info_module
|
||||
options:
|
||||
retrieve_orders:
|
||||
description:
|
||||
@@ -45,8 +49,6 @@ options:
|
||||
seealso:
|
||||
- module: community.crypto.acme_account
|
||||
description: Allows to create, modify or delete an ACME account.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.acme
|
||||
|
||||
'''
|
||||
|
||||
|
||||
@@ -15,35 +15,35 @@ module: acme_certificate
|
||||
author: "Michael Gruener (@mgruener)"
|
||||
short_description: Create SSL/TLS certificates with the ACME protocol
|
||||
description:
|
||||
- "Create and renew SSL/TLS certificates with a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/) or
|
||||
L(Buypass,https://www.buypass.com/). The current implementation
|
||||
supports the C(http-01), C(dns-01) and C(tls-alpn-01) challenges."
|
||||
- "To use this module, it has to be executed twice. Either as two
|
||||
different tasks in the same run or during two runs. Note that the output
|
||||
of the first run needs to be recorded and passed to the second run as the
|
||||
module argument C(data)."
|
||||
- "Between these two tasks you have to fulfill the required steps for the
|
||||
chosen challenge by whatever means necessary. For C(http-01) that means
|
||||
creating the necessary challenge file on the destination webserver. For
|
||||
C(dns-01) the necessary dns record has to be created. For C(tls-alpn-01)
|
||||
the necessary certificate has to be created and served.
|
||||
It is I(not) the responsibility of this module to perform these steps."
|
||||
- "For details on how to fulfill these challenges, you might have to read through
|
||||
L(the main ACME specification,https://tools.ietf.org/html/rfc8555#section-8)
|
||||
and the L(TLS-ALPN-01 specification,https://www.rfc-editor.org/rfc/rfc8737.html#section-3).
|
||||
Also, consider the examples provided for this module."
|
||||
- "The module includes experimental support for IP identifiers according to
|
||||
the L(RFC 8738,https://www.rfc-editor.org/rfc/rfc8738.html)."
|
||||
- "Create and renew SSL/TLS certificates with a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/) or
|
||||
L(Buypass,https://www.buypass.com/). The current implementation
|
||||
supports the C(http-01), C(dns-01) and C(tls-alpn-01) challenges."
|
||||
- "To use this module, it has to be executed twice. Either as two
|
||||
different tasks in the same run or during two runs. Note that the output
|
||||
of the first run needs to be recorded and passed to the second run as the
|
||||
module argument C(data)."
|
||||
- "Between these two tasks you have to fulfill the required steps for the
|
||||
chosen challenge by whatever means necessary. For C(http-01) that means
|
||||
creating the necessary challenge file on the destination webserver. For
|
||||
C(dns-01) the necessary dns record has to be created. For C(tls-alpn-01)
|
||||
the necessary certificate has to be created and served.
|
||||
It is I(not) the responsibility of this module to perform these steps."
|
||||
- "For details on how to fulfill these challenges, you might have to read through
|
||||
L(the main ACME specification,https://tools.ietf.org/html/rfc8555#section-8)
|
||||
and the L(TLS-ALPN-01 specification,https://www.rfc-editor.org/rfc/rfc8737.html#section-3).
|
||||
Also, consider the examples provided for this module."
|
||||
- "The module includes experimental support for IP identifiers according to
|
||||
the L(RFC 8738,https://www.rfc-editor.org/rfc/rfc8738.html)."
|
||||
notes:
|
||||
- "At least one of C(dest) and C(fullchain_dest) must be specified."
|
||||
- "This module includes basic account management functionality.
|
||||
If you want to have more control over your ACME account, use the
|
||||
M(community.crypto.acme_account) module and disable account management
|
||||
for this module using the C(modify_account) option."
|
||||
- "This module was called C(letsencrypt) before Ansible 2.6. The usage
|
||||
did not change."
|
||||
- "At least one of C(dest) and C(fullchain_dest) must be specified."
|
||||
- "This module includes basic account management functionality.
|
||||
If you want to have more control over your ACME account, use the
|
||||
M(community.crypto.acme_account) module and disable account management
|
||||
for this module using the C(modify_account) option."
|
||||
- "This module was called C(letsencrypt) before Ansible 2.6. The usage
|
||||
did not change."
|
||||
seealso:
|
||||
- name: The Let's Encrypt documentation
|
||||
description: Documentation for the Let's Encrypt Certification Authority.
|
||||
@@ -78,8 +78,17 @@ seealso:
|
||||
- module: community.crypto.acme_inspect
|
||||
description: Allows to debug problems.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.acme
|
||||
|
||||
- community.crypto.acme
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
- community.crypto.attributes.actiongroup_acme
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: none
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
account_email:
|
||||
description:
|
||||
|
||||
@@ -15,18 +15,17 @@ module: acme_certificate_revoke
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
short_description: Revoke certificates with the ACME protocol
|
||||
description:
|
||||
- "Allows to revoke certificates issued by a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "Allows to revoke certificates issued by a CA supporting the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
notes:
|
||||
- "Exactly one of C(account_key_src), C(account_key_content),
|
||||
C(private_key_src) or C(private_key_content) must be specified."
|
||||
- "Trying to revoke an already revoked certificate
|
||||
should result in an unchanged status, even if the revocation reason
|
||||
was different than the one specified here. Also, depending on the
|
||||
server, it can happen that some other error is returned if the
|
||||
certificate has already been revoked."
|
||||
- Does not support C(check_mode).
|
||||
- "Exactly one of C(account_key_src), C(account_key_content),
|
||||
C(private_key_src) or C(private_key_content) must be specified."
|
||||
- "Trying to revoke an already revoked certificate
|
||||
should result in an unchanged status, even if the revocation reason
|
||||
was different than the one specified here. Also, depending on the
|
||||
server, it can happen that some other error is returned if the
|
||||
certificate has already been revoked."
|
||||
seealso:
|
||||
- name: The Let's Encrypt documentation
|
||||
description: Documentation for the Let's Encrypt Certification Authority.
|
||||
@@ -38,8 +37,14 @@ seealso:
|
||||
- module: community.crypto.acme_inspect
|
||||
description: Allows to debug problems.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.acme
|
||||
|
||||
- community.crypto.acme
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.actiongroup_acme
|
||||
attributes:
|
||||
check_mode:
|
||||
support: none
|
||||
diff_mode:
|
||||
support: none
|
||||
options:
|
||||
certificate:
|
||||
description:
|
||||
|
||||
@@ -15,10 +15,10 @@ module: acme_challenge_cert_helper
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
short_description: Prepare certificates required for ACME challenges such as C(tls-alpn-01)
|
||||
description:
|
||||
- "Prepares certificates for ACME challenges such as C(tls-alpn-01)."
|
||||
- "The raw data is provided by the M(community.crypto.acme_certificate) module, and needs to be
|
||||
converted to a certificate to be used for challenge validation. This module
|
||||
provides a simple way to generate the required certificates."
|
||||
- "Prepares certificates for ACME challenges such as C(tls-alpn-01)."
|
||||
- "The raw data is provided by the M(community.crypto.acme_certificate) module, and needs to be
|
||||
converted to a certificate to be used for challenge validation. This module
|
||||
provides a simple way to generate the required certificates."
|
||||
seealso:
|
||||
- name: Automatic Certificate Management Environment (ACME)
|
||||
description: The specification of the ACME protocol (RFC 8555).
|
||||
@@ -27,7 +27,18 @@ seealso:
|
||||
description: The specification of the C(tls-alpn-01) challenge (RFC 8737).
|
||||
link: https://www.rfc-editor.org/rfc/rfc8737.html
|
||||
requirements:
|
||||
- "cryptography >= 1.3"
|
||||
- "cryptography >= 1.3"
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
attributes:
|
||||
check_mode:
|
||||
support: none
|
||||
details:
|
||||
- This action does not modify state.
|
||||
diff_mode:
|
||||
support: N/A
|
||||
details:
|
||||
- This action does not modify state.
|
||||
options:
|
||||
challenge:
|
||||
description:
|
||||
@@ -58,8 +69,6 @@ options:
|
||||
- Phassphrase to use to decode the private key.
|
||||
type: str
|
||||
version_added: 1.6.0
|
||||
notes:
|
||||
- Does not support C(check_mode).
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
|
||||
@@ -15,25 +15,25 @@ module: acme_inspect
|
||||
author: "Felix Fontein (@felixfontein)"
|
||||
short_description: Send direct requests to an ACME server
|
||||
description:
|
||||
- "Allows to send direct requests to an ACME server with the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
which is supported by CAs such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module can be used to debug failed certificate request attempts,
|
||||
for example when M(community.crypto.acme_certificate) fails or encounters a problem which
|
||||
you wish to investigate."
|
||||
- "The module can also be used to directly access features of an ACME servers
|
||||
which are not yet supported by the Ansible ACME modules."
|
||||
- "Allows to send direct requests to an ACME server with the
|
||||
L(ACME protocol,https://tools.ietf.org/html/rfc8555),
|
||||
which is supported by CAs such as L(Let's Encrypt,https://letsencrypt.org/)."
|
||||
- "This module can be used to debug failed certificate request attempts,
|
||||
for example when M(community.crypto.acme_certificate) fails or encounters a problem which
|
||||
you wish to investigate."
|
||||
- "The module can also be used to directly access features of an ACME servers
|
||||
which are not yet supported by the Ansible ACME modules."
|
||||
notes:
|
||||
- "The I(account_uri) option must be specified for properly authenticated
|
||||
ACME v2 requests (except a C(new-account) request)."
|
||||
- "Using the C(ansible) tool, M(community.crypto.acme_inspect) can be used to directly execute
|
||||
ACME requests without the need of writing a playbook. For example, the
|
||||
following command retrieves the ACME account with ID 1 from Let's Encrypt
|
||||
(assuming C(/path/to/key) is the correct private account key):
|
||||
C(ansible localhost -m acme_inspect -a \"account_key_src=/path/to/key
|
||||
acme_directory=https://acme-v02.api.letsencrypt.org/directory acme_version=2
|
||||
account_uri=https://acme-v02.api.letsencrypt.org/acme/acct/1 method=get
|
||||
url=https://acme-v02.api.letsencrypt.org/acme/acct/1\")"
|
||||
- "The I(account_uri) option must be specified for properly authenticated
|
||||
ACME v2 requests (except a C(new-account) request)."
|
||||
- "Using the C(ansible) tool, M(community.crypto.acme_inspect) can be used to directly execute
|
||||
ACME requests without the need of writing a playbook. For example, the
|
||||
following command retrieves the ACME account with ID 1 from Let's Encrypt
|
||||
(assuming C(/path/to/key) is the correct private account key):
|
||||
C(ansible localhost -m acme_inspect -a \"account_key_src=/path/to/key
|
||||
acme_directory=https://acme-v02.api.letsencrypt.org/directory acme_version=2
|
||||
account_uri=https://acme-v02.api.letsencrypt.org/acme/acct/1 method=get
|
||||
url=https://acme-v02.api.letsencrypt.org/acme/acct/1\")"
|
||||
seealso:
|
||||
- name: Automatic Certificate Management Environment (ACME)
|
||||
description: The specification of the ACME protocol (RFC 8555).
|
||||
@@ -42,8 +42,14 @@ seealso:
|
||||
description: The specification of the C(tls-alpn-01) challenge (RFC 8737).
|
||||
link: https://www.rfc-editor.org/rfc/rfc8737.html
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.acme
|
||||
|
||||
- community.crypto.acme
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.actiongroup_acme
|
||||
attributes:
|
||||
check_mode:
|
||||
support: none
|
||||
diff_mode:
|
||||
support: none
|
||||
options:
|
||||
url:
|
||||
description:
|
||||
|
||||
@@ -26,6 +26,17 @@ description:
|
||||
generated chain is valid, please use C(openssl verify ...)."
|
||||
requirements:
|
||||
- "cryptography >= 1.5"
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
details:
|
||||
- This action does not modify state.
|
||||
diff_mode:
|
||||
support: N/A
|
||||
details:
|
||||
- This action does not modify state.
|
||||
options:
|
||||
input_chain:
|
||||
description:
|
||||
|
||||
@@ -16,11 +16,12 @@ author: "Felix Fontein (@felixfontein)"
|
||||
short_description: Retrieve cryptographic capabilities
|
||||
version_added: 2.1.0
|
||||
description:
|
||||
- Retrieve information on cryptographic capabilities.
|
||||
- The current version retrieves information on the L(Python cryptography library, https://cryptography.io/) available to
|
||||
Ansible modules, and on the OpenSSL binary C(openssl) found in the path.
|
||||
notes:
|
||||
- Supports C(check_mode).
|
||||
- Retrieve information on cryptographic capabilities.
|
||||
- The current version retrieves information on the L(Python cryptography library, https://cryptography.io/) available to
|
||||
Ansible modules, and on the OpenSSL binary C(openssl) found in the path.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.info_module
|
||||
options: {}
|
||||
'''
|
||||
|
||||
|
||||
@@ -24,6 +24,19 @@ notes:
|
||||
- C(path) must be specified as the output location of the certificate.
|
||||
requirements:
|
||||
- cryptography >= 1.6
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
- community.crypto.ecs_credential
|
||||
attributes:
|
||||
check_mode:
|
||||
support: partial
|
||||
details:
|
||||
- Check mode is only supported if I(request_type=new).
|
||||
diff_mode:
|
||||
support: none
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
backup:
|
||||
description:
|
||||
@@ -337,9 +350,6 @@ seealso:
|
||||
description: Can be used to create private keys (both for certificates and accounts).
|
||||
- module: community.crypto.openssl_csr
|
||||
description: Can be used to create a Certificate Signing Request (CSR).
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.ecs_credential
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -33,6 +33,14 @@ description:
|
||||
notes:
|
||||
- There is a small delay (typically about 5 seconds, but can be as long as 60 seconds) before obtaining the random values when requesting a validation
|
||||
while C(verification_method=dns) or C(verification_method=web_server). Be aware of that if doing many domain validation requests.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.ecs_credential
|
||||
attributes:
|
||||
check_mode:
|
||||
support: none
|
||||
diff_mode:
|
||||
support: none
|
||||
options:
|
||||
client_id:
|
||||
description:
|
||||
@@ -79,9 +87,6 @@ seealso:
|
||||
description: Can be used to request certificates from ECS, with C(provider=entrust).
|
||||
- module: community.crypto.ecs_certificate
|
||||
description: Can be used to request a Certificate from ECS using a verified domain.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.ecs_credential
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -18,6 +18,17 @@ description:
|
||||
- Makes a secure connection and returns information about the presented certificate
|
||||
- The module uses the cryptography Python library.
|
||||
- Support SNI (L(Server Name Indication,https://en.wikipedia.org/wiki/Server_Name_Indication)) only with python >= 2.7.
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
attributes:
|
||||
check_mode:
|
||||
support: none
|
||||
details:
|
||||
- This action does not modify state.
|
||||
diff_mode:
|
||||
support: N/A
|
||||
details:
|
||||
- This action does not modify state.
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
@@ -70,13 +81,23 @@ options:
|
||||
type: str
|
||||
default: auto
|
||||
choices: [ auto, cryptography ]
|
||||
ciphers:
|
||||
description:
|
||||
- SSL/TLS Ciphers to use for the request.
|
||||
- 'When a list is provided, all ciphers are joined in order with C(:).'
|
||||
- See the L(OpenSSL Cipher List Format,https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html#CIPHER-LIST-FORMAT)
|
||||
for more details.
|
||||
- The available ciphers is dependent on the Python and OpenSSL/LibreSSL versions.
|
||||
type: list
|
||||
elements: str
|
||||
version_added: 2.11.0
|
||||
|
||||
notes:
|
||||
- When using ca_cert on OS X it has been reported that in some conditions the validate will always succeed.
|
||||
- When using ca_cert on OS X it has been reported that in some conditions the validate will always succeed.
|
||||
|
||||
requirements:
|
||||
- "python >= 2.7 when using C(proxy_host)"
|
||||
- "cryptography >= 1.6"
|
||||
- "python >= 2.7 when using C(proxy_host)"
|
||||
- "cryptography >= 1.6"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
@@ -236,6 +257,7 @@ def main():
|
||||
timeout=dict(type='int', default=10),
|
||||
select_crypto_backend=dict(type='str', choices=['auto', 'cryptography'], default='auto'),
|
||||
starttls=dict(type='str', choices=['mysql']),
|
||||
ciphers=dict(type='list', elements='str'),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -247,6 +269,7 @@ def main():
|
||||
timeout = module.params.get('timeout')
|
||||
server_name = module.params.get('server_name')
|
||||
start_tls_server_type = module.params.get('starttls')
|
||||
ciphers = module.params.get('ciphers')
|
||||
|
||||
backend = module.params.get('select_crypto_backend')
|
||||
if backend == 'auto':
|
||||
@@ -283,6 +306,9 @@ def main():
|
||||
if proxy_host:
|
||||
module.fail_json(msg='To use proxy_host, you must run the get_certificate module with Python 2.7 or newer.',
|
||||
exception=CREATE_DEFAULT_CONTEXT_IMP_ERR)
|
||||
if ciphers is not None:
|
||||
module.fail_json(msg='To use ciphers, you must run the get_certificate module with Python 2.7 or newer.',
|
||||
exception=CREATE_DEFAULT_CONTEXT_IMP_ERR)
|
||||
try:
|
||||
# Note: get_server_certificate does not support SNI!
|
||||
cert = get_server_certificate((host, port), ca_certs=ca_cert)
|
||||
@@ -314,6 +340,10 @@ def main():
|
||||
if start_tls_server_type is not None:
|
||||
send_starttls_packet(sock, start_tls_server_type)
|
||||
|
||||
if ciphers is not None:
|
||||
ciphers_joined = ":".join(ciphers)
|
||||
ctx.set_ciphers(ciphers_joined)
|
||||
|
||||
cert = ctx.wrap_socket(sock, server_hostname=server_name or host).getpeercert(True)
|
||||
cert = DER_cert_to_PEM_cert(cert)
|
||||
except Exception as e:
|
||||
|
||||
@@ -13,12 +13,20 @@ module: luks_device
|
||||
|
||||
short_description: Manage encrypted (LUKS) devices
|
||||
|
||||
|
||||
description:
|
||||
- "Module manages L(LUKS,https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup)
|
||||
on given device. Supports creating, destroying, opening and closing of
|
||||
LUKS container and adding or removing new keys and passphrases."
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: none
|
||||
|
||||
options:
|
||||
device:
|
||||
description:
|
||||
|
||||
@@ -18,6 +18,17 @@ description:
|
||||
- Generate and regenerate OpenSSH host or user certificates.
|
||||
requirements:
|
||||
- "ssh-keygen"
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -180,8 +191,6 @@ options:
|
||||
The serial number may be omitted for checks, but must be specified again for a new certificate.
|
||||
Note: The default value set by ssh-keygen is 0."
|
||||
type: int
|
||||
|
||||
extends_documentation_fragment: files
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
|
||||
@@ -21,6 +21,17 @@ requirements:
|
||||
- ssh-keygen (if I(backend=openssh))
|
||||
- cryptography >= 2.6 (if I(backend=cryptography) and OpenSSH < 7.8 is installed)
|
||||
- cryptography >= 3.0 (if I(backend=cryptography) and OpenSSH >= 7.8 is installed)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -128,10 +139,7 @@ options:
|
||||
notes:
|
||||
- In case the ssh key is broken or password protected, the module will fail.
|
||||
Set the I(force) option to C(true) if you want to regenerate the keypair.
|
||||
- Supports C(check_mode).
|
||||
- In the case a custom C(mode), C(group), C(owner), or other file attribute is provided it will be applied to both key files.
|
||||
|
||||
extends_documentation_fragment: files
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
|
||||
@@ -19,8 +19,20 @@ description:
|
||||
options, or if it seems to be corrupt. If you are concerned that this could overwrite
|
||||
your existing CSR, consider using the I(backup) option."
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
- community.crypto.module_csr
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -58,11 +70,8 @@ options:
|
||||
version_added: 1.1.0
|
||||
name_constraints_critical:
|
||||
version_added: 1.1.0
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.module_csr
|
||||
seealso:
|
||||
- module: community.crypto.openssl_csr_pipe
|
||||
- module: community.crypto.openssl_csr_pipe
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
@@ -330,9 +339,10 @@ def main():
|
||||
if not os.path.isdir(base_dir):
|
||||
module.fail_json(name=base_dir, msg='The directory %s does not exist or the file is not a directory' % base_dir)
|
||||
|
||||
backend = module.params['select_crypto_backend']
|
||||
backend, module_backend = select_backend(module, backend)
|
||||
try:
|
||||
backend = module.params['select_crypto_backend']
|
||||
backend, module_backend = select_backend(module, backend)
|
||||
|
||||
csr = CertificateSigningRequestModule(module, module_backend)
|
||||
if module.params['state'] == 'present':
|
||||
csr.generate(module)
|
||||
|
||||
@@ -22,8 +22,12 @@ description:
|
||||
requirements:
|
||||
- cryptography >= 1.3
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.info_module
|
||||
- community.crypto.name_encoding
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
@@ -45,12 +49,13 @@ options:
|
||||
default: auto
|
||||
choices: [ auto, cryptography ]
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.name_encoding
|
||||
|
||||
seealso:
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_csr_pipe
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_csr_pipe
|
||||
- ref: community.crypto.openssl_csr_info filter <ansible_collections.community.crypto.openssl_csr_info_filter>
|
||||
# - plugin: community.crypto.openssl_csr_info
|
||||
# plugin_type: filter
|
||||
description: A filter variant of this module.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -19,15 +19,21 @@ description:
|
||||
- "Please note that the module regenerates an existing CSR if it does not match the module's
|
||||
options, or if it seems to be corrupt."
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.module_csr
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
options:
|
||||
content:
|
||||
description:
|
||||
- The existing CSR.
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.module_csr
|
||||
seealso:
|
||||
- module: community.crypto.openssl_csr
|
||||
'''
|
||||
@@ -161,9 +167,10 @@ def main():
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
backend = module.params['select_crypto_backend']
|
||||
backend, module_backend = select_backend(module, backend)
|
||||
try:
|
||||
backend = module.params['select_crypto_backend']
|
||||
backend, module_backend = select_backend(module, backend)
|
||||
|
||||
csr = CertificateSigningRequestModule(module, module_backend)
|
||||
csr.generate(module)
|
||||
result = csr.dump()
|
||||
|
||||
@@ -27,6 +27,17 @@ requirements:
|
||||
- Or OpenSSL binary C(openssl)
|
||||
author:
|
||||
- Thom Wiggers (@thomwiggers)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: none
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -72,16 +83,12 @@ options:
|
||||
type: bool
|
||||
default: false
|
||||
version_added: "1.0.0"
|
||||
notes:
|
||||
- Supports C(check_mode).
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
seealso:
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_pkcs12
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_publickey
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_pkcs12
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_publickey
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -25,6 +25,17 @@ description:
|
||||
# and will be removed in community.crypto (x+1).0.0.
|
||||
requirements:
|
||||
- PyOpenSSL >= 0.15 or cryptography >= 3.0
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: none
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
action:
|
||||
description:
|
||||
@@ -65,15 +76,30 @@ options:
|
||||
iter_size:
|
||||
description:
|
||||
- Number of times to repeat the encryption step.
|
||||
- This is not considered during idempotency checks.
|
||||
- This is only used by the C(pyopenssl) backend. When using it, the default is C(2048).
|
||||
- This is B(not considered during idempotency checks).
|
||||
- This is only used by the C(pyopenssl) backend, or when I(encryption_level=compatibility2022).
|
||||
- When using it, the default is C(2048) for C(pyopenssl) and C(50000) for C(cryptography).
|
||||
type: int
|
||||
maciter_size:
|
||||
description:
|
||||
- Number of times to repeat the MAC step.
|
||||
- This is not considered during idempotency checks.
|
||||
- This is B(not considered during idempotency checks).
|
||||
- This is only used by the C(pyopenssl) backend. When using it, the default is C(1).
|
||||
type: int
|
||||
encryption_level:
|
||||
description:
|
||||
- Determines the encryption level used.
|
||||
- C(auto) uses the default of the selected backend. For C(cryptography), this is what the
|
||||
cryptography library's specific version considers the best available encryption.
|
||||
- C(compatibility2022) uses compatibility settings for older software in 2022.
|
||||
This is only supported by the C(cryptography) backend if cryptography >= 38.0.0 is available.
|
||||
- B(Note) that this option is B(not used for idempotency).
|
||||
choices:
|
||||
- auto
|
||||
- compatibility2022
|
||||
default: auto
|
||||
type: str
|
||||
version_added: 2.8.0
|
||||
passphrase:
|
||||
description:
|
||||
- The PKCS#12 password.
|
||||
@@ -128,8 +154,8 @@ options:
|
||||
description:
|
||||
- Determines which crypto backend to use.
|
||||
- The default choice is C(auto), which tries to use C(cryptography) if available, and falls back to C(pyopenssl).
|
||||
If one of I(iter_size) or I(maciter_size) is used, C(auto) will always result in C(pyopenssl) to be chosen
|
||||
for backwards compatibility.
|
||||
If I(iter_size) is used together with I(encryption_level != compatibility2022), or if I(maciter_size) is used,
|
||||
C(auto) will always result in C(pyopenssl) to be chosen for backwards compatibility.
|
||||
- If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) library.
|
||||
- If set to C(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
|
||||
# - Please note that the C(pyopenssl) backend has been deprecated in community.crypto x.y.0, and will be
|
||||
@@ -139,14 +165,12 @@ options:
|
||||
default: auto
|
||||
choices: [ auto, cryptography, pyopenssl ]
|
||||
version_added: 1.7.0
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
seealso:
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_dhparam
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_publickey
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_dhparam
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_publickey
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
@@ -302,6 +326,18 @@ except ImportError:
|
||||
else:
|
||||
CRYPTOGRAPHY_FOUND = True
|
||||
|
||||
CRYPTOGRAPHY_COMPATIBILITY2022_ERR = None
|
||||
try:
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.serialization.pkcs12 import PBES
|
||||
# Try to build encryption builder for compatibility2022
|
||||
serialization.PrivateFormat.PKCS12.encryption_builder().key_cert_algorithm(PBES.PBESv1SHA1And3KeyTripleDESCBC).hmac_hash(hashes.SHA1())
|
||||
except Exception:
|
||||
CRYPTOGRAPHY_COMPATIBILITY2022_ERR = traceback.format_exc()
|
||||
CRYPTOGRAPHY_HAS_COMPATIBILITY2022 = False
|
||||
else:
|
||||
CRYPTOGRAPHY_HAS_COMPATIBILITY2022 = True
|
||||
|
||||
|
||||
def load_certificate_set(filename, backend):
|
||||
'''
|
||||
@@ -317,7 +353,7 @@ class PkcsError(OpenSSLObjectError):
|
||||
|
||||
|
||||
class Pkcs(OpenSSLObject):
|
||||
def __init__(self, module, backend):
|
||||
def __init__(self, module, backend, iter_size_default=2048):
|
||||
super(Pkcs, self).__init__(
|
||||
module.params['path'],
|
||||
module.params['state'],
|
||||
@@ -330,8 +366,9 @@ class Pkcs(OpenSSLObject):
|
||||
self.other_certificates_parse_all = module.params['other_certificates_parse_all']
|
||||
self.certificate_path = module.params['certificate_path']
|
||||
self.friendly_name = module.params['friendly_name']
|
||||
self.iter_size = module.params['iter_size'] or 2048
|
||||
self.iter_size = module.params['iter_size'] or iter_size_default
|
||||
self.maciter_size = module.params['maciter_size'] or 1
|
||||
self.encryption_level = module.params['encryption_level']
|
||||
self.passphrase = module.params['passphrase']
|
||||
self.pkcs12 = None
|
||||
self.privatekey_passphrase = module.params['privatekey_passphrase']
|
||||
@@ -508,6 +545,8 @@ class Pkcs(OpenSSLObject):
|
||||
class PkcsPyOpenSSL(Pkcs):
|
||||
def __init__(self, module):
|
||||
super(PkcsPyOpenSSL, self).__init__(module, 'pyopenssl')
|
||||
if self.encryption_level != 'auto':
|
||||
module.fail_json(msg='The PyOpenSSL backend only supports encryption_level = auto')
|
||||
|
||||
def generate_bytes(self, module):
|
||||
"""Generate PKCS#12 file archive."""
|
||||
@@ -573,7 +612,12 @@ class PkcsPyOpenSSL(Pkcs):
|
||||
|
||||
class PkcsCryptography(Pkcs):
|
||||
def __init__(self, module):
|
||||
super(PkcsCryptography, self).__init__(module, 'cryptography')
|
||||
super(PkcsCryptography, self).__init__(module, 'cryptography', iter_size_default=50000)
|
||||
if self.encryption_level == 'compatibility2022' and not CRYPTOGRAPHY_HAS_COMPATIBILITY2022:
|
||||
module.fail_json(
|
||||
msg='The installed cryptography version does not support encryption_level = compatibility2022.'
|
||||
' You need cryptography >= 38.0.0 and support for SHA1',
|
||||
exception=CRYPTOGRAPHY_COMPATIBILITY2022_ERR)
|
||||
|
||||
def generate_bytes(self, module):
|
||||
"""Generate PKCS#12 file archive."""
|
||||
@@ -593,13 +637,25 @@ class PkcsCryptography(Pkcs):
|
||||
# Store fake object which can be used to retrieve the components back
|
||||
self.pkcs12 = (pkey, cert, self.other_certificates, friendly_name)
|
||||
|
||||
if not self.passphrase:
|
||||
encryption = serialization.NoEncryption()
|
||||
elif self.encryption_level == 'compatibility2022':
|
||||
encryption = (
|
||||
serialization.PrivateFormat.PKCS12.encryption_builder().
|
||||
kdf_rounds(self.iter_size).
|
||||
key_cert_algorithm(PBES.PBESv1SHA1And3KeyTripleDESCBC).
|
||||
hmac_hash(hashes.SHA1()).
|
||||
build(to_bytes(self.passphrase))
|
||||
)
|
||||
else:
|
||||
encryption = serialization.BestAvailableEncryption(to_bytes(self.passphrase))
|
||||
|
||||
return serialize_key_and_certificates(
|
||||
friendly_name,
|
||||
pkey,
|
||||
cert,
|
||||
self.other_certificates,
|
||||
serialization.BestAvailableEncryption(to_bytes(self.passphrase))
|
||||
if self.passphrase else serialization.NoEncryption(),
|
||||
encryption,
|
||||
)
|
||||
|
||||
def parse_bytes(self, pkcs12_content):
|
||||
@@ -658,8 +714,11 @@ def select_backend(module, backend):
|
||||
can_use_pyopenssl = PYOPENSSL_FOUND and PYOPENSSL_VERSION >= LooseVersion(MINIMAL_PYOPENSSL_VERSION)
|
||||
|
||||
# If no restrictions are provided, first try cryptography, then pyOpenSSL
|
||||
if module.params['iter_size'] is not None or module.params['maciter_size'] is not None:
|
||||
# If iter_size or maciter_size is specified, use pyOpenSSL backend
|
||||
if (
|
||||
(module.params['iter_size'] is not None and module.params['encryption_level'] != 'compatibility2022')
|
||||
or module.params['maciter_size'] is not None
|
||||
):
|
||||
# If iter_size (for encryption_level != compatibility2022) or maciter_size is specified, use pyOpenSSL backend
|
||||
backend = 'pyopenssl'
|
||||
elif can_use_cryptography:
|
||||
backend = 'cryptography'
|
||||
@@ -697,6 +756,7 @@ def main():
|
||||
certificate_path=dict(type='path'),
|
||||
force=dict(type='bool', default=False),
|
||||
friendly_name=dict(type='str', aliases=['name']),
|
||||
encryption_level=dict(type='str', choices=['auto', 'compatibility2022'], default='auto'),
|
||||
iter_size=dict(type='int'),
|
||||
maciter_size=dict(type='int'),
|
||||
passphrase=dict(type='str', no_log=True),
|
||||
|
||||
@@ -19,6 +19,18 @@ description:
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
- community.crypto.module_privatekey
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -59,12 +71,9 @@ options:
|
||||
version_added: '1.0.0'
|
||||
regenerate:
|
||||
version_added: '1.0.0'
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.module_privatekey
|
||||
seealso:
|
||||
- module: community.crypto.openssl_privatekey_pipe
|
||||
- module: community.crypto.openssl_privatekey_info
|
||||
- module: community.crypto.openssl_privatekey_pipe
|
||||
- module: community.crypto.openssl_privatekey_info
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
@@ -76,7 +85,7 @@ EXAMPLES = r'''
|
||||
community.crypto.openssl_privatekey:
|
||||
path: /etc/ssl/private/ansible.com.pem
|
||||
passphrase: ansible
|
||||
cipher: aes256
|
||||
cipher: auto
|
||||
|
||||
- name: Generate an OpenSSL private key with a different size (2048 bits)
|
||||
community.crypto.openssl_privatekey:
|
||||
|
||||
@@ -19,6 +19,18 @@ description:
|
||||
- The default mode for the private key file will be C(0600) if I(mode) is not explicitly set.
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
- community.crypto.module_privatekey_convert
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: none
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
dest_path:
|
||||
description:
|
||||
@@ -32,9 +44,6 @@ options:
|
||||
the original private key back if you overwrote it with a new one by accident.
|
||||
type: bool
|
||||
default: false
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.module_privatekey_convert
|
||||
seealso: []
|
||||
'''
|
||||
|
||||
|
||||
@@ -24,8 +24,11 @@ description:
|
||||
requirements:
|
||||
- cryptography >= 1.2.3
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.info_module
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
@@ -70,12 +73,13 @@ options:
|
||||
default: auto
|
||||
choices: [ auto, cryptography ]
|
||||
|
||||
notes:
|
||||
- Supports C(check_mode).
|
||||
|
||||
seealso:
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_privatekey_pipe
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_privatekey_pipe
|
||||
- ref: community.crypto.openssl_privatekey_info filter <ansible_collections.community.crypto.openssl_privatekey_info_filter>
|
||||
# - plugin: community.crypto.openssl_privatekey_info
|
||||
# plugin_type: filter
|
||||
description: A filter variant of this module.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -23,6 +23,21 @@ description:
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.flow
|
||||
- community.crypto.module_privatekey
|
||||
attributes:
|
||||
action:
|
||||
support: full
|
||||
async:
|
||||
support: none
|
||||
details:
|
||||
- This action runs completely on the controller.
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
options:
|
||||
content:
|
||||
description:
|
||||
@@ -42,11 +57,9 @@ options:
|
||||
current key (if it was provided) and Ansible will replace it by C(VALUE_SPECIFIED_IN_NO_LOG_PARAMETER).
|
||||
type: bool
|
||||
default: false
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.module_privatekey
|
||||
seealso:
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_privatekey_info
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_privatekey_info
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -14,8 +14,9 @@ DOCUMENTATION = r'''
|
||||
module: openssl_publickey
|
||||
short_description: Generate an OpenSSL public key from its private key.
|
||||
description:
|
||||
- This module allows one to (re)generate OpenSSL public keys from their private keys.
|
||||
- Keys are generated in PEM or OpenSSH format.
|
||||
- This module allows one to (re)generate public keys from their private keys.
|
||||
- Public keys are generated in PEM or OpenSSH format. Private keys must be OpenSSL PEM keys.
|
||||
OpenSSH private keys are not supported, use the M(community.crypto.openssh_keypair) module to manage these.
|
||||
- The module uses the cryptography Python library.
|
||||
requirements:
|
||||
- cryptography >= 1.2.3 (older versions might work as well)
|
||||
@@ -23,6 +24,17 @@ requirements:
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -83,17 +95,15 @@ options:
|
||||
type: bool
|
||||
default: false
|
||||
version_added: '1.0.0'
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
seealso:
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.x509_certificate_pipe
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_csr_pipe
|
||||
- module: community.crypto.openssl_dhparam
|
||||
- module: community.crypto.openssl_pkcs12
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_privatekey_pipe
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.x509_certificate_pipe
|
||||
- module: community.crypto.openssl_csr
|
||||
- module: community.crypto.openssl_csr_pipe
|
||||
- module: community.crypto.openssl_dhparam
|
||||
- module: community.crypto.openssl_pkcs12
|
||||
- module: community.crypto.openssl_privatekey
|
||||
- module: community.crypto.openssl_privatekey_pipe
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -21,6 +21,9 @@ requirements:
|
||||
- cryptography >= 1.2.3
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.info_module
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
@@ -41,12 +44,13 @@ options:
|
||||
default: auto
|
||||
choices: [ auto, cryptography ]
|
||||
|
||||
notes:
|
||||
- Supports C(check_mode).
|
||||
|
||||
seealso:
|
||||
- module: community.crypto.openssl_publickey
|
||||
- module: community.crypto.openssl_privatekey_info
|
||||
- module: community.crypto.openssl_publickey
|
||||
- module: community.crypto.openssl_privatekey_info
|
||||
- ref: community.crypto.openssl_publickey_info filter <ansible_collections.community.crypto.openssl_publickey_info_filter>
|
||||
# - plugin: community.crypto.openssl_publickey_info
|
||||
# plugin_type: filter
|
||||
description: A filter variant of this module.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -22,6 +22,15 @@ requirements:
|
||||
author:
|
||||
- Patrick Pichler (@aveexy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
details:
|
||||
- This action does not modify state.
|
||||
diff_mode:
|
||||
support: none
|
||||
options:
|
||||
privatekey_path:
|
||||
description:
|
||||
|
||||
@@ -22,6 +22,9 @@ requirements:
|
||||
author:
|
||||
- Patrick Pichler (@aveexy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.info_module
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
@@ -57,7 +60,6 @@ notes:
|
||||
RSA keys: C(cryptography) >= 1.4
|
||||
DSA and ECDSA keys: C(cryptography) >= 1.5
|
||||
ed448 and ed25519 keys: C(cryptography) >= 2.6
|
||||
- Supports C(check_mode).
|
||||
seealso:
|
||||
- module: community.crypto.openssl_signature
|
||||
- module: community.crypto.x509_certificate
|
||||
|
||||
@@ -29,8 +29,24 @@ description:
|
||||
keyword, the new name M(community.crypto.x509_certificate) should be used to avoid
|
||||
a deprecation warning.
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
- community.crypto.module_certificate
|
||||
- community.crypto.module_certificate.backend_acme_documentation
|
||||
- community.crypto.module_certificate.backend_entrust_documentation
|
||||
- community.crypto.module_certificate.backend_ownca_documentation
|
||||
- community.crypto.module_certificate.backend_selfsigned_documentation
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -82,19 +98,8 @@ options:
|
||||
ownca_privatekey_content:
|
||||
version_added: '1.0.0'
|
||||
|
||||
notes:
|
||||
- Supports C(check_mode).
|
||||
|
||||
seealso:
|
||||
- module: community.crypto.x509_certificate_pipe
|
||||
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.module_certificate
|
||||
- community.crypto.module_certificate.backend_acme_documentation
|
||||
- community.crypto.module_certificate.backend_entrust_documentation
|
||||
- community.crypto.module_certificate.backend_ownca_documentation
|
||||
- community.crypto.module_certificate.backend_selfsigned_documentation
|
||||
- module: community.crypto.x509_certificate_pipe
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -28,9 +28,13 @@ description:
|
||||
requirements:
|
||||
- cryptography >= 1.6
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.info_module
|
||||
- community.crypto.name_encoding
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
@@ -63,16 +67,16 @@ options:
|
||||
default: auto
|
||||
choices: [ auto, cryptography ]
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.name_encoding
|
||||
|
||||
notes:
|
||||
- All timestamp values are provided in ASN.1 TIME format, in other words, following the C(YYYYMMDDHHMMSSZ) pattern.
|
||||
They are all in UTC.
|
||||
- Supports C(check_mode).
|
||||
seealso:
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.x509_certificate_pipe
|
||||
- module: community.crypto.x509_certificate
|
||||
- module: community.crypto.x509_certificate_pipe
|
||||
- ref: community.crypto.x509_certificate_info filter <ansible_collections.community.crypto.x509_certificate_info_filter>
|
||||
# - plugin: community.crypto.x509_certificate_info
|
||||
# plugin_type: filter
|
||||
description: A filter variant of this module.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
@@ -378,6 +382,12 @@ ocsp_uri:
|
||||
C(none) if no OCSP responder URI is included.
|
||||
returned: success
|
||||
type: str
|
||||
issuer_uri:
|
||||
description: The Issuer URI, if included in the certificate. Will be
|
||||
C(none) if no issuer URI is included.
|
||||
returned: success
|
||||
type: str
|
||||
version_added: 2.9.0
|
||||
'''
|
||||
|
||||
|
||||
|
||||
@@ -23,9 +23,20 @@ description:
|
||||
options, or if it seems to be corrupt. If you are concerned that this could overwrite
|
||||
your existing certificate, consider using the I(backup) option."
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
- Felix Fontein (@felixfontein)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Markus Teufelberger (@MarkusTeufelberger)
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.module_certificate
|
||||
- community.crypto.module_certificate.backend_entrust_documentation
|
||||
- community.crypto.module_certificate.backend_ownca_documentation
|
||||
- community.crypto.module_certificate.backend_selfsigned_documentation
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
options:
|
||||
provider:
|
||||
description:
|
||||
@@ -42,16 +53,7 @@ options:
|
||||
type: str
|
||||
|
||||
seealso:
|
||||
- module: community.crypto.x509_certificate
|
||||
|
||||
notes:
|
||||
- Supports C(check_mode).
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.module_certificate
|
||||
- community.crypto.module_certificate.backend_entrust_documentation
|
||||
- community.crypto.module_certificate.backend_ownca_documentation
|
||||
- community.crypto.module_certificate.backend_selfsigned_documentation
|
||||
- module: community.crypto.x509_certificate
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -22,6 +22,18 @@ requirements:
|
||||
- cryptography >= 1.2
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.files
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.files
|
||||
- community.crypto.name_encoding
|
||||
attributes:
|
||||
check_mode:
|
||||
support: full
|
||||
diff_mode:
|
||||
support: full
|
||||
safe_file_operations:
|
||||
support: full
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -241,14 +253,9 @@ options:
|
||||
type: bool
|
||||
default: false
|
||||
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
- community.crypto.name_encoding
|
||||
|
||||
notes:
|
||||
- All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.
|
||||
- Date specified should be UTC. Minutes and seconds are mandatory.
|
||||
- Supports C(check_mode).
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -20,6 +20,10 @@ requirements:
|
||||
- cryptography >= 1.2
|
||||
author:
|
||||
- Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.attributes
|
||||
- community.crypto.attributes.info_module
|
||||
- community.crypto.name_encoding
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
@@ -41,15 +45,15 @@ options:
|
||||
default: true
|
||||
version_added: 1.7.0
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.crypto.name_encoding
|
||||
|
||||
notes:
|
||||
- All timestamp values are provided in ASN.1 TIME format, in other words, following the C(YYYYMMDDHHMMSSZ) pattern.
|
||||
They are all in UTC.
|
||||
- Supports C(check_mode).
|
||||
seealso:
|
||||
- module: community.crypto.x509_crl
|
||||
- ref: community.crypto.x509_crl_info filter <ansible_collections.community.crypto.x509_crl_info_filter>
|
||||
# - plugin: community.crypto.x509_crl_info
|
||||
# plugin_type: filter
|
||||
description: A filter variant of this module.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
|
||||
@@ -69,9 +69,9 @@ try:
|
||||
# For ansible-core 2.11, we can use the ArgumentSpecValidator. We also import
|
||||
# ModuleArgumentSpecValidator since that indicates that the 'classical' approach
|
||||
# will no longer work.
|
||||
from ansible.module_utils.common.arg_spec import (
|
||||
from ansible.module_utils.common.arg_spec import ( # noqa: F401, pylint: disable=unused-import
|
||||
ArgumentSpecValidator,
|
||||
ModuleArgumentSpecValidator, # noqa
|
||||
ModuleArgumentSpecValidator, # ModuleArgumentSpecValidator is not used
|
||||
)
|
||||
from ansible.module_utils.errors import UnsupportedError
|
||||
HAS_ARGSPEC_VALIDATOR = True
|
||||
@@ -145,9 +145,14 @@ class AnsibleActionModule(object):
|
||||
# warnings and deprecations that do not work in plugins. This is a copy of that code adjusted
|
||||
# for our use-case:
|
||||
for d in self._validation_result._deprecations:
|
||||
self.deprecate(
|
||||
"Alias '{name}' is deprecated. See the module docs for more information".format(name=d['name']),
|
||||
version=d.get('version'), date=d.get('date'), collection_name=d.get('collection_name'))
|
||||
# Before ansible-core 2.14.2, deprecations were always for aliases:
|
||||
if 'name' in d:
|
||||
self.deprecate(
|
||||
"Alias '{name}' is deprecated. See the module docs for more information".format(name=d['name']),
|
||||
version=d.get('version'), date=d.get('date'), collection_name=d.get('collection_name'))
|
||||
# Since ansible-core 2.14.2, a message is present that can be directly printed:
|
||||
if 'msg' in d:
|
||||
self.deprecate(d['msg'], version=d.get('version'), date=d.get('date'), collection_name=d.get('collection_name'))
|
||||
|
||||
for w in self._validation_result._warnings:
|
||||
self.warn('Both option {option} and its alias {alias} are set.'.format(option=w['option'], alias=w['alias']))
|
||||
|
||||
22
plugins/plugin_utils/filter_module.py
Normal file
22
plugins/plugin_utils/filter_module.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2022 Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# NOTE: THIS IS ONLY FOR FILTER PLUGINS!
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
|
||||
|
||||
class FilterModuleMock(object):
|
||||
def __init__(self, params):
|
||||
self.check_mode = True
|
||||
self.params = params
|
||||
self._diff = False
|
||||
|
||||
def fail_json(self, msg, **kwargs):
|
||||
raise AnsibleFilterError(msg)
|
||||
@@ -29,7 +29,7 @@ import traceback
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
try:
|
||||
import ipaddress
|
||||
import ipaddress # noqa: F401, pylint: disable=unused-import
|
||||
HAS_IPADDRESS = True
|
||||
IPADDRESS_IMP_ERR = None
|
||||
except ImportError as exc:
|
||||
|
||||
@@ -29,7 +29,7 @@ import traceback
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
try:
|
||||
import yaml
|
||||
import yaml # noqa: F401, pylint: disable=unused-import
|
||||
HAS_PYYAML = True
|
||||
PYYAML_IMP_ERR = None
|
||||
except ImportError as exc:
|
||||
|
||||
@@ -6,9 +6,5 @@ azp/generic/1
|
||||
azp/posix/1
|
||||
cloud/acme
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/macos
|
||||
skip/osx
|
||||
skip/rhel
|
||||
# For some reason connecting to helper containers does not work on the Alpine VMs
|
||||
skip/alpine
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: no
|
||||
ignore_errors: yes
|
||||
allow_creation: false
|
||||
ignore_errors: true
|
||||
register: account_not_created
|
||||
|
||||
- name: Create it now (check mode, diff)
|
||||
@@ -48,14 +48,14 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
allow_creation: true
|
||||
terms_agreed: true
|
||||
contact:
|
||||
- mailto:example@example.org
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
check_mode: true
|
||||
diff: true
|
||||
register: account_created_check
|
||||
|
||||
- name: Create it now
|
||||
@@ -64,10 +64,10 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
allow_creation: true
|
||||
terms_agreed: true
|
||||
contact:
|
||||
- mailto:example@example.org
|
||||
register: account_created
|
||||
@@ -78,10 +78,10 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
allow_creation: true
|
||||
terms_agreed: true
|
||||
contact:
|
||||
- mailto:example@example.org
|
||||
register: account_created_idempotent
|
||||
@@ -97,13 +97,13 @@
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
# allow_creation: no
|
||||
# allow_creation: false
|
||||
contact:
|
||||
- mailto:example@example.com
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
check_mode: true
|
||||
diff: true
|
||||
register: account_modified_check
|
||||
|
||||
- name: Change email address
|
||||
@@ -112,9 +112,9 @@
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
# allow_creation: no
|
||||
# allow_creation: false
|
||||
contact:
|
||||
- mailto:example@example.com
|
||||
register: account_modified
|
||||
@@ -126,9 +126,9 @@
|
||||
account_uri: "{{ account_created.account_uri }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
# allow_creation: no
|
||||
# allow_creation: false
|
||||
contact:
|
||||
- mailto:example@example.com
|
||||
register: account_modified_idempotent
|
||||
@@ -140,10 +140,10 @@
|
||||
account_uri: "{{ account_created.account_uri ~ '12345thisdoesnotexist' }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
contact: []
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: account_modified_wrong_uri
|
||||
|
||||
- name: Clear contact email addresses (check mode, diff)
|
||||
@@ -152,12 +152,12 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
# allow_creation: no
|
||||
# allow_creation: false
|
||||
contact: []
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
check_mode: true
|
||||
diff: true
|
||||
register: account_modified_2_check
|
||||
|
||||
- name: Clear contact email addresses
|
||||
@@ -166,9 +166,9 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
# allow_creation: no
|
||||
# allow_creation: false
|
||||
contact: []
|
||||
register: account_modified_2
|
||||
|
||||
@@ -178,9 +178,9 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
# allow_creation: no
|
||||
# allow_creation: false
|
||||
contact: []
|
||||
register: account_modified_2_idempotent
|
||||
|
||||
@@ -190,14 +190,14 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
new_account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
new_account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
state: changed_key
|
||||
contact:
|
||||
- mailto:example@example.com
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
check_mode: true
|
||||
diff: true
|
||||
register: account_change_key_check
|
||||
|
||||
- name: Change account key
|
||||
@@ -206,7 +206,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
new_account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
new_account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
state: changed_key
|
||||
@@ -221,10 +221,10 @@
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: absent
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
check_mode: true
|
||||
diff: true
|
||||
register: account_deactivate_check
|
||||
|
||||
- name: Deactivate account
|
||||
@@ -234,7 +234,7 @@
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: absent
|
||||
register: account_deactivate
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: absent
|
||||
register: account_deactivate_idempotent
|
||||
|
||||
@@ -256,10 +256,10 @@
|
||||
account_key_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else omit }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: no
|
||||
ignore_errors: yes
|
||||
allow_creation: false
|
||||
ignore_errors: true
|
||||
register: account_not_created_2
|
||||
|
||||
- name: Do not try to create account III
|
||||
@@ -268,10 +268,10 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: no
|
||||
ignore_errors: yes
|
||||
allow_creation: false
|
||||
ignore_errors: true
|
||||
register: account_not_created_3
|
||||
|
||||
- name: Create account with External Account Binding
|
||||
@@ -280,10 +280,10 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/{{ item.account }}.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
allow_creation: true
|
||||
terms_agreed: true
|
||||
contact:
|
||||
- mailto:example@example.org
|
||||
external_account_binding:
|
||||
@@ -291,7 +291,7 @@
|
||||
alg: "{{ item.alg }}"
|
||||
key: "{{ item.key }}"
|
||||
register: account_created_eab
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
loop:
|
||||
- account: accountkey3
|
||||
kid: kid-1
|
||||
|
||||
@@ -6,9 +6,5 @@ azp/generic/1
|
||||
azp/posix/1
|
||||
cloud/acme
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/macos
|
||||
skip/osx
|
||||
skip/rhel
|
||||
# For some reason connecting to helper containers does not work on the Alpine VMs
|
||||
skip/alpine
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
register: account_not_created
|
||||
|
||||
- name: Create it now
|
||||
@@ -38,10 +38,10 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
allow_creation: true
|
||||
terms_agreed: true
|
||||
contact:
|
||||
- mailto:example@example.org
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
register: account_created
|
||||
|
||||
- name: Read account key
|
||||
@@ -65,9 +65,9 @@
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
state: present
|
||||
allow_creation: no
|
||||
allow_creation: false
|
||||
contact: []
|
||||
|
||||
- name: Check that account was modified
|
||||
@@ -76,7 +76,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_uri: "{{ account_created.account_uri }}"
|
||||
register: account_modified
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_uri: "{{ account_created.account_uri }}test1234doesnotexists"
|
||||
register: account_not_exist
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey2.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_uri: "{{ account_created.account_uri }}"
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: account_wrong_key
|
||||
|
||||
@@ -6,9 +6,5 @@ azp/generic/1
|
||||
azp/posix/1
|
||||
cloud/acme
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/macos
|
||||
skip/osx
|
||||
skip/rhel
|
||||
# For some reason connecting to helper containers does not work on the Alpine VMs
|
||||
skip/alpine
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
state: absent
|
||||
- name: Read account key (EC384)
|
||||
@@ -43,11 +43,11 @@
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_content: "{{ slurp.content | b64decode }}"
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
allow_creation: true
|
||||
terms_agreed: true
|
||||
contact:
|
||||
- mailto:example@example.org
|
||||
- mailto:example@example.com
|
||||
@@ -56,11 +56,11 @@
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-rsa.pem"
|
||||
state: present
|
||||
allow_creation: yes
|
||||
terms_agreed: yes
|
||||
allow_creation: true
|
||||
terms_agreed: true
|
||||
contact: []
|
||||
## OBTAIN CERTIFICATES ########################################################################
|
||||
- name: Obtain cert 1
|
||||
@@ -71,16 +71,16 @@
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec256
|
||||
challenge: http-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
retrieve_all_alternates: yes
|
||||
retrieve_all_alternates: true
|
||||
acme_expected_root_number: 1
|
||||
select_chain:
|
||||
- test_certificates: last
|
||||
@@ -98,17 +98,17 @@
|
||||
certificate_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else '' }}"
|
||||
key_type: ec256
|
||||
subject_alt_name: "DNS:*.example.com,DNS:example.com"
|
||||
subject_alt_name_critical: yes
|
||||
subject_alt_name_critical: true
|
||||
account_key: account-ec384
|
||||
challenge: dns-01
|
||||
modify_account: no
|
||||
deactivate_authzs: yes
|
||||
force: no
|
||||
modify_account: false
|
||||
deactivate_authzs: true
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: no
|
||||
terms_agreed: false
|
||||
account_email: ""
|
||||
acme_expected_root_number: 0
|
||||
retrieve_all_alternates: yes
|
||||
retrieve_all_alternates: true
|
||||
select_chain:
|
||||
# All intermediates have the same subject, so always the first
|
||||
# chain will be found, and we need a second condition to make sure
|
||||
@@ -134,17 +134,17 @@
|
||||
certificate_name: cert-3
|
||||
key_type: ec384
|
||||
subject_alt_name: "DNS:*.example.com,DNS:example.org,DNS:t1.example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key_content: "{{ slurp_account_key.content | b64decode }}"
|
||||
challenge: dns-01
|
||||
modify_account: no
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: false
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: no
|
||||
terms_agreed: false
|
||||
account_email: ""
|
||||
acme_expected_root_number: 0
|
||||
retrieve_all_alternates: yes
|
||||
retrieve_all_alternates: true
|
||||
select_chain:
|
||||
- test_certificates: last
|
||||
subject: "{{ acme_roots[1].subject }}"
|
||||
@@ -161,14 +161,14 @@
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.com,DNS:t1.example.com,DNS:test.t2.example.com,DNS:example.org,DNS:test.example.org"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-rsa
|
||||
challenge: http-01
|
||||
modify_account: no
|
||||
deactivate_authzs: yes
|
||||
force: yes
|
||||
modify_account: false
|
||||
deactivate_authzs: true
|
||||
force: true
|
||||
remaining_days: 10
|
||||
terms_agreed: no
|
||||
terms_agreed: false
|
||||
account_email: ""
|
||||
acme_expected_root_number: 2
|
||||
select_chain:
|
||||
@@ -188,14 +188,14 @@
|
||||
certificate_name: cert-5
|
||||
key_type: ec521
|
||||
subject_alt_name: "DNS:t2.example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec384
|
||||
challenge: http-01
|
||||
modify_account: no
|
||||
deactivate_authzs: yes
|
||||
force: yes
|
||||
modify_account: false
|
||||
deactivate_authzs: true
|
||||
force: true
|
||||
remaining_days: 10
|
||||
terms_agreed: no
|
||||
terms_agreed: false
|
||||
account_email: ""
|
||||
use_csr_content: true
|
||||
- name: Store obtain results for cert 5a
|
||||
@@ -209,14 +209,14 @@
|
||||
certificate_name: cert-5
|
||||
key_type: ec521
|
||||
subject_alt_name: "DNS:t2.example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec384
|
||||
challenge: http-01
|
||||
modify_account: no
|
||||
deactivate_authzs: yes
|
||||
force: no
|
||||
modify_account: false
|
||||
deactivate_authzs: true
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: no
|
||||
terms_agreed: false
|
||||
account_email: ""
|
||||
use_csr_content: false
|
||||
- name: Store obtain results for cert 5b
|
||||
@@ -229,14 +229,14 @@
|
||||
certificate_name: cert-5
|
||||
key_type: ec521
|
||||
subject_alt_name: "DNS:t2.example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec384
|
||||
challenge: http-01
|
||||
modify_account: no
|
||||
deactivate_authzs: yes
|
||||
force: yes
|
||||
modify_account: false
|
||||
deactivate_authzs: true
|
||||
force: true
|
||||
remaining_days: 1000
|
||||
terms_agreed: no
|
||||
terms_agreed: false
|
||||
account_email: ""
|
||||
use_csr_content: true
|
||||
- name: Store obtain results for cert 5c
|
||||
@@ -254,14 +254,14 @@
|
||||
certificate_name: cert-5
|
||||
key_type: ec521
|
||||
subject_alt_name: "DNS:t2.example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key_content: "{{ slurp_account_key.content | b64decode }}"
|
||||
challenge: http-01
|
||||
modify_account: no
|
||||
deactivate_authzs: yes
|
||||
force: yes
|
||||
modify_account: false
|
||||
deactivate_authzs: true
|
||||
force: true
|
||||
remaining_days: 10
|
||||
terms_agreed: no
|
||||
terms_agreed: false
|
||||
account_email: ""
|
||||
use_csr_content: false
|
||||
- name: Store obtain results for cert 5d
|
||||
@@ -277,14 +277,14 @@
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.org"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec256
|
||||
challenge: tls-alpn-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
acme_expected_root_number: 0
|
||||
select_chain:
|
||||
@@ -313,14 +313,14 @@
|
||||
subject_alt_name:
|
||||
- "IP:127.0.0.1"
|
||||
# - "IP:::1"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec256
|
||||
challenge: http-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
acme_expected_root_number: 2
|
||||
select_chain:
|
||||
@@ -344,15 +344,15 @@
|
||||
- "IP:127.0.0.1"
|
||||
# IPv4 only since our test validation server doesn't work
|
||||
# with IPv6 (thanks to Python's socketserver).
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec256
|
||||
challenge: tls-alpn-01
|
||||
challenge_alpn_tls: acme_challenge_cert_helper
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
use_csr_content: true
|
||||
- name: Store obtain results for cert 8
|
||||
@@ -364,37 +364,37 @@
|
||||
# Make sure certificates are valid. Root certificate for Pebble equals the chain certificate.
|
||||
- name: Verifying cert 1
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-1-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-1-chain.pem" "{{ remote_tmp_dir }}/cert-1.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_1_valid
|
||||
- name: Verifying cert 2
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-2-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-2-chain.pem" "{{ remote_tmp_dir }}/cert-2.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_2_valid
|
||||
- name: Verifying cert 3
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-3-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-3-chain.pem" "{{ remote_tmp_dir }}/cert-3.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_3_valid
|
||||
- name: Verifying cert 4
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-4-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-4-chain.pem" "{{ remote_tmp_dir }}/cert-4.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_4_valid
|
||||
- name: Verifying cert 5
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-5-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-5-chain.pem" "{{ remote_tmp_dir }}/cert-5.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_5_valid
|
||||
- name: Verifying cert 6
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-6-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-6-chain.pem" "{{ remote_tmp_dir }}/cert-6.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_6_valid
|
||||
when: acme_intermediates[0].subject_key_identifier is defined
|
||||
- name: Verifying cert 7
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-7-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-7-chain.pem" "{{ remote_tmp_dir }}/cert-7.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_7_valid
|
||||
when: acme_roots[2].subject_key_identifier is defined
|
||||
- name: Verifying cert 8
|
||||
command: '{{ openssl_binary }} verify -CAfile "{{ remote_tmp_dir }}/cert-8-root.pem" -untrusted "{{ remote_tmp_dir }}/cert-8-chain.pem" "{{ remote_tmp_dir }}/cert-8.pem"'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
register: cert_8_valid
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
# Dump certificate info
|
||||
@@ -468,7 +468,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
retrieve_orders: ignore
|
||||
register: account_orders_not
|
||||
- name: Retrieve orders as URL list (1/2)
|
||||
@@ -477,7 +477,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
retrieve_orders: url_list
|
||||
register: account_orders_urls
|
||||
- name: Retrieve orders as URL list (2/2)
|
||||
@@ -486,7 +486,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec384.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
retrieve_orders: url_list
|
||||
register: account_orders_urls2
|
||||
- name: Retrieve orders as object list (1/2)
|
||||
@@ -495,7 +495,7 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
retrieve_orders: object_list
|
||||
register: account_orders_full
|
||||
- name: Retrieve orders as object list (2/2)
|
||||
@@ -504,6 +504,6 @@
|
||||
account_key_src: "{{ remote_tmp_dir }}/account-ec384.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
retrieve_orders: object_list
|
||||
register: account_orders_full2
|
||||
|
||||
@@ -6,9 +6,5 @@ azp/generic/1
|
||||
azp/posix/1
|
||||
cloud/acme
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/macos
|
||||
skip/osx
|
||||
skip/rhel
|
||||
# For some reason connecting to helper containers does not work on the Alpine VMs
|
||||
skip/alpine
|
||||
|
||||
@@ -38,14 +38,14 @@
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key_content: "{{ slurp_account_key.content | b64decode }}"
|
||||
challenge: http-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
- name: Obtain cert 2
|
||||
include_tasks: obtain-cert.yml
|
||||
@@ -55,14 +55,14 @@
|
||||
certificate_passphrase: "{{ 'hunter2' if select_crypto_backend != 'openssl' else '' }}"
|
||||
key_type: ec256
|
||||
subject_alt_name: "DNS:*.example.com"
|
||||
subject_alt_name_critical: yes
|
||||
subject_alt_name_critical: true
|
||||
account_key: account-ec384
|
||||
challenge: dns-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: yes
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: true
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
- name: Obtain cert 3
|
||||
include_tasks: obtain-cert.yml
|
||||
@@ -71,14 +71,14 @@
|
||||
certificate_name: cert-3
|
||||
key_type: ec384
|
||||
subject_alt_name: "DNS:t1.example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-rsa
|
||||
challenge: dns-01
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
## REVOKE CERTIFICATES ########################################################################
|
||||
- name: Revoke certificate 1 via account key
|
||||
@@ -88,8 +88,8 @@
|
||||
certificate: "{{ remote_tmp_dir }}/cert-1.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
ignore_errors: yes
|
||||
validate_certs: false
|
||||
ignore_errors: true
|
||||
register: cert_1_revoke
|
||||
- name: Revoke certificate 2 via certificate private key
|
||||
acme_certificate_revoke:
|
||||
@@ -99,8 +99,8 @@
|
||||
certificate: "{{ remote_tmp_dir }}/cert-2.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
ignore_errors: yes
|
||||
validate_certs: false
|
||||
ignore_errors: true
|
||||
register: cert_2_revoke
|
||||
- name: Read account key (RSA)
|
||||
slurp:
|
||||
@@ -113,6 +113,6 @@
|
||||
certificate: "{{ remote_tmp_dir }}/cert-3-fullchain.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
ignore_errors: yes
|
||||
validate_certs: false
|
||||
ignore_errors: true
|
||||
register: cert_3_revoke
|
||||
|
||||
@@ -6,9 +6,5 @@ azp/generic/1
|
||||
azp/posix/1
|
||||
cloud/acme
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/macos
|
||||
skip/osx
|
||||
skip/rhel
|
||||
# For some reason connecting to helper containers does not work on the Alpine VMs
|
||||
skip/alpine
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
key_type: rsa
|
||||
rsa_bits: "{{ default_rsa_key_size }}"
|
||||
subject_alt_name: "DNS:example.com"
|
||||
subject_alt_name_critical: no
|
||||
subject_alt_name_critical: false
|
||||
account_key: account-ec256
|
||||
challenge: tls-alpn-01
|
||||
challenge_alpn_tls: acme_challenge_cert_helper
|
||||
modify_account: yes
|
||||
deactivate_authzs: no
|
||||
force: no
|
||||
modify_account: true
|
||||
deactivate_authzs: false
|
||||
force: false
|
||||
remaining_days: 10
|
||||
terms_agreed: yes
|
||||
terms_agreed: true
|
||||
account_email: "example@example.org"
|
||||
|
||||
when: cryptography_version.stdout is version('1.5', '>=')
|
||||
|
||||
@@ -6,9 +6,5 @@ azp/generic/1
|
||||
azp/posix/1
|
||||
cloud/acme
|
||||
|
||||
# Skip all VMs, since we cannot talk to the ACME simulator from these:
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/macos
|
||||
skip/osx
|
||||
skip/rhel
|
||||
# For some reason connecting to helper containers does not work on the Alpine VMs
|
||||
skip/alpine
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
method: directory-only
|
||||
register: directory
|
||||
- debug: var=directory
|
||||
@@ -35,7 +35,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
url: "{{ directory.directory.newAccount}}"
|
||||
method: post
|
||||
@@ -49,7 +49,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ account_creation.headers.location }}"
|
||||
@@ -61,7 +61,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ account_creation.headers.location }}"
|
||||
@@ -80,7 +80,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ directory.directory.newOrder }}"
|
||||
@@ -103,7 +103,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ new_order.headers.location }}"
|
||||
@@ -115,7 +115,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ item }}"
|
||||
@@ -128,7 +128,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ (item.challenges | selectattr('type', 'equalto', 'http-01') | list)[0].url }}"
|
||||
@@ -141,7 +141,7 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ item.url }}"
|
||||
@@ -155,14 +155,14 @@
|
||||
acme_inspect:
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
acme_version: 2
|
||||
validate_certs: no
|
||||
validate_certs: false
|
||||
account_key_src: "{{ remote_tmp_dir }}/accountkey.pem"
|
||||
account_uri: "{{ account_creation.headers.location }}"
|
||||
url: "{{ item.url }}"
|
||||
method: get
|
||||
register: validation_result
|
||||
loop: "{{ http01challenge.results | map(attribute='output_json') | list }}"
|
||||
until: "validation_result.output_json.status != 'pending'"
|
||||
until: "validation_result.output_json.status not in ['pending', 'processing']"
|
||||
retries: 20
|
||||
delay: 1
|
||||
- debug: var=validation_result
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
- "'headers' in item"
|
||||
- "'output_text' in item"
|
||||
- "'output_json' in item"
|
||||
- item.output_json.status == 'pending'
|
||||
- item.output_json.status in ['pending', 'processing']
|
||||
- item.output_json.type == 'http-01'
|
||||
- item.output_json.url == item.invocation.module_args.url
|
||||
- "'token' in item.output_json"
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/generic/1
|
||||
azp/posix/1
|
||||
azp/generic/2
|
||||
azp/posix/2
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
- '{{ remote_tmp_dir }}/a-root.pem'
|
||||
|
||||
- name: Case B => doesn't work, but this is expected
|
||||
failed_when: no
|
||||
failed_when: false
|
||||
register: caseb
|
||||
certificate_complete_chain:
|
||||
input_chain: "{{ read_certificates['d-leaf'] }}"
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
context/controller
|
||||
azp/generic/1
|
||||
azp/posix/1
|
||||
azp/generic/2
|
||||
azp/posix/2
|
||||
destructive
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/generic/2
|
||||
azp/posix/2
|
||||
destructive
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
144
tests/integration/targets/filter_openssl_csr_info/tasks/impl.yml
Normal file
144
tests/integration/targets/filter_openssl_csr_info/tasks/impl.yml
Normal file
@@ -0,0 +1,144 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: "Get CSR info"
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/csr_1.csr') | community.crypto.openssl_csr_info }}
|
||||
result_idna: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/csr_1.csr') | community.crypto.openssl_csr_info(name_encoding='idna') }}
|
||||
result_unicode: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/csr_1.csr') | community.crypto.openssl_csr_info(name_encoding='unicode') }}
|
||||
|
||||
- name: "Check whether subject and extensions behaves as expected"
|
||||
assert:
|
||||
that:
|
||||
- result.subject.organizationalUnitName == 'ACME Department'
|
||||
- "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
|
||||
- "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
|
||||
- result.public_key_type == 'RSA'
|
||||
- result.public_key_data.size == default_rsa_key_size
|
||||
# TLS Feature
|
||||
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].critical == false
|
||||
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].value == 'MAMCAQU='
|
||||
# Key Usage
|
||||
- result.extensions_by_oid['2.5.29.15'].critical == true
|
||||
- result.extensions_by_oid['2.5.29.15'].value in ['AwMA/4A=', 'AwMH/4A=']
|
||||
# Subject Alternative Names
|
||||
- result.subject_alt_name[1] == ("DNS:âņsïbłè.com" if cryptography_version.stdout is version('2.1', '<') else "DNS:xn--sb-oia0a7a53bya.com")
|
||||
- result_unicode.subject_alt_name[1] == "DNS:âņsïbłè.com"
|
||||
- result_idna.subject_alt_name[1] == "DNS:xn--sb-oia0a7a53bya.com"
|
||||
- result.extensions_by_oid['2.5.29.17'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.17'].value == 'MHmCD3d3dy5hbnNpYmxlLmNvbYIXeG4tLXNiLW9pYTBhN2E1M2J5YS5jb22HBAECAwSHEAAAAAAAAAAAAAAAAAAAAAGBEHRlc3RAZXhhbXBsZS5vcmeGI2h0dHBzOi8vZXhhbXBsZS5vcmcvdGVzdC9pbmRleC5odG1s'
|
||||
# Basic Constraints
|
||||
- result.extensions_by_oid['2.5.29.19'].critical == true
|
||||
- result.extensions_by_oid['2.5.29.19'].value == 'MAYBAf8CARc='
|
||||
# Extended Key Usage
|
||||
- result.extensions_by_oid['2.5.29.37'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.37'].value == 'MHQGCCsGAQUFBwMBBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgGCCsGAQUFBwMJBgRVHSUABggrBgEFBQcBAwYIKwYBBQUHAwoGCCsGAQUFBwMHBggrBgEFBQcBAg=='
|
||||
|
||||
- name: "Check SubjectKeyIdentifier and AuthorityKeyIdentifier"
|
||||
assert:
|
||||
that:
|
||||
- result.subject_key_identifier == "00:11:22:33"
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
# Subject Key Identifier
|
||||
- result.extensions_by_oid['2.5.29.14'].critical == false
|
||||
# Authority Key Identifier
|
||||
- result.extensions_by_oid['2.5.29.35'].critical == false
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: "Get CSR info"
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/csr_2.csr') | community.crypto.openssl_csr_info }}
|
||||
|
||||
- name: "Get CSR info"
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/csr_3.csr') | community.crypto.openssl_csr_info }}
|
||||
|
||||
- name: "Check AuthorityKeyIdentifier"
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier is none
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: "Get CSR info"
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/csr_4.csr') | community.crypto.openssl_csr_info }}
|
||||
|
||||
- name: "Check AuthorityKeyIdentifier"
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer is none
|
||||
- result.authority_cert_serial_number is none
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Get invalid certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ [] | community.crypto.openssl_csr_info }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The community.crypto.openssl_csr_info input must be a text type, not <(?:class|type) 'list'>$")
|
||||
|
||||
- name: Get invalid certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ 'foo' | community.crypto.openssl_csr_info }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^Unable to load (?:request|PEM file)(?:\.|$)")
|
||||
|
||||
- name: Get invalid certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ 'foo' | community.crypto.openssl_csr_info(name_encoding=[]) }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The name_encoding option must be of a text type, not <(?:class|type) 'list'>$")
|
||||
|
||||
- name: Get invalid name_encoding parameter
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ 'bar' | community.crypto.openssl_csr_info(name_encoding='foo') }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The name_encoding option must be one of the values \"ignore\", \"idna\", or \"unicode\", not \"foo\"$")
|
||||
133
tests/integration/targets/filter_openssl_csr_info/tasks/main.yml
Normal file
133
tests/integration/targets/filter_openssl_csr_info/tasks/main.yml
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Make sure the Python idna library is installed
|
||||
pip:
|
||||
name: idna
|
||||
state: present
|
||||
|
||||
- name: Generate privatekey
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: Generate privatekey with password
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: Generate CSR 1
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_1.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.example.com
|
||||
C: de
|
||||
L: Somewhere
|
||||
ST: Zurich
|
||||
streetAddress: Welcome Street
|
||||
O: Ansible
|
||||
organizationalUnitName:
|
||||
- Crypto Department
|
||||
- ACME Department
|
||||
serialNumber: "1234"
|
||||
SN: Last Name
|
||||
GN: First Name
|
||||
title: Chief
|
||||
pseudonym: test
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
postalAddress: 1234 Somewhere
|
||||
postalCode: "1234"
|
||||
useCommonNameForSAN: false
|
||||
key_usage:
|
||||
- digitalSignature
|
||||
- keyAgreement
|
||||
- Non Repudiation
|
||||
- Key Encipherment
|
||||
- dataEncipherment
|
||||
- Certificate Sign
|
||||
- cRLSign
|
||||
- Encipher Only
|
||||
- decipherOnly
|
||||
key_usage_critical: true
|
||||
extended_key_usage:
|
||||
- serverAuth # the same as "TLS Web Server Authentication"
|
||||
- TLS Web Server Authentication
|
||||
- TLS Web Client Authentication
|
||||
- Code Signing
|
||||
- E-mail Protection
|
||||
- timeStamping
|
||||
- OCSPSigning
|
||||
- Any Extended Key Usage
|
||||
- qcStatements
|
||||
- DVCS
|
||||
- IPSec User
|
||||
- biometricInfo
|
||||
subject_alt_name:
|
||||
- "DNS:www.ansible.com"
|
||||
- "DNS:âņsïbłè.com"
|
||||
- "IP:1.2.3.4"
|
||||
- "IP:::1"
|
||||
- "email:test@example.org"
|
||||
- "URI:https://example.org/test/index.html"
|
||||
basic_constraints:
|
||||
- "CA:TRUE"
|
||||
- "pathlen:23"
|
||||
basic_constraints_critical: true
|
||||
ocsp_must_staple: true
|
||||
subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 2
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_2.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
useCommonNameForSAN: false
|
||||
basic_constraints:
|
||||
- "CA:TRUE"
|
||||
|
||||
- name: Generate CSR 3
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_3.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: false
|
||||
subject_alt_name:
|
||||
- "DNS:*.ansible.com"
|
||||
- "DNS:*.example.org"
|
||||
- "IP:DEAD:BEEF::1"
|
||||
basic_constraints:
|
||||
- "CA:FALSE"
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 4
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_4.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: false
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
|
||||
- name: Running tests
|
||||
include_tasks: impl.yml
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
@@ -0,0 +1,7 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/generic/2
|
||||
azp/posix/2
|
||||
destructive
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Get key 1 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/privatekey_1.pem') | community.crypto.openssl_privatekey_info }}
|
||||
|
||||
- name: Check that RSA key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'public_key' in result"
|
||||
- "'public_key_fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'RSA'"
|
||||
- "'public_data' in result"
|
||||
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
|
||||
- "result.public_data.exponent > 5"
|
||||
- "'private_data' not in result"
|
||||
|
||||
- name: Get key 2 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/privatekey_2.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
|
||||
|
||||
- name: Check that RSA key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'public_key' in result"
|
||||
- "'public_key_fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'RSA'"
|
||||
- "'public_data' in result"
|
||||
- "result.public_data.size == default_rsa_key_size"
|
||||
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
|
||||
- "result.public_data.exponent > 5"
|
||||
- "'private_data' in result"
|
||||
- "result.public_data.modulus == result.private_data.p * result.private_data.q"
|
||||
- "result.private_data.exponent > 5"
|
||||
|
||||
- name: Get key 3 info (without passphrase)
|
||||
set_fact:
|
||||
result_: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/privatekey_3.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
|
||||
ignore_errors: true
|
||||
register: result
|
||||
|
||||
- name: Check that loading passphrase protected key without passphrase failed
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- result.msg == 'Wrong or empty passphrase provided for private key'
|
||||
|
||||
- name: Get key 3 info (with passphrase)
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/privatekey_3.pem') | community.crypto.openssl_privatekey_info(passphrase='hunter2', return_private_key_data=true) }}
|
||||
|
||||
- name: Check that RSA key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'public_key' in result"
|
||||
- "'public_key_fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'RSA'"
|
||||
- "'public_data' in result"
|
||||
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
|
||||
- "result.public_data.exponent > 5"
|
||||
- "'private_data' in result"
|
||||
- "result.public_data.modulus == result.private_data.p * result.private_data.q"
|
||||
- "result.private_data.exponent > 5"
|
||||
|
||||
- name: Get key 4 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/privatekey_4.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
|
||||
|
||||
- name: Check that ECC key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'public_key' in result"
|
||||
- "'public_key_fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'ECC'"
|
||||
- "'public_data' in result"
|
||||
- "result.public_data.curve is string"
|
||||
- "result.public_data.x != 0"
|
||||
- "result.public_data.y != 0"
|
||||
- "result.public_data.exponent_size == (521 if (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') else 256)"
|
||||
- "'private_data' in result"
|
||||
- "result.private_data.multiplier > 1024"
|
||||
|
||||
- name: Get key 5 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/privatekey_5.pem') | community.crypto.openssl_privatekey_info(return_private_key_data=true) }}
|
||||
|
||||
- name: Check that DSA key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'public_key' in result"
|
||||
- "'public_key_fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'DSA'"
|
||||
- "'public_data' in result"
|
||||
- "result.public_data.p > 2"
|
||||
- "result.public_data.q > 2"
|
||||
- "result.public_data.g >= 2"
|
||||
- "result.public_data.y > 2"
|
||||
- "'private_data' in result"
|
||||
- "result.private_data.x > 2"
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Generate privatekey 1
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_1.pem'
|
||||
|
||||
- name: Generate privatekey 2 (less bits)
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_2.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: Generate privatekey 3 (with password)
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_3.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: Generate privatekey 4 (ECC)
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_4.pem'
|
||||
type: ECC
|
||||
curve: "{{ (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') | ternary('secp521r1', 'secp256k1') }}"
|
||||
# ^ cryptography on CentOS6 doesn't support secp256k1, so we use secp521r1 instead
|
||||
|
||||
- name: Generate privatekey 5 (DSA)
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_5.pem'
|
||||
type: DSA
|
||||
size: 1024
|
||||
|
||||
- name: Running tests
|
||||
include_tasks: impl.yml
|
||||
when: cryptography_version.stdout is version('1.2.3', '>=')
|
||||
@@ -0,0 +1,7 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/generic/2
|
||||
azp/posix/2
|
||||
destructive
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Get key 1 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/publickey_1.pem') | community.crypto.openssl_publickey_info }}
|
||||
|
||||
- name: Check that RSA key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'RSA'"
|
||||
- "'public_data' in result"
|
||||
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
|
||||
- "result.public_data.exponent > 5"
|
||||
|
||||
- name: Get key 2 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/publickey_2.pem') | community.crypto.openssl_publickey_info }}
|
||||
|
||||
- name: Check that RSA key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'RSA'"
|
||||
- "'public_data' in result"
|
||||
- "result.public_data.size == default_rsa_key_size"
|
||||
- "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
|
||||
- "result.public_data.exponent > 5"
|
||||
|
||||
- name: Get key 3 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/publickey_3.pem') | community.crypto.openssl_publickey_info }}
|
||||
|
||||
- name: Check that ECC key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'ECC'"
|
||||
- "'public_data' in result"
|
||||
- "result.public_data.curve is string"
|
||||
- "result.public_data.x != 0"
|
||||
- "result.public_data.y != 0"
|
||||
- "result.public_data.exponent_size == (521 if (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') else 256)"
|
||||
|
||||
- name: Get key 4 info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/publickey_4.pem') | community.crypto.openssl_publickey_info }}
|
||||
|
||||
- name: Check that DSA key info is ok
|
||||
assert:
|
||||
that:
|
||||
- "'fingerprints' in result"
|
||||
- "'type' in result"
|
||||
- "result.type == 'DSA'"
|
||||
- "'public_data' in result"
|
||||
- "result.public_data.p > 2"
|
||||
- "result.public_data.q > 2"
|
||||
- "result.public_data.g >= 2"
|
||||
- "result.public_data.y > 2"
|
||||
|
||||
- name: Get invalid key info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ [] | community.crypto.openssl_publickey_info }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The community.crypto.openssl_publickey_info input must be a text type, not <(?:class|type) 'list'>$")
|
||||
|
||||
- name: Get invalid key info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ 'foo' | community.crypto.openssl_publickey_info }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- 'output.msg is search("^Error while deserializing key: ")'
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Generate privatekey 1
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_1.pem'
|
||||
|
||||
- name: Generate privatekey 2 (less bits)
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_2.pem'
|
||||
type: RSA
|
||||
size: '{{ default_rsa_key_size }}'
|
||||
|
||||
- name: Generate privatekey 3 (ECC)
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_3.pem'
|
||||
type: ECC
|
||||
curve: "{{ (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') | ternary('secp521r1', 'secp256k1') }}"
|
||||
# ^ cryptography on CentOS6 doesn't support secp256k1, so we use secp521r1 instead
|
||||
select_crypto_backend: cryptography
|
||||
|
||||
- name: Generate privatekey 4 (DSA)
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey_4.pem'
|
||||
type: DSA
|
||||
size: 1024
|
||||
|
||||
- name: Generate public keys
|
||||
openssl_publickey:
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey_{{ item }}.pem'
|
||||
path: '{{ remote_tmp_dir }}/publickey_{{ item }}.pem'
|
||||
loop:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
|
||||
- name: Running tests
|
||||
include_tasks: impl.yml
|
||||
when: cryptography_version.stdout is version('1.2.3', '>=')
|
||||
6
tests/integration/targets/filter_split_pem/aliases
Normal file
6
tests/integration/targets/filter_split_pem/aliases
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/generic/2
|
||||
azp/posix/2
|
||||
64
tests/integration/targets/filter_split_pem/tasks/main.yml
Normal file
64
tests/integration/targets/filter_split_pem/tasks/main.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Run tests that raise no errors
|
||||
assert:
|
||||
that:
|
||||
- >-
|
||||
'' | community.crypto.split_pem == []
|
||||
- >-
|
||||
(pem_1 + pem_2 + pem_3) | community.crypto.split_pem == [pem_1, pem_2, pem_3]
|
||||
- >-
|
||||
(pem_3 + pem_2 + pem_1) | community.crypto.split_pem == [pem_3, pem_2, pem_1]
|
||||
- >-
|
||||
(crap_1 + pem_3 + crap_2 + pem_2 + crap_3 + pem_1 + crap_2) | community.crypto.split_pem == [pem_3, pem_2, pem_1]
|
||||
- >-
|
||||
(crap_1 + pem_1 + crap_2 + pem_1 + crap_3 + crap_4 + crap_4) | community.crypto.split_pem == [pem_1, pem_1]
|
||||
vars:
|
||||
pem_1: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
AAb=
|
||||
-----END CERTIFICATE-----
|
||||
pem_2: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
Foo
|
||||
Bar
|
||||
Baz
|
||||
Bam
|
||||
-----END PRIVATE KEY-----
|
||||
pem_3: |
|
||||
-----BEGIN
|
||||
foo
|
||||
-----END
|
||||
crap_1: |
|
||||
# Comment
|
||||
crap_2: |
|
||||
Random text
|
||||
In multiple
|
||||
Lines
|
||||
crap_3: |
|
||||
----BEGIN CERTIFICATE----
|
||||
Certificate with too few dashes
|
||||
----END CERTIFICATE----
|
||||
crap_4: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
AAb=
|
||||
|
||||
- name: Invalid input
|
||||
debug:
|
||||
msg: "{{ [] | community.crypto.split_pem }}"
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Validate error
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The community.crypto.split_pem input must be a text type, not <(?:class|type) 'list'>$")
|
||||
@@ -0,0 +1,8 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/generic/2
|
||||
azp/posix/2
|
||||
needs/target/x509_certificate_info
|
||||
destructive
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_openssl
|
||||
- setup_remote_tmp_dir
|
||||
- prepare_jinja2_compat
|
||||
@@ -0,0 +1,221 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Get certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/cert_1.pem') | community.crypto.x509_certificate_info }}
|
||||
result_idna: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/cert_1.pem') | community.crypto.x509_certificate_info(name_encoding='idna') }}
|
||||
result_unicode: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/cert_1.pem') | community.crypto.x509_certificate_info(name_encoding='unicode') }}
|
||||
|
||||
- name: Check whether issuer and subject and extensions behave as expected
|
||||
assert:
|
||||
that:
|
||||
- result.issuer.organizationalUnitName == 'ACME Department'
|
||||
- "['organizationalUnitName', 'Crypto Department'] in result.issuer_ordered"
|
||||
- "['organizationalUnitName', 'ACME Department'] in result.issuer_ordered"
|
||||
- result.subject.organizationalUnitName == 'ACME Department'
|
||||
- "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
|
||||
- "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
|
||||
- result.public_key_type == 'RSA'
|
||||
- result.public_key_data.size == (default_rsa_key_size_certifiates | int)
|
||||
- "result.subject_alt_name == [
|
||||
'DNS:www.ansible.com',
|
||||
'DNS:' ~ ('öç' if cryptography_version.stdout is version('2.1', '<') else 'xn--7ca3a') ~ '.com',
|
||||
'DNS:' ~ ('www.öç' if cryptography_version.stdout is version('2.1', '<') else 'xn--74h') ~ '.com',
|
||||
'IP:1.2.3.4',
|
||||
'IP:::1',
|
||||
'email:test@example.org',
|
||||
'URI:https://example.org/test/index.html'
|
||||
]"
|
||||
- "result_idna.subject_alt_name == [
|
||||
'DNS:www.ansible.com',
|
||||
'DNS:xn--7ca3a.com',
|
||||
'DNS:' ~ ('www.xn--7ca3a' if cryptography_version.stdout is version('2.1', '<') else 'xn--74h') ~ '.com',
|
||||
'IP:1.2.3.4',
|
||||
'IP:::1',
|
||||
'email:test@example.org',
|
||||
'URI:https://example.org/test/index.html'
|
||||
]"
|
||||
- "result_unicode.subject_alt_name == [
|
||||
'DNS:www.ansible.com',
|
||||
'DNS:öç.com',
|
||||
'DNS:' ~ ('www.öç' if cryptography_version.stdout is version('2.1', '<') else '☺') ~ '.com',
|
||||
'IP:1.2.3.4',
|
||||
'IP:::1',
|
||||
'email:test@example.org',
|
||||
'URI:https://example.org/test/index.html'
|
||||
]"
|
||||
# TLS Feature
|
||||
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].critical == false
|
||||
- result.extensions_by_oid['1.3.6.1.5.5.7.1.24'].value == 'MAMCAQU='
|
||||
# Key Usage
|
||||
- result.extensions_by_oid['2.5.29.15'].critical == true
|
||||
- result.extensions_by_oid['2.5.29.15'].value in ['AwMA/4A=', 'AwMH/4A=']
|
||||
# Subject Alternative Names
|
||||
- result.extensions_by_oid['2.5.29.17'].critical == false
|
||||
- >
|
||||
result.extensions_by_oid['2.5.29.17'].value == (
|
||||
'MIGCgg93d3cuYW5zaWJsZS5jb22CDXhuLS03Y2EzYS5jb22CEXd3dy54bi0tN2NhM2EuY29thwQBAgMEhxAAAAAAAAAAAAAAAAAAAAABgRB0ZXN0QGV4YW1wbGUub3JnhiNodHRwczovL2V4YW1wbGUub3JnL3Rlc3QvaW5kZXguaHRtbA=='
|
||||
if cryptography_version.stdout is version('2.1', '<') else
|
||||
'MHyCD3d3dy5hbnNpYmxlLmNvbYINeG4tLTdjYTNhLmNvbYILeG4tLTc0aC5jb22HBAECAwSHEAAAAAAAAAAAAAAAAAAAAAGBEHRlc3RAZXhhbXBsZS5vcmeGI2h0dHBzOi8vZXhhbXBsZS5vcmcvdGVzdC9pbmRleC5odG1s'
|
||||
)
|
||||
# Basic Constraints
|
||||
- result.extensions_by_oid['2.5.29.19'].critical == true
|
||||
- result.extensions_by_oid['2.5.29.19'].value == 'MAYBAf8CARc='
|
||||
# Extended Key Usage
|
||||
- result.extensions_by_oid['2.5.29.37'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.37'].value == 'MHQGCCsGAQUFBwMBBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgGCCsGAQUFBwMJBgRVHSUABggrBgEFBQcBAwYIKwYBBQUHAwoGCCsGAQUFBwMHBggrBgEFBQcBAg=='
|
||||
|
||||
- name: Check SubjectKeyIdentifier and AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.subject_key_identifier == "00:11:22:33"
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
# Subject Key Identifier
|
||||
- result.extensions_by_oid['2.5.29.14'].critical == false
|
||||
# Authority Key Identifier
|
||||
- result.extensions_by_oid['2.5.29.35'].critical == false
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Get certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/cert_2.pem') | community.crypto.x509_certificate_info }}
|
||||
|
||||
- name: Get certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/cert_3.pem') | community.crypto.x509_certificate_info }}
|
||||
|
||||
- name: Check AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier is none
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Get certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', remote_tmp_dir ~ '/cert_4.pem') | community.crypto.x509_certificate_info }}
|
||||
|
||||
- name: Check AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer is none
|
||||
- result.authority_cert_serial_number is none
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Get certificate info for packaged cert 1
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ lookup('file', role_path ~ '/../x509_certificate_info/files/cert1.pem') | community.crypto.x509_certificate_info }}
|
||||
- name: Check extensions
|
||||
assert:
|
||||
that:
|
||||
- "'ocsp_uri' in result"
|
||||
- "result.ocsp_uri == 'http://ocsp.int-x3.letsencrypt.org'"
|
||||
- "'issuer_uri' in result"
|
||||
- "result.issuer_uri == 'http://cert.int-x3.letsencrypt.org/'"
|
||||
- result.extensions_by_oid | length == 9
|
||||
# Precert Signed Certificate Timestamps
|
||||
- result.extensions_by_oid['1.3.6.1.4.1.11129.2.4.2'].critical == false
|
||||
- result.extensions_by_oid['1.3.6.1.4.1.11129.2.4.2'].value == 'BIHyAPAAdgDBFkrgp3LS1DktyArBB3DU8MSb3pkaSEDB+gdRZPYzYAAAAWTdAoU6AAAEAwBHMEUCIG5WpfKF536KKa9fnVlYbwcfrKh09Hi2MSRwU2kad49UAiEA4RUKjJOgw11IHFNdit+sy1RcCU3QCSOEQYrJ1/oPltAAdgApPFGWVMg5ZbqqUPxYB9S3b79Yeily3KTDDPTlRUf0eAAAAWTdAoc+AAAEAwBHMEUCIQCJjo75K4rVDSiWQe3XFLY6MiG3zcHQrKb0YhM17r1UKAIgGa8qMoN03DLp+Rm9nRJ9XLbTJz1vbuu9PyXUY741P8E='
|
||||
# Authority Information Access
|
||||
- result.extensions_by_oid['1.3.6.1.5.5.7.1.1'].critical == false
|
||||
- result.extensions_by_oid['1.3.6.1.5.5.7.1.1'].value == 'MGEwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcv'
|
||||
# Subject Key Identifier
|
||||
- result.extensions_by_oid['2.5.29.14'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.14'].value == 'BBRtcOI/yg62Ehbu5vQzxMUUdBOYMw=='
|
||||
# Key Usage (The certificate has 'AwIFoA==', while de-serializing and re-serializing yields 'AwIAoA=='!)
|
||||
- result.extensions_by_oid['2.5.29.15'].critical == true
|
||||
- result.extensions_by_oid['2.5.29.15'].value in ['AwIFoA==', 'AwIAoA==']
|
||||
# Subject Alternative Names
|
||||
- result.extensions_by_oid['2.5.29.17'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.17'].value == 'MIIB5IIbY2VydC5pbnQteDEubGV0c2VuY3J5cHQub3JnghtjZXJ0LmludC14Mi5sZXRzZW5jcnlwdC5vcmeCG2NlcnQuaW50LXgzLmxldHNlbmNyeXB0Lm9yZ4IbY2VydC5pbnQteDQubGV0c2VuY3J5cHQub3JnghxjZXJ0LnJvb3QteDEubGV0c2VuY3J5cHQub3Jngh9jZXJ0LnN0YWdpbmcteDEubGV0c2VuY3J5cHQub3Jngh9jZXJ0LnN0Zy1pbnQteDEubGV0c2VuY3J5cHQub3JngiBjZXJ0LnN0Zy1yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ISY3AubGV0c2VuY3J5cHQub3JnghpjcC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ITY3BzLmxldHNlbmNyeXB0Lm9yZ4IbY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3Jnghtjcmwucm9vdC14MS5sZXRzZW5jcnlwdC5vcmeCD2xldHNlbmNyeXB0Lm9yZ4IWb3JpZ2luLmxldHNlbmNyeXB0Lm9yZ4IXb3JpZ2luMi5sZXRzZW5jcnlwdC5vcmeCFnN0YXR1cy5sZXRzZW5jcnlwdC5vcmeCE3d3dy5sZXRzZW5jcnlwdC5vcmc='
|
||||
# Basic Constraints
|
||||
- result.extensions_by_oid['2.5.29.19'].critical == true
|
||||
- result.extensions_by_oid['2.5.29.19'].value == 'MAA='
|
||||
# Certificate Policies
|
||||
- result.extensions_by_oid['2.5.29.32'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.32'].value == 'MIHzMAgGBmeBDAECATCB5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5kIGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkv'
|
||||
# Authority Key Identifier
|
||||
- result.extensions_by_oid['2.5.29.35'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.35'].value == 'MBaAFKhKamMEfd265tE5t6ZFZe/zqOyh'
|
||||
# Extended Key Usage
|
||||
- result.extensions_by_oid['2.5.29.37'].critical == false
|
||||
- result.extensions_by_oid['2.5.29.37'].value == 'MBQGCCsGAQUFBwMBBggrBgEFBQcDAg=='
|
||||
- name: Check fingerprints
|
||||
assert:
|
||||
that:
|
||||
- (result.fingerprints.sha256 == '57:7c:f1:f5:dd:cc:6e:e9:f3:17:28:73:17:e4:25:c7:69:74:3e:f7:9a:df:58:20:7a:5a:e4:aa:de:bf:24:5b' if result.fingerprints.sha256 is defined else true)
|
||||
- (result.fingerprints.sha1 == 'b7:79:64:f4:2b:e0:ae:45:74:d4:f3:08:f6:53:cb:39:26:fa:52:6b' if result.fingerprints.sha1 is defined else true)
|
||||
|
||||
- name: Get invalid certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ [] | community.crypto.x509_certificate_info }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The community.crypto.x509_certificate_info input must be a text type, not <(?:class|type) 'list'>$")
|
||||
|
||||
- name: Get invalid certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ 'foo' | community.crypto.x509_certificate_info }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^Unable to load (?:certificate|PEM file)(?:\.|$)")
|
||||
|
||||
- name: Get invalid certificate info
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ 'foo' | community.crypto.x509_certificate_info(name_encoding=[]) }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The name_encoding option must be of a text type, not <(?:class|type) 'list'>$")
|
||||
|
||||
- name: Get invalid name_encoding parameter
|
||||
set_fact:
|
||||
result: >-
|
||||
{{ 'bar' | community.crypto.x509_certificate_info(name_encoding='foo') }}
|
||||
ignore_errors: true
|
||||
register: output
|
||||
|
||||
- name: Check that task failed and error message is OK
|
||||
assert:
|
||||
that:
|
||||
- output is failed
|
||||
- output.msg is search("^The name_encoding option must be one of the values \"ignore\", \"idna\", or \"unicode\", not \"foo\"$")
|
||||
@@ -0,0 +1,151 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
- name: Make sure the Python idna library is installed
|
||||
pip:
|
||||
name: idna
|
||||
state: present
|
||||
|
||||
- name: Generate privatekey
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
size: '{{ default_rsa_key_size_certifiates }}'
|
||||
|
||||
- name: Generate privatekey with password
|
||||
openssl_privatekey:
|
||||
path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
select_crypto_backend: cryptography
|
||||
size: '{{ default_rsa_key_size_certifiates }}'
|
||||
|
||||
- name: Generate CSR 1
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_1.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.example.com
|
||||
C: de
|
||||
L: Somewhere
|
||||
ST: Zurich
|
||||
streetAddress: Welcome Street
|
||||
O: Ansible
|
||||
organizationalUnitName:
|
||||
- Crypto Department
|
||||
- ACME Department
|
||||
serialNumber: "1234"
|
||||
SN: Last Name
|
||||
GN: First Name
|
||||
title: Chief
|
||||
pseudonym: test
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
postalAddress: 1234 Somewhere
|
||||
postalCode: "1234"
|
||||
useCommonNameForSAN: false
|
||||
key_usage:
|
||||
- digitalSignature
|
||||
- keyAgreement
|
||||
- Non Repudiation
|
||||
- Key Encipherment
|
||||
- dataEncipherment
|
||||
- Certificate Sign
|
||||
- cRLSign
|
||||
- Encipher Only
|
||||
- decipherOnly
|
||||
key_usage_critical: true
|
||||
extended_key_usage:
|
||||
- serverAuth # the same as "TLS Web Server Authentication"
|
||||
- TLS Web Server Authentication
|
||||
- TLS Web Client Authentication
|
||||
- Code Signing
|
||||
- E-mail Protection
|
||||
- timeStamping
|
||||
- OCSPSigning
|
||||
- Any Extended Key Usage
|
||||
- qcStatements
|
||||
- DVCS
|
||||
- IPSec User
|
||||
- biometricInfo
|
||||
subject_alt_name:
|
||||
- "DNS:www.ansible.com"
|
||||
- "DNS:öç.com"
|
||||
# cryptography < 2.1 cannot handle certain Unicode characters
|
||||
- "DNS:{{ 'www.öç' if cryptography_version.stdout is version('2.1', '<') else '☺' }}.com"
|
||||
- "IP:1.2.3.4"
|
||||
- "IP:::1"
|
||||
- "email:test@example.org"
|
||||
- "URI:https://example.org/test/index.html"
|
||||
basic_constraints:
|
||||
- "CA:TRUE"
|
||||
- "pathlen:23"
|
||||
basic_constraints_critical: true
|
||||
ocsp_must_staple: true
|
||||
subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 2
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_2.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
useCommonNameForSAN: false
|
||||
basic_constraints:
|
||||
- "CA:TRUE"
|
||||
|
||||
- name: Generate CSR 3
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_3.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: false
|
||||
subject_alt_name:
|
||||
- "DNS:*.ansible.com"
|
||||
- "DNS:*.example.org"
|
||||
- "IP:DEAD:BEEF::1"
|
||||
basic_constraints:
|
||||
- "CA:FALSE"
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 4
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_4.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: false
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
|
||||
- name: Generate selfsigned certificates
|
||||
x509_certificate:
|
||||
path: '{{ remote_tmp_dir }}/cert_{{ item }}.pem'
|
||||
csr_path: '{{ remote_tmp_dir }}/csr_{{ item }}.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
provider: selfsigned
|
||||
selfsigned_digest: sha256
|
||||
selfsigned_not_after: "+10d"
|
||||
selfsigned_not_before: "-3d"
|
||||
loop:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
|
||||
- name: Running tests
|
||||
include_tasks: impl.yml
|
||||
when: cryptography_version.stdout is version('1.6', '>=')
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user