Skip to content
Open
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
10 changes: 6 additions & 4 deletions jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
import org.apache.zeppelin.jdbc.security.JDBCSecurityImpl;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.apache.zeppelin.user.UserCredentials;
import org.apache.zeppelin.user.UsernamePassword;
import org.apache.zeppelin.user.UsernamePasswords;

/**
* JDBC interpreter for Zeppelin. This interpreter can also be used for accessing HAWQ,
Expand Down Expand Up @@ -259,6 +259,7 @@ public void open() {
this.sqlSplitter = new SqlSplitter();
}

@Override
protected boolean isKerboseEnabled() {
if (!isEmpty(getProperty("zeppelin.jdbc.auth.type"))) {
UserGroupInformation.AuthenticationMethod authType = JDBCSecurityImpl.getAuthType(properties);
Expand Down Expand Up @@ -401,9 +402,9 @@ private boolean existAccountInBaseProperty(String propertyKey) {

private UsernamePassword getUsernamePassword(InterpreterContext interpreterContext,
String entity) {
UserCredentials uc = interpreterContext.getAuthenticationInfo().getUserCredentials();
if (uc != null) {
return uc.getUsernamePassword(entity);
UsernamePasswords ups = interpreterContext.getAuthenticationInfo().getUsernamePasswords();
if (ups != null) {
return ups.getUsernamePassword(entity);
}
return null;
}
Expand Down Expand Up @@ -734,6 +735,7 @@ private boolean isDDLCommand(int updatedCount, int columnCount) throws SQLExcept
return updatedCount < 0 && columnCount <= 0 ? true : false;
}

@Override
public InterpreterResult executePrecode(InterpreterContext interpreterContext)
throws InterpreterException {
InterpreterResult interpreterResult = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import org.apache.zeppelin.scheduler.ParallelScheduler;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.apache.zeppelin.user.UserCredentials;
import org.apache.zeppelin.user.UsernamePassword;
import org.apache.zeppelin.user.UsernamePasswords;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -532,13 +532,13 @@ private Properties getDBProperty(String dbPrefix,

private AuthenticationInfo getUserAuth(String user, String entityName, String dbUser,
String dbPassword) {
UserCredentials userCredentials = new UserCredentials();
UsernamePasswords userCredentials = new UsernamePasswords();
if (entityName != null && dbUser != null && dbPassword != null) {
UsernamePassword up = new UsernamePassword(dbUser, dbPassword);
userCredentials.putUsernamePassword(entityName, up);
}
AuthenticationInfo authInfo = new AuthenticationInfo();
authInfo.setUserCredentials(userCredentials);
authInfo.setUsernamePasswords(userCredentials);
authInfo.setUser(user);
return authInfo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public class AuthenticationInfo implements JsonSerializable {
String user;
Set<String> roles;
String ticket;
UserCredentials userCredentials;
// enitiy -> UsernamePassword
UsernamePasswords usernamePasswords;
public static final AuthenticationInfo ANONYMOUS = new AuthenticationInfo("anonymous", new HashSet<>(),
"anonymous");

Expand Down Expand Up @@ -89,8 +90,8 @@ public void setRoles(Set<String> roles) {
this.roles = roles;
}

public List<String> getUsersAndRoles() {
List<String> usersAndRoles = new ArrayList<>();
public Set<String> getUsersAndRoles() {
Set<String> usersAndRoles = new HashSet<>();
if (roles != null) {
usersAndRoles.addAll(roles);
}
Expand All @@ -109,12 +110,12 @@ public void setTicket(String ticket) {
this.ticket = ticket;
}

public UserCredentials getUserCredentials() {
return userCredentials;
public UsernamePasswords getUsernamePasswords() {
return usernamePasswords;
}

public void setUserCredentials(UserCredentials userCredentials) {
this.userCredentials = userCredentials;
public void setUsernamePasswords(UsernamePasswords usernamePasswords) {
this.usernamePasswords = usernamePasswords;
}

public static boolean isAnonymous(AuthenticationInfo subject) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
/*
* 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.
*/
* 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.
*/

package org.apache.zeppelin.user;

