Skip to content
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
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ jobs:
- name: Setup hammer
run: |
./foremanctl setup-hammer
- name: Set up Foreman Proxy
run: |
./foremanctl setup-foreman-proxy
- name: Run tests
run: |
./forge test --pytest-args="--certificate-source=${{ matrix.certificate_source }}"
Expand Down Expand Up @@ -193,6 +196,9 @@ jobs:
- name: Setup hammer
run: |
./foremanctl setup-hammer
- name: Set up Foreman Proxy
run: |
./foremanctl setup-foreman-proxy
- name: Run tests
run: |
./forge test
Expand Down
6 changes: 6 additions & 0 deletions src/playbooks/setup-foreman-proxy/metadata.obsah.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
help: |
Set up Foreman Proxy

include:
- _certificate_source
17 changes: 17 additions & 0 deletions src/playbooks/setup-foreman-proxy/setup-foreman-proxy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
- name: Set up Foreman Proxy
hosts:
- quadlet
become: true
vars_files:
- "../../vars/defaults.yml"
- "../../vars/{{ certificate_source }}_certificates.yml"
- "../../vars/foreman.yml"
- "../../vars/images.yml"
vars:
foreman_url: "https://{{ ansible_facts['fqdn'] }}"

roles:
- pre_install
- checks
- foreman_proxy
8 changes: 8 additions & 0 deletions src/roles/foreman_proxy/defaults/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
foreman_proxy_name: "{{ ansible_facts['fqdn'] }}"
foreman_proxy_https_port: 8443
foreman_proxy_url: "https://{{ foreman_proxy_name }}:{{ foreman_proxy_https_port }}"

# Settings
foreman_proxy_trusted_hosts:
- "{{ foreman_proxy_name }}"
5 changes: 5 additions & 0 deletions src/roles/foreman_proxy/handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
- name: Restart Foreman Proxy
ansible.builtin.systemd:
name: foreman-proxy
state: restarted
48 changes: 48 additions & 0 deletions src/roles/foreman_proxy/tasks/certs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
- name: Create the podman secret for Foreman Proxy CA certificate
containers.podman.podman_secret:
name: foreman-proxy-ssl-ca
path: "{{ server_ca_certificate }}"
state: present
notify:
- Restart Foreman Proxy

- name: Create the podman secret for foreman-proxy Proxy server certificate (for HTTPS)
containers.podman.podman_secret:
state: present
name: foreman-proxy-ssl-cert
path: "{{ server_certificate }}"
notify:
- Restart Foreman Proxy

- name: Create the podman secret for Foreman Proxy server key (for HTTPS)
containers.podman.podman_secret:
state: present
name: foreman-proxy-ssl-key
path: "{{ server_key }}"
notify:
- Restart Foreman Proxy

- name: Create the podman secret for Foreman Proxy Foreman CA
containers.podman.podman_secret:
state: present
name: foreman-proxy-foreman-ssl-ca
path: "{{ server_ca_certificate }}"
notify:
- Restart Foreman Proxy

- name: Create the podman secret for Foreman Proxy Foreman client certificate
containers.podman.podman_secret:
state: present
name: foreman-proxy-foreman-ssl-cert
path: "{{ client_certificate }}"
notify:
- Restart Foreman Proxy

- name: Create the podman secret for Foreman Proxy Foreman client key
containers.podman.podman_secret:
state: present
name: foreman-proxy-foreman-ssl-key
path: "{{ client_key }}"
notify:
- Restart Foreman Proxy
16 changes: 16 additions & 0 deletions src/roles/foreman_proxy/tasks/configs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
- name: Create settings config secret
containers.podman.podman_secret:
state: present
name: foreman-proxy-settings-yaml
data: "{{ lookup('ansible.builtin.template', 'settings.yaml.j2') }}"
notify:
- Restart Foreman Proxy

- name: Create logs config secret
containers.podman.podman_secret:
state: present
name: foreman-proxy-logs-yaml
data: "{{ lookup('ansible.builtin.template', 'settings.d/logs.yaml.j2') }}"
notify:
- Restart Foreman Proxy
57 changes: 57 additions & 0 deletions src/roles/foreman_proxy/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
- name: Pull the Foreman Proxy container image
containers.podman.podman_image:
name: "{{ foreman_proxy_container_image }}:{{ foreman_proxy_container_tag }}"
state: present

