Skip to content

Commit

Permalink
Add EE support (#440)
Browse files Browse the repository at this point in the history
* Add EE files.

* Install cryptography and PyOpenSSL from PyPi.

* Revert "Install cryptography and PyOpenSSL from PyPi."

This reverts commit 6b90a1e.

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

* And another one.

* Extend changelog.
  • Loading branch information
felixfontein authored May 3, 2022
1 parent c16d9f7 commit 640bdbc
Show file tree
Hide file tree
Showing 21 changed files with 447 additions and 0 deletions.
109 changes: 109 additions & 0 deletions .github/workflows/ee.yml
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions changelogs/fragments/440-ee.yml
Original file line number Diff line number Diff line change
@@ -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 changes: 10 additions & 0 deletions meta/ee-bindep.txt
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions meta/ee-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PyYAML
5 changes: 5 additions & 0 deletions meta/execution-environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
version: 1
dependencies:
python: meta/ee-requirements.txt
system: meta/ee-bindep.txt
34 changes: 34 additions & 0 deletions tests/ee/all.yml
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions tests/ee/roles/crypto_info/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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
45 changes: 45 additions & 0 deletions tests/ee/roles/luks_device/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions tests/ee/roles/openssh_keypair/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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', '>=')
41 changes: 41 additions & 0 deletions tests/ee/roles/openssl_pkcs12/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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
11 changes: 11 additions & 0 deletions tests/ee/roles/openssl_privatekey/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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
48 changes: 48 additions & 0 deletions tests/ee/roles/smoke/library/smoke_ipaddress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# (c) 2022 Felix Fontein <[email protected]>
# 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
Loading

0 comments on commit 640bdbc

Please sign in to comment.