From edf5687aa0d2093681e1c4ffb00589a32314108b Mon Sep 17 00:00:00 2001 From: metamben <103100869+metamben@users.noreply.github.com> Date: Mon, 6 Jun 2022 21:50:20 +0300 Subject: [PATCH] Properly decode uploaded Postgres SSL fields (#23176) Fixes #22626. --- src/metabase/models/secret.clj | 13 ++++--- test/metabase/models/secret_test.clj | 51 ++++++++++++++++++---------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/metabase/models/secret.clj b/src/metabase/models/secret.clj index c17e862fa09..0e0402ae143 100644 --- a/src/metabase/models/secret.clj +++ b/src/metabase/models/secret.clj @@ -100,7 +100,7 @@ (.write out v))) tmp-file))) -(def ^:private uploaded-base-64-prefix "data:application/x-x509-ca-cert;base64,") +(def ^:private uploaded-base-64-pattern #"^data:application/([^;]*);base64,") (defn db-details-prop->secret-map "Returns a map containing `:value` and `:source` for the given `conn-prop-nm`. `conn-prop-nm` is expected to be the @@ -126,9 +126,14 @@ id-kw (sub-prop "-id") value (cond ;; ssl-root-certs will need their prefix removed, and to be base 64 decoded (#20319) - (and (value-kw details) (= "ssl-root-cert" conn-prop-nm) - (str/starts-with? (value-kw details) uploaded-base-64-prefix)) - (-> (value-kw details) (str/replace-first uploaded-base-64-prefix "") u/decode-base64) + (and (value-kw details) (#{"ssl-client-cert" "ssl-root-cert"} conn-prop-nm) + (re-find uploaded-base-64-pattern (value-kw details))) + (-> (value-kw details) (str/replace-first uploaded-base-64-pattern "") u/decode-base64) + + (and (value-kw details) (#{"ssl-key"} conn-prop-nm) + (re-find uploaded-base-64-pattern (value-kw details))) + (.decode (java.util.Base64/getDecoder) + (str/replace-first (value-kw details) uploaded-base-64-pattern "")) ;; the -value suffix was specified; use that (value-kw details) diff --git a/test/metabase/models/secret_test.clj b/test/metabase/models/secret_test.clj index a5e6f2d666a..1f765204d10 100644 --- a/test/metabase/models/secret_test.clj +++ b/test/metabase/models/secret_test.clj @@ -75,21 +75,38 @@ (.readFully in result)) result)))))))))) -(deftest ssl-root-cert-base +(defn- decode-ssl-db-property [content mime-type property] + (let [value-key (keyword (str property "-value")) + options-key (keyword (str property "-options"))] + (:value (secret/db-details-prop->secret-map + {:ssl true + :ssl-mode "verify-ca" + value-key (format "data:%s;base64,%s" mime-type (u/encode-base64 content)) + options-key "uploaded" + :port 5432, + :advanced-options false + :dbname "the-bean-base" + :host "localhost" + :tunnel-enabled false + :engine :postgres + :user "human-bean"} + property)))) + +(deftest ssl-cert-base (testing "db-details-prop->secret-map" - (testing "decodes root cert value properly (#20319)" - (is (= "<Certificate text goes here>" - (:value (secret/db-details-prop->secret-map - {:ssl true - :ssl-mode "verify-ca" - :ssl-root-cert-value (str "data:application/x-x509-ca-cert;base64," - (u/encode-base64 "<Certificate text goes here>")) - :ssl-root-cert-options "uploaded" - :port 5432, - :advanced-options false - :dbname "the-bean-base" - :host "localhost" - :tunnel-enabled false - :engine :postgres - :user "human-bean"} - "ssl-root-cert"))))))) + (let [content "<Certificate text goes here>" + mime-types ["application/x-x509-ca-cert" "application/octet-stream"]] + (testing "decodes root cert value properly (#20319, #22626)" + (doseq [property ["ssl-root-cert" "ssl-client-cert"] + mime-type mime-types] + (testing (format "property %s with mime-type %s" property mime-type) + (is (= content + (decode-ssl-db-property content mime-type property)))))) + (testing "decodes client key value properly (#22626)" + (doseq [property ["ssl-key"] + mime-type mime-types] + (testing (format "property %s with mime-type %s" property mime-type) + (let [decoded (decode-ssl-db-property content mime-type property)] + (is (instance? (Class/forName "[B") decoded)) + (is (= content + (String. decoded "UTF-8")))))))))) -- GitLab