fix(octavia): switch to cert-manager issuer certs
diff --git a/atmosphere/tasks/constants.py b/atmosphere/tasks/constants.py
index 9cc9fd7..b121bff 100644
--- a/atmosphere/tasks/constants.py
+++ b/atmosphere/tasks/constants.py
@@ -341,6 +341,7 @@
 HELM_RELEASE_CERT_MANAGER_VERSION = "v1.7.1"
 HELM_RELEASE_CERT_MANAGER_VALUES = {
     "installCRDs": True,
+    "featureGates": "AdditionalCertificateOutputFormats=true",
     "volumes": [
         {
             "name": "etc-ssl-certs",
@@ -358,6 +359,9 @@
     ],
     "nodeSelector": NODE_SELECTOR_CONTROL_PLANE,
     "webhook": {
+        "extraArgs": [
+            "--feature-gates=AdditionalCertificateOutputFormats=true",
+        ],
         "nodeSelector": NODE_SELECTOR_CONTROL_PLANE,
     },
     "cainjector": {
diff --git a/atmosphere/tasks/kubernetes/cert_manager.py b/atmosphere/tasks/kubernetes/cert_manager.py
index 2d2caca..40e9082 100644
--- a/atmosphere/tasks/kubernetes/cert_manager.py
+++ b/atmosphere/tasks/kubernetes/cert_manager.py
@@ -79,7 +79,15 @@
 
 
 def issuer_tasks_from_config(config: config.Issuer) -> list:
-    objects = []
+    objects = [
+        ApplyIssuerTask(
+            namespace=constants.NAMESPACE_OPENSTACK,
+            name="self-signed",
+            spec={
+                "selfSigned": {},
+            },
+        )
+    ]
 
     if config.type == "acme":
         spec = {
@@ -184,13 +192,6 @@
     elif config.type == "self-signed":
         # NOTE(mnaser): We have to setup the self-signed CA in this case
         objects += [
-            ApplyIssuerTask(
-                namespace=constants.NAMESPACE_OPENSTACK,
-                name="self-signed",
-                spec={
-                    "selfSigned": {},
-                },
-            ),
             ApplyCertificateTask(
                 namespace=constants.NAMESPACE_OPENSTACK,
                 name="self-signed-ca",
diff --git a/roles/openstack_helm_octavia/tasks/main.yml b/roles/openstack_helm_octavia/tasks/main.yml
index 967da01..dce8c18 100644
--- a/roles/openstack_helm_octavia/tasks/main.yml
+++ b/roles/openstack_helm_octavia/tasks/main.yml
@@ -86,6 +86,8 @@
   ansible.builtin.set_fact:
     _openstack_helm_octavia_controller_ip_port_list: "{{ _openstack_helm_octavia_controller_ip_port_list | d([]) + [item.openstack_ports[0].fixed_ips[0].ip_address + ':5555'] }}"
   loop: "{{ _openstack_helm_octavia_health_manager_ports.results }}"
+  loop_control:
+    label: "{{ item.openstack_ports[0].name }}"
 
 - name: Create amphora security group
   openstack.cloud.security_group:
@@ -134,91 +136,61 @@
       - "amphora"
   register: _openstack_helm_octavia_amphora_image
 
-- name: Check if certificate secret exists
-  kubernetes.core.k8s_info:
-    kind: Secret
-    name: octavia-certs
-    namespace: openstack
-  register: _openstack_helm_octavia_cert_secret
+- name: Create CAs & Issuers
+  kubernetes.core.k8s:
+    state: present
+    definition:
+      - apiVersion: cert-manager.io/v1
+        kind: Certificate
+        metadata:
+          name: "{{ item }}-ca"
+          namespace: openstack
+        spec:
+          isCA: true
+          commonName: "{{ item }}"
+          secretName: "{{ item }}-ca"
+          duration: 87600h
+          renewBefore: 720h
+          privateKey:
+            algorithm: ECDSA
+            size: 256
+          issuerRef:
+            name: self-signed
+            kind: Issuer
+            group: cert-manager.io
 
-# TODO(mnaser): we should just use cert-manager for this?
-- name: Create certificate secret
-  when: (_openstack_helm_octavia_cert_secret.resources | length) == 0
-  block:
-    - name: Create CA private key
-      community.crypto.openssl_privatekey_pipe:
-        type: RSA
-      register: _openstack_helm_octavia_ca_key
+      - apiVersion: cert-manager.io/v1
+        kind: Issuer
+        metadata:
+          name: "{{ item }}"
+          namespace: openstack
+        spec:
+          ca:
+            secretName: "{{ item }}-ca"
+  loop:
+    - octavia-client
+    - octavia-server
 
-    - name: Create certificate signing request (CSR) for CA
-      community.crypto.openssl_csr_pipe:
-        basic_constraints:
-          - 'CA:TRUE'
-        basic_constraints_critical: true
-        common_name: "octavia"
-        key_usage:
-          - "keyEncipherment"
-          - "digitalSignature"
-          - "keyCertSign"
-        key_usage_critical: true
-        organization_name: "VEXXHOST OpenStack - Octavia"
-        privatekey_content: "{{ _openstack_helm_octavia_ca_key.privatekey }}"
-        use_common_name_for_san: false
-      register: _openstack_helm_octavia_ca_csr
-
-    - name: Create self-signed CA certificate from CSR
-      community.crypto.x509_certificate_pipe:
-        csr_content: "{{ _openstack_helm_octavia_ca_csr.csr }}"
-        entrust_not_after: "+3650d"
-        privatekey_content: "{{ _openstack_helm_octavia_ca_key.privatekey }}"
-        provider: selfsigned
-      register: _openstack_helm_octavia_ca
-
-    - name: Create client private key
-      community.crypto.openssl_privatekey_pipe:
-        type: RSA
-      register: _openstack_helm_octavia_client_ca_key
-
-    - name: Create certificate signing request (CSR) for client
-      community.crypto.openssl_csr_pipe:
-        common_name: "octavia-node"
-        key_usage:
-          - "keyEncipherment"
-          - "digitalSignature"
-          - "keyCertSign"
-        organization_name: "VEXXHOST OpenStack - Octavia"
-        privatekey_content: "{{ _openstack_helm_octavia_client_ca_key.privatekey }}"
-        use_common_name_for_san: false
-      register: _openstack_helm_octavia_client_csr
-
-    - name: Create self-signed client certificate
-      community.crypto.x509_certificate_pipe:
-        csr_content: "{{ _openstack_helm_octavia_client_csr.csr }}"
-        ownca_content: "{{ _openstack_helm_octavia_ca.certificate }}"
-        ownca_privatekey_content: "{{ _openstack_helm_octavia_ca_key.privatekey }}"
-        ownca_not_after: "+3650d"
-        entrust_not_after: "+3650d"
-        privatekey_content: "{{ _openstack_helm_octavia_client_ca_key.privatekey }}"
-        provider: ownca
-      register: _openstack_helm_octavia_client_ca
-
-    - name: Createa kubernetes secret
-      kubernetes.core.k8s:
-        state: present
-        definition:
-          apiVersion: v1
-          kind: Secret
-          metadata:
-            name: octavia-certs
-            namespace: openstack
-          stringData:
-            ca_01.pem: |
-              {{ _openstack_helm_octavia_ca.certificate }}
-            cakey.pem: |
-              {{ _openstack_helm_octavia_ca_key.privatekey }}
-            client.pem: |
-              {{ _openstack_helm_octavia_client_ca.certificate }}
-              {{ _openstack_helm_octavia_client_ca_key.privatekey }}
+- name: Create certificate for Octavia clients
+  kubernetes.core.k8s:
+    state: present
+    definition:
+      apiVersion: cert-manager.io/v1
+      kind: Certificate
+      metadata:
+        name: octavia-client-certs
+        namespace: openstack
+      spec:
+        commonName: octavia-client
+        secretName: octavia-client-certs
+        additionalOutputFormats:
+          - type: CombinedPEM
+        duration: 87600h
+        renewBefore: 720h
+        issuerRef:
+          name: octavia-client
+          kind: Issuer
+          group: cert-manager.io
 
 - name: Create admin compute quotaset
   openstack.cloud.quota:
diff --git a/roles/openstack_helm_octavia/vars/main.yml b/roles/openstack_helm_octavia/vars/main.yml
index e34a990..002101f 100644
--- a/roles/openstack_helm_octavia/vars/main.yml
+++ b/roles/openstack_helm_octavia/vars/main.yml
@@ -36,67 +36,59 @@
       octavia_api:
         octavia_api:
           volumeMounts:
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/private/cakey.pem"
-              subPath: "cakey.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/ca_01.pem"
-              subPath: "ca_01.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/client.pem"
-              subPath: "client.pem"
+            - name: octavia-server-ca
+              mountPath: /etc/octavia/certs/server
+            - name: octavia-client-certs
+              mountPath: /etc/octavia/certs/client
           volumes:
-            - name: octavia-certs
+            - name: octavia-server-ca
               secret:
-                secretName: octavia-certs
+                secretName: octavia-server-ca
+            - name: octavia-client-certs
+              secret:
+                secretName: octavia-client-certs
       octavia_worker:
         octavia_worker:
           volumeMounts:
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/private/cakey.pem"
-              subPath: "cakey.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/ca_01.pem"
-              subPath: "ca_01.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/client.pem"
-              subPath: "client.pem"
+            - name: octavia-server-ca
+              mountPath: /etc/octavia/certs/server
+            - name: octavia-client-certs
+              mountPath: /etc/octavia/certs/client
           volumes:
-            - name: octavia-certs
+            - name: octavia-server-ca
               secret:
-                secretName: octavia-certs
+                secretName: octavia-server-ca
+            - name: octavia-client-certs
+              secret:
+                secretName: octavia-client-certs
       octavia_housekeeping:
         octavia_housekeeping:
           volumeMounts:
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/private/cakey.pem"
-              subPath: "cakey.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/ca_01.pem"
-              subPath: "ca_01.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/client.pem"
-              subPath: "client.pem"
+            - name: octavia-server-ca
+              mountPath: /etc/octavia/certs/server
+            - name: octavia-client-certs
+              mountPath: /etc/octavia/certs/client
           volumes:
-            - name: octavia-certs
+            - name: octavia-server-ca
               secret:
-                secretName: octavia-certs
+                secretName: octavia-server-ca
+            - name: octavia-client-certs
+              secret:
+                secretName: octavia-client-certs
       octavia_health_manager:
         octavia_health_manager:
           volumeMounts:
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/private/cakey.pem"
-              subPath: "cakey.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/ca_01.pem"
-              subPath: "ca_01.pem"
-            - name: octavia-certs
-              mountPath: "/etc/octavia/certs/client.pem"
-              subPath: "client.pem"
+            - name: octavia-server-ca
+              mountPath: /etc/octavia/certs/server
+            - name: octavia-client-certs
+              mountPath: /etc/octavia/certs/client
           volumes:
-            - name: octavia-certs
+            - name: octavia-server-ca
               secret:
-                secretName: octavia-certs
+                secretName: octavia-server-ca
+            - name: octavia-client-certs
+              secret:
+                secretName: octavia-client-certs
     replicas:
       api: 3
       worker: 3
@@ -106,6 +98,8 @@
       DEFAULT:
         log_config_append: null
       certificates:
+        ca_certificate: /etc/octavia/certs/server/ca.crt
+        ca_private_key: /etc/octavia/certs/server/tls.key
         ca_private_key_passphrase: null
         endpoint_type: internalURL
       cinder:
@@ -116,9 +110,13 @@
         amp_image_owner_id: "{{ _openstack_helm_octavia_amphora_image.image.owner }}"
         amp_secgroup_list: "{{ _openstack_helm_octavia_amphora_sg.id }}"
         amp_ssh_key_name: null
+        client_ca: /etc/octavia/certs/client/ca.crt
         workers: 4
       glance:
         endpoint_type: internalURL
+      haproxy_amphora:
+        client_cert: /etc/octavia/certs/client/tls-combined.pem
+        server_ca: /etc/octavia/certs/server/ca.crt
       health_manager:
         controller_ip_port_list: "{{ _openstack_helm_octavia_controller_ip_port_list | join(',') }}"
         heartbeat_key: "{{ openstack_helm_octavia_heartbeat_key }}"