- name: Create config secrets
ansible.builtin.include_tasks: configs.yaml

- name: Create certs secrets
ansible.builtin.include_tasks: certs.yaml

- name: Deploy Foreman Container
containers.podman.podman_container:
name: "foreman-proxy"
image: "{{ foreman_proxy_container_image }}:{{ foreman_proxy_container_tag }}"
state: quadlet
sdnotify: true
network: host
hostname: "{{ ansible_facts['fqdn'] }}"
secrets:
- 'foreman-proxy-settings-yaml,type=mount,target=/etc/foreman-proxy/settings.yml'
- 'foreman-proxy-logs-yaml,type=mount,target=/etc/foreman-proxy/settings.d/logs.yml'
Copy link
Member

Choose a reason for hiding this comment

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

Not a blocking comment, but this is more a forward thinking discussion, but we know it's coming soon so it's best to start thinking about it.

Thinking more about this, how are we going to make it extensible? We know there will be many modules. Just to name a few off the top of my head:

  • REX
  • DHCP (with a provider, so at least 2 config files)
  • DNS (also with a provider)
  • TFTP
  • Realm

Design wise we may want to split those out into into separate Ansible task files. How are we going to add the secrets? Will we use systemd drop in files to keep the container file here reasonably simple?

Copy link
Member

@evgeni evgeni Nov 11, 2025

Choose a reason for hiding this comment

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

I think /etc/containers/systemd/foreman-proxy.container.d/<feature>.conf makes a lot of sense for this.

- 'foreman-proxy-ssl-ca,type=mount,target=/etc/foreman-proxy/ssl_ca.pem'
- 'foreman-proxy-ssl-cert,type=mount,target=/etc/foreman-proxy/ssl_cert.pem'
- 'foreman-proxy-ssl-key,type=mount,target=/etc/foreman-proxy/ssl_key.pem'
- 'foreman-proxy-foreman-ssl-ca,type=mount,target=/etc/foreman-proxy/foreman_ssl_ca.pem'
- 'foreman-proxy-foreman-ssl-cert,type=mount,target=/etc/foreman-proxy/foreman_ssl_cert.pem'
- 'foreman-proxy-foreman-ssl-key,type=mount,target=/etc/foreman-proxy/foreman_ssl_key.pem'
quadlet_options:
- |
[Install]
WantedBy=default.target foreman.target
[Unit]
PartOf=foreman.target
notify: Restart Foreman Proxy

- name: Run daemon reload to make Quadlet create the service files
ansible.builtin.systemd:
daemon_reload: true

- name: Flush handlers to restart services
ansible.builtin.meta: flush_handlers

- name: Start the Foreman Proxy Service
ansible.builtin.systemd:
name: foreman-proxy
state: started

- name: Register Foreman Proxy to Foreman
theforeman.foreman.smart_proxy:
name: "{{ foreman_proxy_name }}"
url: "{{ foreman_proxy_url }}"
server_url: "{{ foreman_url }}"
username: "{{ foreman_initial_admin_username }}"
password: "{{ foreman_initial_admin_password }}"
Comment on lines +55 to +56
Copy link
Member

Choose a reason for hiding this comment

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

This is unreliable, since the user may change username & password after installation. The oauth credentials should be reliable.

Copy link
Member

Choose a reason for hiding this comment

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

Our Ansible collection can't do OAutho tho.

Copy link
Member

Choose a reason for hiding this comment

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

username: "{{ foreman_initial_admin_username }}"
password: "{{ foreman_initial_admin_password }}"
has the same issue

Copy link
Member

Choose a reason for hiding this comment

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

Oh, that's going to be some reliability issue down the line. We should track that somehow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

validate_certs: false
Copy link
Member

Choose a reason for hiding this comment

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

IMHO we should always validate certificates. We should have them on the system already.

Copy link
Member

Choose a reason for hiding this comment

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

On the system yes, but not in the system trust. you'll have to use ca_path parameter to the module (which we currently also don't do for the pulp proxy)

Copy link
Member

Choose a reason for hiding this comment

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

