#1490 WIP: AWX: Initial configuration
Merged 10 months ago by darknao. Opened 11 months ago by darknao.
fedora-infra/ darknao/ansible awx  into  main

@@ -900,3 +900,15 @@ 

      ocp4: true

      keephost: true

      tags: ipsilon-website

+ 

+   - role: httpd/reverseproxy

+     website: awx.fedoraproject.org

+     destname: awx

+     balancer_name: app-ocp

+     balancer_members: "{{ ocp_nodes }}"

+     targettype: openshift

+     ocp4: true

+     keephost: true

+     tags:

+     - awx

+     when: env == "production"

@@ -580,7 +580,12 @@ 

      tags:

      - coreos.fedoraproject.org

  

- 

+   - role: httpd/website

+     site_name: awx.fedoraproject.org

+     sslonly: true

+     cert_name: "{{wildcard_cert_name}}"

+     tags:

+     - awx

  #

  # Make a website here so we can redirect it to paste.fedoraproject.org

  #

@@ -0,0 +1,20 @@ 

+ ---

+ - name: make the app be real

+   hosts: localhost

+   connection: local

+   user: root

+   gather_facts: False

+ 

+   vars_files:

+     - /srv/web/infra/ansible/vars/global.yml

+     - "/srv/private/ansible/vars.yml"

+     - /srv/web/infra/ansible/vars/{{ ansible_distribution }}.yml

+ 

+   module_defaults:

+     group/awx.awx.controller:

+       controller_host: awx.fedoraproject.org

+       controller_username: "{{ awx_admin_username }}"

+       controller_password: "{{ awx_admin_password }}"

+ 

+   roles:

+   - role: awx/controller

@@ -0,0 +1,3 @@ 

+ ---

+ collections:

+ - awx.awx

@@ -0,0 +1,6 @@ 

+ ---

+ - name: Create Fedora Ansible Execution Environment

+   execution_environment:

+     name: Fedora ansible EE

+     image: registry.gitlab.com/darknao/fedora-ansible-ee:latest

+     pull: always

@@ -0,0 +1,11 @@ 

+ ---

+ - name: Define batcave01 as execution node

+   instance:

+     hostname: batcave01.vpn.fedoraproject.org

+     node_type: execution

+ 

+ - name: Create batcave instance group

+   instance_group:

+     name: batcave

+     instances:

+     - batcave01.vpn.fedoraproject.org

@@ -0,0 +1,6 @@ 

+ ---

+ - include_tasks: saml2.yml

+ - include_tasks: execution_environment.yml

+ - include_tasks: org.yml

+ - include_tasks: execution_nodes.yml

+ - include_tasks: projects.yml

@@ -0,0 +1,5 @@ 

+ ---

+ - name: Create Fedora organization

+   organization:

+     name: Fedora

+     description: Fedora Project Org

@@ -0,0 +1,31 @@ 

+ ---

+ - name: Create Fedora Infra project

+   project:

+     name: Fedora Infra

+     description: ""

+     scm_type: git

+     scm_url: https://pagure.io/fedora-infra/ansible.git

+     scm_clean: true

+     organization: Fedora

+     scm_update_on_launch: true

+     default_environment: Fedora ansible EE

+ 

+ - name: Create Fedora Infra Inventory

+   inventory:

+     name: Fedora Infra

+     description: ""

+     organization: Fedora

+ 

+ - name: Set up Fedora Infra Inventory source

+   inventory_source:

+     source_project: Fedora Infra

+     inventory: Fedora Infra

+     name: Fedora Infra Git

+     source: scm

+     source_path: inventory

+     update_on_launch: true

+ 

+ - name: Trigger inventory update

+   inventory_source_update:

+     name: Fedora Infra Git

+     inventory: Fedora Infra

@@ -0,0 +1,50 @@ 

+ ---

+ - name: Configure SAML2 authentication

+   settings:

+     settings:

+       SAML_AUTO_CREATE_OBJECTS: true

+       SOCIAL_AUTH_SAML_SP_ENTITY_ID: https://awx.fedoraproject.org/

+       SOCIAL_AUTH_SAML_SP_PUBLIC_CERT:

+         "{{ lookup('file', '{{ private }}/files/awx/{{ env }}/awx-saml.crt') }}"

+       SOCIAL_AUTH_SAML_SP_PRIVATE_KEY:

+         "{{ lookup('file', '{{ private }}/files/awx/{{ env }}/awx-saml.key') }}"

+       SOCIAL_AUTH_SAML_ORG_INFO:

+         en-US:

+           url: https://awx.fedoraproject.org/

+           name: AWX

+           displayname: Ansible AWX

+       SOCIAL_AUTH_SAML_TECHNICAL_CONTACT:

+         emailAddress: infrastructure@lists.fedoraproject.org

+         givenName: Fedora Infrastructure

+       SOCIAL_AUTH_SAML_SUPPORT_CONTACT:

+         emailAddress: infrastructure@lists.fedoraproject.org

+         givenName: Fedora Infrastructure

+       SOCIAL_AUTH_SAML_ENABLED_IDPS:

+         fedora:

+           x509cert:

+             "{{ lookup(

+                   'file',

+                   '{{ private }}/files/saml2/{{ env }}/keys/idp.crt'

+                 )

+                 | regex_replace('\n', '')

