diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e0b758de9..d438f4969 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -104,7 +104,7 @@ jobs:
run: ./setup-environment
- name: Start VMs
run: |
- ./forge vms start --vms "quadlet client ${{ matrix.database == 'external' && 'database' || '' }}"
+ ./forge vms start --vms "quadlet proxy client ${{ matrix.database == 'external' && 'database' || '' }}"
- name: Configure remote-database
if: matrix.database == 'external'
run: |
@@ -116,6 +116,7 @@ jobs:
if: matrix.certificate_source == 'custom_server'
run: |
./forge custom-certs
+ ./forge custom-certs --hostname proxy.example.com
- name: Setup security mode ${{ matrix.security }}
if: matrix.security != 'none'
run: |
@@ -153,6 +154,16 @@ jobs:
--add-feature remote-execution \
--add-feature bmc \
${{ matrix.iop == 'enabled' && '--add-feature iop' || '' }}
+ - name: Build certs bundle for proxy
+ run: |
+ ./foremanctl certificate-bundle proxy.example.com \
+ ${{ matrix.certificate_source == 'custom_server' && '--certificate-server-certificate /root/custom-certificates/certs/proxy.example.com.crt --certificate-server-key /root/custom-certificates/private/proxy.example.com.key' || '' }}
+ - name: Deploy proxy
+ run: |
+ ./forge fetch-bundle proxy.example.com
+ ./foremanctl deploy-node \
+ --certificate-bundle $(pwd)/.var/lib/foremanctl/proxy.example.com.tar.gz \
+ --foreman-name quadlet.example.com
- name: Run tests
run: |
./forge test --pytest-args="--database-mode=${{ matrix.database }}"
diff --git a/Vagrantfile b/Vagrantfile
index da3af4e88..32a8f683f 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -30,6 +30,20 @@ Vagrant.configure("2") do |config|
end
end
+ config.vm.define "proxy" do |override|
+ override.vm.box = ENV.fetch("FOREMANCTL_BASE_BOX", "centos/stream9")
+ if override.vm.box == "centos/stream10"
+ override.vm.box_url = "https://cloud.centos.org/centos/10-stream/x86_64/images/CentOS-Stream-Vagrant-10-latest.x86_64.vagrant-libvirt.box"
+ end
+ override.vm.hostname = "proxy.#{DOMAIN}"
+
+ override.vm.provider "libvirt" do |libvirt, provider|
+ libvirt.memory = 10240
+ libvirt.cpus = 4
+ libvirt.machine_virtual_size = 30
+ end
+ end
+
config.vm.define "client" do |override|
override.vm.box = "centos/stream9"
override.vm.hostname = "client.#{DOMAIN}"
diff --git a/development/playbooks/deploy-dev/deploy-dev.yaml b/development/playbooks/deploy-dev/deploy-dev.yaml
index d716d3abe..0892960ed 100644
--- a/development/playbooks/deploy-dev/deploy-dev.yaml
+++ b/development/playbooks/deploy-dev/deploy-dev.yaml
@@ -45,12 +45,12 @@
- role: redis
- role: candlepin
- role: httpd
- - role: pulp
- role: foreman_development
vars:
foreman_development_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}"
foreman_development_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}"
foreman_development_candlepin_oauth_secret: "{{ candlepin_oauth_secret }}"
+ - role: pulp
- role: iop_core
when:
- "'iop' in enabled_features"
diff --git a/development/playbooks/fetch-bundle/fetch-bundle.yaml b/development/playbooks/fetch-bundle/fetch-bundle.yaml
new file mode 100644
index 000000000..144c4f08d
--- /dev/null
+++ b/development/playbooks/fetch-bundle/fetch-bundle.yaml
@@ -0,0 +1,14 @@
+---
+- name: Fetch generated bundle from server
+ hosts:
+ - quadlet
+ become: true
+ vars_files:
+ - "../../../src/vars/base.yaml"
+ - "../../../src/vars/certificates.yml"
+ tasks:
+ - name: Fetch bundle
+ ansible.builtin.fetch:
+ src: "{{ certificates_ca_directory }}/bundles/{{ hostname }}.tar.gz"
+ dest: "{{ obsah_state_path }}/{{ hostname }}.tar.gz"
+ flat: true
diff --git a/development/playbooks/fetch-bundle/metadata.obsah.yaml b/development/playbooks/fetch-bundle/metadata.obsah.yaml
new file mode 100644
index 000000000..f2d2d635c
--- /dev/null
+++ b/development/playbooks/fetch-bundle/metadata.obsah.yaml
@@ -0,0 +1,8 @@
+---
+help: |
+ Fetch a certificate bundle
+
+variables:
+ hostname:
+ parameter: hostname
+ help: Hostname to fetch the certificate bundle for.
diff --git a/src/playbooks/deploy-node/deploy-node.yaml b/src/playbooks/deploy-node/deploy-node.yaml
new file mode 100644
index 000000000..532e2d574
--- /dev/null
+++ b/src/playbooks/deploy-node/deploy-node.yaml
@@ -0,0 +1,33 @@
+---
+- name: Setup proxy demo machine
+ hosts:
+ - proxy
+ become: true
+ vars_files:
+ - "../../vars/defaults.yml"
+ - "../../vars/flavors/{{ flavor }}.yml"
+ - "../../vars/certificates.yml"
+ - "../../vars/images.yml"
+ - "../../vars/tuning/{{ tuning }}.yml"
+ - "../../vars/database.yml"
+ - "../../vars/foreman.yml"
+ - "../../vars/base.yaml"
+ roles:
+ - role: pre_install
+ - role: checks
+ vars:
+ checks_databases: "{{ all_databases }}"
+ - role: certificates
+ - role: certificate_checks
+ vars:
+ certificate_checks_certificate: "{{ server_certificate }}"
+ certificate_checks_key: "{{ server_key }}"
+ certificate_checks_ca: "{{ server_ca_certificate }}"
+ - role: postgresql
+ when:
+ - database_mode == 'internal'
+ - redis
+ - httpd
+ - pulp
+ - role: systemd_target
+ - role: foreman_proxy
diff --git a/src/playbooks/deploy-node/metadata.obsah.yaml b/src/playbooks/deploy-node/metadata.obsah.yaml
new file mode 100644
index 000000000..c39158d7c
--- /dev/null
+++ b/src/playbooks/deploy-node/metadata.obsah.yaml
@@ -0,0 +1,20 @@
+---
+help: |
+ Install infra node
+
+variables:
+ certificates_bundle:
+ help: Path to the certificates bundle
+ type: AbsolutePath
+ parameter: --certificate-bundle
+ persist: false
+ foreman_name:
+ help: Hostname of the main Foreman instance
+ type: FQDN
+
+include:
+ - _database_mode
+ - _database_connection
+ - _tuning
+ - _flavor_features
+ - _pulp
diff --git a/src/playbooks/deploy/deploy.yaml b/src/playbooks/deploy/deploy.yaml
index 29940f6ad..0352c17f8 100644
--- a/src/playbooks/deploy/deploy.yaml
+++ b/src/playbooks/deploy/deploy.yaml
@@ -30,8 +30,8 @@
- redis
- candlepin
- httpd
- - pulp
- foreman
+ - pulp
- role: systemd_target
- role: iop_core
when:
diff --git a/src/roles/certificates/tasks/main.yml b/src/roles/certificates/tasks/main.yml
index a3a5e22ff..3d15a9e88 100644
--- a/src/roles/certificates/tasks/main.yml
+++ b/src/roles/certificates/tasks/main.yml
@@ -29,23 +29,37 @@
state: directory
mode: '0755'
-- name: 'Generate CA certificate'
- ansible.builtin.include_tasks: ca.yml
- when: certificates_ca
-
-- name: Issue host certificates
- ansible.builtin.include_tasks: host.yml
- when: certificates_hostnames is defined
- with_items: "{{ certificates_hostnames }}"
- loop_control:
- loop_var: certificates_hostname
-
-- name: Create CA bundle with internal CA and custom server CA
- ansible.builtin.assemble:
- src: "{{ certificates_ca_directory_certs }}"
- dest: "{{ certificates_ca_directory_certs }}/ca-bundle.crt"
- regexp: '(ca|server-ca)\.crt$'
- mode: '0444'
- when:
- - certificates_source == 'custom_server'
- - certificates_custom_server_certificate is defined
+- name: 'Main certs'
+ when: certificates_bundle is not defined
+ block:
+ - name: 'Generate CA certificate'
+ ansible.builtin.include_tasks: ca.yml
+ when: certificates_ca
+
+ - name: Issue host certificates
+ ansible.builtin.include_tasks: host.yml
+ when: certificates_hostnames is defined
+ with_items: "{{ certificates_hostnames }}"
+ loop_control:
+ loop_var: certificates_hostname
+
+ - name: Create CA bundle with internal CA and custom server CA
+ ansible.builtin.assemble:
+ src: "{{ certificates_ca_directory_certs }}"
+ dest: "{{ certificates_ca_directory_certs }}/ca-bundle.crt"
+ regexp: '(ca|server-ca)\.crt$'
+ mode: '0444'
+ when:
+ - certificates_source == 'custom_server'
+ - certificates_custom_server_certificate is defined
+
+- name: 'Bundle certs'
+ when: certificates_bundle is defined
+ block:
+ - name: 'Unarchive the bundle'
+ ansible.builtin.unarchive:
+ src: "{{ certificates_bundle }}"
+ dest: "{{ certificates_ca_directory }}"
+ extra_opts:
+ - "--strip-components"
+ - "1"
diff --git a/src/roles/foreman/tasks/main.yaml b/src/roles/foreman/tasks/main.yaml
index 34f974bb4..481b0aee7 100644
--- a/src/roles/foreman/tasks/main.yaml
+++ b/src/roles/foreman/tasks/main.yaml
@@ -312,12 +312,3 @@
register: foreman_tasks_status
when:
- "'katello' in foreman_status.json['results']"
-
-- name: Configure Foreman Proxy
- theforeman.foreman.smart_proxy:
- name: "{{ ansible_facts['fqdn'] }}-pulp"
- url: "https://{{ ansible_facts['fqdn'] }}/pulp/api/v3/smart_proxy"
- server_url: "{{ foreman_url }}"
- oauth1_consumer_key: "{{ foreman_oauth_consumer_key }}"
- oauth1_consumer_secret: "{{ foreman_oauth_consumer_secret }}"
- ca_path: "{{ foreman_ca_certificate }}"
diff --git a/src/roles/foreman_proxy/defaults/main.yaml b/src/roles/foreman_proxy/defaults/main.yaml
index 4791507b1..fdf7f9fb2 100644
--- a/src/roles/foreman_proxy/defaults/main.yaml
+++ b/src/roles/foreman_proxy/defaults/main.yaml
@@ -7,8 +7,7 @@ foreman_proxy_https_port: 8443
foreman_proxy_url: "https://{{ foreman_proxy_name }}:{{ foreman_proxy_https_port }}"
# Settings
-foreman_proxy_trusted_hosts:
- - "{{ foreman_proxy_name }}"
+foreman_proxy_trusted_hosts: "{{ undef(hint='You need to provide the list of trusted hosts') }}"
foreman_proxy_base_features:
- logs
diff --git a/src/roles/httpd/defaults/main.yml b/src/roles/httpd/defaults/main.yml
index 7f4f7b35a..29258ad4e 100644
--- a/src/roles/httpd/defaults/main.yml
+++ b/src/roles/httpd/defaults/main.yml
@@ -20,3 +20,6 @@ httpd_ipa_manage_sssd: true
httpd_ipa_keytab: /etc/httpd/conf/http.keytab
httpd_ipa_pam_service: "{{ external_authentication_pam_service | default('foreman') }}"
httpd_ipa_gssapi_local_name: true
+
+# Pulp configuration
+httpd_pulp_trusted_hosts: "{{ undef(hint='You need to provide the list of trusted hosts') }}"
diff --git a/src/roles/httpd/templates/foreman-ssl-vhost.conf.j2 b/src/roles/httpd/templates/foreman-ssl-vhost.conf.j2
index dfec667b5..be95a4d7e 100644
--- a/src/roles/httpd/templates/foreman-ssl-vhost.conf.j2
+++ b/src/roles/httpd/templates/foreman-ssl-vhost.conf.j2
@@ -53,7 +53,9 @@
RequestHeader unset REMOTE_USER
RequestHeader unset REMOTE-USER
- RequestHeader set REMOTE-USER "admin" "expr=%{SSL_CLIENT_S_DN_CN} == '{{ ansible_facts['fqdn'] }}'"
+ {% for httpd_pulp_trusted_host in httpd_pulp_trusted_hosts %}
+ RequestHeader set REMOTE-USER "admin" "expr=%{SSL_CLIENT_S_DN_CN} == '{{ httpd_pulp_trusted_host }}'"
+ {% endfor %}
ProxyPass {{ httpd_pulp_api_backend }}/v2/
ProxyPassReverse {{ httpd_pulp_api_backend }}/v2/
@@ -75,7 +77,9 @@
RequestHeader unset REMOTE_USER
RequestHeader unset REMOTE-USER
- RequestHeader set REMOTE-USER "admin" "expr=%{SSL_CLIENT_S_DN_CN} == '{{ ansible_facts['fqdn'] }}'"
+ {% for httpd_pulp_trusted_host in httpd_pulp_trusted_hosts %}
+ RequestHeader set REMOTE-USER "admin" "expr=%{SSL_CLIENT_S_DN_CN} == '{{ httpd_pulp_trusted_host }}'"
+ {% endfor %}
ProxyPass {{ httpd_pulp_api_backend }}/pulp/api/v3 timeout=600
ProxyPassReverse {{ httpd_pulp_api_backend }}/pulp/api/v3
diff --git a/src/roles/pulp/tasks/main.yaml b/src/roles/pulp/tasks/main.yaml
index a9a9a7d03..bdb6e96a5 100644
--- a/src/roles/pulp/tasks/main.yaml
+++ b/src/roles/pulp/tasks/main.yaml
@@ -311,3 +311,12 @@
when:
- pulp_existing_workers | length > 0
- (item | regex_replace('^' + pulp_worker_container_name + '@(\\d+)\\.service$', '\\1') | int) > (pulp_worker_count | int)
+
+- name: Configure Foreman Proxy
+ theforeman.foreman.smart_proxy:
+ name: "{{ ansible_facts['fqdn'] }}-pulp"
+ url: "https://{{ ansible_facts['fqdn'] }}/pulp/api/v3/smart_proxy"
+ server_url: "{{ pulp_foreman_url }}"
+ oauth1_consumer_key: "{{ pulp_foreman_oauth_consumer_key }}"
+ oauth1_consumer_secret: "{{ pulp_foreman_oauth_consumer_secret }}"
+ ca_path: "{{ pulp_foreman_ca_certificate }}"
diff --git a/src/vars/base.yaml b/src/vars/base.yaml
index d39164531..5fb1f9da0 100644
--- a/src/vars/base.yaml
+++ b/src/vars/base.yaml
@@ -30,11 +30,17 @@ httpd_client_ca_certificate: "{{ client_ca_certificate }}"
httpd_server_certificate: "{{ server_certificate }}"
httpd_server_key: "{{ server_key }}"
httpd_enabled_pulp_snippets: "{{ ['pypi'] if 'pulp_python' in pulp_plugins else [] }}"
+httpd_pulp_trusted_hosts:
+ - "{{ foreman_name }}"
pulp_storage_path: /var/lib/pulp
pulp_content_origin: "https://{{ ansible_facts['fqdn'] }}"
pulp_pulp_url: "https://{{ ansible_facts['fqdn'] }}"
pulp_plugins: "{{ enabled_features | select('contains', 'content/') | map('replace', 'content/', 'pulp_') | list }}"
+pulp_foreman_url: "{{ foreman_url }}"
+pulp_foreman_ca_certificate: "{{ foreman_ca_certificate }}"
+pulp_foreman_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}"
+pulp_foreman_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}"
hammer_ca_certificate: "{{ server_ca_certificate }}"
hammer_plugins: "{{ enabled_features | features_to_hammer_plugins }}"
@@ -45,6 +51,8 @@ foreman_proxy_foreman_server_url: "{{ foreman_url }}"
foreman_proxy_foreman_ca_certificate: "{{ foreman_ca_certificate }}"
foreman_proxy_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}"
foreman_proxy_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}"
+foreman_proxy_trusted_hosts:
+ - "{{ foreman_name }}"
iop_core_foreman_url: "{{ foreman_url }}"
iop_core_foreman_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}"