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
50 changes: 50 additions & 0 deletions conf/interpreter-authorization.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"authInfo": {
"md": [
"user2",
"user3"
],
"angular": [
"admin",
"user1",
"user3"
],
"sh": [
"admin",
"user1",
"user2"
],
"livy": [
"admin",
"user3"
],
"file": [
"admin",
"user1",
"user2"
],
"flink": [
"user1"
],
"python": [
"admin",
"user1",
"user2"
],
"jdbc": [
"user1",
"user2"
],
"hbase": [
"admin",
"user1",
"user2",
"user3"
],
"myspark": [
"admin",
"user2",
"user3"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
package org.apache.zeppelin.rest;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.*;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
Expand All @@ -33,16 +31,14 @@

import com.google.gson.Gson;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.zeppelin.interpreter.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.aether.RepositoryException;
import org.sonatype.aether.repository.RemoteRepository;

import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.dep.Repository;
import org.apache.zeppelin.interpreter.InterpreterException;
import org.apache.zeppelin.interpreter.InterpreterFactory;
import org.apache.zeppelin.interpreter.InterpreterSetting;
import org.apache.zeppelin.rest.message.NewInterpreterSettingRequest;
import org.apache.zeppelin.rest.message.UpdateInterpreterSettingRequest;
import org.apache.zeppelin.server.JsonResponse;
Expand Down Expand Up @@ -176,6 +172,20 @@ public Response listInterpreter(String message) {
return new JsonResponse<>(Status.OK, "", m).build();
}

/**
* List all available interpreter group names
*/
@GET
@Path("names")
@ZeppelinApi
public Response listInterpreterNames(String message) {
List<String> m = new LinkedList<>();
for (InterpreterSetting intp: interpreterFactory.get()) {
m.add(intp.getName());
}
return new JsonResponse<>(Status.OK, "", m).build();
}

/**
* List of dependency resolving repositories
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,39 @@ public int compare(String o1, String o2) {
return new JsonResponse<>(Response.Status.OK, "", autoSuggestList).build();
}

/**
* Get all userlist
* Returns list of all user from available realms
*
* @return 200 response
*/
@GET
@Path("alluserlist")
public Response getAllUserList() {
List<String> usersList = new ArrayList<>();
try {
GetUserList getUserListObj = new GetUserList();
Collection realmsList = SecurityUtils.getRealmsList();
if (realmsList != null) {
for (Iterator<Realm> iterator = realmsList.iterator(); iterator.hasNext(); ) {
Realm realm = iterator.next();
String name = realm.getName();
if (name.equals("iniRealm")) {
usersList.addAll(getUserListObj.getUserList((IniRealm) realm));
} else if (name.equals("ldapRealm")) {
usersList.addAll(getUserListObj.getUserList((JndiLdapRealm) realm, ""));
} else if (name.equals("activeDirectoryRealm")) {
usersList.addAll(getUserListObj.getUserList((ActiveDirectoryGroupRealm) realm,
""));
} else if (name.equals("jdbcRealm")) {
usersList.addAll(getUserListObj.getUserList((JdbcRealm) realm));
}
}
}
} catch (Exception e) {
LOG.error("Exception in retrieving Users from realms ", e);
}
return new JsonResponse<>(Response.Status.OK, "", usersList).build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,12 @@ public void onMessage(NotebookSocket conn, String msg) {
case LIST_UPDATE_NOTEBOOK_JOBS:
unicastUpdateNotebookJobInfo(conn, messagereceived);
break;
case GET_INTERPRETER_AUTH:
getInterpreterAuthList(conn, messagereceived);
break;
case UPDATE_INTERPRETER_AUTH:
updateInterpreterAuth(conn, messagereceived);
break;
default:
break;
}
Expand Down Expand Up @@ -411,6 +417,44 @@ public void unicastUpdateNotebookJobInfo(NotebookSocket conn, Message fromMessag
.put("notebookRunningJobs", response)));
}

private boolean isAdmin(String user) {
if (!user.equals("admin")) {
LOG.error("There is no authorization for {}", user);
return false;
}
return true;
}

public void updateInterpreterAuth(NotebookSocket conn, Message fromMessage)
throws IOException {
if (!isAdmin(fromMessage.principal)) {
conn.send(serializeMessage(new Message(OP.GET_INTERPRETER_AUTH_LIST)
.put("interpreterAuth", null)));
return;
}

Map<String, Set<String>> authList = notebook().getInterpreterFactory().
getInterpreterAuthorization().updateInterpreterAuthorization(fromMessage.data);

conn.send(serializeMessage(new Message(OP.GET_INTERPRETER_AUTH_LIST)
.put("authInfo", authList)));
}

public void getInterpreterAuthList(NotebookSocket conn, Message fromMessage)
throws IOException {
if (!isAdmin(fromMessage.principal)) {
conn.send(serializeMessage(new Message(OP.GET_INTERPRETER_AUTH_LIST)
.put("interpreterAuth", null)));
return;
}

Map<String, Set<String>> authList = notebook().getInterpreterFactory().
getInterpreterAuthorization().getInterpreterAuthorization(fromMessage.data);

conn.send(serializeMessage(new Message(OP.GET_INTERPRETER_AUTH_LIST)
.put("authInfo", authList)));
}

public List<Map<String, String>> generateNotebooksInfo(boolean needsReload,
AuthenticationInfo subject) {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
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.
-->

<div>
<div class="row" ng-init="init()">
<div class="col-md-12" ng-show="showInterpreterAuth">
<hr />
<h4>Setting interpreter authorization</h4>
<div>
<table class="table table-bordered">
<thead>
<tr>
<th class="text-center">#</th>
<th ng-repeat="(intpIdx,intpName) in interpreterNames" class="text-center">{{intpName}}</th>
</tr>
</thead>

<tbody>
<tr ng-repeat="(userIdx,userId) in userIds">
<th scope="row" class="text-center">{{userId}}</th>
<td ng-repeat="(intpIdx,intpName) in interpreterNames" class="text-center">
<input type="checkbox" ng-model="interpreterAuthResults[intpIdx][userIdx]"/>
</td>
</tr>
</tbody>
</table>
<button class="btn btn-default btn-sm"
ng-click="updateInterpreterAuth()">
<i class="fa fa-plus"></i>
Update
</button>
</div>
</div>
</div>
</div>
111 changes: 110 additions & 1 deletion zeppelin-web/src/app/interpreter/interpreter.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
'use strict';

angular.module('zeppelinWebApp').controller('InterpreterCtrl',
function($scope, $http, baseUrlSrv, ngToast) {
function($scope, $http, baseUrlSrv, ngToast, $rootScope, $q, websocketMsgSrv) {
var interpreterSettingsTmp = [];
$scope.interpreterSettings = [];
$scope.availableInterpreters = {};
$scope.showAddNewSetting = false;
$scope.showRepositoryInfo = false;
$scope.showInterpreterAuth = false;
$scope.interpreterAuthList = [];
$scope.interpreterNames = [];
$scope.userIds = [];
$scope.interpreterAuthResults = [];
$scope._ = _;

var getInterpreterSettings = function() {
Expand Down Expand Up @@ -456,6 +461,110 @@ angular.module('zeppelinWebApp').controller('InterpreterCtrl',
}
};

var getInterpreterList = function() {
return $q(function(success, fail) {
$http.get(baseUrlSrv.getRestApiBase() + '/interpreter/names')
.success(function(data, status, headers, config) {
console.log('getInterpreterList %o', data);
$scope.interpreterNames = data.body;
success();
})
.error(function(err, status, headers, config) {
console.log('Error %o', err);
fail();
});
});
};

var getUserList = function() {
return $q(function(success, fail) {
$http.get(baseUrlSrv.getRestApiBase() + '/security/alluserlist')
.success(function(data, status, headers, config) {
console.log('getUserList %o', data);
$scope.userIds = data.body;
success();
})
.error(function(err, status, headers, config) {
console.log('Error %o', err);
fail();
});
});
};

$scope.init = function() {
websocketMsgSrv.getInterpreterAuthList($rootScope.ticket.principal);
};

// request
$scope.updateInterpreterAuth = function() {
var intpAuthObj = new Object();
for (var i = 0; i < $scope.interpreterAuthResults.length; i++) {

for (var j = 0; j < $scope.interpreterAuthResults[i].length; j++) {
if ($scope.interpreterAuthResults[i][j] === true) {
console.log($scope.interpreterNames[i], '(', i, ') use ', $scope.userIds[j], '(', j, ')');

if (intpAuthObj[$scope.interpreterNames[i]] === undefined) {
intpAuthObj[$scope.interpreterNames[i]] = new Array();
}
intpAuthObj[$scope.interpreterNames[i]].push($scope.userIds[j]);
}
}
}
websocketMsgSrv.updateInterpreterAuth($rootScope.ticket.principal, intpAuthObj);
};

// request
$scope.getInterpreterAuth = function() {
websocketMsgSrv.getInterpreterAuthList($rootScope.ticket.principal);
};

// receive
$scope.$on('getInterpreterAuthList', function(event, data) {
$scope.interpreterAuthList = data;

_promise(true).then(
function() {
// make dimension.
for (var i = 0; i < $scope.interpreterNames.length; i++) {
$scope.interpreterAuthResults[i] = [];
for (var j = 0; j < $scope.userIds.length; j++) {
$scope.interpreterAuthResults[i][j] = isSelected($scope.interpreterNames[i], $scope.userIds[j]);
}
}
}
);
});

var _promise = function(param) {
return $q(function(resolve, reject) {
getInterpreterList().then(function() {
getUserList().then(
function() {
resolve('success');
},
function() {
reject(Error('fail'));
}
);
},
function() {
reject(Error('fail'));
});
});
};

var isSelected = function(intpName, userId) {
var result = false;
for (var intp in $scope.interpreterAuthList.authInfo) {
var userList = $scope.interpreterAuthList.authInfo[intp];
if (!_.isEmpty(_.where(userList, userId)) && intpName === intp) {
result = true;
}
}
return result;
};

var init = function() {
$scope.resetNewInterpreterSetting();
$scope.resetNewRepositorySetting();
Expand Down
Loading