+             }}"

+           attr_email: "email"

+           attr_first_name: "givenname"

+           attr_last_name: "surname"

+           attr_user_permanent_id: "name_id"

+           attr_username: "name_id"

+           entity_id: "https://id.fedoraproject.org/idp/saml2/metadata"

+           url: "https://id.fedoraproject.org/idp/saml2/SSO/Redirect"

+       SOCIAL_AUTH_SAML_SECURITY_CONFIG:

+         authnRequestsSigned: true

+       SOCIAL_AUTH_SAML_USER_FLAGS_BY_ATTR:

+         is_superuser_attr: groups

+         is_superuser_value:

+           - sysadmin-main

+       SOCIAL_AUTH_SAML_ORGANIZATION_MAP: {}

+       SOCIAL_AUTH_SAML_TEAM_ATTR:

+         saml_attr: groups

+         remove: true

+         team_org_map:

+           - organization: Fedora

+             team: fedora-websites

@@ -0,0 +1,57 @@ 

+ ---

+ - name: Create the awx user

+   user:

+     name: awx

+     shell: /bin/bash

+ 

+ - name: Enable Copr repo for Ansible Receptor (Fedora)

+   community.general.copr:

+     name: ansible-awx/receptor

+   when: ansible_distribution == 'Fedora'

+ 

+ - name: Enable Copr repo for Ansible Receptor (RHEL)

+   community.general.copr:

+     name: ansible-awx/receptor

+     chroot: epel-9-x86_64

+   when:

+   - ansible_distribution == 'RedHat'

+   - ansible_distribution_major_version|int == 9

+ 

+ - name: Deploy podman

+   include_role:

+     name: awx/podman

+   vars:

+     podman_user: awx

+     podman_group: awx

+ 

+ - name: Deploy Ansible Receptor

+   include_role:

+     name: awx/receptor

+   vars:

+     receptor_user: awx

+     receptor_group: awx

+     receptor_verify: true

+     receptor_tls: true

+     receptor_mintls13: false

+     receptor_work_commands:

+       ansible-runner:

+         command: ansible-runner

+         params: worker

+         allowruntimeparams: true

+         verifysignature: true

+     custom_worksign_public_keyfile:

+       "{{ private }}/files/awx/{{ inventory_hostname }}/work-public-key.pem"

+     custom_tls_certfile: "{{ private }}/files/awx/{{ inventory_hostname }}/tls/receptor.crt"

+     custom_tls_keyfile: "{{ private }}/files/awx/{{ inventory_hostname }}/tls/receptor.key"

+     custom_ca_certfile: "{{ private }}/files/awx/{{ inventory_hostname }}/tls/ca/receptor-ca.crt"

+     receptor_protocol: 'tcp'

+     receptor_listener: true

+     receptor_port: 27199

+     receptor_dependencies:

+       - python3-pip

+     ansible_host: "{{ inventory_hostname }}"

+ 

+ - name: Install ansible-runner

+   pip:

+     name: ansible-runner

+     executable: pip3

@@ -0,0 +1,32 @@ 

+ # Ansible Role: Podman

+ 

+ Installs and configures Podman on RHEL/CentOS/Fedora servers.

+ 

+ ## Role Variables

+ 

+ Available variables are listed below, along with default values.

+ 

+ ---

+ 

+     podman_user: 'podman'

+     podman_group: 'podman'

+ 

+ The user and group under which podman will be configured.

+ 

+ ---

+ 

+     default_runtime: 'crun'

+ 

+ The default container runtime to use for Podman. 

+ 

+ ---

+ 

+     default_cgroup_manager: 'cgroupfs'

+ 

+ The default cgroup manager to use for Podman.

+ 

+ ---

+ 

+ # License

+ 

+ Apache 2

@@ -0,0 +1,8 @@ 

+ ---

+ podman_user: 'podman'

+ podman_group: 'podman'

+ 

+ default_runtime: 'crun'

+ default_cgroup_manager: 'cgroupfs'

+ 

+ _hostname: "{{ routable_hostname | default(ansible_host) }}"

@@ -0,0 +1,48 @@ 

+ ---

+ # Variable configuration.

+ - include_tasks: variables.yml

+ 

+ # Setup/install tasks.

+ - include_tasks: setup-RedHat.yml

+   when: ansible_os_family == 'RedHat'

+ 

+ - name: Create directory for podman runtime config

+   ansible.builtin.file:

+     path: "~{{ podman_user }}/.config/containers"

+     state: directory

+     mode: 0700

+     owner: "{{ podman_user }}"

+     group: "{{ podman_group }}"

+ 

+ - name: Configure podman default runtime

+   ansible.builtin.copy:

+     content: |

+       [engine]

+       runtime = "{{ default_runtime }}"

+       cgroup_manager = "{{ default_cgroup_manager }}"

+     dest: "~{{ podman_user }}/.config/containers/containers.conf"

+     owner: "{{ podman_user }}"

+     group: "{{ podman_group }}"

+     mode: 0600

+ 

+ - name: Create empty mounts config file to avoid permissions error message

+   ansible.builtin.copy:

+     content: ""

+     dest: "~{{ podman_user }}/.config/containers/mounts.conf"

+     force: false

+     owner: "{{ podman_user }}"

+     group: "{{ podman_group }}"

+     mode: 0600

+ 

+ - name: Ensure registries.conf.d exists

+   ansible.builtin.file:

+     path: /etc/containers/registries.conf.d/

+     state: directory

+     mode: 0755

+ 

+ - name: Force fully qualified image names to be provided to podman pull

+   ansible.builtin.copy:

+     content: |

+       unqualified-search-registries = []

+     dest: /etc/containers/registries.conf.d/force-fully-qualified-images.conf

+     mode: 0644

@@ -0,0 +1,5 @@ 

+ ---

+ - name: Install podman packages

+   ansible.builtin.dnf:

+     name: "{{ podman_packages }}"

+     state: present

@@ -0,0 +1,10 @@ 

+ ---

+ - name: Include OS-specific variables (RedHat)

+   ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"

+   when:

+     - ansible_os_family == 'RedHat'

+ 

+ - name: Define podman_packages

+   ansible.builtin.set_fact:

+     podman_packages: "{{ __podman_packages | list }}"

+   when: podman_packages is not defined

@@ -0,0 +1,4 @@ 

+ ---

+ __podman_packages:

+   - podman

+   - crun

@@ -0,0 +1,219 @@ 

+ # Ansible Role: Setup

+ 

+ Installs and configures a Receptor node on RHEL/CentOS/Fedora servers.

+ 

+ 

+ ## Role Variables

+ 

+ Available variables are listed below, along with default values.

+ 

+ ---

+ 

+     receptor_packages:

+       - receptor

+ 

+ Set the names of the packages needed to install Receptor.

+ 

+ ---

+ 

+     receptor_dependencies: []

+ 

+ Specify other packages needed, probably on a per-node-type basis using

+ groupvars or hostvars.

+ 

+ ---

+ 

+     receptor_user: 'receptor'

+     receptor_group: 'receptor'

+ 

+ The user and group under which Receptor will run.

+ 

+ ---

+ 

+     receptor_socket_dir: '/var/run/receptor'

+ 

+ The directory that Receptor will place its control socket into.

+ 

+ ---

+ 

+     receptor_control_filename: 'receptor.sock'

+ 

+ The name of the control socket file.

+ 

+ ---

+ 

+     receptor_config_path: '/etc/receptor'

+ 

+ Path to the Receptor config file.

+ 

+ ---

+ 

+     routable_hostname: # defaults to not set

+ 

+ Hostvar for the routable address to this node.  If this is unset

+ `ansible_host` will be used instead.  Must be unique.

+ 

+ ---

+ 

+     receptor_peers: # defaults to not set

+ 

+ Hostvar for the Ansible hosts that this node is peering outwards to.

+ This is expected to be a list of dicts.

+ 

+ In the dicts, the `'host'` key is required, `'port'` and `'protocol'`

+ are optional and will default to the overall defaults for

+ `receptor_port` and `receptor_protocol`.

+ 

+ ---

+ 

+     receptor_tls: false

+ 

+ Enables the TLS protocol to be used for communication between nodes.

+ If enabled, appropriate certificates will have to be provided or

+ generated.

+ 

+ ---

+ 

+     receptor_mintls13: false

+ 

+ If set to true, this forces the minimum TLS version used to be 1.3.

+ Otherwise, the minimum version will be 1.2.  This variable has no

+ effect unless `receptor_tls` is enabled.

+ 

+ ---

+ 

+     receptor_tls_dir: '/etc/receptor/tls'

+     receptor_tls_ca_dir: '{{ receptor_tls_dir }}/ca'

+ 

+ Directories on the server where the TLS keys and CA keys would be located.

+ 

+ ---

+ 

+     receptor_tls_certfile: "{{ receptor_tls_dir }}/{{ receptor_host_identifier }}.crt"

+     receptor_tls_keyfile: "{{ receptor_tls_dir }}/{{ receptor_host_identifier }}.key"

+ 

+ Path on the server to the public and private TLS key files.

+ 

+ ---

+ 

+     receptor_ca_certfile: "{{ receptor_tls_ca_dir }}/mesh-CA.crt"

+     receptor_ca_keyfile: "{{ receptor_tls_ca_dir }}/mesh-CA.key"

+ 

+ Path on the server where the public and private Certificate Authority

+ key files would be located.

+ 

+ ---

+ 

+     custom_ca_certfile: # defaults to not set

+     custom_ca_keyfile: # defaults to not set

+ 

+ Path on the local filesystem to user-provided Certificate Authority

+ files.

+ 

+ ---

+ 

+     custom_tls_certfile: # defaults to not set

+     custom_tls_keyfile: # defaults to not set

+ 

+ Hostvar that is the path on the local filesystem to user-provided

+ per-node certificate files.  If used, both must be provided in

+ combination with a `custom_ca_certfile` that was used to sign them.

+ 

+ ---

+ 

+     receptor_sign: false

+ 

+ Hostvar designating that this host will sign any work that it sends

+ over the Receptor mesh.

+ 

+ ---

+ 

+     receptor_verify: false

+ 

+ Hostvar designating that this host will verify any work that it

+ receives using a public key.

+ 

+ ---

+ 

+     receptor_worksign_key_dir: "/etc/receptor"

+     receptor_worksign_private_keyfile: "{{ receptor_worksign_key_dir }}/work_private_key.pem"

