From 911872b43a87967b0f1ac4bb13b97790b08dd36b Mon Sep 17 00:00:00 2001
From: Christian Elberfeld <elberfeld@web.de>
Date: Tue, 21 Feb 2023 22:55:26 +0100
Subject: [PATCH] =?UTF-8?q?Erweiterung=20traefik=20Rolle=20f=C3=BCr=20Zert?=
 =?UTF-8?q?ifikatserzeugung?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 common/docker_traefik/tasks/certificate.yml   | 84 +++++++++++++++++++
 common/docker_traefik/tasks/main.yml          | 14 +++-
 .../templates/docker-compose.yml              |  8 +-
 .../docker_traefik/templates/dynamic/tls.yml  |  6 +-
 common/docker_traefik/templates/traefik.yml   |  4 +
 5 files changed, 108 insertions(+), 8 deletions(-)
 create mode 100644 common/docker_traefik/tasks/certificate.yml

diff --git a/common/docker_traefik/tasks/certificate.yml b/common/docker_traefik/tasks/certificate.yml
new file mode 100644
index 00000000..b32f1c8a
--- /dev/null
+++ b/common/docker_traefik/tasks/certificate.yml
@@ -0,0 +1,84 @@
+
+# Eigene CA und Server Zertifikat erstellen, falls diese noch nicht existiert   
+
+- name: "Install Packages"
+  apt:
+    name: "{{ packages }}"
+    state: present
+  vars:
+    packages:
+      - python3-cryptography
+
+
+- name: "Check if SelfSigned CA key exists"
+  stat:
+    path: "{{ basedir }}/ca.key"
+  register: ca_key_stat_result
+
+- name: "Create SelfSigned CA key"
+  community.crypto.openssl_privatekey:
+    path: "{{ basedir }}/ca.key"
+  when: not ca_key_stat_result.stat.exists
+
+- name: "Check if SelfSigned CA cert exists"
+  stat:
+    path: "{{ basedir }}/ca.pem"
+  register: ca_cert_stat_result
+
+- name: "Check if SelfSigned CA cert CSR"
+  community.crypto.openssl_csr_pipe:
+    privatekey_path: "{{ basedir }}/ca.key"
+    common_name: "{{ selfSignedCN }} CA"
+    use_common_name_for_san: false  # since we do not specify SANs, don't use CN as a SAN
+    basic_constraints:
+      - 'CA:TRUE'
+    basic_constraints_critical: true
+    key_usage:
+      - keyCertSign
+    key_usage_critical: true
+  register: ca_csr
+  when: not ca_cert_stat_result.stat.exists
+
+- name: "Create SelfSigned CA cert from CSR"
+  community.crypto.x509_certificate:
+    path: "{{ basedir }}/ca.pem"
+    csr_content: "{{ ca_csr.csr }}"
+    privatekey_path: "{{ basedir }}/ca.key"
+    provider: selfsigned
+  when: not ca_cert_stat_result.stat.exists
+
+
+- name: "Check if ServerCert key exists"
+  stat:
+    path: "{{ basedir }}/cert.key"
+  register: cert_key_stat_result
+
+- name: "Create ServerCert key"
+  community.crypto.openssl_privatekey:
+    path: "{{ basedir }}/cert.key"
+  when: not cert_key_stat_result.stat.exists
+
+- name: "Check if ServerCert cert exists"
+  stat:
+    path: "{{ basedir }}/cert.pem"
+  register: cert_cert_stat_result
+
+- name: "Create ServerCert CSR"
+  community.crypto.openssl_csr_pipe:
+    privatekey_path: "{{ basedir }}/cert.key"
+    subject_alt_name:
+      - "DNS:{{ selfSignedDomain }}"
+      - "DNS:{{ domain }}"
+  register: cert_csr
+  when: not cert_cert_stat_result.stat.exists
+
+- name: "Create ServerCert from CSR"
+  community.crypto.x509_certificate:
+    path: "{{ basedir }}/cert.pem"
+    csr_content: "{{ cert_csr.csr }}"
+    provider: ownca
+    ownca_path: "{{ basedir }}/ca.pem"
+    ownca_privatekey_path: "{{ basedir }}/ca.key"
+    ownca_not_after: +9999d  # long lifetime 
+    ownca_not_before: "-1d"  # valid since yesterday
+  when: not cert_cert_stat_result.stat.exists
diff --git a/common/docker_traefik/tasks/main.yml b/common/docker_traefik/tasks/main.yml
index 4785cfad..a13407e7 100644
--- a/common/docker_traefik/tasks/main.yml
+++ b/common/docker_traefik/tasks/main.yml
@@ -1,7 +1,8 @@
-       
+
 - include: ../functions/get_secret.yml
   with_items:
     - { path: "{{ basedir }}/letsencrypt_notification_email",  length: -1 }
+  when: selfSignedCN is not defined 
 
 - name: "create folder struct for {{ servicename }}"
   file:
@@ -11,6 +12,11 @@
     - "{{ basedir }}"
     - "{{ basedir }}/dynamic"
 
+- name: "Check if CertStore exists"
+  stat:
+    path: "{{ basedir }}/acme.json"
+  register: acme_stat_result
+
 - name: "Create CertStore if needed and set permissions"
   file:
     path: "{{ basedir }}/acme.json"
@@ -18,6 +24,12 @@
     group: root
     mode: '600'
     state: touch
+  when: not acme_stat_result.stat.exists
+
+- name: "Create SelfSigned CA and Cert"
+  ansible.builtin.include_tasks: certificate.yml
+  when: selfSignedCN is defined 
+  
 
 - name: Docker Compose Konfig-Datei erstellen
   template:
diff --git a/common/docker_traefik/templates/docker-compose.yml b/common/docker_traefik/templates/docker-compose.yml
index abf80734..478f3210 100644
--- a/common/docker_traefik/templates/docker-compose.yml
+++ b/common/docker_traefik/templates/docker-compose.yml
@@ -10,15 +10,15 @@ services:
             - "443:443"
 {% if matrix_federation is defined and matrix_federation == true %}            - "8448:8448"
 {% endif %}
-            - "{{ int_ip4 }}:8081:8080"
+            - "{{ int_ip4 }}:8080:8080"
         volumes:
             - "/srv/traefik/traefik.yml:/etc/traefik/traefik.yml:ro"
             - "/srv/traefik/dynamic:/etc/traefik/dynamic:ro"
             - "/srv/traefik/acme.json:/acme.json"
             - "/var/run/docker.sock:/var/run/docker.sock"
-{% if certFile is defined %}
-            - "{{ basedir }}/{{ certFile }}:/{{ certFile }}:ro"
-            - "{{ basedir }}/{{ keyFile }}:/{{ keyFile }}:ro"
+{% if selfSignedCN is defined %}
+            - "{{ basedir }}/cert.pem:/cert.pem:ro"
+            - "{{ basedir }}/cert.key:/cert.key:ro"
 {% endif %}
         networks:
             - default
diff --git a/common/docker_traefik/templates/dynamic/tls.yml b/common/docker_traefik/templates/dynamic/tls.yml
index 787dabae..e372473f 100644
--- a/common/docker_traefik/templates/dynamic/tls.yml
+++ b/common/docker_traefik/templates/dynamic/tls.yml
@@ -2,12 +2,12 @@
 # TLS Options 
 tls:
 
-{% if certFile is defined %}
+{% if selfSignedCN is defined %}
 
     # use local certificate 
     certificates:
-        - certFile: "/{{ certFile }}"
-          keyFile: "/{{ keyFile }}"
+        - certFile: "/cert.pem"
+          keyFile: "/cert.key"
 
 {% endif %}
 
diff --git a/common/docker_traefik/templates/traefik.yml b/common/docker_traefik/templates/traefik.yml
index 9c0e2027..f96aa28e 100644
--- a/common/docker_traefik/templates/traefik.yml
+++ b/common/docker_traefik/templates/traefik.yml
@@ -73,6 +73,8 @@ log:
     format: "common"
 
 
+{% if selfSignedCN is not defined %}
+
 # get certificates from letsEncrypt 
 certificatesResolvers:
     letsencrypt:
@@ -80,3 +82,5 @@ certificatesResolvers:
             email: "{{ letsencrypt_notification_email }}"
             storage: "/acme.json"
             tlsChallenge: true
+
+{% endif %}
-- 
GitLab