/**
* Username and Password POJO
*/
public class UsernamePassword {
private String username;
private String password;

private final String username;
private final String password;

public UsernamePassword(String username, String password) {
this.username = username;
Expand All @@ -33,18 +31,10 @@ public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public String toString() {
return "UsernamePassword{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,45 @@

package org.apache.zeppelin.user;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;

/**
* User Credentials POJO
*
* Key: Credential entity
*
* Value: credentials
*/
public class UserCredentials {
private Map<String, UsernamePassword> userCredentials = new ConcurrentHashMap<>();
public class UsernamePasswords extends HashMap<String, UsernamePassword> {

/**
*
*/
private static final long serialVersionUID = 1L;

public UsernamePassword getUsernamePassword(String entity) {
return userCredentials.get(entity);
return get(entity);
}

public void putUsernamePassword(String entity, UsernamePassword up) {
userCredentials.put(entity, up);
/**
* Wrapper method for {@link HashMap#remove(Object)}
*/
public UsernamePassword removeUsernamePassword(String entity) {
return remove(entity);
}

public void removeUsernamePassword(String entity) {
userCredentials.remove(entity);
/**
* Wrapper method for {@link HashMap#put(Object, Object)}
*/
public UsernamePassword putUsernamePassword(String entity, UsernamePassword up) {
return put(entity, up);
}

/**
* Wrapper method for {@link HashMap#containsKey(Object)}
*/
public boolean existUsernamePassword(String entity) {
return userCredentials.containsKey(entity);
return containsKey(entity);
}

@Override
public String toString() {
return "UserCredentials{" +
"userCredentials=" + userCredentials +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ protected AbstractRestApi(AuthenticationService authenticationService) {
protected ServiceContext getServiceContext() {
AuthenticationInfo authInfo = new AuthenticationInfo(authenticationService.getPrincipal());
authInfo.setRoles(authenticationService.getAssociatedRoles());
return new ServiceContext(authInfo, getUserAndRoles());
}

protected Set<String> getUserAndRoles() {
Set<String> userAndRoles = new HashSet<>();
userAndRoles.add(authenticationService.getPrincipal());
userAndRoles.addAll(authenticationService.getAssociatedRoles());
return new ServiceContext(authInfo, userAndRoles);
return userAndRoles;
}

public static class RestServiceCallback<T> extends SimpleServiceCallback<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.zeppelin.notebook.AuthorizationService;
import org.apache.zeppelin.rest.message.CredentialRequest;
import org.apache.zeppelin.server.JsonResponse;
import org.apache.zeppelin.service.AuthenticationService;
import org.apache.zeppelin.user.Credential;
import org.apache.zeppelin.user.Credentials;
import org.apache.zeppelin.user.UserCredentials;
import org.apache.zeppelin.user.UsernamePassword;
import org.apache.zeppelin.user.CredentialsMgr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -45,18 +48,18 @@
@Singleton
public class CredentialRestApi extends AbstractRestApi {
private static final Logger LOGGER = LoggerFactory.getLogger(CredentialRestApi.class);
private final Credentials credentials;
private final CredentialsMgr credentialsMgr;

@Inject
public CredentialRestApi(Credentials credentials, AuthenticationService authenticationService) {
public CredentialRestApi(CredentialsMgr credentials, AuthenticationService authenticationService) {
super(authenticationService);
this.credentials = credentials;
this.credentialsMgr = credentials;
}

/**
* Put User Credentials REST API.
*
* @param message - JSON with entity, username, password.
* @param message - JSON with entity, username, password and shares
* @return JSON with status.OK
*/
@PUT
Expand All @@ -67,12 +70,20 @@ public Response putCredentials(String message) {
}

String user = authenticationService.getPrincipal();
LOGGER.info("Update credentials for user {} entity {}", user, request.getEntity());
UserCredentials uc;
Set<String> roles = authenticationService.getAssociatedRoles();
LOGGER.info("Update credential entity {} by user {} with roles {}", request.getEntity(), user, roles);
try {
uc = credentials.getUserCredentials(user);
uc.putUsernamePassword(request.getEntity(), new UsernamePassword(request.getUsername(), request.getPassword()));
credentials.putUserCredentials(user, uc);
Credential credOld = credentialsMgr.getCredentialByEntity(request.getEntity());
if (credOld != null && !credentialsMgr.isOwner(request.getEntity(), getUserAndRoles())) {
return new JsonResponse<>(Status.FORBIDDEN).build();
}
// Ensure that the owner does not lose access to a created credential.
Set<String> owners = new HashSet<>(request.getOwners());
if (owners.isEmpty() || !AuthorizationService.isMember(getUserAndRoles(), owners)) {
owners.add(user);
}
Credential credNew = new Credential(request.getUsername(), request.getPassword(), request.getReader(), owners);
credentialsMgr.putCredentialsEntity(request.getEntity(), credNew);
return new JsonResponse<>(Status.OK).build();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
Expand All @@ -88,37 +99,10 @@ public Response putCredentials(String message) {
@GET
public Response getCredentials() {
String user = authenticationService.getPrincipal();
LOGGER.info("getCredentials for user {} ", user);
UserCredentials uc;
try {
uc = credentials.getUserCredentials(user);
return new JsonResponse<>(Status.OK, uc).build();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
return new JsonResponse<>(Status.INTERNAL_SERVER_ERROR).build();
}
}

/**
* Remove User Credentials REST API.
*
* @return JSON with status.OK
*/
@DELETE
public Response removeCredentials() {
String user = authenticationService.getPrincipal();
LOGGER.info("removeCredentials for user {} ", user);
UserCredentials uc;
try {
uc = credentials.removeUserCredentials(user);
if (uc == null) {
return new JsonResponse<>(Status.NOT_FOUND).build();
}
return new JsonResponse<>(Status.OK).build();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
return new JsonResponse<>(Status.INTERNAL_SERVER_ERROR).build();
}
Set<String> roles = authenticationService.getAssociatedRoles();
LOGGER.info("getCredentials for user {} with roles {}", user, roles);
Credentials creds = credentialsMgr.getAllReadableCredentials(getUserAndRoles(), true);
return new JsonResponse<>(Status.OK, creds).build();
}

/**
Expand All @@ -133,7 +117,14 @@ public Response removeCredentialEntity(@PathParam("entity") String entity) {
String user = authenticationService.getPrincipal();
LOGGER.info("removeCredentialEntity for user {} entity {}", user, entity);
try {
if (!credentials.removeCredentialEntity(user, entity)) {
if (!credentialsMgr.exists(entity)) {
return new JsonResponse<>(Status.NOT_FOUND).build();
}
if (!credentialsMgr.isOwner(entity, getUserAndRoles())) {
return new JsonResponse<>(Status.FORBIDDEN).build();
}
boolean found = credentialsMgr.removeCredentialEntity(entity);
if (!found) {
return new JsonResponse<>(Status.NOT_FOUND).build();
}
return new JsonResponse<>(Status.OK).build();
Expand Down
Loading
Loading