+     receptor_worksign_public_keyfile: "{{ receptor_worksign_key_dir }}/work_public_key.pem"

+ 

+ Path on the server to the public and private OpenSSL work signing key files.

+ 

+ ---

+ 

+     custom_worksign_private_keyfile: # defaults to not set

+     custom_worksign_public_keyfile: # defaults to not set

+ 

+ Path on the local filesystem to user-provided OpenSSL work signing key

+ files.

+ 

+ ---

+ 

+     receptor_fd_limit_soft: 4096

+     receptor_fd_limit_hard: 8192

+ 

+ The file descriptor limits in PAM for Receptor.

+ 

+ ---

+ 

+     receptor_app_service: # defaults to not set

+ 

+ Optional variable to tie Receptor together with some other service in systemd.

+ 

+ ---

+ 

+     receptor_log_level: 'info'

+ 

+ The level at which Receptor should write logs.  Allowable options are 'error', 'warning', 'info', and 'debug'.

+ 

+ ---

+ 

+     receptor_listener: true

+ 

+ Hostvar to enable Receptor to listen for incoming remote connections.

+ 

+ ---

+ 

+     receptor_local_only: false

+ 

+ Hostvar to make this instance of Receptor listen for local-only

+ connections.  If set to true, this will take precedence over the value

+ of `receptor_listener`.

+ 

+ ---

+ 

+     receptor_protocol: 'tcp'

+     receptor_port: 27199

+ 

+ Override with hostvars for the protocol this instance of Receptor will

+ use (allowable options are 'tcp', 'udp', and 'ws' for websockets), and

+ the port number it will listen for those connections on.

+ 

+ ---

+ 

+     receptor_work_commands: # defaults to not set

+ 

+ The definition of the Receptor work commands.  This variable is

+ expected to be a dictionary, with keys the unique worktype name, and

+ values a dict of the rest of the key-value pairs of the work

+ definition.  See

+ <https://receptor.readthedocs.io/en/latest/workceptor.html> for more

+ information.

+ 

+ ---

+ 

+     receptor_kubernetes_commands: # defaults to not set

+ 

+ The definition of the Receptor work-kubernetes commands.  This

+ variable is expected to be a dictionary, with keys the unique worktype

+ name, and values a dict of the rest of the key-value pairs of the work

+ definition.  See <https://receptor.readthedocs.io/en/latest/k8s.html>

+ for more information.

+ 

+ ---

+ 

+ # License

+ 

+ Apache 2

@@ -0,0 +1,38 @@ 

+ ---

+ receptor_user: receptor

+ receptor_group: receptor

+ 

+ receptor_config_path: '/etc/receptor'

+ receptor_socket_dir: '/var/run/receptor'

+ receptor_control_filename: 'receptor.sock'

+ 

+ receptor_tls: false

+ receptor_mintls13: false

+ 

+ receptor_tls_dir: '/etc/receptor/tls'

+ receptor_tls_ca_dir: '{{ receptor_tls_dir }}/ca'

+ receptor_tls_certfile: "{{ receptor_tls_dir }}/{{ receptor_host_identifier }}.crt"

+ receptor_tls_keyfile: "{{ receptor_tls_dir }}/{{ receptor_host_identifier }}.key"

+ receptor_ca_certfile: "{{ receptor_tls_ca_dir }}/mesh-CA.crt"

+ receptor_ca_keyfile: "{{ receptor_tls_ca_dir }}/mesh-CA.key"

+ 

+ receptor_worksign_key_dir: "/etc/receptor"

+ receptor_worksign_private_keyfile: "{{ receptor_worksign_key_dir }}/work_private_key.pem"

+ receptor_worksign_public_keyfile: "{{ receptor_worksign_key_dir }}/work_public_key.pem"

+ 

+ receptor_fd_limit_soft: 4096

+ receptor_fd_limit_hard: 8192

+ 

+ receptor_listener: true

+ receptor_local_only: false

+ 

+ receptor_protocol: 'tcp'

+ receptor_port: 27199

+ receptor_sign: false

+ receptor_verify: false

+ 

+ receptor_log_level: 'info'

+ 

+ _hostname: "{{ routable_hostname | default(ansible_host) }}"

+ receptor_host_identifier:

+   "{{ (_hostname == 'localhost') | ternary('localhost.localdomain', _hostname) }}"

@@ -0,0 +1,41 @@ 

+ ---

+ - name: Ensure soft/hard file descriptors limits

+   ansible.builtin.template:

+     src: templates/pam_limits.conf.j2

+     dest: /etc/security/limits.d/receptor.conf

+     mode: '0600'

+     owner: root

+     group: root

+ 

+ - name: Ensure systemd override directory exists

+   ansible.builtin.file:

+     dest: /etc/systemd/system/receptor.service.d

+     state: directory

+     owner: root

+     group: root

+     mode: '0755'

+ 

+ - name: Override receptor's systemd service runuser

+   ansible.builtin.template:

+     src: templates/systemd_receptor_override.conf.j2

+     dest: /etc/systemd/system/receptor.service.d/override.conf

+     mode: '0644'

+     owner: root

+     group: root

+ #  notify: Restart Receptor

+ 

+ - name: Configure the receptor socket directory

+   ansible.builtin.file:

+     path: "{{ receptor_socket_dir }}"

+     state: directory

+     owner: "{{ receptor_user }}"

