Skip to content
Snippets Groups Projects
Unverified Commit 1647552d authored by john-metabase's avatar john-metabase Committed by GitHub
Browse files

Fix Snowflake sync with uploaded private key (#31593)

parent d46c82f5
No related merge requests found
......@@ -10,7 +10,7 @@ driver:
connection-properties:
- name: account
display-name: Account name
helper-text: Enter your Account ID with the region that your Snowflake cluster is running on e.g. "xxxxxxxx.us-east-2.aws". Some regions don't have this suffix.
helper-text: Enter your Account ID with the region that your Snowflake cluster is running on e.g. "xxxxxxxx.us-east-2.aws". Some regions don't have this suffix.
placeholder: xxxxxxxx.us-east-2.aws
required: true
- user
......
......@@ -20,7 +20,6 @@
[metabase.driver.sql.util :as sql.u]
[metabase.driver.sql.util.unprepare :as unprepare]
[metabase.driver.sync :as driver.s]
[metabase.driver.util :as driver.u]
[metabase.models.secret :as secret]
[metabase.query-processor.error-type :as qp.error-type]
[metabase.query-processor.store :as qp.store]
......@@ -34,7 +33,6 @@
[ring.util.codec :as codec])
(:import
(java.io File)
(java.nio.charset StandardCharsets)
(java.sql Connection DatabaseMetaData ResultSet Types)
(java.time OffsetDateTime ZonedDateTime)))
......@@ -76,34 +74,37 @@
{:user (codec/url-encode user)
:private_key_file (codec/url-encode (.getCanonicalPath ^File private-key-file))})
new-conn-uri (sql-jdbc.common/conn-str-with-additional-opts existing-conn-uri :url opts-str)]
(assoc details :connection-uri new-conn-uri)))
(-> details
(assoc :connection-uri new-conn-uri)
;; The Snowflake driver uses the :account property, but we need to drop the region from it first
(assoc :account (first (str/split account #"\."))))))
(defn- resolve-private-key
"Convert the private-key secret properties into a private_key_file property in `details`.
Setting the Snowflake driver property privatekey would be easier, but that doesn't work
because clojure.java.jdbc (properly) converts the property values into strings while the
Snowflake driver expects a java.security.PrivateKey instance."
[{:keys [user password account private-key-value private-key-path] :as details}]
(cond
password
details
private-key-path
(let [secret-map (secret/db-details-prop->secret-map details "private-key")
private-key-file (when (some? (:value secret-map))
(secret/value->file! secret-map :snowflake))]
(cond-> (apply dissoc details (vals (secret/get-sub-props "private-key")))
private-key-file (handle-conn-uri user account private-key-file)))
private-key-value
(let [private-key-str (if (bytes? private-key-value)
(String. ^bytes private-key-value StandardCharsets/UTF_8)
private-key-value)
private-key-file-val (cond-> private-key-str
(re-find driver.u/data-url-pattern private-key-str) driver.u/decode-uploaded)
private-key-file (secret/value->file! {:connection-property-name "private-key-file"
:value private-key-file-val})]
(handle-conn-uri details user account private-key-file))))
[{:keys [user password account private-key-path]
:as details}]
(let [base-details (apply dissoc details (vals (secret/get-sub-props "private-key")))]
(cond
password
details
private-key-path
(let [secret-map (secret/db-details-prop->secret-map details "private-key")
private-key-file (when (some? (:value secret-map))
(secret/value->file! secret-map :snowflake))]
(cond-> base-details
private-key-file (handle-conn-uri user account private-key-file)))
:else
;; get-secret-string should get the right value (using private-key-value or private-key-id) and decode it automatically
(let [decoded (secret/get-secret-string details "private-key")
file (secret/value->file! {:connection-property-name "private-key-file"
:value decoded})]
(assoc (handle-conn-uri base-details user account file)
:private_key_file file)))))
(defmethod sql-jdbc.conn/connection-details->spec :snowflake
[_ {:keys [account additional-options], :as details}]
......
......@@ -427,7 +427,7 @@
;; version of the -value property (the :type "textFile" one)
(let [textfile-prop (val-kw secrets-server->client)]
(:treat-before-posting textfile-prop)))))
value (let [^String v (val-kw acc)]
value (when-let [^String v (val-kw acc)]
(case (get-treat)
"base64" (decode-uploaded v)
v))]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment