Skip to content
Open
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
7 changes: 1 addition & 6 deletions src/roles/candlepin/tasks/certs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,11 @@
notify:
- Restart candlepin

- name: Decrypt Candlepin CA key
ansible.builtin.command: openssl pkey -in "{{ candlepin_ca_key }}" -passin "file:{{ candlepin_ca_key_password }}"
register: _candlepin_ca_key
changed_when: false

- name: Create the podman secret for Candlepin CA key
containers.podman.podman_secret:
state: present
name: candlepin-ca-key
data: "{{ _candlepin_ca_key.stdout }}"
path: "{{ candlepin_ca_key }}"
labels:
app: candlepin
notify:
Expand Down
42 changes: 30 additions & 12 deletions src/roles/certificates/tasks/ca.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,45 @@
path: "{{ certificates_ca_directory_certs }}/ca.crt"
register: _certificates_ca_cert

- name: 'Check for an existing CA key'
ansible.builtin.stat:
path: "{{ certificates_ca_directory_keys }}/ca.key"
register: _certificates_existing_ca_key

- name: 'Detect whether the existing CA key is password-encrypted'
ansible.builtin.command:
cmd: "grep -q ENCRYPTED {{ certificates_ca_directory_keys }}/ca.key"
register: _certificates_ca_key_encrypted
changed_when: false
failed_when: false
when: _certificates_existing_ca_key.stat.exists

- name: 'Decrypt a legacy password-encrypted CA key in place'
community.crypto.openssl_privatekey_convert:
src_path: "{{ certificates_ca_directory_keys }}/ca.key"
src_passphrase: "{{ certificates_ca_password }}"
dest_path: "{{ certificates_ca_directory_keys }}/ca.key"
format: pkcs8
mode: '0600'
when:
- _certificates_existing_ca_key.stat.exists
- (_certificates_ca_key_encrypted.rc | default(1)) == 0
no_log: true

- name: 'Remove the obsolete CA key password file'
ansible.builtin.file:
path: "{{ certificates_ca_directory_keys }}/ca.pwd"
state: absent

- name: 'Generate CA'
when:
- (not _certificates_ca_cert.stat.exists or certificates_renew_ca)
block:
- name: 'Create CA key password file'
ansible.builtin.copy:
content: "{{ certificates_ca_password }}"
dest: "{{ certificates_ca_directory_keys }}/ca.pwd"
owner: root
group: root
mode: '0600'
no_log: true

- name: 'Create CA private key'
community.crypto.openssl_privatekey:
path: "{{ certificates_ca_directory_keys }}/ca.key"
type: "{{ certificates_algorithm_type }}"
size: "{{ certificates_algorithm_size }}"
passphrase: "{{ certificates_ca_password }}"
owner: root
group: root
mode: '0600'
Expand All @@ -31,7 +51,6 @@
community.crypto.openssl_csr:
path: "{{ certificates_ca_directory_requests }}/ca.csr"
privatekey_path: "{{ certificates_ca_directory_keys }}/ca.key"
privatekey_passphrase: "{{ certificates_ca_password }}"
common_name: "{{ certificates_ca_subject }}"
use_common_name_for_san: false
basic_constraints:
Expand All @@ -49,7 +68,6 @@
path: "{{ certificates_ca_directory_certs }}/ca.crt"
csr_path: "{{ certificates_ca_directory_requests }}/ca.csr"
privatekey_path: "{{ certificates_ca_directory_keys }}/ca.key"
privatekey_passphrase: "{{ certificates_ca_password }}"
provider: selfsigned
selfsigned_not_after: "+{{ certificates_ca_validity_days }}d"
force: "{{ certificates_renew_ca | bool }}"
Expand Down
2 changes: 0 additions & 2 deletions src/roles/certificates/tasks/issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
provider: ownca
ownca_path: "{{ certificates_ca_directory_certs }}/ca.crt"
ownca_privatekey_path: "{{ certificates_ca_directory_keys }}/ca.key"
ownca_privatekey_passphrase: "{{ certificates_ca_password }}"
ownca_not_after: "+{{ certificates_validity_days }}d"
force: "{{ certificates_renew | bool }}"