+     group: "{{ receptor_group }}"

+     mode: '0750'

+ 

+ - name: Create tmpfiles.d entry for receptor socket directory

+   ansible.builtin.template:

+     src: templates/receptor_tmpd.conf.j2

+     dest: /etc/tmpfiles.d/receptor.conf

+     mode: '0640'

+     owner: root

+     group: root

@@ -0,0 +1,32 @@ 

+ ---

+ # Variable configuration.

+ - include_tasks: variables.yml

+ 

+ # Setup/install tasks.

+ - include_tasks: setup-RedHat.yml

+   when: ansible_os_family == 'RedHat'

+ 

+ - include_tasks: configure.yml

+ 

+ - include_tasks: tls.yml

+   when: receptor_tls

+ 

+ - include_tasks: worksign.yml

+   when: receptor_sign or receptor_verify

+ 

+ - name: Deploy receptor config

+   ansible.builtin.template:

+     src: templates/receptor.conf.j2

+     dest: "{{ receptor_config_path }}/receptor.conf"

+     mode: '0644'

+     owner: "{{ receptor_user }}"

+     group: "{{ receptor_group }}"

+ #   notify:

+ #   - "Receptor Reload"

+ 

+ - name: Start Receptor service

+   ansible.builtin.systemd:

+     name: receptor

+     state: started

+     daemon_reload: true

+     enabled: true

@@ -0,0 +1,10 @@ 

+ ---

+ - name: Install receptor packages

+   ansible.builtin.dnf:

+     name: "{{ receptor_packages }}"

+     state: present

+ 

+ - name: Install dependencies specific to the node type

+   ansible.builtin.dnf:

+     name: "{{ receptor_dependencies | default([]) }}"

+     state: present

@@ -0,0 +1,27 @@ 

+ ---

+ - name: Create Receptor cert directories

+   ansible.builtin.file:

+     dest: "{{ item }}"

+     state: directory

+     mode: '0750'

+     owner: "{{ receptor_user }}"

+     group: "{{ receptor_group }}"

+     recurse: true

+   with_items:

+     - "{{ receptor_tls_dir }}"

+     - "{{ receptor_tls_ca_dir }}"

+ 

+ - name: Process provided TLS files

+   include_tasks: tls_local.yml

+   when: custom_tls_certfile is defined or custom_tls_keyfile is defined

+ 

+ - name: Set TLS file permissions

+   ansible.builtin.file:

+     dest: "{{ item }}"

+     owner: "{{ receptor_user }}"

+     group: "{{ receptor_group }}"

+     mode: '0640'

+   with_items:

+     - "{{ receptor_tls_certfile }}"

+     - "{{ receptor_tls_keyfile }}"

+     - "{{ receptor_ca_certfile }}"

@@ -0,0 +1,61 @@ 

+ ---

+ - name: Ensure both TLS files are provided

+   ansible.builtin.assert:

+     quiet: true

+     that:

+       - custom_tls_certfile | default('') | length

+       - custom_tls_keyfile | default('') | length

+     fail_msg: >

+       "You must provide both 'custom_tls_certfile' and 'custom_tls_keyfile'."

+ 

+ - name: Ensure CA certfile is provided

+   ansible.builtin.assert:

+     quiet: true

+     that:

+       - custom_ca_certfile | default('') | length

+     fail_msg: >

+       "You must provide the public CA file when providing custom TLS certificates."

+ 

+ - name: Check TLS private key modulus

+   delegate_to: localhost

+   become: false

+   ansible.builtin.command: openssl rsa -modulus -noout -in "{{ custom_tls_keyfile }}"

+   register: _tls_keyfile_modulus

+   changed_when: false

+ 

+ - name: Check TLS x509 key modulus

+   delegate_to: localhost

+   become: false

+   ansible.builtin.command: openssl x509 -modulus -noout -in "{{ custom_tls_certfile }}"

+   register: _tls_certfile_modulus

+   changed_when: false

+ 

+ - name: Ensure TLS pair matches

+   ansible.builtin.assert:

+     quiet: true

+     that:

+       - _tls_keyfile_modulus.stdout == _tls_certfile_modulus.stdout

+     fail_msg: >

+       "TLS !modulus! for {{ custom_tls_keyfile }} and {{ custom_tls_certfile }} doesn't match."

+     success_msg: "TLS !modulus! for {{ custom_tls_keyfile }} and {{ custom_tls_certfile }} matches."

+ 

+ - name: Ensure x509 certificate was signed by the expected Certificate Authority

+   delegate_to: localhost

+   become: false

+   ansible.builtin.command:

+     openssl verify -CAfile "{{ custom_ca_certfile }}" "{{ custom_tls_certfile }}"

+   changed_when: false

+ 

+ - name: Upload TLS files

+   become: true

+   become_user: "{{ receptor_user }}"

+   ansible.builtin.copy:

+     src: "{{ item.src }}"

+     dest: "{{ item.dest }}"

+     owner: "{{ receptor_user }}"

+     group: "{{ receptor_group }}"

+     mode: '0640'

+   with_items:

+     - {src: '{{ custom_tls_certfile }}', dest: '{{ receptor_tls_certfile }}'}

+     - {src: '{{ custom_tls_keyfile }}', dest: '{{ receptor_tls_keyfile }}'}

