Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/_includes/themes/zeppelin/_navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
<li><a href="{{BASE_PATH}}/security/authentication.html">Authentication for NGINX</a></li>
<li><a href="{{BASE_PATH}}/security/shiroauthentication.html">Shiro Authentication</a></li>
<li><a href="{{BASE_PATH}}/security/notebook_authorization.html">Notebook Authorization</a></li>
<li><a href="{{BASE_PATH}}/security/interpreter_authorization.html">Interpreter & Data Resource Authorization</a></li>
<li><a href="{{BASE_PATH}}/security/datasource_authorization.html">Data Source Authorization</a></li>
<li role="separator" class="divider"></li>
<li class="title"><span><b>Contibute</b><span></li>
<li><a href="{{BASE_PATH}}/development/writingzeppelininterpreter.html">Writing Zeppelin Interpreter</a></li>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ Join to our [Mailing list](https://zeppelin.apache.org/community.html) and repor
* [Authentication for NGINX](./security/authentication.html)
* [Shiro Authentication](./security/shiroauthentication.html)
* [Notebook Authorization](./security/notebook_authorization.html)
* [Interpreter & Data Resource Authorization](./security/interpreter_authorization.html)
* [Data Source Authorization](./security/datasource_authorization.html)
* Contribute
* [Writing Zeppelin Interpreter](./development/writingzeppelininterpreter.html)
* [Writing Zeppelin Application (Experimental)](./development/writingzeppelinapplication.html)
Expand Down
59 changes: 59 additions & 0 deletions docs/security/datasource_authorization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
layout: page
title: "Data Source Authorization"
description: "Data Source Authorization"
group: security
---
<!--
Licensed 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.
-->
# Data Source Authorization in Apache Zeppelin

<div id="toc"></div>

## Overview

Data source authorization involves authenticating to the data source like a Mysql database and letting it determine user permissions.
Apache Zeppelin allows users to use their own credentials to authenticate with **Data Sources**.

For example, let's assume you have an account in the Vertica databases with credentials.
You might want to use this account to create a JDBC connection instead of a shared account with all users who are defined in `conf/shiro.ini`.
In this case, you can add your credential information to Apache Zeppelin and use them with below simple steps.

## How to save the credential information?
You can add new credentials in the dropdown menu for your data source which can be passed to interpreters.

<img class="img-responsive" src="../assets/themes/zeppelin/img/docs-img/credential_tab.png" width="180px"/>

**Entity** can be the key that distinguishes each credential sets. Type **Username & Password** for your own credentials. ex) user & password of Mysql

<img class="img-responsive" src="../assets/themes/zeppelin/img/docs-img/add_credential.png" />

The credentials saved as per users defined in `conf/shiro.ini`.
If you didn't activate [shiro authentication in Apache Zeppelin](./shiroauthentication.html), your credential information will be saved as `anonymous`.
All credential information also can be found in `conf/credentials.json`.

#### JDBC interpreter
You need to maintain per-user connection pools.
The interpret method takes the user string as a parameter and executes the jdbc call using a connection in the user's connection pool.

#### Presto
You don't need a password if the Presto DB server runs backend code using HDFS authorization for the user.

#### Vertica and Mysql
You have to store the password information for users.