Expand Down Expand Up @@ -63,6 +62,5 @@
provider: ownca
ownca_path: "{{ certificates_ca_directory }}/certs/ca.crt"
ownca_privatekey_path: "{{ certificates_ca_directory }}/private/ca.key"
ownca_privatekey_passphrase: "{{ certificates_ca_password }}"
ownca_not_after: "+{{ certificates_validity_days }}d"
force: "{{ certificates_renew | bool }}"
1 change: 0 additions & 1 deletion src/vars/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ certificates_ca_password: "{{ lookup('ansible.builtin.password', certificates_ca
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) }}"

candlepin_ca_key_password: "{{ ca_key_password }}"
candlepin_ca_key: "{{ ca_key }}"
candlepin_ca_certificate: "{{ ca_certificate }}"
candlepin_tomcat_key: "{{ localhost_key }}"
Expand Down
1 change: 0 additions & 1 deletion src/vars/certificates.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
certificates_ca_directory: /var/lib/foremanctl/certs
ca_key_password: "{{ certificates_ca_directory }}/private/ca.pwd"
ca_certificate: "{{ certificates_ca_directory }}/certs/ca.crt"
ca_key: "{{ certificates_ca_directory }}/private/ca.key"
server_certificate: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}.crt"
Expand Down
4 changes: 0 additions & 4 deletions tests/backup_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,6 @@ def test_foremanctl_state_archive_contents(server, backup_result):

assert len(file_list) > 0, "Archive should contain at least one file"

# Check for certificates-ca-password which should be present in all deployments
assert 'certificates-ca-password' in archive_contents, \
"Archive should contain certificates-ca-password (generated during deployment)"


def test_pulp_content_archived(server, backup_result):
backup_dir = backup_result['backup_dir']
Expand Down
22 changes: 22 additions & 0 deletions tests/certificates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,28 @@ def test_ca_bundle_verifies_server_certificate(server, certificates):
assert "OK" in cmd.stdout


def test_ca_key_unencrypted(server, certificates):
f = server.file(certificates['ca_key'])
assert f.exists
assert f.mode == 0o600
assert 'ENCRYPTED' not in f.content_string
cmd = server.run(f"openssl pkey -in {certificates['ca_key']} -noout")
assert cmd.succeeded


def test_ca_key_password_file_absent(server, certificates):
ca_pwd = certificates['ca_key'].rsplit('/', 1)[0] + '/ca.pwd'
assert not server.file(ca_pwd).exists


def test_ca_key_matches_ca_certificate(server, certificates):
key_pub = server.run(f"openssl pkey -in {certificates['ca_key']} -pubout")
cert_pub = server.run(f"openssl x509 -in {certificates['ca_certificate']} -noout -pubkey")
assert key_pub.succeeded
assert cert_pub.succeeded
assert key_pub.stdout == cert_pub.stdout


@pytest.mark.parametrize("cert_key,expected_mode", [
('server_certificate', 0o444),
('server_ca_certificate', 0o444),
Expand Down
10 changes: 6 additions & 4 deletions tests/migration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ def test_certificate_directories(server, migrated_environment, subdir):
assert d.mode == 0o755


def test_ca_password_file(server, migrated_environment):
f = server.file("/var/lib/foremanctl/certs/private/ca.pwd")
assert f.exists
assert f.mode == 0o600
def test_ca_key_unencrypted(server, migrated_environment):
assert not server.file("/var/lib/foremanctl/certs/private/ca.pwd").exists
key = server.file("/var/lib/foremanctl/certs/private/ca.key")
assert key.exists
assert key.mode == 0o600
assert "ENCRYPTED" not in key.content_string


def test_ca_password_persisted(migrated_environment, obsah_state_path):
Expand Down
Loading