+     - {src: '{{ custom_ca_certfile }}', dest: '{{ receptor_ca_certfile }}'}

@@ -0,0 +1,10 @@ 

+ ---

+ - name: Include OS-specific variables (RedHat)

+   ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"

+   when:

+     - ansible_os_family == 'RedHat'

+ 

+ - name: Define receptor_packages

+   ansible.builtin.set_fact:

+     receptor_packages: "{{ __receptor_packages | list }}"

+   when: receptor_packages is not defined

@@ -0,0 +1,3 @@ 

+ ---

+ - include_tasks: worksign_local.yml

+   when: custom_worksign_private_keyfile is defined or custom_worksign_public_keyfile is defined

@@ -0,0 +1,18 @@ 

+ ---

+ - name: Distribute private work signing key

+   ansible.builtin.copy:

+     src: "{{ custom_worksign_private_keyfile }}"

+     dest: "{{ receptor_worksign_private_keyfile }}"

+     owner: "{{ receptor_user }}"

+     group: "{{ receptor_group }}"

+     mode: '0640'

+   when: receptor_sign

+ 

+ - name: Distribute public work signing key

+   ansible.builtin.copy:

+     src: "{{ custom_worksign_public_keyfile }}"

+     dest: "{{ receptor_worksign_public_keyfile }}"

+     owner: "{{ receptor_user }}"

+     group: "{{ receptor_group }}"

+     mode: '0640'

+   when: receptor_verify

@@ -0,0 +1,3 @@ 

+ # Receptor limits

+ {{ receptor_user }} soft nofile {{ receptor_fd_limit_soft }}

+ {{ receptor_user }} hard nofile {{ receptor_fd_limit_hard }}

@@ -0,0 +1,83 @@ 

+ ---

+ - node:

+     id: {{ receptor_host_identifier }}

+ 

+ {% if receptor_sign %}

+ - work-signing:

+     privatekey: {{ receptor_worksign_private_keyfile }}

+     tokenexpiration: 1m

+ {% endif %}

+ 

+ {% if receptor_verify %}

+ - work-verification:

+     publickey: {{ receptor_worksign_public_keyfile }}

+ {% endif %}

+ 

+ - log-level: {{ receptor_log_level }}

+ 

+ - control-service:

+     service: control

+     filename: {{ receptor_socket_dir }}/{{ receptor_control_filename }}

+     permissions: 0660

+     {% if receptor_tls -%}

+     tls: tls_server

+     {%- endif %}

+ 

+ {% if receptor_tls -%}

+ - tls-server:

+     name: tls_server

+     cert: {{ receptor_tls_certfile }}

+     key: {{ receptor_tls_keyfile }}

+     clientcas: {{ receptor_ca_certfile }}

+     requireclientcert: true

+     mintls13: {{ receptor_mintls13 | bool }}

+ 

+ - tls-client:

+     name: tls_client

+     cert: {{ receptor_tls_certfile }}

+     key: {{ receptor_tls_keyfile }}

+     rootcas: {{ receptor_ca_certfile }}

+     insecureskipverify: false

+     mintls13: {{ receptor_mintls13 | bool }}

+ {%- endif %}

+ 

+ {% if receptor_local_only %}

+ - local-only

+ {% elif receptor_listener %}

+ - {{ receptor_protocol }}-listener:

+     port: {{ receptor_port }}

+     {% if receptor_tls -%}

+     tls: tls_server

+     {%- endif %}

+ {% endif %}

+ 

+ {% if receptor_peers | default([]) %}

+ {% for peer in receptor_peers %}

+ - {{ peer['protocol'] }}-peer:

+     address: {{ peer['address'] | default(peer['host']) }}:{{ peer['port'] }}

+     redial: true

+ {% if receptor_tls -%}

+     tls: tls_client

+ {%- endif %}

+ {% endfor %}

+ {% endif %}

+ 

+ {% if receptor_work_commands is defined -%}

+ {% for command, config in receptor_work_commands.items() %}

+ - work-command:

+     worktype: {{ command }}

+ {% for key, value in config.items() %}

+     {{ key }}: {{ value }}

+ {% endfor %}

+ {% endfor %}

+ {%- endif %}

+ 

+ {%- if receptor_kubernetes_commands is defined %}

+ {% for command, config in receptor_kubernetes_commands.items() %}

+ - work-kubernetes:

+     worktype: {{ command }}

+ {% for key, value in config.items() %}

+     {{ key }}: {{ value }}

+ {% endfor %}

+ {% endfor %}

+ {% endif -%}

@@ -0,0 +1,1 @@ 

+ D {{ receptor_socket_dir }} 0750 {{ receptor_user }} {{ receptor_group }} -

@@ -0,0 +1,7 @@ 

+ [Service]

+ User={{ receptor_user }}

+ Group={{ receptor_group }}

+ {% if receptor_app_service is defined %}

+ [Unit]

+ PartOf={{ receptor_app_service }}

+ {% endif %}

@@ -0,0 +1,3 @@ 

+ ---

+ __receptor_packages:

+   - receptor

@@ -122,6 +122,16 @@ 

    - ipsilon

    - config

  

+ - name: load the AWX SAML2 metadata that will be included in the configuration.conf file

+   uri:

+     url: https://awx.fedoraproject.org/sso/metadata/saml/

+     return_content: yes

