blob: f95c0e76f0de8250741b173d80fc51127c4ca024 [file] [log] [blame]
/**
* 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.ambari.server.view;
import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
import org.apache.ambari.server.controller.internal.URLStreamProvider;
import org.apache.ambari.server.proxy.ProxyService;
import org.apache.ambari.view.ImpersonatorSetting;
import org.apache.ambari.view.ViewContext;
import org.apache.ambari.view.HttpImpersonator;
import org.apache.http.client.utils.URIBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
/**
* Class for Ambari to impersonate users over HTTP request.
* This is handy for Views like Jobs that needs to query ATS via HTTP Get requests and
* impersonate the currently logged on user.
* Or a file browser view that needs to use WebHDFS with the credentials of the current user.
*/
public class HttpImpersonatorImpl implements HttpImpersonator {
private ViewContext context;
private final URLStreamProvider urlStreamProvider;
private static Logger LOG = LoggerFactory.getLogger(HttpImpersonatorImpl.class);
public HttpImpersonatorImpl(ViewContext c) {
this.context = c;
ComponentSSLConfiguration configuration = ComponentSSLConfiguration.instance();
this.urlStreamProvider = new URLStreamProvider(ProxyService.URL_CONNECT_TIMEOUT,
ProxyService.URL_READ_TIMEOUT, configuration.getTruststorePath(),
configuration.getTruststorePassword(), configuration.getTruststoreType());
}
public HttpImpersonatorImpl(ViewContext c, URLStreamProvider urlStreamProvider) {
this.context = c;
this.urlStreamProvider = urlStreamProvider;
}
public ViewContext getContext() {
return this.context;
}
public String getUsername() {
return getContext().getUsername();
}
/**
* @param conn HTTP connection that will be modified and returned
* @param type HTTP Request type: GET, PUT, POST, DELETE, etc.
* @return HTTP Connection object with the "doAs" query param set to the currently logged on user.
*/
@Override
public HttpURLConnection doAs(HttpURLConnection conn, String type) {
String username = getUsername();
return doAs(conn, type, username, ImpersonatorSettingImpl.DEFAULT_DO_AS_PARAM);
}
/**
* @param conn HTTP connection that will be modified and returned
* @param type HTTP Request type: GET, PUT, POST, DELETE, etc.
* @param username Username to impersonate
* @param doAsParamName Query param, typically "doAs"
* @return HTTP Connection object with the doAs query param set to the provider username.
*/
@Override
public HttpURLConnection doAs(HttpURLConnection conn, String type, String username, String doAsParamName) {
String url = conn.getURL().toString();
if (url.toLowerCase().contains(doAsParamName.toLowerCase())) {
throw new IllegalArgumentException("URL cannot contain \"" + doAsParamName + "\" parameter");
}
try {
conn.setRequestMethod(type);
} catch (IOException e) {
return null;
}
conn.setRequestProperty(doAsParamName, username);
return conn;
}
/**
* Returns the result of the HTTP request by setting the "doAs" impersonation for the query param and username
* in @param impersonatorSetting.
* @param url URL to request
* @param requestType HTTP Request type: GET, PUT, POST, DELETE, etc.
* @param impersonatorSetting Setting class with default values for username and doAs param name.
* To use different values, call the setters of the object.
* @return Return a response as a String
*/
@Override
public String requestURL(String url, String requestType, final ImpersonatorSetting impersonatorSetting) {
String result = "";
BufferedReader rd;
String line;
if (url.toLowerCase().contains(impersonatorSetting.getDoAsParamName().toLowerCase())) {
throw new IllegalArgumentException("URL cannot contain \"" + impersonatorSetting.getDoAsParamName() + "\" parameter");
}
try {
String username = impersonatorSetting.getUsername();
if (username != null) {
URIBuilder builder = new URIBuilder(url);
builder.addParameter(impersonatorSetting.getDoAsParamName(), username);
url = builder.build().toString();
}
HttpURLConnection connection = urlStreamProvider.processURL(url, requestType, (String) null, null);
int responseCode = connection.getResponseCode();
InputStream resultInputStream;
if (responseCode >= ProxyService.HTTP_ERROR_RANGE_START) {
resultInputStream = connection.getErrorStream();
} else {
resultInputStream = connection.getInputStream();
}
rd = new BufferedReader(new InputStreamReader(resultInputStream));
if (rd != null) {
line = rd.readLine();
while (line != null) {
result += line;
line = rd.readLine();
}
rd.close();
}
} catch (Exception e) {
LOG.error("Exception caught processing impersonator request.", e);
}
return result;
}
}