From 55358e9b5d758920c9b2033c89a059e54839e001 Mon Sep 17 00:00:00 2001 From: Arvind Jangir Date: Thu, 23 Jul 2026 14:08:34 +0530 Subject: [PATCH 1/5] transfer oauth creds as part of certificate bundle --- docs/developer/deployment.md | 3 +++ docs/user/certificates.md | 2 ++ .../certificate-bundle.yaml | 3 +++ .../deploy-proxy/metadata.obsah.yaml | 6 ------ .../certificate_bundle/defaults/main.yml | 2 ++ src/roles/certificate_bundle/tasks/main.yml | 14 +++++++++++++ src/roles/foreman_proxy/tasks/main.yaml | 10 +++++++++ .../foreman_proxy/tasks/oauth_from_bundle.yml | 21 +++++++++++++++++++ tests/certificate_bundle_test.py | 10 +++++++++ .../foreman-proxy-content/oauth_test.py | 18 ++++++++++++++++ 10 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 src/roles/foreman_proxy/tasks/oauth_from_bundle.yml create mode 100644 tests/flavor/foreman-proxy-content/oauth_test.py diff --git a/docs/developer/deployment.md b/docs/developer/deployment.md index cc8f67bc2..29e245d30 100644 --- a/docs/developer/deployment.md +++ b/docs/developer/deployment.md @@ -27,6 +27,9 @@ Before running the proxy deployment, a certificate bundle must be generated on t This produces a tar archive at a path like `/var/lib/foremanctl/certs/bundles/.tar.gz`. +> [!NOTE] +> The bundle includes the proxy's certificates and OAuth credentials needed for the proxy to communicate with the Foreman server. + 2. Copy the bundle to the **proxy VM**: ```bash diff --git a/docs/user/certificates.md b/docs/user/certificates.md index 0a3fa8914..495c7eda5 100644 --- a/docs/user/certificates.md +++ b/docs/user/certificates.md @@ -176,6 +176,8 @@ certs/ private/ ├── .key # Server private key └── -client.key # Client private key +foreman-oauth-consumer-key # OAuth consumer key for Foreman API auth +foreman-oauth-consumer-secret # OAuth consumer secret for Foreman API auth ``` When using the internal CA only, `server-ca.crt` and `ca.crt` are identical. When custom server certificates are provided, `server-ca.crt` contains the custom CA and `ca.crt` contains the internal CA. diff --git a/src/playbooks/certificate-bundle/certificate-bundle.yaml b/src/playbooks/certificate-bundle/certificate-bundle.yaml index 7971da4ec..b4112c514 100644 --- a/src/playbooks/certificate-bundle/certificate-bundle.yaml +++ b/src/playbooks/certificate-bundle/certificate-bundle.yaml @@ -6,6 +6,7 @@ vars_files: - "../../vars/base.yaml" - "../../vars/certificates.yml" + - "../../vars/foreman.yml" roles: - role: certificate_checks when: certificates_source == 'custom_server' @@ -29,3 +30,5 @@ certificate_bundle_server_key: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/private/{{ hostname }}.key" certificate_bundle_client_certificate: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/certs/{{ hostname }}-client.crt" certificate_bundle_client_key: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/private/{{ hostname }}-client.key" + certificate_bundle_oauth_consumer_key_file: "{{ foreman_oauth_consumer_key_file }}" + certificate_bundle_oauth_consumer_secret_file: "{{ foreman_oauth_consumer_secret_file }}" diff --git a/src/playbooks/deploy-proxy/metadata.obsah.yaml b/src/playbooks/deploy-proxy/metadata.obsah.yaml index c2772050b..836a2f5f9 100644 --- a/src/playbooks/deploy-proxy/metadata.obsah.yaml +++ b/src/playbooks/deploy-proxy/metadata.obsah.yaml @@ -15,12 +15,6 @@ variables: foreman_name: parameter: --foreman-fqdn help: FQDN of the Foreman server this proxy connects to. - foreman_proxy_oauth_consumer_key: - parameter: --oauth-consumer-key - help: OAuth key to be used for communication with Foreman. - foreman_proxy_oauth_consumer_secret: - parameter: --oauth-consumer-secret - help: OAuth secret to be used for communication with Foreman. include: - _flavor_features diff --git a/src/roles/certificate_bundle/defaults/main.yml b/src/roles/certificate_bundle/defaults/main.yml index 736f7ee44..280762f92 100644 --- a/src/roles/certificate_bundle/defaults/main.yml +++ b/src/roles/certificate_bundle/defaults/main.yml @@ -1,3 +1,5 @@ --- certificate_bundle_output_directory: "{{ certificates_ca_directory }}/bundles" certificate_bundle_server_ca_certificate: "{{ certificate_bundle_ca_certificate }}" +certificate_bundle_oauth_consumer_key_file: # noqa: no-empty-defaults +certificate_bundle_oauth_consumer_secret_file: # noqa: no-empty-defaults diff --git a/src/roles/certificate_bundle/tasks/main.yml b/src/roles/certificate_bundle/tasks/main.yml index 288f82f2f..e85c8e5db 100644 --- a/src/roles/certificate_bundle/tasks/main.yml +++ b/src/roles/certificate_bundle/tasks/main.yml @@ -77,6 +77,20 @@ remote_src: true mode: '0440' + - name: Copy OAuth consumer key + ansible.builtin.copy: + src: "{{ certificate_bundle_oauth_consumer_key_file }}" + dest: "{{ certificate_bundle_build_directory.path }}/certs/foreman-oauth-consumer-key" + mode: '0440' + when: certificate_bundle_oauth_consumer_key_file is exists + + - name: Copy OAuth consumer secret + ansible.builtin.copy: + src: "{{ certificate_bundle_oauth_consumer_secret_file }}" + dest: "{{ certificate_bundle_build_directory.path }}/certs/foreman-oauth-consumer-secret" + mode: '0440' + when: certificate_bundle_oauth_consumer_secret_file is exists + - name: Create tarball community.general.archive: path: "{{ certificate_bundle_build_directory.path }}/certs/*" diff --git a/src/roles/foreman_proxy/tasks/main.yaml b/src/roles/foreman_proxy/tasks/main.yaml index 8033c9457..505b1f91b 100644 --- a/src/roles/foreman_proxy/tasks/main.yaml +++ b/src/roles/foreman_proxy/tasks/main.yaml @@ -2,6 +2,16 @@ - name: Deploy foreman-proxy image ansible.builtin.include_tasks: image.yaml +- name: Load OAuth credentials from certificate bundle + ansible.builtin.include_tasks: oauth_from_bundle.yml + loop: + - key + - secret + loop_control: + loop_var: oauth_credential + when: + - flavor == 'foreman-proxy-content' + - name: Create config secrets ansible.builtin.include_tasks: configs.yaml diff --git a/src/roles/foreman_proxy/tasks/oauth_from_bundle.yml b/src/roles/foreman_proxy/tasks/oauth_from_bundle.yml new file mode 100644 index 000000000..e681c97e1 --- /dev/null +++ b/src/roles/foreman_proxy/tasks/oauth_from_bundle.yml @@ -0,0 +1,21 @@ +--- +- name: Load OAuth credentials from certificate bundle + vars: + oauth_path: "{{ certificates_ca_directory }}/foreman-oauth-consumer-{{ oauth_credential }}" + block: + - name: Check for OAuth consumer file in certificate bundle - {{ oauth_credential }} + ansible.builtin.stat: + path: "{{ oauth_path }}" + register: foreman_proxy_oauth_file + + - name: Read OAuth consumer from certificate bundle - {{ oauth_credential }} + when: foreman_proxy_oauth_file.stat.exists + block: + - name: Slurp OAuth consumer - {{ oauth_credential }} + ansible.builtin.slurp: + src: "{{ oauth_path }}" + register: foreman_proxy_oauth_content + + - name: Set OAuth consumer from certificate bundle - {{ oauth_credential }} + ansible.builtin.set_fact: + "foreman_proxy_oauth_consumer_{{ oauth_credential }}": "{{ foreman_proxy_oauth_content.content | b64decode | trim }}" diff --git a/tests/certificate_bundle_test.py b/tests/certificate_bundle_test.py index 5a2d3cfd7..444fd03fe 100644 --- a/tests/certificate_bundle_test.py +++ b/tests/certificate_bundle_test.py @@ -24,6 +24,11 @@ f'private/{HOSTNAME}-client.key', ] +EXPECTED_OAUTH_FILES = [ + 'foreman-oauth-consumer-key', + 'foreman-oauth-consumer-secret', +] + @pytest.fixture(scope="module") def generate_custom_proxy_certs(server, certificate_source): @@ -77,6 +82,11 @@ def test_tarball_contains_client_certificate(tarball_members, expected_file): assert expected_file in tarball_members +@pytest.mark.parametrize("expected_file", EXPECTED_OAUTH_FILES) +def test_tarball_contains_oauth_credentials(tarball_members, expected_file): + assert expected_file in tarball_members + + def test_proxy_certs_stored_in_hosts_subdirectory(server, generate_bundle): """Verify proxy certificates are stored in a per-host subdirectory.""" proxy_cert = server.file(f'/var/lib/foremanctl/certs/hosts/{HOSTNAME}/certs/{HOSTNAME}.crt') diff --git a/tests/flavor/foreman-proxy-content/oauth_test.py b/tests/flavor/foreman-proxy-content/oauth_test.py new file mode 100644 index 000000000..ced65e75b --- /dev/null +++ b/tests/flavor/foreman-proxy-content/oauth_test.py @@ -0,0 +1,18 @@ +import pytest + +OAUTH_FILES = [ + 'foreman-oauth-consumer-key', + 'foreman-oauth-consumer-secret', +] + +CERTS_DIR = '/var/lib/foremanctl/certs' + + +@pytest.mark.parametrize("oauth_file", OAUTH_FILES) +def test_oauth_credentials_extracted_from_bundle(server, oauth_file): + """Proxy deploy must extract OAuth credentials from the certificate bundle.""" + oauth_path = f'{CERTS_DIR}/{oauth_file}' + oauth = server.file(oauth_path) + assert oauth.exists, f'{oauth_path} was not extracted from the certificate bundle' + assert oauth.size > 0 + assert oauth.mode == 0o440, f'{oauth_path} should have mode 0440, got {oct(oauth.mode)}' From 97d2aa1bf12c743d23b52ff738617cb637e5ae4e Mon Sep 17 00:00:00 2001 From: Arvind Jangir Date: Thu, 23 Jul 2026 18:57:15 +0530 Subject: [PATCH 2/5] add new role for oauth creds --- .github/workflows/test.yml | 2 -- docs/user/certificates.md | 5 ++-- src/playbooks/deploy-proxy/deploy-proxy.yaml | 1 + src/roles/certificate_bundle/tasks/main.yml | 5 ++-- src/roles/foreman_proxy/tasks/main.yaml | 10 ------- .../foreman_proxy/tasks/oauth_from_bundle.yml | 21 --------------- src/roles/oauth_from_bundle/defaults/main.yml | 2 ++ .../oauth_from_bundle/tasks/credential.yml | 27 +++++++++++++++++++ src/roles/oauth_from_bundle/tasks/main.yml | 8 ++++++ tests/certificate_bundle_test.py | 4 +-- .../foreman-proxy-content/oauth_test.py | 4 +-- 11 files changed, 48 insertions(+), 41 deletions(-) delete mode 100644 src/roles/foreman_proxy/tasks/oauth_from_bundle.yml create mode 100644 src/roles/oauth_from_bundle/defaults/main.yml create mode 100644 src/roles/oauth_from_bundle/tasks/credential.yml create mode 100644 src/roles/oauth_from_bundle/tasks/main.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 29bbd0ab3..b5104dc00 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -442,8 +442,6 @@ jobs: --flavor foreman-proxy-content \ --certificate-bundle $(pwd)/.var/lib/foremanctl/proxy.example.com.tar.gz \ --foreman-fqdn quadlet.example.com \ - --oauth-consumer-key $(cat .var/lib/foremanctl/foreman-oauth-consumer-key) \ - --oauth-consumer-secret $(cat .var/lib/foremanctl/foreman-oauth-consumer-secret) \ --templates-listen-on http \ --templates-url http://proxy.example.com:8000 - name: Run tests diff --git a/docs/user/certificates.md b/docs/user/certificates.md index 495c7eda5..f03c7a68a 100644 --- a/docs/user/certificates.md +++ b/docs/user/certificates.md @@ -176,8 +176,9 @@ certs/ private/ ├── .key # Server private key └── -client.key # Client private key -foreman-oauth-consumer-key # OAuth consumer key for Foreman API auth -foreman-oauth-consumer-secret # OAuth consumer secret for Foreman API auth +oauth/ +├── foreman-oauth-consumer-key # OAuth consumer key for Foreman API auth +└── foreman-oauth-consumer-secret # OAuth consumer secret for Foreman API auth ``` When using the internal CA only, `server-ca.crt` and `ca.crt` are identical. When custom server certificates are provided, `server-ca.crt` contains the custom CA and `ca.crt` contains the internal CA. diff --git a/src/playbooks/deploy-proxy/deploy-proxy.yaml b/src/playbooks/deploy-proxy/deploy-proxy.yaml index 1462e7c6a..5ba00c2a1 100644 --- a/src/playbooks/deploy-proxy/deploy-proxy.yaml +++ b/src/playbooks/deploy-proxy/deploy-proxy.yaml @@ -25,6 +25,7 @@ certificate_checks_certificate: "{{ server_certificate }}" certificate_checks_key: "{{ server_key }}" certificate_checks_ca: "{{ server_ca_certificate }}" + - role: oauth_from_bundle - role: postgresql when: - database_mode == 'internal' diff --git a/src/roles/certificate_bundle/tasks/main.yml b/src/roles/certificate_bundle/tasks/main.yml index e85c8e5db..3d141d8cc 100644 --- a/src/roles/certificate_bundle/tasks/main.yml +++ b/src/roles/certificate_bundle/tasks/main.yml @@ -27,6 +27,7 @@ loop: - certs - private + - oauth - name: Copy default CA certificate ansible.builtin.copy: @@ -80,14 +81,14 @@ - name: Copy OAuth consumer key ansible.builtin.copy: src: "{{ certificate_bundle_oauth_consumer_key_file }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/foreman-oauth-consumer-key" + dest: "{{ certificate_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-key" mode: '0440' when: certificate_bundle_oauth_consumer_key_file is exists - name: Copy OAuth consumer secret ansible.builtin.copy: src: "{{ certificate_bundle_oauth_consumer_secret_file }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/foreman-oauth-consumer-secret" + dest: "{{ certificate_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-secret" mode: '0440' when: certificate_bundle_oauth_consumer_secret_file is exists diff --git a/src/roles/foreman_proxy/tasks/main.yaml b/src/roles/foreman_proxy/tasks/main.yaml index 505b1f91b..8033c9457 100644 --- a/src/roles/foreman_proxy/tasks/main.yaml +++ b/src/roles/foreman_proxy/tasks/main.yaml @@ -2,16 +2,6 @@ - name: Deploy foreman-proxy image ansible.builtin.include_tasks: image.yaml -- name: Load OAuth credentials from certificate bundle - ansible.builtin.include_tasks: oauth_from_bundle.yml - loop: - - key - - secret - loop_control: - loop_var: oauth_credential - when: - - flavor == 'foreman-proxy-content' - - name: Create config secrets ansible.builtin.include_tasks: configs.yaml diff --git a/src/roles/foreman_proxy/tasks/oauth_from_bundle.yml b/src/roles/foreman_proxy/tasks/oauth_from_bundle.yml deleted file mode 100644 index e681c97e1..000000000 --- a/src/roles/foreman_proxy/tasks/oauth_from_bundle.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -- name: Load OAuth credentials from certificate bundle - vars: - oauth_path: "{{ certificates_ca_directory }}/foreman-oauth-consumer-{{ oauth_credential }}" - block: - - name: Check for OAuth consumer file in certificate bundle - {{ oauth_credential }} - ansible.builtin.stat: - path: "{{ oauth_path }}" - register: foreman_proxy_oauth_file - - - name: Read OAuth consumer from certificate bundle - {{ oauth_credential }} - when: foreman_proxy_oauth_file.stat.exists - block: - - name: Slurp OAuth consumer - {{ oauth_credential }} - ansible.builtin.slurp: - src: "{{ oauth_path }}" - register: foreman_proxy_oauth_content - - - name: Set OAuth consumer from certificate bundle - {{ oauth_credential }} - ansible.builtin.set_fact: - "foreman_proxy_oauth_consumer_{{ oauth_credential }}": "{{ foreman_proxy_oauth_content.content | b64decode | trim }}" diff --git a/src/roles/oauth_from_bundle/defaults/main.yml b/src/roles/oauth_from_bundle/defaults/main.yml new file mode 100644 index 000000000..65ec41625 --- /dev/null +++ b/src/roles/oauth_from_bundle/defaults/main.yml @@ -0,0 +1,2 @@ +--- +oauth_from_bundle_directory: "{{ certificates_ca_directory }}/oauth" diff --git a/src/roles/oauth_from_bundle/tasks/credential.yml b/src/roles/oauth_from_bundle/tasks/credential.yml new file mode 100644 index 000000000..6c1fde6b0 --- /dev/null +++ b/src/roles/oauth_from_bundle/tasks/credential.yml @@ -0,0 +1,27 @@ +--- +- name: Load OAuth credential from certificate bundle - {{ oauth_from_bundle_credential }} + vars: + oauth_from_bundle_path: "{{ oauth_from_bundle_directory }}/foreman-oauth-consumer-{{ oauth_from_bundle_credential }}" + block: + - name: Check for OAuth consumer file in certificate bundle - {{ oauth_from_bundle_credential }} + ansible.builtin.stat: + path: "{{ oauth_from_bundle_path }}" + register: oauth_from_bundle_file + + - name: Fail when OAuth consumer is missing from certificate bundle - {{ oauth_from_bundle_credential }} + ansible.builtin.fail: + msg: >- + OAuth consumer {{ oauth_from_bundle_credential }} not found in certificate bundle + at {{ oauth_from_bundle_path }}. + Regenerate the bundle with foremanctl certificate-bundle. + when: not oauth_from_bundle_file.stat.exists + + - name: Slurp OAuth consumer - {{ oauth_from_bundle_credential }} + ansible.builtin.slurp: + src: "{{ oauth_from_bundle_path }}" + register: oauth_from_bundle_content + + - name: Set OAuth consumer from certificate bundle - {{ oauth_from_bundle_credential }} + ansible.builtin.set_fact: + "foreman_proxy_oauth_consumer_{{ oauth_from_bundle_credential }}": "{{ oauth_from_bundle_content.content | b64decode | trim }}" + "pulp_foreman_oauth_consumer_{{ oauth_from_bundle_credential }}": "{{ oauth_from_bundle_content.content | b64decode | trim }}" diff --git a/src/roles/oauth_from_bundle/tasks/main.yml b/src/roles/oauth_from_bundle/tasks/main.yml new file mode 100644 index 000000000..77736b56a --- /dev/null +++ b/src/roles/oauth_from_bundle/tasks/main.yml @@ -0,0 +1,8 @@ +--- +- name: Load OAuth credentials from certificate bundle + ansible.builtin.include_tasks: credential.yml + loop: + - key + - secret + loop_control: + loop_var: oauth_from_bundle_credential diff --git a/tests/certificate_bundle_test.py b/tests/certificate_bundle_test.py index 444fd03fe..73f101050 100644 --- a/tests/certificate_bundle_test.py +++ b/tests/certificate_bundle_test.py @@ -25,8 +25,8 @@ ] EXPECTED_OAUTH_FILES = [ - 'foreman-oauth-consumer-key', - 'foreman-oauth-consumer-secret', + 'oauth/foreman-oauth-consumer-key', + 'oauth/foreman-oauth-consumer-secret', ] diff --git a/tests/flavor/foreman-proxy-content/oauth_test.py b/tests/flavor/foreman-proxy-content/oauth_test.py index ced65e75b..41a5cc5cf 100644 --- a/tests/flavor/foreman-proxy-content/oauth_test.py +++ b/tests/flavor/foreman-proxy-content/oauth_test.py @@ -5,13 +5,13 @@ 'foreman-oauth-consumer-secret', ] -CERTS_DIR = '/var/lib/foremanctl/certs' +OAUTH_DIR = '/var/lib/foremanctl/certs/oauth' @pytest.mark.parametrize("oauth_file", OAUTH_FILES) def test_oauth_credentials_extracted_from_bundle(server, oauth_file): """Proxy deploy must extract OAuth credentials from the certificate bundle.""" - oauth_path = f'{CERTS_DIR}/{oauth_file}' + oauth_path = f'{OAUTH_DIR}/{oauth_file}' oauth = server.file(oauth_path) assert oauth.exists, f'{oauth_path} was not extracted from the certificate bundle' assert oauth.size > 0 From f10a9731eb25249856fffe03edb3c287c3550ad3 Mon Sep 17 00:00:00 2001 From: Arvind Jangir Date: Fri, 24 Jul 2026 14:05:24 +0530 Subject: [PATCH 3/5] store and extract oauth credentials to /var/lib/foremanctl/oauth --- src/roles/certificate_bundle/defaults/main.yml | 2 -- src/roles/certificate_bundle/tasks/main.yml | 2 -- src/roles/certificates/defaults/main.yml | 1 + src/roles/certificates/tasks/extract.yml | 15 ++++++++++++++- src/roles/certificates/tasks/main.yml | 6 ++++++ src/roles/oauth_from_bundle/defaults/main.yml | 2 +- src/vars/base.yaml | 3 +++ src/vars/foreman.yml | 4 ++-- tests/flavor/foreman-proxy-content/oauth_test.py | 2 +- 9 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/roles/certificate_bundle/defaults/main.yml b/src/roles/certificate_bundle/defaults/main.yml index 280762f92..736f7ee44 100644 --- a/src/roles/certificate_bundle/defaults/main.yml +++ b/src/roles/certificate_bundle/defaults/main.yml @@ -1,5 +1,3 @@ --- certificate_bundle_output_directory: "{{ certificates_ca_directory }}/bundles" certificate_bundle_server_ca_certificate: "{{ certificate_bundle_ca_certificate }}" -certificate_bundle_oauth_consumer_key_file: # noqa: no-empty-defaults -certificate_bundle_oauth_consumer_secret_file: # noqa: no-empty-defaults diff --git a/src/roles/certificate_bundle/tasks/main.yml b/src/roles/certificate_bundle/tasks/main.yml index 3d141d8cc..7db4900b4 100644 --- a/src/roles/certificate_bundle/tasks/main.yml +++ b/src/roles/certificate_bundle/tasks/main.yml @@ -83,14 +83,12 @@ src: "{{ certificate_bundle_oauth_consumer_key_file }}" dest: "{{ certificate_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-key" mode: '0440' - when: certificate_bundle_oauth_consumer_key_file is exists - name: Copy OAuth consumer secret ansible.builtin.copy: src: "{{ certificate_bundle_oauth_consumer_secret_file }}" dest: "{{ certificate_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-secret" mode: '0440' - when: certificate_bundle_oauth_consumer_secret_file is exists - name: Create tarball community.general.archive: diff --git a/src/roles/certificates/defaults/main.yml b/src/roles/certificates/defaults/main.yml index fc88df1f1..d194c2bcc 100644 --- a/src/roles/certificates/defaults/main.yml +++ b/src/roles/certificates/defaults/main.yml @@ -2,6 +2,7 @@ certificates_source: default certificates_ca: true certificates_ca_directory: /var/lib/foremanctl/certs +certificates_oauth_directory: /var/lib/foremanctl/oauth certificates_ca_directory_certs: "{{ certificates_ca_directory }}/certs" certificates_ca_directory_keys: "{{ certificates_ca_directory }}/private" certificates_ca_directory_requests: "{{ certificates_ca_directory }}/requests" diff --git a/src/roles/certificates/tasks/extract.yml b/src/roles/certificates/tasks/extract.yml index 65efdaa5a..75296bbf1 100644 --- a/src/roles/certificates/tasks/extract.yml +++ b/src/roles/certificates/tasks/extract.yml @@ -11,7 +11,20 @@ msg: "Path to certificate tar file not found: {{ certificates_bundle }}" when: not _certificates_tar_file_path.stat.exists -- name: Extract certificate bundle +- name: Extract certificates from bundle ansible.builtin.unarchive: src: "{{ certificates_bundle }}" dest: "{{ certificates_ca_directory }}" + exclude: + - oauth + - oauth/* + +- name: Extract OAuth credentials from bundle + ansible.builtin.unarchive: + src: "{{ certificates_bundle }}" + dest: "{{ certificates_oauth_directory | dirname }}" + exclude: + - certs + - certs/* + - private + - private/* diff --git a/src/roles/certificates/tasks/main.yml b/src/roles/certificates/tasks/main.yml index ac793d261..dce213d7a 100644 --- a/src/roles/certificates/tasks/main.yml +++ b/src/roles/certificates/tasks/main.yml @@ -11,6 +11,12 @@ state: directory mode: '0755' +- name: 'Create OAuth directory' + ansible.builtin.file: + path: "{{ certificates_oauth_directory }}" + state: directory + mode: '0755' + - name: 'Create certs directory' ansible.builtin.file: path: "{{ certificates_output_directory_certs }}" diff --git a/src/roles/oauth_from_bundle/defaults/main.yml b/src/roles/oauth_from_bundle/defaults/main.yml index 65ec41625..03f52be2f 100644 --- a/src/roles/oauth_from_bundle/defaults/main.yml +++ b/src/roles/oauth_from_bundle/defaults/main.yml @@ -1,2 +1,2 @@ --- -oauth_from_bundle_directory: "{{ certificates_ca_directory }}/oauth" +oauth_from_bundle_directory: "{{ certificates_oauth_directory }}" diff --git a/src/vars/base.yaml b/src/vars/base.yaml index 27211fd0c..2f99435ca 100644 --- a/src/vars/base.yaml +++ b/src/vars/base.yaml @@ -3,10 +3,13 @@ certificates_hostnames: - "{{ ansible_facts['fqdn'] }}" - localhost +oauth_directory: "{{ obsah_state_path }}/oauth" + certificates_ca_password_file: "{{ obsah_state_path }}/certificates-ca-password" certificates_ca_password: "{{ lookup('ansible.builtin.password', certificates_ca_password_file, chars=['ascii_letters', 'digits']) }}" candlepin_oauth_secret_file: "{{ obsah_state_path }}/candlepin-oauth-secret" candlepin_oauth_secret: "{{ lookup('ansible.builtin.password', candlepin_oauth_secret_file, chars=['ascii_letters', 'digits'], length=32) }}" +certificates_oauth_directory: /var/lib/foremanctl/oauth candlepin_ca_key: "{{ ca_key }}" candlepin_ca_certificate: "{{ ca_certificate }}" diff --git a/src/vars/foreman.yml b/src/vars/foreman.yml index e2326929c..ac1429c83 100644 --- a/src/vars/foreman.yml +++ b/src/vars/foreman.yml @@ -5,9 +5,9 @@ foreman_initial_admin_password: "{{ lookup('ansible.builtin.password', foreman_a foreman_initial_organization: "Default Organization" foreman_initial_location: "Default Location" -foreman_oauth_consumer_key_file: "{{ obsah_state_path }}/foreman-oauth-consumer-key" +foreman_oauth_consumer_key_file: "{{ oauth_directory }}/foreman-oauth-consumer-key" foreman_oauth_consumer_key: "{{ lookup('ansible.builtin.password', foreman_oauth_consumer_key_file, chars=['ascii_letters', 'digits'], length=32) }}" -foreman_oauth_consumer_secret_file: "{{ obsah_state_path }}/foreman-oauth-consumer-secret" +foreman_oauth_consumer_secret_file: "{{ oauth_directory }}/foreman-oauth-consumer-secret" foreman_oauth_consumer_secret: "{{ lookup('ansible.builtin.password', foreman_oauth_consumer_secret_file, chars=['ascii_letters', 'digits'], length=32) }}" foreman_encryption_key_file: "{{ obsah_state_path }}/foreman-encryption-key" foreman_encryption_key: "{{ lookup('ansible.builtin.password', foreman_encryption_key_file, chars=['digits', 'abcdef'], length=32) }}" diff --git a/tests/flavor/foreman-proxy-content/oauth_test.py b/tests/flavor/foreman-proxy-content/oauth_test.py index 41a5cc5cf..c491f039e 100644 --- a/tests/flavor/foreman-proxy-content/oauth_test.py +++ b/tests/flavor/foreman-proxy-content/oauth_test.py @@ -5,7 +5,7 @@ 'foreman-oauth-consumer-secret', ] -OAUTH_DIR = '/var/lib/foremanctl/certs/oauth' +OAUTH_DIR = '/var/lib/foremanctl/oauth' @pytest.mark.parametrize("oauth_file", OAUTH_FILES) From 41fc3c8869c85d6d9a62b120d735dada06b3f50d Mon Sep 17 00:00:00 2001 From: Arvind Jangir Date: Mon, 27 Jul 2026 12:43:16 +0530 Subject: [PATCH 4/5] Change certificate-bundle to auth-bundle --- .github/workflows/test.yml | 8 +- .../fetch-bundle/metadata.obsah.yaml | 4 +- docs/developer/deployment.md | 8 +- docs/user/certificates.md | 26 +++-- src/playbooks/auth-bundle/auth-bundle.yaml | 34 ++++++ .../metadata.obsah.yaml | 4 +- .../certificate-bundle.yaml | 34 ------ .../deploy-proxy/metadata.obsah.yaml | 6 +- src/roles/auth_bundle/defaults/main.yml | 3 + src/roles/auth_bundle/tasks/main.yml | 107 ++++++++++++++++++ .../certificate_bundle/defaults/main.yml | 3 - src/roles/certificate_bundle/tasks/main.yml | 107 ------------------ src/roles/certificates/tasks/extract.yml | 12 +- src/roles/certificates/tasks/main.yml | 6 +- .../oauth_from_bundle/tasks/credential.yml | 12 +- src/roles/oauth_from_bundle/tasks/main.yml | 2 +- ...ate_bundle_test.py => auth_bundle_test.py} | 4 +- .../foreman-proxy-content/oauth_test.py | 4 +- 18 files changed, 193 insertions(+), 191 deletions(-) create mode 100644 src/playbooks/auth-bundle/auth-bundle.yaml rename src/playbooks/{certificate-bundle => auth-bundle}/metadata.obsah.yaml (89%) delete mode 100644 src/playbooks/certificate-bundle/certificate-bundle.yaml create mode 100644 src/roles/auth_bundle/defaults/main.yml create mode 100644 src/roles/auth_bundle/tasks/main.yml delete mode 100644 src/roles/certificate_bundle/defaults/main.yml delete mode 100644 src/roles/certificate_bundle/tasks/main.yml rename tests/{certificate_bundle_test.py => auth_bundle_test.py} (96%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b5104dc00..9acfe2396 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -422,15 +422,15 @@ jobs: --initial-admin-password=changeme \ --tuning development \ --add-feature foreman-proxy - - name: Generate certificates bundle on quadlet + - name: Generate auth bundle on quadlet run: | - ./foremanctl certificate-bundle proxy.example.com \ + ./foremanctl auth-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: Refresh internal CA to ensure it doesn't break the bundle if: matrix.certificate_source != 'custom_server' run: | ./foremanctl deploy --certificate-ca-renew - - name: Fetch certificates bundle from quadlet + - name: Fetch auth bundle from quadlet run: | ./forge fetch-bundle proxy.example.com - name: Remove old parameters, but keep certificates_source for tests @@ -440,7 +440,7 @@ jobs: run: | ./foremanctl deploy-proxy \ --flavor foreman-proxy-content \ - --certificate-bundle $(pwd)/.var/lib/foremanctl/proxy.example.com.tar.gz \ + --auth-bundle $(pwd)/.var/lib/foremanctl/proxy.example.com.tar.gz \ --foreman-fqdn quadlet.example.com \ --templates-listen-on http \ --templates-url http://proxy.example.com:8000 diff --git a/development/playbooks/fetch-bundle/metadata.obsah.yaml b/development/playbooks/fetch-bundle/metadata.obsah.yaml index f2d2d635c..1fc9a64b9 100644 --- a/development/playbooks/fetch-bundle/metadata.obsah.yaml +++ b/development/playbooks/fetch-bundle/metadata.obsah.yaml @@ -1,8 +1,8 @@ --- help: | - Fetch a certificate bundle + Fetch an auth bundle variables: hostname: parameter: hostname - help: Hostname to fetch the certificate bundle for. + help: Hostname to fetch the auth bundle for. diff --git a/docs/developer/deployment.md b/docs/developer/deployment.md index 29e245d30..7b9a92d03 100644 --- a/docs/developer/deployment.md +++ b/docs/developer/deployment.md @@ -17,12 +17,12 @@ Deploys a Foreman server. This is the primary deployment type and the default en Deploys a Foreman Proxy node that connects to a Foreman server. -Before running the proxy deployment, a certificate bundle must be generated on the Foreman server and copied to the proxy VM: +Before running the proxy deployment, an auth bundle must be generated on the Foreman server and copied to the proxy VM: -1. On the **Foreman server**, generate a certificate bundle for the proxy hostname: +1. On the **Foreman server**, generate an auth bundle for the proxy hostname: ```bash - ./foremanctl certificate-bundle proxy.example.com + ./foremanctl auth-bundle proxy.example.com ``` This produces a tar archive at a path like `/var/lib/foremanctl/certs/bundles/.tar.gz`. @@ -41,7 +41,7 @@ Before running the proxy deployment, a certificate bundle must be generated on t ```bash ./foremanctl deploy-proxy \ --flavor foreman-proxy-content \ - --certificate-bundle /root/proxy.example.com.tar.gz \ + --auth-bundle /root/proxy.example.com.tar.gz \ --foreman-fqdn quadlet.example.com ``` diff --git a/docs/user/certificates.md b/docs/user/certificates.md index f03c7a68a..4a246b490 100644 --- a/docs/user/certificates.md +++ b/docs/user/certificates.md @@ -84,7 +84,7 @@ After deployment, certificates are available at: - Certificates from `foreman-installer` are normalized into the same paths as the Default Source above - Original directory is backed up to `/root/ssl-build.bak/` -**Proxy/Secondary System Certificates (from certificate-bundle):** +**Proxy/Secondary System Certificates (from auth-bundle):** - Generated in per-host subdirectories: `/var/lib/foremanctl/certs/hosts//` - Packaged tarball: `/var/lib/foremanctl/certs/bundles/.tar.gz` @@ -138,20 +138,20 @@ foremanctl deploy --certificate-ca-renew Both flags are **not persisted** in foremanctl’s answers file (one-shot). -### Certificate Bundle for Secondary Systems +### Auth Bundle for Secondary Systems -The `certificate-bundle` command generates a certificate tarball for a secondary system such as a foreman-proxy host. This is the foremanctl equivalent of `foreman-proxy-certs-generate`. +The `auth-bundle` command generates a certificate and OAuth credential tarball for a secondary system such as a foreman-proxy host. This is the foremanctl equivalent of `foreman-proxy-certs-generate`. The internal CA must already exist from a prior `foremanctl deploy`. #### Usage ```bash -# Generate a certificate bundle using the internal CA -foremanctl certificate-bundle proxy.example.com +# Generate an auth bundle using the internal CA +foremanctl auth-bundle proxy.example.com -# Generate a certificate bundle with custom server certificates for the proxy -foremanctl certificate-bundle \ +# Generate an auth bundle with custom server certificates for the proxy +foremanctl auth-bundle \ --certificate-server-certificate /path/to/proxy.example.com.crt \ --certificate-server-key /path/to/proxy.example.com.key \ proxy.example.com @@ -165,7 +165,7 @@ If the Foreman server was deployed with custom server certificates, each proxy m #### Tarball Contents -The tarball uses the same directory structure as `/var/lib/foremanctl/certs/`: +The tarball mirrors the on-disk layout under `/var/lib/foremanctl/`: ``` certs/ @@ -181,6 +181,8 @@ oauth/ └── foreman-oauth-consumer-secret # OAuth consumer secret for Foreman API auth ``` +On extract, `certs/` and `private/` are installed under `/var/lib/foremanctl/certs/`, and `oauth/` is installed under `/var/lib/foremanctl/oauth/`. + When using the internal CA only, `server-ca.crt` and `ca.crt` are identical. When custom server certificates are provided, `server-ca.crt` contains the custom CA and `ca.crt` contains the internal CA. ### Current Limitations @@ -206,7 +208,7 @@ src/roles/certificates/ │ └── custom.yml # Applies user-provided custom server certs └── defaults/main.yml # Default configuration variables -src/roles/certificate_bundle/ +src/roles/auth_bundle/ ├── tasks/main.yml # Packages certificates into a tarball └── defaults/main.yml # Output directory configuration ``` @@ -233,11 +235,11 @@ For `certificate_source: custom_server`: 2. **Custom Server Certificates**: Copy the custom server cert, key, and CA bundle from user-provided paths to `/var/lib/foremanctl/certs/` (only when certificate paths are provided) 3. **Host Certificate Issuance**: Generate client certificate and localhost certificate signed by the internal CA (server cert for FQDN is skipped) -#### Certificate Bundle Generation +#### Auth Bundle Generation -The `certificate-bundle` playbook reuses the `certificates` role to generate proxy certificates in a per-host subdirectory (`certificates_ca_directory/hosts//`). It overrides `certificates_ca_directory_certs`, `certificates_ca_directory_keys`, and `certificates_ca_directory_requests` to point to the subdirectory while keeping `certificates_ca_directory` unchanged so the CA can still be found for signing. It sets `certificates_ca: false` (the CA already exists from a prior deploy) and passes the proxy hostname via `certificates_hostnames`. The `certificate_bundle` role then packages the generated certificates along with the CA into a tarball under `certificates_ca_directory/bundles/`. +The `auth-bundle` playbook reuses the `certificates` role to generate proxy certificates in a per-host subdirectory (`certificates_ca_directory/hosts//`). It overrides `certificates_ca_directory_certs`, `certificates_ca_directory_keys`, and `certificates_ca_directory_requests` to point to the subdirectory while keeping `certificates_ca_directory` unchanged so the CA can still be found for signing. It sets `certificates_ca: false` (the CA already exists from a prior deploy) and passes the proxy hostname via `certificates_hostnames`. The `auth_bundle` role then packages the generated certificates along with the CA into a tarball under `certificates_ca_directory/bundles/`. -When custom server certificates are provided for the proxy, `certificates_source` is set to `custom_server` so only client certificates are generated by the internal CA. The custom server certificate, key, and CA are validated by the `certificate_checks` role and then packaged directly into the tarball by the `certificate_bundle` role. +When custom server certificates are provided for the proxy, `certificates_source` is set to `custom_server` so only client certificates are generated by the internal CA. The custom server certificate, key, and CA are validated by the `certificate_checks` role and then packaged directly into the tarball by the `auth_bundle` role. #### Migration from foreman-installer diff --git a/src/playbooks/auth-bundle/auth-bundle.yaml b/src/playbooks/auth-bundle/auth-bundle.yaml new file mode 100644 index 000000000..3343fe29d --- /dev/null +++ b/src/playbooks/auth-bundle/auth-bundle.yaml @@ -0,0 +1,34 @@ +--- +- name: Generate an auth bundle for a hostname + hosts: + - quadlet + become: true + vars_files: + - "../../vars/base.yaml" + - "../../vars/certificates.yml" + - "../../vars/foreman.yml" + roles: + - role: certificate_checks + when: certificates_source == 'custom_server' + vars: + certificate_checks_certificate: "{{ certificates_custom_server_certificate }}" + certificate_checks_key: "{{ certificates_custom_server_key }}" + certificate_checks_ca: "{{ server_ca_certificate }}" + - role: certificates + vars: + certificates_ca: false + certificates_output_directory: "{{ certificates_ca_directory }}/hosts/{{ hostname }}" + certificates_hostnames: + - "{{ hostname }}" + - role: auth_bundle + vars: + auth_bundle_hostname: "{{ hostname }}" + auth_bundle_ca_bundle: "{{ ca_bundle }}" + auth_bundle_ca_certificate: "{{ ca_certificate }}" + auth_bundle_server_ca_certificate: "{{ server_ca_certificate }}" + auth_bundle_server_certificate: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/certs/{{ hostname }}.crt" + auth_bundle_server_key: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/private/{{ hostname }}.key" + auth_bundle_client_certificate: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/certs/{{ hostname }}-client.crt" + auth_bundle_client_key: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/private/{{ hostname }}-client.key" + auth_bundle_oauth_consumer_key_file: "{{ foreman_oauth_consumer_key_file }}" + auth_bundle_oauth_consumer_secret_file: "{{ foreman_oauth_consumer_secret_file }}" diff --git a/src/playbooks/certificate-bundle/metadata.obsah.yaml b/src/playbooks/auth-bundle/metadata.obsah.yaml similarity index 89% rename from src/playbooks/certificate-bundle/metadata.obsah.yaml rename to src/playbooks/auth-bundle/metadata.obsah.yaml index 3fa6cc15d..b8bfd2bab 100644 --- a/src/playbooks/certificate-bundle/metadata.obsah.yaml +++ b/src/playbooks/auth-bundle/metadata.obsah.yaml @@ -1,11 +1,11 @@ --- help: | - Generate a certificate bundle + Generate an auth bundle variables: hostname: parameter: hostname - help: Hostname to generate a certificate bundle for that will be the common name. + help: Hostname to generate an auth bundle for that will be the common name. certificates_custom_server_certificate: help: Path to a custom server certificate for the proxy. type: AbsolutePath diff --git a/src/playbooks/certificate-bundle/certificate-bundle.yaml b/src/playbooks/certificate-bundle/certificate-bundle.yaml deleted file mode 100644 index b4112c514..000000000 --- a/src/playbooks/certificate-bundle/certificate-bundle.yaml +++ /dev/null @@ -1,34 +0,0 @@ ---- -- name: Generate a certificate bundle for a hostname - hosts: - - quadlet - become: true - vars_files: - - "../../vars/base.yaml" - - "../../vars/certificates.yml" - - "../../vars/foreman.yml" - roles: - - role: certificate_checks - when: certificates_source == 'custom_server' - vars: - certificate_checks_certificate: "{{ certificates_custom_server_certificate }}" - certificate_checks_key: "{{ certificates_custom_server_key }}" - certificate_checks_ca: "{{ server_ca_certificate }}" - - role: certificates - vars: - certificates_ca: false - certificates_output_directory: "{{ certificates_ca_directory }}/hosts/{{ hostname }}" - certificates_hostnames: - - "{{ hostname }}" - - role: certificate_bundle - vars: - certificate_bundle_hostname: "{{ hostname }}" - certificate_bundle_ca_bundle: "{{ ca_bundle }}" - certificate_bundle_ca_certificate: "{{ ca_certificate }}" - certificate_bundle_server_ca_certificate: "{{ server_ca_certificate }}" - certificate_bundle_server_certificate: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/certs/{{ hostname }}.crt" - certificate_bundle_server_key: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/private/{{ hostname }}.key" - certificate_bundle_client_certificate: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/certs/{{ hostname }}-client.crt" - certificate_bundle_client_key: "{{ certificates_ca_directory }}/hosts/{{ hostname }}/private/{{ hostname }}-client.key" - certificate_bundle_oauth_consumer_key_file: "{{ foreman_oauth_consumer_key_file }}" - certificate_bundle_oauth_consumer_secret_file: "{{ foreman_oauth_consumer_secret_file }}" diff --git a/src/playbooks/deploy-proxy/metadata.obsah.yaml b/src/playbooks/deploy-proxy/metadata.obsah.yaml index 836a2f5f9..16070eb65 100644 --- a/src/playbooks/deploy-proxy/metadata.obsah.yaml +++ b/src/playbooks/deploy-proxy/metadata.obsah.yaml @@ -7,10 +7,10 @@ variables: help: Base flavor to use in this deployment. choices: - foreman-proxy-content - certificates_bundle: - help: Path to the certificate bundle tar file. + auth_bundle: + help: Path to the auth bundle tar file. type: AbsolutePath - parameter: --certificate-bundle + parameter: --auth-bundle persist: false foreman_name: parameter: --foreman-fqdn diff --git a/src/roles/auth_bundle/defaults/main.yml b/src/roles/auth_bundle/defaults/main.yml new file mode 100644 index 000000000..8e7a56571 --- /dev/null +++ b/src/roles/auth_bundle/defaults/main.yml @@ -0,0 +1,3 @@ +--- +auth_bundle_output_directory: "{{ certificates_ca_directory }}/bundles" +auth_bundle_server_ca_certificate: "{{ auth_bundle_ca_certificate }}" diff --git a/src/roles/auth_bundle/tasks/main.yml b/src/roles/auth_bundle/tasks/main.yml new file mode 100644 index 000000000..0a31232f3 --- /dev/null +++ b/src/roles/auth_bundle/tasks/main.yml @@ -0,0 +1,107 @@ +--- +- name: Create output directory + ansible.builtin.file: + path: "{{ auth_bundle_output_directory }}" + state: directory + mode: '0755' + +- name: Check for existing auth bundle + ansible.builtin.stat: + path: "{{ auth_bundle_output_directory }}/{{ auth_bundle_hostname }}.tar.gz" + register: _auth_bundle_tarball + +- name: Build auth bundle + when: not _auth_bundle_tarball.stat.exists or (certificates_renew | default(false) | bool) + block: + - name: Create temporary directory + ansible.builtin.tempfile: + state: directory + suffix: auth-bundle-build + register: auth_bundle_build_directory + + - name: Create directory structure + ansible.builtin.file: + state: directory + path: "{{ auth_bundle_build_directory.path }}/certs/{{ item }}" + mode: '0755' + loop: + - certs + - private + - oauth + + - name: Copy default CA certificate + ansible.builtin.copy: + src: "{{ auth_bundle_ca_certificate }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/certs/ca.crt" + remote_src: true + mode: '0444' + + - name: Copy server CA certificate + ansible.builtin.copy: + src: "{{ auth_bundle_server_ca_certificate }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/certs/server-ca.crt" + remote_src: true + mode: '0444' + + - name: Copy CA bundle + ansible.builtin.copy: + src: "{{ auth_bundle_ca_bundle }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/certs/ca-bundle.crt" + remote_src: true + mode: '0444' + + - name: Copy server certificate + ansible.builtin.copy: + src: "{{ auth_bundle_server_certificate }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/certs/{{ auth_bundle_hostname }}.crt" + remote_src: true + mode: '0444' + + - name: Copy server key + ansible.builtin.copy: + src: "{{ auth_bundle_server_key }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/private/{{ auth_bundle_hostname }}.key" + remote_src: true + mode: '0440' + + - name: Copy client certificate + ansible.builtin.copy: + src: "{{ auth_bundle_client_certificate }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/certs/{{ auth_bundle_hostname }}-client.crt" + remote_src: true + mode: '0444' + + - name: Copy client key + ansible.builtin.copy: + src: "{{ auth_bundle_client_key }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/private/{{ auth_bundle_hostname }}-client.key" + remote_src: true + mode: '0440' + + - name: Copy OAuth consumer key + ansible.builtin.copy: + src: "{{ auth_bundle_oauth_consumer_key_file }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-key" + mode: '0440' + + - name: Copy OAuth consumer secret + ansible.builtin.copy: + src: "{{ auth_bundle_oauth_consumer_secret_file }}" + dest: "{{ auth_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-secret" + mode: '0440' + + - name: Create tarball + community.general.archive: + path: "{{ auth_bundle_build_directory.path }}/certs/*" + dest: "{{ auth_bundle_output_directory }}/{{ auth_bundle_hostname }}.tar.gz" + format: gz + mode: '0640' + + - name: Remove temporary directory + ansible.builtin.file: + path: "{{ auth_bundle_build_directory.path }}" + state: absent + +- name: Report auth bundle location + ansible.builtin.debug: + msg: "Auth bundle created: {{ auth_bundle_output_directory }}/{{ auth_bundle_hostname }}.tar.gz" diff --git a/src/roles/certificate_bundle/defaults/main.yml b/src/roles/certificate_bundle/defaults/main.yml deleted file mode 100644 index 736f7ee44..000000000 --- a/src/roles/certificate_bundle/defaults/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -certificate_bundle_output_directory: "{{ certificates_ca_directory }}/bundles" -certificate_bundle_server_ca_certificate: "{{ certificate_bundle_ca_certificate }}" diff --git a/src/roles/certificate_bundle/tasks/main.yml b/src/roles/certificate_bundle/tasks/main.yml deleted file mode 100644 index 7db4900b4..000000000 --- a/src/roles/certificate_bundle/tasks/main.yml +++ /dev/null @@ -1,107 +0,0 @@ ---- -- name: Create output directory - ansible.builtin.file: - path: "{{ certificate_bundle_output_directory }}" - state: directory - mode: '0755' - -- name: Check for existing certificate bundle - ansible.builtin.stat: - path: "{{ certificate_bundle_output_directory }}/{{ certificate_bundle_hostname }}.tar.gz" - register: _certificate_bundle_tarball - -- name: Build certificate bundle - when: not _certificate_bundle_tarball.stat.exists or (certificates_renew | default(false) | bool) - block: - - name: Create temporary directory - ansible.builtin.tempfile: - state: directory - suffix: certificate-bundle-build - register: certificate_bundle_build_directory - - - name: Create directory structure - ansible.builtin.file: - state: directory - path: "{{ certificate_bundle_build_directory.path }}/certs/{{ item }}" - mode: '0755' - loop: - - certs - - private - - oauth - - - name: Copy default CA certificate - ansible.builtin.copy: - src: "{{ certificate_bundle_ca_certificate }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/certs/ca.crt" - remote_src: true - mode: '0444' - - - name: Copy server CA certificate - ansible.builtin.copy: - src: "{{ certificate_bundle_server_ca_certificate }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/certs/server-ca.crt" - remote_src: true - mode: '0444' - - - name: Copy CA bundle - ansible.builtin.copy: - src: "{{ certificate_bundle_ca_bundle }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/certs/ca-bundle.crt" - remote_src: true - mode: '0444' - - - name: Copy server certificate - ansible.builtin.copy: - src: "{{ certificate_bundle_server_certificate }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/certs/{{ certificate_bundle_hostname }}.crt" - remote_src: true - mode: '0444' - - - name: Copy server key - ansible.builtin.copy: - src: "{{ certificate_bundle_server_key }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/private/{{ certificate_bundle_hostname }}.key" - remote_src: true - mode: '0440' - - - name: Copy client certificate - ansible.builtin.copy: - src: "{{ certificate_bundle_client_certificate }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/certs/{{ certificate_bundle_hostname }}-client.crt" - remote_src: true - mode: '0444' - - - name: Copy client key - ansible.builtin.copy: - src: "{{ certificate_bundle_client_key }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/private/{{ certificate_bundle_hostname }}-client.key" - remote_src: true - mode: '0440' - - - name: Copy OAuth consumer key - ansible.builtin.copy: - src: "{{ certificate_bundle_oauth_consumer_key_file }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-key" - mode: '0440' - - - name: Copy OAuth consumer secret - ansible.builtin.copy: - src: "{{ certificate_bundle_oauth_consumer_secret_file }}" - dest: "{{ certificate_bundle_build_directory.path }}/certs/oauth/foreman-oauth-consumer-secret" - mode: '0440' - - - name: Create tarball - community.general.archive: - path: "{{ certificate_bundle_build_directory.path }}/certs/*" - dest: "{{ certificate_bundle_output_directory }}/{{ certificate_bundle_hostname }}.tar.gz" - format: gz - mode: '0640' - - - name: Remove temporary directory - ansible.builtin.file: - path: "{{ certificate_bundle_build_directory.path }}" - state: absent - -- name: Report certificate bundle location - ansible.builtin.debug: - msg: "Certificate bundle created: {{ certificate_bundle_output_directory }}/{{ certificate_bundle_hostname }}.tar.gz" diff --git a/src/roles/certificates/tasks/extract.yml b/src/roles/certificates/tasks/extract.yml index 75296bbf1..d2938ff73 100644 --- a/src/roles/certificates/tasks/extract.yml +++ b/src/roles/certificates/tasks/extract.yml @@ -1,19 +1,19 @@ --- -- name: Check path to certificate tar file exists +- name: Check path to auth bundle tar file exists ansible.builtin.stat: - path: "{{ certificates_bundle }}" + path: "{{ auth_bundle }}" register: _certificates_tar_file_path delegate_to: localhost become: false -- name: Fail if path to certificate tar file does not exist +- name: Fail if path to auth bundle tar file does not exist ansible.builtin.fail: - msg: "Path to certificate tar file not found: {{ certificates_bundle }}" + msg: "Path to auth bundle tar file not found: {{ auth_bundle }}" when: not _certificates_tar_file_path.stat.exists - name: Extract certificates from bundle ansible.builtin.unarchive: - src: "{{ certificates_bundle }}" + src: "{{ auth_bundle }}" dest: "{{ certificates_ca_directory }}" exclude: - oauth @@ -21,7 +21,7 @@ - name: Extract OAuth credentials from bundle ansible.builtin.unarchive: - src: "{{ certificates_bundle }}" + src: "{{ auth_bundle }}" dest: "{{ certificates_oauth_directory | dirname }}" exclude: - certs diff --git a/src/roles/certificates/tasks/main.yml b/src/roles/certificates/tasks/main.yml index dce213d7a..dd1e86eb4 100644 --- a/src/roles/certificates/tasks/main.yml +++ b/src/roles/certificates/tasks/main.yml @@ -37,7 +37,7 @@ - name: 'Generate certificates' when: - - certificates_bundle is not defined + - auth_bundle is not defined - certificates_generate block: - name: 'Generate CA certificate' @@ -65,8 +65,8 @@ - name: 'Consume certs' when: - - certificates_bundle is defined + - auth_bundle is defined - not certificates_generate block: - - name: Extract proxy certificate bundle + - name: Extract proxy auth bundle ansible.builtin.include_tasks: extract.yml diff --git a/src/roles/oauth_from_bundle/tasks/credential.yml b/src/roles/oauth_from_bundle/tasks/credential.yml index 6c1fde6b0..713cc3e1e 100644 --- a/src/roles/oauth_from_bundle/tasks/credential.yml +++ b/src/roles/oauth_from_bundle/tasks/credential.yml @@ -1,19 +1,19 @@ --- -- name: Load OAuth credential from certificate bundle - {{ oauth_from_bundle_credential }} +- name: Load OAuth credential from auth bundle - {{ oauth_from_bundle_credential }} vars: oauth_from_bundle_path: "{{ oauth_from_bundle_directory }}/foreman-oauth-consumer-{{ oauth_from_bundle_credential }}" block: - - name: Check for OAuth consumer file in certificate bundle - {{ oauth_from_bundle_credential }} + - name: Check for OAuth consumer file in auth bundle - {{ oauth_from_bundle_credential }} ansible.builtin.stat: path: "{{ oauth_from_bundle_path }}" register: oauth_from_bundle_file - - name: Fail when OAuth consumer is missing from certificate bundle - {{ oauth_from_bundle_credential }} + - name: Fail when OAuth consumer is missing from auth bundle - {{ oauth_from_bundle_credential }} ansible.builtin.fail: msg: >- - OAuth consumer {{ oauth_from_bundle_credential }} not found in certificate bundle + OAuth consumer {{ oauth_from_bundle_credential }} not found in auth bundle at {{ oauth_from_bundle_path }}. - Regenerate the bundle with foremanctl certificate-bundle. + Regenerate the bundle with foremanctl auth-bundle. when: not oauth_from_bundle_file.stat.exists - name: Slurp OAuth consumer - {{ oauth_from_bundle_credential }} @@ -21,7 +21,7 @@ src: "{{ oauth_from_bundle_path }}" register: oauth_from_bundle_content - - name: Set OAuth consumer from certificate bundle - {{ oauth_from_bundle_credential }} + - name: Set OAuth consumer from auth bundle - {{ oauth_from_bundle_credential }} ansible.builtin.set_fact: "foreman_proxy_oauth_consumer_{{ oauth_from_bundle_credential }}": "{{ oauth_from_bundle_content.content | b64decode | trim }}" "pulp_foreman_oauth_consumer_{{ oauth_from_bundle_credential }}": "{{ oauth_from_bundle_content.content | b64decode | trim }}" diff --git a/src/roles/oauth_from_bundle/tasks/main.yml b/src/roles/oauth_from_bundle/tasks/main.yml index 77736b56a..a4780c54b 100644 --- a/src/roles/oauth_from_bundle/tasks/main.yml +++ b/src/roles/oauth_from_bundle/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: Load OAuth credentials from certificate bundle +- name: Load OAuth credentials from auth bundle ansible.builtin.include_tasks: credential.yml loop: - key diff --git a/tests/certificate_bundle_test.py b/tests/auth_bundle_test.py similarity index 96% rename from tests/certificate_bundle_test.py rename to tests/auth_bundle_test.py index 73f101050..cfd53b817 100644 --- a/tests/certificate_bundle_test.py +++ b/tests/auth_bundle_test.py @@ -44,7 +44,7 @@ def generate_custom_proxy_certs(server, certificate_source): @pytest.fixture(scope="module") def generate_bundle(server, certificate_source, generate_custom_proxy_certs): - command = ['./foremanctl', 'certificate-bundle'] + command = ['./foremanctl', 'auth-bundle'] if certificate_source == 'custom_server': command.extend([ '--certificate-server-certificate', f'/root/custom-certificates/certs/{HOSTNAME}.crt', @@ -53,7 +53,7 @@ def generate_bundle(server, certificate_source, generate_custom_proxy_certs): command.append(HOSTNAME) result = subprocess.run(command, capture_output=True, text=True) - assert result.returncode == 0, f'certificate-bundle failed: {result.stdout}\n{result.stderr}' + assert result.returncode == 0, f'auth-bundle failed: {result.stdout}\n{result.stderr}' @pytest.fixture(scope="module") diff --git a/tests/flavor/foreman-proxy-content/oauth_test.py b/tests/flavor/foreman-proxy-content/oauth_test.py index c491f039e..977f072db 100644 --- a/tests/flavor/foreman-proxy-content/oauth_test.py +++ b/tests/flavor/foreman-proxy-content/oauth_test.py @@ -10,9 +10,9 @@ @pytest.mark.parametrize("oauth_file", OAUTH_FILES) def test_oauth_credentials_extracted_from_bundle(server, oauth_file): - """Proxy deploy must extract OAuth credentials from the certificate bundle.""" + """Proxy deploy must extract OAuth credentials from the auth bundle.""" oauth_path = f'{OAUTH_DIR}/{oauth_file}' oauth = server.file(oauth_path) - assert oauth.exists, f'{oauth_path} was not extracted from the certificate bundle' + assert oauth.exists, f'{oauth_path} was not extracted from the auth bundle' assert oauth.size > 0 assert oauth.mode == 0o440, f'{oauth_path} should have mode 0440, got {oct(oauth.mode)}' From 584f8ec97de17b98e4eef2c3ec6e77a55730cd7c Mon Sep 17 00:00:00 2001 From: Arvind Jangir Date: Tue, 28 Jul 2026 19:23:35 +0530 Subject: [PATCH 5/5] update parameters --- docs/user/parameters.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/user/parameters.md b/docs/user/parameters.md index 865a0019f..e9f4086be 100644 --- a/docs/user/parameters.md +++ b/docs/user/parameters.md @@ -132,6 +132,13 @@ There are multiple use cases from the users perspective that dictate what parame | `--templates-listen-on` | Templates proxy to listen on https, http, or both | `--foreman-proxy-templates-listen-on` | | `--templates-url` | URL that hosts will use to contact the proxy for provisioning templates | `--foreman-proxy-templates-url` | +### Unmapped + +| foreman-installer Parameter | Description | Reason | +| --------------------------- | ----------- | ------ | +| `--foreman-proxy-oauth-consumer-key` | OAuth consumer key for Smart Proxy | Not required(Managed automatically via auth bundle) | +| `--foreman-proxy-oauth-consumer-secret` | OAuth consumer secret for Smart Proxy | Not required(Managed automatically via auth bundle) | + ### Undetermined | Installer Parameter | Description | Module | Puppet Parameter | @@ -139,8 +146,6 @@ There are multiple use cases from the users perspective that dictate what parame | `--foreman-proxy-cname` | Enables DHCP feature in smart-proxy | foreman_proxy | cname | | `--foreman-proxy-fqdn` | Enables DHCP feature in smart-proxy | foreman_proxy | fqdn | | `--foreman-proxy-foreman-base-url` | | foreman_proxy | foreman_base_url | -| `--foreman-proxy-oauth-consumer-key` | | foreman_proxy | oauth_consumer_key | -| `--foreman-proxy-oauth-consumer-secret` | | foreman_proxy | oauth_consumer_secret | | `--foreman-proxy-register-in-foreman` | | foreman_proxy | register_in_foreman | | `--foreman-proxy-trusted-hosts` | | foreman_proxy | trusted_hosts | | `--foreman-proxy-dhcp` | Enables DHCP feature in smart-proxy | foreman_proxy | dhcp |