Skip to content
Snippets Groups Projects
Commit f08ebd5c authored by Cam Saül's avatar Cam Saül
Browse files

:scream: block native queries against H2 databases that don't use a non-default user

parent 0b527b3f
Branches
Tags
No related merge requests found
......@@ -128,21 +128,30 @@
(float (/ url-count total-non-null-count))))))
0.0))
(defn extend-add-generic-sql-mixins [driver-type]
(extend driver-type
IDriver
{:can-connect? can-connect?
:can-connect-with-details? can-connect-with-details?
:wrap-process-query-middleware wrap-process-query-middleware
:process-query process-query
:sync-in-context sync-in-context
:active-table-names active-table-names
:active-column-names->type active-column-names->type
:table-pks table-pks
:field-values-lazy-seq field-values-lazy-seq}
ISyncDriverTableFKs
{:table-fks table-fks}
ISyncDriverFieldAvgLength
{:field-avg-length field-avg-length}
ISyncDriverFieldPercentUrls
{:field-percent-urls field-percent-urls}))
(def ^:const GenericSQLIDriverMixin
"Generic SQL implementation of the `IDriver` protocol.
(extend H2Driver
IDriver
GenericSQLIDriverMixin)"
{:can-connect? can-connect?
:can-connect-with-details? can-connect-with-details?
:wrap-process-query-middleware wrap-process-query-middleware
:process-query process-query
:sync-in-context sync-in-context
:active-table-names active-table-names
:active-column-names->type active-column-names->type
:table-pks table-pks
:field-values-lazy-seq field-values-lazy-seq})
(def ^:const GenericSQLISyncDriverTableFKsMixin
"Generic SQL implementation of the `ISyncDriverTableFKs` protocol."
{:table-fks table-fks})
(def ^:const GenericSQLISyncDriverFieldAvgLengthMixin
"Generic SQL implementation of the `ISyncDriverFieldAvgLengthMixin` protocol."
{:field-avg-length field-avg-length})
(def ^:const GenericSQLISyncDriverFieldPercentUrlsMixin
"Generic SQL implementation of the `ISyncDriverFieldPercentUrls` protocol."
{:field-percent-urls field-percent-urls})
......@@ -3,8 +3,11 @@
[korma.db :as kdb]
[metabase.db :as db]
[metabase.driver :as driver]
[metabase.driver.generic-sql :as generic-sql]
[metabase.driver.generic-sql.interface :refer :all]))
(metabase.driver [generic-sql :as generic-sql, :refer [GenericSQLIDriverMixin GenericSQLISyncDriverTableFKsMixin
GenericSQLISyncDriverFieldAvgLengthMixin GenericSQLISyncDriverFieldPercentUrlsMixin]]
[interface :refer [IDriver ISyncDriverTableFKs ISyncDriverFieldAvgLength ISyncDriverFieldPercentUrls]])
[metabase.driver.generic-sql.interface :refer :all]
[metabase.models.database :refer [Database]]))
(def ^:private ^:const column->base-type
"Map of H2 Column types -> Field base types. (Add more mappings here as needed)"
......@@ -115,7 +118,29 @@
:milliseconds "MILLISECOND")
table-name field-name)))
(generic-sql/extend-add-generic-sql-mixins H2Driver)
(defn- wrap-process-query-middleware [_ qp]
(fn [{query-type :type, :as query}]
{:pre [query-type]}
;; For :native queries check to make sure the DB in question has a NAME property specified in the connection string.
;; We don't want to allow SQL queries on DBs connected with the default H2 admin account because they have access
;; to potentially unsafe functions like FILEREAD and FILEWRITE.
;; Assume any specified non-default USER for this H2 database doesn't have admin privs
(when (= (keyword query-type) :native)
(let [{:keys [db]} (db/sel :one :field [Database :details] :id (:database query))
_ (assert db)
[_ options] (connection-string->file+options db)
{:strs [USER]} options]
(when (or (not USER)
(= USER "sa")) ; "sa" is the default USER
(throw (Exception. "Running SQL queries against H2 databases using the default (admin) database user is forbidden.")))))
(qp query)))
(extend H2Driver
;; Override the generic SQL implementation of wrap-process-query-middleware so we can block unsafe native queries (see above)
IDriver (assoc GenericSQLIDriverMixin :wrap-process-query-middleware wrap-process-query-middleware)
ISyncDriverTableFKs GenericSQLISyncDriverTableFKsMixin
ISyncDriverFieldAvgLength GenericSQLISyncDriverFieldAvgLengthMixin
ISyncDriverFieldPercentUrls GenericSQLISyncDriverFieldPercentUrlsMixin)
(def ^:const driver
(map->H2Driver {:column->base-type column->base-type
......
......@@ -8,7 +8,10 @@
[metabase.db :refer [upd]]
[metabase.models.field :refer [Field]]
[metabase.driver :as driver]
[metabase.driver.interface :refer [ISyncDriverSpecificSyncField driver-specific-sync-field!]]
(metabase.driver [generic-sql :as generic-sql, :refer [GenericSQLIDriverMixin GenericSQLISyncDriverTableFKsMixin
GenericSQLISyncDriverFieldAvgLengthMixin GenericSQLISyncDriverFieldPercentUrlsMixin]]
[interface :refer [IDriver ISyncDriverTableFKs ISyncDriverFieldAvgLength ISyncDriverFieldPercentUrls
ISyncDriverSpecificSyncField driver-specific-sync-field!]])
[metabase.driver.generic-sql :as generic-sql]
(metabase.driver.generic-sql [interface :refer :all]
[util :refer [with-jdbc-metadata]])))
......@@ -117,7 +120,11 @@
(upd Field (:id field) :special_type :json)
(assoc field :special_type :json))))))
(generic-sql/extend-add-generic-sql-mixins PostgresDriver)
(extend PostgresDriver
IDriver GenericSQLIDriverMixin
ISyncDriverTableFKs GenericSQLISyncDriverTableFKsMixin
ISyncDriverFieldAvgLength GenericSQLISyncDriverFieldAvgLengthMixin
ISyncDriverFieldPercentUrls GenericSQLISyncDriverFieldPercentUrlsMixin)
(def ^:const driver
(map->PostgresDriver {:column->base-type column->base-type
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment