diff --git a/infra/ansible/roles/haproxy/files/selfsigned.pem b/infra/ansible/roles/haproxy/files/selfsigned.pem new file mode 100644 index 000000000..596ac15b1 --- /dev/null +++ b/infra/ansible/roles/haproxy/files/selfsigned.pem @@ -0,0 +1,50 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCgyerZjp1+RxU8 +/bISXduo8OjR2ejl5SD034PyQvT5B9tk83yplplHoG+JL78UGqpflPlhU9fQSoT9 +Walusf/MDDCEbQ75sjPui+yNuvcgWkmpN0MUdOHR8gvfiADCR6/eDQuRf7JJh5N8 +YdCtLtnOYsha7Bix+bN11GO6XzPG869I/UGdg4g0v7LvDCP3tI0tpno+y4MuiDvJ +R1pQd7sl6jxPp4zvNtVw8vrSVA3qJ8G6F78nnPUUPFnrAlUFNcnMVLamxY0IA3H4 +n9o7X73RnphrpcnPr6eyEYxOL0UGhsDMsQxTrhSaOErL68QDTk3hV60SxWqsVlxX +/DoKAb9VAgMBAAECggEAenTt6V3Fsxv+H+Jz0assFYHNP63/w797FyR4QHUgT93d +CQisRBjPio61A72agHxCj+NM/wQ1FIz8tluoQAdO8x/Bf8nzotZG2QI2Wkcv2bMJ +8NeGvji6mAQJaOgS8+RXG/3BdsHTjk60VAHHRW6uMZJoV18C++FZ/X6RqarCK13N +UEfHX529qNvLhw+xkjXFW/qiB3dQTTEJq+9y0U4nGrjZCXtspkXN3g6ETU6Svzhq +z4tq0udC7FjZPqdA79ChXweZlDCq89FQfxAnxRoZAiwymK91VrGz/GyMIwdBPidm ++or8Rk6nodKk8AuwsGE6ub9UhWUS+Kdpl9fNcV1jLQKBgQDRA7D786sf25tgyooF +6IMZwQfHWGmIepUPruHLz5aV6ozO8XQBgEN4XBI15mxJTu+eeXGbqOhwwuhvYR9u +G02qPE0OlftBRnBJp2AH5+gRphLyrRAvgnjVw323ucnsjOzO0TPwdehomKC0J3b9 +B+hZ2tKW/nNxqX/iU1ue969lAwKBgQDE7vJnppvAZLSMo4PCtBTJm11u58AZ9LyZ +6dxvpiq6XxPw9DcC2gj91pCST2g4vIqDYQgmh5U3RzMIFsKLtKfDvHEAYbFOnEfz +UXoNFjlCEmB2jHgpn51/ZDokpPSF9MooDUFna0JPaUrduHs8Zzv7kfrsAhq2N++C +eB+jMea+xwKBgESDzEFbB85io5Vf70yugkMv9ofPIJD/ddt1PUkdHES6ZTv1BEz1 +qahLriCDDx4cxQmSz73x6XgFPEI+eRoT0yqpp6zPV1R3bZmHR0BwMa+PXAi22GZq +g4e3FH/kZB+ptnq5MyhwziVzWsKTaTram7zQsVWTxW4N3QDoyFDc6l7XAoGBAI85 ++bLIyZ4zn9xpT/rbXgMCrAFtK5m1FTYbj+bjw0+otqgX9aptSPzUgHDor7QT6+mB +OJxNH4kEj2jipLtWuGzzMHxGkN3La8jbCRlbgGk9VErj/sDHBZURH/hmwDBsyFo4 +ycidiayXt4tqELbtngJpOUVMgoDkTZ1mIBxgvqEhAoGBAK6uX4k2xiOQorpByvjd +gT16MbuntXO/bDXnXaq1keNMr1JzQ5aS346XweiUgRG7ZJdEb2C8sXwSmh2+oeGa +G+QCLH73hwo/PWbU560dFY8s6z5E79WBjYUu5+1/a0SCBwQ4mEVB7REQVY1mQoJT +A+A8WW+EDvaPpVFujA26K3fc +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIUbgZuZRFj8M8ZcdhRFikB2bJKswYwDQYJKoZIhvcNAQEL +BQAwVjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE +CgwTRGVmYXVsdCBDb21wYW55IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIy +MDQwODEwMTA0OFoXDTQ5MDgyNDEwMTA0OFowVjELMAkGA1UEBhMCWFgxFTATBgNV +BAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDES +MBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAoMnq2Y6dfkcVPP2yEl3bqPDo0dno5eUg9N+D8kL0+QfbZPN8qZaZR6BviS+/ +FBqqX5T5YVPX0EqE/VmpbrH/zAwwhG0O+bIz7ovsjbr3IFpJqTdDFHTh0fIL34gA +wkev3g0LkX+ySYeTfGHQrS7ZzmLIWuwYsfmzddRjul8zxvOvSP1BnYOINL+y7wwj +97SNLaZ6PsuDLog7yUdaUHe7Jeo8T6eM7zbVcPL60lQN6ifBuhe/J5z1FDxZ6wJV +BTXJzFS2psWNCANx+J/aO1+90Z6Ya6XJz6+nshGMTi9FBobAzLEMU64UmjhKy+vE +A05N4VetEsVqrFZcV/w6CgG/VQIDAQABo1MwUTAdBgNVHQ4EFgQUJZDike5gfaOV +k8uCwfCh2OrPXd0wHwYDVR0jBBgwFoAUJZDike5gfaOVk8uCwfCh2OrPXd0wDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQbXAIBoDHQakksvKGo3X +/bIyc+IQKFpsyWrn5GvS69wTE7XBfKLtyY3X8NygvsCaRx0r2OIdVERNjrhELkes +tWQE17D1+tDnsaEQRUNJsjBYmealNPpqqacdRlBNnkTSGM/3d3m/ihlA51A1QzyI +IOtKxRRIZ+24L/eww5Hv96ub3Wu4rVmepXP4cVIcPEnN6ntmOv4Ja/M83hLI2oXy +4XmXOVsyliYDGWiyvT2U3LcRsv9PHr09SqYO/5yW+fYC7diLGSHW0kfwht2Q8Zqg +IFMJMDmmKTbCWCmFYdoVTRm2fFl0YvgpC5JrXuSloHh3hRiLwDIUiTxlTM3JDP8q +PQ== +-----END CERTIFICATE----- diff --git a/infra/ansible/roles/haproxy/tasks/main.yml b/infra/ansible/roles/haproxy/tasks/main.yml index f081d37d6..e547a63ae 100644 --- a/infra/ansible/roles/haproxy/tasks/main.yml +++ b/infra/ansible/roles/haproxy/tasks/main.yml @@ -29,42 +29,25 @@ # Chicken-and-egg : haproxy.cfg.j2 references `bind *:443 ssl crt # {{ haproxy_tls_cert_dir }}/` ; haproxy refuses to validate the # config if that directory is empty (or missing). dehydrated creates -# real LE certs there LATER (in letsencrypt.yml). To break the cycle, -# pre-create the dir with a 30-day self-signed placeholder cert. -# The placeholder is overwritten / shadowed once dehydrated lands ; -# SNI picks the matching real cert. -- name: Ensure TLS cert dir + placeholder cert exist (gates the haproxy.cfg validate) - when: haproxy_letsencrypt | default(false) - block: - - name: Ensure {{ haproxy_tls_cert_dir }} exists - ansible.builtin.file: - path: "{{ haproxy_tls_cert_dir }}" - state: directory - owner: root - group: haproxy - mode: "0750" +# real LE certs there LATER (in letsencrypt.yml). Break the cycle +# the same way the working roles in +# /home/senke/Documents/TG__Talas_Group/.../roles/haproxy do : ship a +# checked-in `selfsigned.pem` and copy it into the cert dir. +# Once dehydrated lands real certs alongside, SNI picks the matching +# real cert ; selfsigned.pem only matches CN=localhost (harmless). +- name: Ensure {{ haproxy_tls_cert_dir }} exists + ansible.builtin.file: + path: "{{ haproxy_tls_cert_dir }}" + state: directory + mode: "0755" + tags: [haproxy, config] - - name: Generate self-signed placeholder cert if dir is empty - ansible.builtin.shell: | - set -e - if ls "{{ haproxy_tls_cert_dir }}"/*.pem >/dev/null 2>&1; then - echo "cert already present" - exit 0 - fi - openssl req -x509 -nodes -newkey rsa:2048 \ - -keyout /tmp/_placeholder.key \ - -out /tmp/_placeholder.crt \ - -days 30 \ - -subj '/CN=placeholder.veza.local' >/dev/null 2>&1 - cat /tmp/_placeholder.crt /tmp/_placeholder.key \ - > "{{ haproxy_tls_cert_dir }}/_placeholder.pem" - chmod 0640 "{{ haproxy_tls_cert_dir }}/_placeholder.pem" - chown root:haproxy "{{ haproxy_tls_cert_dir }}/_placeholder.pem" - rm -f /tmp/_placeholder.key /tmp/_placeholder.crt - echo "placeholder cert generated" - register: placeholder_cert - changed_when: "'placeholder cert generated' in placeholder_cert.stdout" - tags: [haproxy, config, letsencrypt] +- name: Drop selfsigned.pem so haproxy can validate the cfg + ansible.builtin.copy: + src: selfsigned.pem + dest: "{{ haproxy_tls_cert_dir }}/selfsigned.pem" + mode: "0640" + tags: [haproxy, config] - name: Render haproxy.cfg ansible.builtin.template: