Skip to content
Snippets Groups Projects
Unverified Commit 2bd0b3c7 authored by Nícolas Sims Botelho's avatar Nícolas Sims Botelho Committed by GitHub
Browse files

Add Basic Authentication to Druid (#20412)


* feat: allow authorization token for druid database

* fix:  adjust in basic auth  header and new field username

* fix: add scenario test

* fix: remove debug code

* fix: use metabase-plugin for new fields and improve tests

* fix: change type of auth-token to password

* fix: adjustment tested

* fix: adjustment tested

---------

Co-authored-by: default avatarNícolas Botelho <nicolas.botelho@piposaude.com.br>
Co-authored-by: default avatarmetamben <103100869+metamben@users.noreply.github.com>
parent 4ae9c926
No related branches found
No related tags found
No related merge requests found
......@@ -17,7 +17,25 @@ driver:
- cloud-ip-address-info
- ssh-tunnel
- advanced-options-start
- name: auth-enabled
display-name: Authentication header
default: false
type: boolean
visible-if:
advanced-options: true
- name: auth-username
display-name: Username
type: string
visible-if:
auth-enabled: true
- name: auth-token
display-name: Token
type: secret
secret-kind: password
visible-if:
auth-enabled: true
- default-advanced-options
init:
- step: load-namespace
namespace: metabase.driver.druid
......@@ -20,7 +20,10 @@
[_ details]
{:pre [(map? details)]}
(ssh/with-ssh-tunnel [details-with-tunnel details]
(= 200 (:status (http/get (druid.client/details->url details-with-tunnel "/status"))))))
(let [{:keys [auth-enabled auth-username auth-token-value]} details]
(= 200 (:status (http/get (druid.client/details->url details-with-tunnel "/status")
(cond-> {}
auth-enabled (assoc :basic-auth (str auth-username ":" auth-token-value)))))))))
(defmethod driver/describe-table :druid
[_ database table]
......
......@@ -2,6 +2,7 @@
(:require [cheshire.core :as json]
[clj-http.client :as http]
[clojure.core.async :as a]
[metabase.models.secret :as secret]
[metabase.query-processor.error-type :as qp.error-type]
[metabase.util :as u]
[metabase.util.i18n :refer [trs tru]]
......@@ -25,8 +26,11 @@
[request-fn url & {:as options}]
{:pre [(fn? request-fn) (string? url)]}
;; this is the way the `Content-Type` header is formatted in requests made by the Druid web interface
(let [options (cond-> (merge {:content-type "application/json;charset=UTF-8"} options)
(:body options) (update :body json/generate-string))]
(let [{:keys [auth-enabled auth-username auth-token-value]} options
options (cond-> (merge {:content-type "application/json;charset=UTF-8"} options)
(:body options) (update :body json/generate-string)
auth-enabled (assoc :basic-auth (str auth-username ":" auth-token-value)))]
(try
(let [{:keys [status body]} (request-fn url options)]
(when (not= status 200)
......@@ -62,7 +66,13 @@
{:pre [(map? details) (map? query)]}
(ssh/with-ssh-tunnel [details-with-tunnel details]
(try
(POST (details->url details-with-tunnel "/druid/v2"), :body query)
(POST (details->url details-with-tunnel "/druid/v2"),
:body query
:auth-enabled (:auth-enabled details)
:auth-username (:auth-username details)
:auth-token-value (-> details
(secret/db-details-prop->secret-map "auth-token")
secret/value->string))
;; don't need to do anything fancy if the query was killed
(catch InterruptedException e
(throw e))
......@@ -82,7 +92,12 @@
(log/warn (trs "Client closed connection, canceling Druid queryId {0}" query-id))
(try
(log/debug (trs "Canceling Druid query with ID {0}" query-id))
(DELETE (details->url details-with-tunnel (format "/druid/v2/%s" query-id)))
(DELETE (details->url details-with-tunnel (format "/druid/v2/%s" query-id))
:auth-enabled (:auth-enabled details)
:auth-username (:auth-username details)
:auth-token-value (-> details
(secret/db-details-prop->secret-map "auth-token")
secret/value->string))
(catch Exception cancel-e
(log/warn cancel-e (trs "Failed to cancel Druid query with queryId {0}" query-id)))))))
......
(ns metabase.driver.druid.sync
(:require [medley.core :as m]
[metabase.driver.druid.client :as druid.client]
[metabase.models.secret :as secret]
[metabase.util.ssh :as ssh]))
(defn- do-segment-metadata-query [details datasource]
......@@ -50,7 +51,12 @@
[database]
{:pre [(map? (:details database))]}
(ssh/with-ssh-tunnel [details-with-tunnel (:details database)]
(let [druid-datasources (druid.client/GET (druid.client/details->url details-with-tunnel "/druid/v2/datasources"))]
(let [druid-datasources (druid.client/GET (druid.client/details->url details-with-tunnel "/druid/v2/datasources")
:auth-enabled (-> database :details :auth-enabled)
:auth-username (-> database :details :auth-username)
:auth-token-value (-> (:details database)
(secret/db-details-prop->secret-map "auth-token")
secret/value->string))]
{:tables (set (for [table-name druid-datasources]
{:schema nil, :name table-name}))})))
......
......@@ -70,3 +70,36 @@
(or (when (instance? java.net.ConnectException e)
(throw e))
(some-> (.getCause e) recur)))))))))
(defn- test-request
([request-fn]
(test-request request-fn true))
([request-fn basic-auth?]
(try
(request-fn "http://localhost:8082/druid/v2"
:auth-enabled basic-auth?
:auth-username "nbotelho"
:auth-token-value "12345678910")
(catch Exception e
(ex-data e)))))
(defn- get-auth-header [m]
(select-keys (:request-options m) [:basic-auth]))
(deftest basic-auth-test
(let [get-request (test-request druid.client/GET)
post-request (test-request druid.client/POST)
delete-request (test-request druid.client/DELETE)]
(is (= {:basic-auth "nbotelho:12345678910"}
(get-auth-header get-request)
(get-auth-header post-request)
(get-auth-header delete-request)) "basic auth header included with successfully"))
(let [no-auth-basic false
get-request (test-request druid.client/GET no-auth-basic)
post-request (test-request druid.client/POST no-auth-basic)
delete-request (test-request druid.client/DELETE no-auth-basic)]
(is (= no-auth-basic
(contains? (get-auth-header get-request) :basic-auth)
(contains? (get-auth-header post-request) :basic-auth)
(contains? (get-auth-header delete-request) :basic-auth)) "basic auth header not included")))
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