Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EE support #440

Merged
merged 6 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do they not have stable-2.13 yet?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't (https://quay.io/repository/ansible/ansible-runner?tab=tags&tag=latest). I guess it will show up once 2.13.0 has been released.

- 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