Add EE support (#440)

* Add EE files.

* Install cryptography and PyOpenSSL from PyPi.

* Revert "Install cryptography and PyOpenSSL from PyPi."

This reverts commit 6b90a1efae.

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

* And another one.

* Extend changelog.
pull/452/head
Felix Fontein 2022-05-03 19:22:55 +02:00 committed by GitHub
parent c16d9f78b8
commit 640bdbc066
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 447 additions and 0 deletions

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

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

View File

@ -0,0 +1,7 @@
minor_changes:
- "Prepare collection for inclusion in an Execution Environment by declaring its dependencies.
Please note that system packages are used for cryptography and PyOpenSSL, which can be
rather limited. If you need features from newer cryptography versions, you will have to
manually force a newer version to be installed by pip by specifying something like
``cryptography >= 37.0.0`` in your Execution Environment's Python dependencies file
(https://github.com/ansible-collections/community.crypto/pull/440)."

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

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

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

@ -0,0 +1 @@
PyYAML

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,3 +5,5 @@
.azure-pipelines/scripts/publish-codecov.py future-import-boilerplate
.azure-pipelines/scripts/publish-codecov.py metaclass-boilerplate
plugins/modules/acme_account_info.py validate-modules:return-syntax-error
tests/ee/roles/smoke/library/smoke_ipaddress.py shebang
tests/ee/roles/smoke/library/smoke_pyyaml.py shebang

View File

@ -5,3 +5,5 @@
.azure-pipelines/scripts/publish-codecov.py future-import-boilerplate
.azure-pipelines/scripts/publish-codecov.py metaclass-boilerplate
plugins/modules/acme_account_info.py validate-modules:return-syntax-error
tests/ee/roles/smoke/library/smoke_ipaddress.py shebang
tests/ee/roles/smoke/library/smoke_pyyaml.py shebang

View File

@ -1,2 +1,4 @@
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
plugins/modules/acme_account_info.py validate-modules:return-syntax-error
tests/ee/roles/smoke/library/smoke_ipaddress.py shebang
tests/ee/roles/smoke/library/smoke_pyyaml.py shebang

View File

@ -1 +1,3 @@
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
tests/ee/roles/smoke/library/smoke_ipaddress.py shebang
tests/ee/roles/smoke/library/smoke_pyyaml.py shebang

View File

@ -1 +1,3 @@
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
tests/ee/roles/smoke/library/smoke_ipaddress.py shebang
tests/ee/roles/smoke/library/smoke_pyyaml.py shebang

View File

@ -4,3 +4,5 @@
.azure-pipelines/scripts/publish-codecov.py compile-3.5!skip # Uses Python 3.6+ syntax
.azure-pipelines/scripts/publish-codecov.py future-import-boilerplate
.azure-pipelines/scripts/publish-codecov.py metaclass-boilerplate
tests/ee/roles/smoke/library/smoke_ipaddress.py shebang
tests/ee/roles/smoke/library/smoke_pyyaml.py shebang