Skip to content

Commit

Permalink
Add HTTP Basic Auth for Druid (Issue #4776) (#6795)
Browse files Browse the repository at this point in the history
* Add HTTP Basic Auth for Druid (Issue #4776)

This should resolve [Issue #4776](#4776)

Add HTTP Basic Auth to the Druid Broker.

Signed-off-by: Don Bowman <don@agilicus.com>

* Encrypt broker password in database

Signed-off-by: Don Bowman <don@agilicus.com>

* Merge from master, new migration needed

Signed-off-by: Don Bowman <don@agilicus.com>

* Do not expose hashed druid basic auth password

* docs: add description_columns for druid basic auth
  • Loading branch information
donbowman authored and mistercrunch committed Mar 25, 2019
1 parent 71f1bbd commit 4c5e6ca
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 4 deletions.
13 changes: 10 additions & 3 deletions superset/connectors/druid/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
Boolean, Column, DateTime, ForeignKey, Integer, String, Table, Text, UniqueConstraint,
)
from sqlalchemy.orm import backref, relationship
from sqlalchemy_utils import EncryptedType

from superset import conf, db, security_manager
from superset.connectors.base.models import BaseColumn, BaseDatasource, BaseMetric
Expand Down Expand Up @@ -102,9 +103,11 @@ class DruidCluster(Model, AuditMixinNullable, ImportMixin):
broker_endpoint = Column(String(255), default='druid/v2')
metadata_last_refreshed = Column(DateTime)
cache_timeout = Column(Integer)
broker_user = Column(String(255))
broker_pass = Column(EncryptedType(String(255), conf.get('SECRET_KEY')))

export_fields = ('cluster_name', 'broker_host', 'broker_port',
'broker_endpoint', 'cache_timeout')
'broker_endpoint', 'cache_timeout', 'broker_user')
update_from_object_fields = export_fields
export_children = ['datasources']

Expand Down Expand Up @@ -139,16 +142,20 @@ def get_pydruid_client(self):
cli = PyDruid(
self.get_base_url(self.broker_host, self.broker_port),
self.broker_endpoint)
if self.broker_user and self.broker_pass:
cli.set_basic_auth_credentials(self.broker_user, self.broker_pass)
return cli

def get_datasources(self):
endpoint = self.get_base_broker_url() + '/datasources'
return json.loads(requests.get(endpoint).text)
auth = requests.auth.HTTPBasicAuth(self.broker_user, self.broker_pass)
return json.loads(requests.get(endpoint, auth=auth).text)

def get_druid_version(self):
endpoint = self.get_base_url(
self.broker_host, self.broker_port) + '/status'
return json.loads(requests.get(endpoint).text)['version']
auth = requests.auth.HTTPBasicAuth(self.broker_user, self.broker_pass)
return json.loads(requests.get(endpoint, auth=auth).text)['version']

@property
@utils.memoized
Expand Down
15 changes: 14 additions & 1 deletion superset/connectors/druid/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ class DruidClusterModelView(SupersetModelView, DeleteMixin, YamlExportMixin): #

add_columns = [
'verbose_name', 'broker_host', 'broker_port',
'broker_endpoint', 'cache_timeout', 'cluster_name',
'broker_user', 'broker_pass', 'broker_endpoint',
'cache_timeout', 'cluster_name',
]
edit_columns = add_columns
list_columns = ['cluster_name', 'metadata_last_refreshed']
Expand All @@ -176,6 +177,8 @@ class DruidClusterModelView(SupersetModelView, DeleteMixin, YamlExportMixin): #
'cluster_name': _('Cluster'),
'broker_host': _('Broker Host'),
'broker_port': _('Broker Port'),
'broker_user': _('Broker Username'),
'broker_pass': _('Broker Password'),
'broker_endpoint': _('Broker Endpoint'),
'verbose_name': _('Verbose Name'),
'cache_timeout': _('Cache Timeout'),
Expand All @@ -186,6 +189,16 @@ class DruidClusterModelView(SupersetModelView, DeleteMixin, YamlExportMixin): #
'Duration (in seconds) of the caching timeout for this cluster. '
'A timeout of 0 indicates that the cache never expires. '
'Note this defaults to the global timeout if undefined.'),
'broker_user': _(
'Druid supports basic authentication. See '
'[auth](http://druid.io/docs/latest/design/auth.html) and '
'druid-basic-security extension',
),
'broker_pass': _(
'Druid supports basic authentication. See '
'[auth](http://druid.io/docs/latest/design/auth.html) and '
'druid-basic-security extension',
),
}

def pre_add(self, cluster):
Expand Down
38 changes: 38 additions & 0 deletions superset/migrations/versions/45e7da7cfeba_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""empty message
Revision ID: 45e7da7cfeba
Revises: ('e553e78e90c5', 'c82ee8a39623')
Create Date: 2019-02-16 17:44:44.493427
"""

# revision identifiers, used by Alembic.
revision = '45e7da7cfeba'
down_revision = ('e553e78e90c5', 'c82ee8a39623')

from alembic import op
import sqlalchemy as sa


def upgrade():
pass


def downgrade():
pass
46 changes: 46 additions & 0 deletions superset/migrations/versions/e553e78e90c5_add_druid_auth_py_py.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""add_druid_auth_py.py
Revision ID: e553e78e90c5
Revises: 18dc26817ad2
Create Date: 2019-02-01 16:07:04.268023
"""

# revision identifiers, used by Alembic.
revision = 'e553e78e90c5'
down_revision = '18dc26817ad2'

from alembic import op
import sqlalchemy as sa
from sqlalchemy_utils import EncryptedType



def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('clusters', sa.Column('broker_pass', EncryptedType(), nullable=True))
op.add_column('clusters', sa.Column('broker_user', sa.String(length=255), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('clusters', 'broker_user')
op.drop_column('clusters', 'broker_pass')
# ### end Alembic commands ###

0 comments on commit 4c5e6ca

Please sign in to comment.