diff --git a/src/main/cljc/dda/c4k_website/website.cljc b/src/main/cljc/dda/c4k_website/website.cljc index 4c121a9..bd7b74b 100644 --- a/src/main/cljc/dda/c4k_website/website.cljc +++ b/src/main/cljc/dda/c4k_website/website.cljc @@ -16,7 +16,7 @@ [input] (every? true? (map pred/fqdn-string? input))) -(s/def ::uname pred/fqdn-string?) +(s/def ::unique-name pred/fqdn-string?) (s/def ::issuer pred/letsencrypt-issuer?) (s/def ::authtoken pred/bash-env-string?) (s/def ::fqdns fqdn-list?) @@ -25,38 +25,17 @@ (s/def ::branchname string?) (s/def ::username string?) -(def websitedata? (s/keys :req-un [::uname ::fqdns ::gitea-host ::gitea-repo ::branchname] - :opt-un [::issuer])) +(def websitedata? (s/keys :req-un [::unique-name ::fqdns ::gitea-host ::gitea-repo ::branchname] + :opt-un [::issuer])) -(def websiteauth? (s/keys :req-un [::authtoken ::username])) +(def websiteauth? (s/keys :req-un [::unique-name ::username ::authtoken])) -(defn auth-data-list? - [input] - (every? #(and - (map? %) - (and (s/valid? ::uname (% :uname)) (contains? % :uname)) - (and (s/valid? ::username (% :username)) (contains? % :username)) - (and (s/valid? ::authtoken (% :authtoken)) (contains? % :authtoken))) input)) +(s/def ::auth (s/coll-of websiteauth?)) -(s/def ::auth auth-data-list?) +(s/def ::websites (s/coll-of websitedata?)) (def auth? (s/keys :req-un [::auth])) -(defn website-data-list? - [input] - (every? #(and - (map? %) - (and (s/valid? ::uname (% :uname)) (contains? % :uname)) - (and (s/valid? ::fqdns (% :fqdns)) (contains? % :fqdns)) - (and (s/valid? ::gitea-host (% :gitea-host)) (contains? % :gitea-host)) - (and (s/valid? ::gitea-repo (% :gitea-repo)) (contains? % :gitea-repo)) - (and (s/valid? ::branchname (% :branchname)) (contains? % :branchname))) input)) - -(defn websites? [input] - (and (contains? input :websites) (website-data-list? (input :websites))) ) - -(s/def ::websites website-data-list?) - (def config? (s/keys :req-un [::websites] :opt-un [::issuer])) @@ -67,20 +46,20 @@ (str/replace fqdn #"\." "-")) (defn generate-service-name - [uname] - (str (unique-name-from-fqdn uname) "-service")) + [unique-name] + (str (unique-name-from-fqdn unique-name) "-service")) (defn generate-cert-name - [uname] - (str (unique-name-from-fqdn uname) "-cert")) + [unique-name] + (str (unique-name-from-fqdn unique-name) "-cert")) (defn generate-http-ingress-name - [uname] - (str (unique-name-from-fqdn uname) "-http-ingress")) + [unique-name] + (str (unique-name-from-fqdn unique-name) "-http-ingress")) (defn generate-https-ingress-name - [uname] - (str (unique-name-from-fqdn uname) "-https-ingress")) + [unique-name] + (str (unique-name-from-fqdn unique-name) "-https-ingress")) ; https://your.gitea.host/api/v1/repos///archive/main.zip (defn make-gitrepourl @@ -123,6 +102,7 @@ (mapv #(assoc-in rule [:host] %) fqdns)) ;create working ingress +; todo: move to common/ingress (defn generate-common-http-ingress [config] (let [{:keys [fqdn service-name]} config] @@ -133,12 +113,12 @@ (defn-spec generate-website-http-ingress pred/map-or-seq? [config websitedata?] - (let [{:keys [uname fqdns]} config + (let [{:keys [unique-name fqdns]} config spec-rules [:spec :rules]] (-> (generate-common-http-ingress - {:fqdn (first fqdns) :service-name (generate-service-name uname)}) - (cm/replace-all-matching-values-by-new-value "c4k-common-http-ingress" (generate-http-ingress-name uname)) + {:fqdn (first fqdns) :service-name (generate-service-name unique-name)}) + (cm/replace-all-matching-values-by-new-value "c4k-common-http-ingress" (generate-http-ingress-name unique-name)) (#(assoc-in % spec-rules (make-host-rules-from-fqdns @@ -156,14 +136,14 @@ (defn-spec generate-website-https-ingress pred/map-or-seq? [config websitedata?] - (let [{:keys [uname fqdns]} config + (let [{:keys [unique-name fqdns]} config spec-rules [:spec :rules] spec-tls-hosts [:spec :tls 0 :hosts]] (-> (generate-common-https-ingress - {:fqdn (first fqdns) :service-name (generate-service-name uname)}) - (cm/replace-all-matching-values-by-new-value "c4k-common-https-ingress" (generate-https-ingress-name uname)) - (cm/replace-all-matching-values-by-new-value "c4k-common-cert" (generate-cert-name uname)) + {:fqdn (first fqdns) :service-name (generate-service-name unique-name)}) + (cm/replace-all-matching-values-by-new-value "c4k-common-https-ingress" (generate-https-ingress-name unique-name)) + (cm/replace-all-matching-values-by-new-value "c4k-common-cert" (generate-cert-name unique-name)) (#(assoc-in % spec-tls-hosts fqdns)) (#(assoc-in % spec-rules (make-host-rules-from-fqdns (-> % :spec :rules first) fqdns)))))) @@ -179,20 +159,20 @@ (defn-spec generate-website-certificate pred/map-or-seq? [config websitedata?] - (let [{:keys [uname issuer fqdns]} config + (let [{:keys [unique-name issuer fqdns]} config spec-dnsNames [:spec :dnsNames]] (-> (generate-common-certificate {:issuer issuer, :fqdn (first fqdns)}) - (cm/replace-all-matching-values-by-new-value "c4k-common-cert" (generate-cert-name uname)) + (cm/replace-all-matching-values-by-new-value "c4k-common-cert" (generate-cert-name unique-name)) (assoc-in spec-dnsNames fqdns)))) (defn-spec generate-nginx-configmap pred/map-or-seq? [config websitedata?] - (let [{:keys [uname fqdns]} config] + (let [{:keys [unique-name fqdns]} config] (-> (yaml/load-as-edn "website/nginx-configmap.yaml") - (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname)) + (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn unique-name)) (#(assoc-in % [:data :website.conf] (str/replace @@ -200,43 +180,43 @@ (defn-spec generate-nginx-deployment pred/map-or-seq? [config websitedata?] - (let [{:keys [uname]} config] + (let [{:keys [unique-name]} config] (-> (yaml/load-as-edn "website/nginx-deployment.yaml") - (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) + (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn unique-name))))) (defn-spec generate-nginx-service pred/map-or-seq? [config websitedata?] - (let [{:keys [uname]} config] + (let [{:keys [unique-name]} config] (-> (yaml/load-as-edn "website/nginx-service.yaml") - (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) + (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn unique-name))))) (defn-spec generate-website-content-volume pred/map-or-seq? [config websitedata?] - (let [{:keys [uname]} config] + (let [{:keys [unique-name]} config] (-> (yaml/load-as-edn "website/website-content-volume.yaml") - (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname)) + (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn unique-name)) (cm/replace-all-matching-values-by-new-value "WEBSITESTORAGESIZE" (str (str volume-size) "Gi"))))) (defn-spec generate-website-build-cron pred/map-or-seq? [config websitedata?] - (let [{:keys [uname]} config] + (let [{:keys [unique-name]} config] (-> (yaml/load-as-edn "website/website-build-cron.yaml") - (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) + (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn unique-name))))) (defn-spec generate-website-build-deployment pred/map-or-seq? [config websitedata?] - (let [{:keys [uname]} config] + (let [{:keys [unique-name]} config] (-> (yaml/load-as-edn "website/website-build-deployment.yaml") - (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname))))) + (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn unique-name))))) (defn-spec generate-website-build-secret pred/map-or-seq? [auth websiteauth?] - (let [{:keys [uname + (let [{:keys [unique-name authtoken gitea-host gitea-repo @@ -244,7 +224,7 @@ branchname]} auth] (-> (yaml/load-as-edn "website/website-build-secret.yaml") - (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn uname)) + (replace-all-matching-subvalues-in-string-start "NAME" (unique-name-from-fqdn unique-name)) (cm/replace-all-matching-values-by-new-value "TOKEN" (b64/encode authtoken)) (cm/replace-all-matching-values-by-new-value "URL" (b64/encode (make-gitrepourl diff --git a/src/main/cljs/dda/c4k_website/browser.cljs b/src/main/cljs/dda/c4k_website/browser.cljs index af82de6..4e62b4b 100644 --- a/src/main/cljs/dda/c4k_website/browser.cljs +++ b/src/main/cljs/dda/c4k_website/browser.cljs @@ -32,12 +32,12 @@ (br/generate-input-field "issuer" "(Optional) Your issuer prod/staging:" "") (br/generate-text-area "websites" "A map containing fqdns and repo infos for each website:" - "[{:uname \"test.io \", + "[{:unique-name \"test.io \", :fqdns [\"test.de \" \"www.test.de \"], :gitea-host \"githost.de \", :gitea-repo \"repo \", :branchname \"main \"} - {:uname \"example.io \", + {:unique-name \"example.io \", :fqdns [\"example.org \" \"www.example.org \"], :gitea-host \"githost.org \", :gitea-repo \"repo \", @@ -48,10 +48,10 @@ (br/generate-text-area "auth" "Your authentication data for each website/ git repo:" "{:auth - [{:uname \"test.io\", + [{:unique-name \"test.io\", :username \"someuser\", :authtoken \"abedjgbasdodj\"} - {:uname \"example.io\", + {:unique-name \"example.io\", :username \"someuser\", :authtoken \"abedjgbasdodj\"}]}" "7")) diff --git a/src/test/cljc/dda/c4k_website/website_test.cljc b/src/test/cljc/dda/c4k_website/website_test.cljc index bb05c3d..4d04741 100644 --- a/src/test/cljc/dda/c4k_website/website_test.cljc +++ b/src/test/cljc/dda/c4k_website/website_test.cljc @@ -5,8 +5,8 @@ [clojure.spec.test.alpha :as st] [dda.c4k-common.test-helper :as th] [dda.c4k-common.base64 :as b64] - [dda.c4k-website.website :as cut] - [dda.c4k-website.core :as cutc])) + [dda.c4k-website.website :as cut] + [clojure.spec.alpha :as s])) (st/instrument `cut/generate-http-ingress) (st/instrument `cut/generate-https-ingress) @@ -19,6 +19,29 @@ (st/instrument `cut/generate-website-build-deployment) (st/instrument `cut/generate-website-build-secret) +(deftest should-be-valid-website-auth-spec + (is (true? (s/valid? cut/auth? {:auth + [{:unique-name "test.io" + :username "someuser" + :authtoken "abedjgbasdodj"} + {:unique-name "example.io" + :username "someuser" + :authtoken "abedjgbasdodj"}]})))) + +(deftest should-be-valid-website-conf-spec + (is (true? (s/valid? cut/config? {:issuer "staging" + :websites + [{:unique-name "test.io" ; + :fqdns ["test.de" "test.org" "www.test.de" "www.test.org"] + :gitea-host "gitlab.de" + :gitea-repo "repo" + :branchname "main"} + {:unique-name "example.io" + :fqdns ["example.org", "www.example.com"] + :gitea-host "finegitehost.net" + :gitea-repo "repo" + :branchname "main"}]})))) + (deftest should-generate-http-ingress (is (= {:apiVersion "networking.k8s.io/v1", :kind "Ingress", @@ -42,7 +65,11 @@ {:host "www.test-it.de", :http {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}]}} - (cut/generate-website-http-ingress {:uname "test.io" + (cut/generate-website-http-ingress {:unique-name "test.io" + :gitea-host "gitea.evilorg" + :gitea-repo "none" + :branchname "mablain" + :issuer "prod" :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))) (deftest should-generate-https-ingress @@ -67,18 +94,22 @@ {:host "www.test-it.de", :http {:paths [{:pathType "Prefix", :path "/", :backend {:service {:name "test-io-service", :port {:number 80}}}}]}}]}} - (cut/generate-website-https-ingress {:uname "test.io" + (cut/generate-website-https-ingress {:unique-name "test.io" + :gitea-host "gitea.evilorg" + :gitea-repo "none" + :branchname "mablain" + :issuer "prod" :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]})))) (deftest should-generate-website-certificate (is (= {:name-c1 "prod", :name-c2 "staging"} - (th/map-diff (cut/generate-website-certificate {:uname "test.io" + (th/map-diff (cut/generate-website-certificate {:unique-name "test.io" :gitea-host "gitea.evilorg" :gitea-repo "none" :branchname "mablain" :issuer "prod" :fqdns ["test.org" "test.de"]}) - (cut/generate-website-certificate {:uname "test.io" + (cut/generate-website-certificate {:unique-name "test.io" :gitea-host "gitea.evilorg" :gitea-repo "none" :branchname "mablain" @@ -90,12 +121,12 @@ :website.conf-c2 "server {\n listen 80 default_server;\n listen [::]:80 default_server;\n listen 443 ssl;\n ssl_certificate /etc/certs/tls.crt;\n ssl_certificate_key /etc/certs/tls.key;\n server_name example.de www.example.de example-by.de www.example-by.de; \n add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';\n add_header Content-Security-Policy \"default-src 'self'; font-src *;img-src * data:; script-src *; style-src *\";\n add_header X-XSS-Protection \"1; mode=block\";\n add_header X-Frame-Options \"SAMEORIGIN\";\n add_header X-Content-Type-Options nosniff;\n add_header Referrer-Policy \"strict-origin\";\n # add_header Permissions-Policy \"permissions here\";\n root /var/www/html/website/;\n index index.html;\n location / {\n try_files $uri $uri/ /index.html =404;\n }\n}\n", :name-c1 "test-io-configmap", :name-c2 "example-io-configmap"} - (th/map-diff (cut/generate-nginx-configmap {:uname "test.io", + (th/map-diff (cut/generate-nginx-configmap {:unique-name "test.io", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}) - (cut/generate-nginx-configmap {:uname "example.io", + (cut/generate-nginx-configmap {:unique-name "example.io", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", @@ -134,7 +165,7 @@ {:name "website-cert", :secret {:secretName "test-io-cert", :items [{:key "tls.crt", :path "tls.crt"} {:key "tls.key", :path "tls.key"}]}}]}}}} - (cut/generate-nginx-deployment {:uname "test.io", + (cut/generate-nginx-deployment {:unique-name "test.io", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", @@ -145,12 +176,12 @@ :name-c2 "test-org-service", :app-c1 "test-io-nginx", :app-c2 "test-org-nginx"} - (th/map-diff (cut/generate-nginx-service {:uname "test.io", + (th/map-diff (cut/generate-nginx-service {:unique-name "test.io", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}) - (cut/generate-nginx-service {:uname "test.org", + (cut/generate-nginx-service {:unique-name "test.org", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", @@ -177,7 +208,7 @@ :volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}], :volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}], :restartPolicy "OnFailure"}}}}}} - (cut/generate-website-build-cron {:uname "test.io", + (cut/generate-website-build-cron {:unique-name "test.io", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", @@ -203,7 +234,7 @@ :envFrom [{:secretRef {:name "test-io-secret"}}], :volumeMounts [{:name "content-volume", :mountPath "/var/www/html/website"}]}], :volumes [{:name "content-volume", :persistentVolumeClaim {:claimName "test-io-content-volume"}}]}}}} - (cut/generate-website-build-deployment {:uname "test.io", + (cut/generate-website-build-deployment {:unique-name "test.io", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", @@ -216,13 +247,13 @@ :AUTHTOKEN-c2 (b64/encode "token2"), :GITREPOURL-c1 (b64/encode "https://gitlab.org/api/v1/repos/dumpty/websitebau/archive/testname.zip"), :GITREPOURL-c2 (b64/encode "https://github.com/api/v1/repos/humpty/websitedachs/archive/testname.zip")} - (th/map-diff (cut/generate-website-build-secret {:uname "test.io", + (th/map-diff (cut/generate-website-build-secret {:unique-name "test.io", :authtoken "token1", :gitea-host "gitlab.org", :gitea-repo "websitebau", :username "dumpty", :branchname "testname"}) - (cut/generate-website-build-secret {:uname "test.org", + (cut/generate-website-build-secret {:unique-name "test.org", :authtoken "token2", :gitea-host "github.com", :gitea-repo "websitedachs", @@ -234,12 +265,12 @@ :name-c2 "test-org-content-volume", :app-c1 "test-io-nginx", :app-c2 "test-org-nginx"} - (th/map-diff (cut/generate-website-content-volume {:uname "test.io", + (th/map-diff (cut/generate-website-content-volume {:unique-name "test.io", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", :fqdns ["test.de" "www.test.de" "test-it.de" "www.test-it.de"]}) - (cut/generate-website-content-volume {:uname "test.org", + (cut/generate-website-content-volume {:unique-name "test.org", :gitea-host "gitea.evilorg", :gitea-repo "none", :branchname "mablain", diff --git a/valid-auth.edn b/valid-auth.edn index 9cf7db6..f8766c0 100644 --- a/valid-auth.edn +++ b/valid-auth.edn @@ -1,7 +1,7 @@ {:auth - [{:uname "meissa.io" + [{:unique-name "test.io" :username "someuser" :authtoken "abedjgbasdodj"} - {:uname "dda.io" + {:unique-name "example.io" :username "someuser" :authtoken "abedjgbasdodj"}]} diff --git a/valid-config.edn b/valid-config.edn index 1102e34..1302435 100644 --- a/valid-config.edn +++ b/valid-config.edn @@ -1,14 +1,12 @@ {:issuer "staging" :websites - [{:uname "meissa.io" - :fqdns ["meissa.de" "meissa-gmbh.de" "www.meissa-gmbh.de" - "www.meissa.de" "www.prod.meissa-gmbh.de" "www.prod.meissa.de"] - :gitea-host "repo.prod.meissa.de" + [{:unique-name "test.io" ; todo: call this unique-name + :fqdns ["test.de" "test.org" "www.test.de" "www.test.org"] + :gitea-host "gitlab.de" :gitea-repo "repo" :branchname "main"} - {:uname "dda.io" - :fqdns ["domaindrivenarchitecture.org", "www.domaindrivenarchitecture.org", - "www.prod.domaindrivenarchitecture.org"] - :gitea-host "repo.prod.meissa.de" + {:unique-name "example.io" + :fqdns ["example.org", "www.example.com"] + :gitea-host "finegitehost.net" :gitea-repo "repo" :branchname "main"}]}