## Please note
As a first step of data source authentication feature, [ZEPPELIN-828](https://issues.apache.org/jira/browse/ZEPPELIN-828) was proposed and implemented in Pull Request [#860](https://github.com/apache/zeppelin/pull/860).
Currently, only customized 3rd party interpreters can use this feature. We are planning to apply this mechanism to [the community interpreters](../manual/interpreterinstallation.md#available-community-managed-interpreters) in the near future.
Please keep track [ZEPPELIN-1070](https://issues.apache.org/jira/browse/ZEPPELIN-1070).
38 changes: 0 additions & 38 deletions docs/security/interpreter_authorization.md

This file was deleted.

2 changes: 1 addition & 1 deletion zeppelin-distribution/src/bin_license/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ The text of each license is also included at licenses/LICENSE-[project]-[version
(The MIT License) angular-elastic v2.4.2 (https://github.com/monospaced/angular-elastic) - https://github.com/monospaced/angular-elastic/blob/v2.4.2/LICENCE.txt
(The MIT License) angular-elastic-input v2.2.0 (https://github.com/jacek-pulit/angular-elastic-input) - https://github.com/jacek-pulit/angular-elastic-input/blob/v2.2.0/LICENSE
(The MIT License) ng-focus-if v1.0.2 (https://github.com/hiebj/ng-focus-if) - https://github.com/hiebj/ng-focus-if/blob/v1.0.2/LICENSE
(The MIT License) angular-xeditable v0.1.8 (http://vitalets.github.io/angular-xeditable/) - https://github.com/vitalets/angular-xeditable/tree/0.1.8
(The MIT License) angular-xeditable v0.1.12 (http://vitalets.github.io/angular-xeditable/) - https://github.com/vitalets/angular-xeditable/tree/0.1.12
(The MIT License) lodash v3.9.3 (https://lodash.com/) - https://github.com/lodash/lodash/blob/3.9.3/LICENSE.txt
(The MIT License) angular-filter v0.5.4 (https://github.com/a8m/angular-filter) - https://github.com/a8m/angular-filter/blob/v0.5.4/license.md
(The MIT License) ngToast v2.0.0 (http://tamerayd.in/ngToast/) - http://tameraydin.mit-license.org/
Expand Down
2 changes: 1 addition & 1 deletion zeppelin-web/bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"ng-sortable": "~1.3.3",
"angular-elastic": "~2.4.2",
"angular-elastic-input": "~2.2.0",
"angular-xeditable": "0.1.8",
"angular-xeditable": "0.1.12",
"highlightjs": "^9.2.0",
"lodash": "~3.9.3",
"angular-filter": "~0.5.4",
Expand Down
136 changes: 114 additions & 22 deletions zeppelin-web/src/app/credential/credential.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,134 @@
'use strict';

angular.module('zeppelinWebApp').controller('CredentialCtrl', function($scope, $route, $routeParams, $location,
$rootScope, $http, baseUrlSrv) {
$rootScope, $http, baseUrlSrv, ngToast) {
$scope._ = _;

$scope.credentialEntity = '';
$scope.credentialUsername = '';
$scope.credentialPassword = '';
$scope.credentialInfo = [];
$scope.showAddNewCredentialInfo = false;

$scope.updateCredentials = function() {
if (_.isEmpty($scope.credentialEntity.trim()) ||
_.isEmpty($scope.credentialUsername.trim())) {
BootstrapDialog.alert({
closable: true,
message: 'Username \\ Entity can not be empty.'
var getCredentialInfo = function() {
$http.get(baseUrlSrv.getRestApiBase() + '/credential').
success(function(data, status, headers, config) {
$scope.credentialInfo = _.map(data.body.userCredentials, function(value, prop) {
return {entity: prop, password: value.password, username: value.username};
});
console.log('Success %o %o', status, $scope.credentialInfo);
}).
error(function(data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
};

$scope.addNewCredentialInfo = function() {
if ($scope.entity && _.isEmpty($scope.entity.trim()) &&
$scope.username && _.isEmpty($scope.username.trim())) {
ngToast.danger({
content: 'Username \\ Entity can not be empty.',
verticalPosition: 'bottom',
timeout: '3000'
});
return;
}

$http.put(baseUrlSrv.getRestApiBase() + '/credential',
{'entity': $scope.credentialEntity,
'username': $scope.credentialUsername,
'password': $scope.credentialPassword
}).
var newCredential = {
'entity': $scope.entity,
'username': $scope.username,
'password': $scope.password
};

$http.put(baseUrlSrv.getRestApiBase() + '/credential', newCredential).
success(function(data, status, headers, config) {
BootstrapDialog.alert({
closable: true,
message: 'Successfully saved credentials.'
ngToast.success({
content: 'Successfully saved credentials.',
verticalPosition: 'bottom',
timeout: '3000'
});
$scope.credentialEntity = '';
$scope.credentialUsername = '';
$scope.credentialPassword = '';
$scope.credentialInfo.push(newCredential);
resetCredentialInfo();
$scope.showAddNewCredentialInfo = false;
console.log('Success %o %o', status, data.message);
}).
error(function(data, status, headers, config) {
alert('Error saving credentials');
ngToast.danger({
content: 'Error saving credentials',
verticalPosition: 'bottom',
timeout: '3000'
});
console.log('Error %o %o', status, data.message);
});
};

$scope.cancelCredentialInfo = function() {
$scope.showAddNewCredentialInfo = false;
resetCredentialInfo();
};

var resetCredentialInfo = function() {
$scope.entity = '';
$scope.username = '';
$scope.password = '';
};

$scope.copyOriginCredentialsInfo = function() {
ngToast.info({
content: 'Since entity is a unique key, you can edit only username & password',
verticalPosition: 'bottom',
timeout: '3000'
});
};

$scope.updateCredentialInfo = function(form, data, entity) {
var request = {
entity: entity,
username: data.username,
password: data.password
};

$http.put(baseUrlSrv.getRestApiBase() + '/credential/', request).
success(function(data, status, headers, config) {
var index = _.findIndex($scope.credentialInfo, {'entity': entity});
$scope.credentialInfo[index] = request;
return true;
}).
error(function(data, status, headers, config) {
console.log('Error %o %o', status, data.message);
ngToast.danger({
content: 'We couldn\'t save the credential',
verticalPosition: 'bottom',
timeout: '3000'
});
form.$show();
});
return false;
};

$scope.removeCredentialInfo = function(entity) {
BootstrapDialog.confirm({
closable: false,
closeByBackdrop: false,
closeByKeyboard: false,
title: '',
message: 'Do you want to delete this credential information?',
callback: function(result) {
if (result) {
$http.delete(baseUrlSrv.getRestApiBase() + '/credential/' + entity).
success(function(data, status, headers, config) {
var index = _.findIndex($scope.credentialInfo, {'entity': entity});
$scope.credentialInfo.splice(index, 1);
console.log('Success %o %o', status, data.message);
}).
error(function(data, status, headers, config) {
console.log('Error %o %o', status, data.message);
});
}
}
});
};

var init = function() {
getCredentialInfo();
};

init();
});
Loading