Follow up issue for foremanctl 3.0?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, please.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Clarification for the 3.0 ticket:
Do we want to support the ca_path parameter for the Ansible module, or do we want to add the CA to the trusted store?

Copy link
Member

Choose a reason for hiding this comment

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

ca_path, we should not alter the trust store.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

2 changes: 2 additions & 0 deletions src/roles/foreman_proxy/templates/settings.d/logs.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
:enabled: https
Copy link
Member

Choose a reason for hiding this comment

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

Do we need this to be done in foremanctl? I see 2 options:

  1. Properly templated in foremanctl where the user can enable/disable the module via a variable
  2. The container image defaults it to this and we don't override it at all

My preference would be to keep it simple and go for option 2.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right now the image does not do it by default, so should I move the logic from here to the image?

I can do it, but if we are going to manage the other features and their templates with foremanctl, IMHO, we can keep it as it is.

Copy link
Member

Choose a reason for hiding this comment

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

I tend to agree. While logging is a tad special (as we're effectively abusing it for the proxy to work at all here), we'll be adding more modules soon, and those will be configurable, so… leave it here as is and (maybe) make it configurable later

20 changes: 20 additions & 0 deletions src/roles/foreman_proxy/templates/settings.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
:settings_directory: /etc/foreman-proxy/settings.d

:foreman_url: {{ foreman_url }}
:trusted_hosts: {{ foreman_proxy_trusted_hosts }}

:https_port: {{ foreman_proxy_https_port }}
:ssl_ca_file: /etc/foreman-proxy/ssl_ca.pem
:ssl_certificate: /etc/foreman-proxy/ssl_cert.pem
:ssl_private_key: /etc/foreman-proxy/ssl_key.pem

:foreman_ssl_ca: /etc/foreman-proxy/foreman_ssl_ca.pem
:foreman_ssl_cert: /etc/foreman-proxy/foreman_ssl_cert.pem
:foreman_ssl_key: /etc/foreman-proxy/foreman_ssl_key.pem

:bind_host: '*'

:log_level: INFO
:log_file: JOURNAL
Copy link
Member

Choose a reason for hiding this comment

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

I didn't expect this to work, but it does. Magic.

Is there any benefit over STDOUT (which will also work in the OpenShift case)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know TBH, not really sure how this smart-proxy -> container -> journal relationship works under the hood, so I'll leave the final decision up to you

Copy link
Member

@evgeni evgeni Nov 11, 2025

Choose a reason for hiding this comment

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

Then I think I'd prefer the plain STDOUT

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we can start with journal now and investigate whether Foreman Proxy can learn to autodetect it?

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

theforeman/smart-proxy#925 is what I was thinking about. Not something we need to sort out right now, but I'm starting to think about ways we can make foreman-proxy itself more container native.

:log_buffer: 2000
:log_buffer_errors: 1000
3 changes: 3 additions & 0 deletions src/vars/images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ candlepin_container_image: quay.io/foreman/candlepin
candlepin_container_tag: "foreman-{{ container_tag_stream }}"
foreman_container_image: quay.io/foreman/foreman
foreman_container_tag: "{{ container_tag_stream }}"
foreman_proxy_container_image: "quay.io/foreman/foreman-proxy"
foreman_proxy_container_tag: "{{ container_tag_stream }}"

postgresql_container_image: quay.io/sclorg/postgresql-13-c9s
postgresql_container_tag: "latest"
pulp_container_image: quay.io/foreman/pulp
Expand Down
15 changes: 15 additions & 0 deletions tests/foreman_proxy_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FOREMAN_PROXY_PORT = 8443

def test_foreman_proxy_features(server, certificates, server_fqdn):
cmd = server.run(f"curl --cacert {certificates['ca_certificate']} --silent https://{server_fqdn}:{FOREMAN_PROXY_PORT}/features")
assert cmd.succeeded
assert "logs" in cmd.stdout

def test_foreman_proxy_service(server):
foreman_proxy = server.service("foreman-proxy")
assert foreman_proxy.is_running
assert foreman_proxy.is_enabled

def test_foreman_proxy_port(server):
foreman_proxy = server.addr('localhost')
assert foreman_proxy.port(FOREMAN_PROXY_PORT).is_reachable