+   register: awx_metadata

+   when: env == "production"

+   tags:

+   - ipsilon

+   - config

+ 

  - name: copy ipsilon admin configuration

    template:

      src: "configuration.conf"

@@ -46,8 +46,8 @@ 

  awx id = https://awx.fedoraproject.org/

  awx type = SP

  awx name = AWX

- awx Allowed Attributes = ["groups", "email"]

- awx metadata = <?xml version="1.0" ?><md:EntityDescriptor cacheDuration="P10D" entityID="https://awx.fedoraproject.org/" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"><md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIFADCCAugCCQCtO4Mdj/UfEjANBgkqhkiG9w0BAQsFADBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMB4XDTE4MDQxMjE2MDQzOFoXDTE5MDQxMjE2MDQzOFowQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM0xqadxtdgfZhQe5nbQvKwIutxEAqnFht+U/87N0x8LClTn4xqTSjt78Uw3Mmm9LI1Xp/X/Q5vQWBpCntM16ACLEArACwh+qP3JRq2n89FPpIuuOQp7ZCve/gMHtMTjSmfp+P/NNkNRwSnT1V8ruOn1GKc8uv9uOaHHlFN+d8I0TBGMzzmNcZmn/ZKEHfhlAon+3ogZ4d0ExYapSbTuE0TNoTn0nM21hHgZreDFvXHHgXZKQy2ROiFp4AnWNeZ03zvswwWuJ6Y0L1psVmwYoZ1pLtoEA9881ZYx7RyS49Lje7Ixqej8DJPQ88ntUguz/pUeGAc0210MIcfqPr3TqvCteCjFNCo/GHO+vu3HbNBDH3iPKr+Sj9H96jWQXgEcOFPLZZuZ3UzsfXBC6dEdarUw96jsg7p0Y67mLWHGWhKmdjKLe1hRUfT4ZYVPsuqKxU+KYU5XdrfPCryeh7zd/dMGaZSaxAdSzIr0PdyEjcOPBo5Kn2QDYl2VEBRk6Qxjx2aRk6ET/PIvvz/VYm2S5fTYazvN8L3r3mpnK4G5zF8j1W4Y34qGrANhZDryZV1dFVwWQr31AemxEoLHYkBw5OqusKSBjcDb4+ek5SdfJuRbd8DyjEN+klDeF9+XhouedLC29Z3jRNvgzE6XarfjVZUaHSmw4qsM8YFRV7Wz2R0tAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAD9bqMfBUfNfS9gP+isOXAgs0Sb8Klaq+YAkzY06PQP1ia7EAXBiDX85je8+NdU3v3wQhACzOsS9aPBQT0eK+1urbeNd5vr7zsOUKcCFknFV9wP+LNNhMGbcysEf7WUVjPkEpor36aldTrUsnkGb6bVxlrWEnJtWqekOlpwDPC3Hrv9F+4/auhKzLs98lqAOhIT5c+72oT6viffaiWhvvsJhJj6weZuBR+Rat4F+60TtONX8jAtZaWzlIfSacMDp5QNj688GJRm2wJ6IQjaf1maJEBjMSWqCyBsuskEvEF2YWrdRpaY1+gZ2X7OjQ+iuvuLzxFYlnznIrsSHEPMHjSuL+JYIJM2dEGf6NKi5EQy9mzz3Fi3bJJD9mHqjWY3AFWM3u1ig+u94AZJCsmXGDOuqDOyUqbin6leDgDQdbwjpgBZWygmu2BxV1nWrtgz90qD9MyD10wuKIA6Sp3Z69kYXGgNe13bQ4r8r1vvdqgj2BJRxIujOPyBFCxhsFG8hIaMrqrhNqYnFzrx58LfNgj7OEeI+YhZfCx1iuDlU1AkvSxQhO0HioFg+ahWxLydHwGuI9U489UccVmIYDZd7UYSHq11OBCtCiOwwVUhAMwVTdJJGK0qChDYDOXFXYw/nzTTwhIo7aO70EVHzF2jRdv47ukBui52LsDnlFyTa8uJH</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>      <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://awx.fedoraproject.org/sso/complete/saml/" index="1"/>    </md:SPSSODescriptor>    <md:Organization>        <md:OrganizationName xml:lang="en-US">fedora</md:OrganizationName>        <md:OrganizationDisplayName xml:lang="en-US">Fedora Authentication</md:OrganizationDisplayName>        <md:OrganizationURL xml:lang="en-US">https://id.fedoraproject.org</md:OrganizationURL>    </md:Organization>    <md:ContactPerson contactType="technical">        <md:GivenName>Fedora Infrastructure</md:GivenName>        <md:EmailAddress>infrastructure@lists.fedoraproject.org</md:EmailAddress>    </md:ContactPerson>    <md:ContactPerson contactType="support">        <md:GivenName>Fedora Infrastructure</md:GivenName>        <md:EmailAddress>infrastructure@lists.fedoraproject.org</md:EmailAddress>    </md:ContactPerson></md:EntityDescriptor>

+ awx Allowed Attributes = ["email", "_groups", "givenname", "surname"]

+ awx metadata = {{ awx_metadata.content | replace("\n", " ") }}

  

  

  rhbzdev id = https://bugzilla.dev.redhat.com/saml2_metadata.cgi

