/** * 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 * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * 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.ambari.view.hive2.resources.browser; import com.google.common.base.Optional; import org.apache.ambari.view.ViewContext; import org.apache.ambari.view.hive2.AuthParams; import org.apache.ambari.view.hive2.ConnectionFactory; import org.apache.ambari.view.hive2.ConnectionSystem; import org.apache.ambari.view.hive2.client.ConnectionConfig; import org.apache.ambari.view.hive2.internal.ConnectionException; import org.apache.ambari.view.hive2.internal.HiveConnectionWrapper; import org.apache.ambari.view.hive2.utils.ServiceFormattedException; import org.json.simple.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; /** * Connection verification and management controller */ public class ConnectionService { public static final String NO_PASSWORD = ""; public static final String SUFFIX = "validating the login"; @Inject protected ViewContext context; protected final static Logger LOG = LoggerFactory.getLogger(ConnectionService.class); /** * Check if LDAP is configured on Hive * if no password is cached , ask for one(401) * if yes and a password is cached, try * to connect, if connection succeeds * return OK, * * if connection fails - ask for one again(401) */ @GET @Path("connect") @Produces(MediaType.APPLICATION_JSON) public Response attemptConnection() { boolean ldapEnabled = ConnectionFactory.isLdapEnabled(context); if(ldapEnabled) { ConnectionSystem instance = ConnectionSystem.getInstance(); Optional<String> password = instance.getPassword(context); if (!password.isPresent()) { // No password cached - request for one return Response.status(Response.Status.UNAUTHORIZED).build(); } // if there was a password cached, make a connection attempt // get the password String pass = password.get(); // password may be stale, try to connect to Hive return attemptHiveConnection(pass,ldapEnabled); } return attemptHiveConnection(NO_PASSWORD,ldapEnabled); } private Response getOKResponse() { JSONObject response = new JSONObject(); response.put("message", "OK"); response.put("trace", null); response.put("status", "200"); return Response.ok().entity(response).type(MediaType.APPLICATION_JSON).build(); } private Response attemptHiveConnection(String pass, boolean ldapEnabled) { ConnectionConfig connectionConfig = ConnectionFactory.create(context); HiveConnectionWrapper hiveConnectionWrapper = new HiveConnectionWrapper(connectionConfig.getJdbcUrl(), connectionConfig.getUsername(), pass,new AuthParams(context)); try { hiveConnectionWrapper.connect(); } catch (ConnectionException e) { // Cannot connect with the current credentials // check the message to see if the cause was a login failure // return a 401 // else return a 500 if(isLoginError(e) && ldapEnabled) return Response.status(Response.Status.UNAUTHORIZED).build(); else throw new ServiceFormattedException(e.getMessage(), e); } finally { try { hiveConnectionWrapper.disconnect(); } catch(ConnectionException e){ LOG.warn("Cannot close the connection"); } } return getOKResponse() ; } private boolean isLoginError(ConnectionException ce) { return ce.getCause().getMessage().toLowerCase().endsWith(SUFFIX); } /** * Set password * This just updates the caches. */ @POST @Path("auth") @Consumes(MediaType.APPLICATION_JSON) public Response setupPassword(AuthRequest request) { try { //Cache the password for the user ConnectionSystem instance = ConnectionSystem.getInstance(); instance.persistCredentials(context.getUsername(),request.password); return getOKResponse(); } catch (WebApplicationException ex) { throw ex; } catch (Exception ex) { throw new ServiceFormattedException(ex.getMessage(), ex); } } public static class AuthRequest { public String password; } }