Related: https://pagure.io/fedora-infrastructure/issue/11377

This is a work in progress.

This is the initial setup of AWX. This creates:

  • awx.fedoraproject.org website on proxies
  • AWX SAML2 Service Provider on Ipsilon
  • Then on AWX:

    • Configure SAML2 authentication
    • Set up the Execution Environment
    • Create the Fedora Organization
    • Set up the fedora-infra/ansible repository & hosts inventory (We will most likely not be able to run any playbooks, but we can still use the inventory)
    • Set up batcave01 as an Execution Node

I've also added an awx/execution_node role (not used yet) to configure an execution node (in our case, batcave01).
It's based on the playbook generated by AWX and slightly tailored for our infra. Here is what it does:

  • Create the awx user used to run the service
  • Enable ansible-awx/receptor Copr repository (to install ansible-receptor)
  • Install & configure Podman
  • Install & configure Ansible Receptor service
  • Install ansible-runner via pip3

I haven't included it in the batcave playbook as it requires certificates that will be created once AWX is configured.
These certificates can be downloaded from the AWX UI, and should be installed in {{ private }}/files/awx/{{ inventory_hostname }}/.
I'll create another PR for that part later.

Requirements:

  • This role requires the awx.awx collection.
  • an SSL certificate/key must be created for the SAML2 authentication and stored in /srv/private/files/awx/production/awx-saml.{crt,key}. Using a non-expiring self-signed certificate is recommended to avoid periodically updating certificates.
  • The AWX operator must be deployed, and the AWX instance created on Openshift.
  • The AWX admin/password must be defined in /srv/private/ansible/vars.yml: awx_admin_username & awx_admin_password. The generated admin password can be found in the awx-admin-password secret in Openshift.

Extra notes:

  • The currently defined SAML configuration will map Fedora awx-admin users as superadmin.
  • Users are not assigned to any organization on login, and have no rights.
  • The fedora-websites AWX team will be created and mapped to the matching Fedora group. (This is just an example of how to map Fedora groups, there is no fedora-websites group in Fedora).

rebased onto 71c5bef26945e3ed06b1e57eef827a7d52ecc94f

11 months ago

rebased onto 54619922cad7fc6b9768d410e1c1f53ad3af27e9

10 months ago

rebased onto 723ce3efb281ae373d2750759ecde437e5a0a456

10 months ago

Sorry for the delay getting back here.

Feel free to merge this and move it forward.

Note that batcave01 is now rhel9... if that changes any package requirements, etc.

I'd prefer not to use a copr for any packages, ideally we should get them into epel9, but if thats not possible, we should (re)build them into epel9-infra in koji. That way they are signed by our keys etc.

rebased onto d86babd

10 months ago

I changed the admin group to sysadmin-main for the POC as we don't have an awx-admin group yet, and I'll put the execution node deployment (batcave01) on hold until I figure out how to rebuild the required package in koji.

I'm going to merge this and I will update the ticket with my progress.

Pull-Request has been merged by darknao

10 months ago
Metadata
Changes Summary 34
+12 -0
file changed
playbooks/include/proxies-reverseproxy.yml
+6 -1
file changed
playbooks/include/proxies-websites.yml
+20
file added
playbooks/openshift-apps/awx.yml
+3
file added
roles/awx/controller/meta/main.yml
+6
file added
roles/awx/controller/tasks/execution_environment.yml
+11
file added
roles/awx/controller/tasks/execution_nodes.yml
+6
file added
roles/awx/controller/tasks/main.yml
+5
file added
roles/awx/controller/tasks/org.yml
+31
file added
roles/awx/controller/tasks/projects.yml
+50
file added
roles/awx/controller/tasks/saml2.yml
+57
file added
roles/awx/execution_node/tasks/main.yml
+32
file added
roles/awx/podman/README.md
+8
file added
roles/awx/podman/defaults/main.yml
+48
file added
roles/awx/podman/tasks/main.yml
+5
file added
roles/awx/podman/tasks/setup-RedHat.yml
+10
file added
roles/awx/podman/tasks/variables.yml
+4
file added
roles/awx/podman/vars/RedHat.yml
+219
file added
roles/awx/receptor/README.md
+38
file added
roles/awx/receptor/defaults/main.yml
+41
file added
roles/awx/receptor/tasks/configure.yml
+32
file added
roles/awx/receptor/tasks/main.yml
+10
file added
roles/awx/receptor/tasks/setup-RedHat.yml
+27
file added
roles/awx/receptor/tasks/tls.yml
+61
file added
roles/awx/receptor/tasks/tls_local.yml
+10
file added
roles/awx/receptor/tasks/variables.yml
+3
file added
roles/awx/receptor/tasks/worksign.yml
+18
file added
roles/awx/receptor/tasks/worksign_local.yml
+3
file added
roles/awx/receptor/templates/pam_limits.conf.j2
+83
file added
roles/awx/receptor/templates/receptor.conf.j2
+1
file added
roles/awx/receptor/templates/receptor_tmpd.conf.j2
+7
file added
roles/awx/receptor/templates/systemd_receptor_override.conf.j2
+3
file added
roles/awx/receptor/vars/RedHat.yml
+10 -0
file changed
roles/ipsilon/tasks/main.yml
+2 -2
file changed
roles/ipsilon/templates/saml2_data