blob: 11dc8ef766ab06331c987ab43ec29b749d7c04d5 [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.
*/
#ifndef IMPALA_TRANSPORT_THTTPSERVER_H
#define IMPALA_TRANSPORT_THTTPSERVER_H
#include "transport/THttpTransport.h"
#include "util/metrics-fwd.h"
namespace apache {
namespace thrift {
namespace transport {
struct HttpMetrics {
// If 'has_ldap_' is true, metrics for the number of successful and failed Basic
// auth attempts.
impala::IntCounter* total_basic_auth_success_ = nullptr;
impala::IntCounter* total_basic_auth_failure_ = nullptr;
// If 'has_kerberos_' is true, metrics for the number of successful and failed Negotiate
// auth attempts.
impala::IntCounter* total_negotiate_auth_success_ = nullptr;
impala::IntCounter* total_negotiate_auth_failure_ = nullptr;
// If 'use_cookies_' is true, metrics for the number of successful and failed cookie
// auth attempts.
impala::IntCounter* total_cookie_auth_success_ = nullptr;
impala::IntCounter* total_cookie_auth_failure_ = nullptr;
};
/*
* Implements server side work for http connections, including support for Basic auth,
* SPNEGO, and cookies.
*/
class THttpServer : public THttpTransport {
public:
struct HttpCallbacks {
public:
// Function that takes the value from a 'Authorization: Basic' header. Returns true
// if authentication is successful. Must be set if 'has_ldap_' is true.
std::function<bool(const std::string&)> basic_auth_fn =
[&](const std::string&) { DCHECK(false); return false; };
// Function that takes the value from a 'Authorization: Negotiate' header. Returns
// true if successful and sets 'is_complete' to true if negoation is done. Must be set
// if 'has_kerberos_' is true.
std::function<bool(const std::string&, bool* is_complete)> negotiate_auth_fn =
[&](const std::string&, bool*) { DCHECK(false); return false; };
// Function that returns a list of headers to return to the client.
std::function<std::vector<std::string>()> return_headers_fn =
[&]() { return std::vector<std::string>(); };
// Function that takes the path component of an HTTP request. Returns false and sets
// 'err_msg' if an error is encountered.
std::function<bool(const std::string& path, std::string* err_msg)> path_fn =
[&](const std::string&, std::string*) { return true; };
// Function that takes the value from the 'Cookie' header and returns true if
// authentication is successful.
std::function<bool(const std::string&)> cookie_auth_fn =
[&](const std::string&) { return false; };
};
THttpServer(boost::shared_ptr<TTransport> transport, bool has_ldap, bool has_kerberos,
bool use_cookies, bool metrics_enabled, HttpMetrics* http_metrics);
virtual ~THttpServer();
virtual void flush();
void setCallbacks(const HttpCallbacks& callbacks) { callbacks_ = callbacks; }
protected:
void readHeaders();
virtual void parseHeader(char* header);
virtual bool parseStatusLine(char* status);
virtual void headersDone();
std::string getTimeRFC1123();
// Returns a '401 - Unauthorized' to the client.
void returnUnauthorized();
private:
// If either of the following is true, a '401 - Unauthorized' will be returned to the
// client on requests that do not contain a valid 'Authorization' header. If 'has_ldap_'
// is true, 'Basic' auth headers will be processed, and if 'has_kerberos_' is true
// 'Negotiate' auth headers will be processed.
bool has_ldap_ = false;
bool has_kerberos_ = false;
HttpCallbacks callbacks_;
// The value from the 'Authorization' header.
std::string auth_value_ = "";
// If true, the value of any 'Cookie' header will be passed to 'cookie_auth_fn' to
// attempt to authenticate before calling other auth functions.
bool use_cookies_ = false;
// The value from the 'Cookie' header.
std::string cookie_value_ = "";
bool metrics_enabled_ = false;
HttpMetrics* http_metrics_ = nullptr;
};
/**
* Wraps a transport into HTTP protocol
*/
class THttpServerTransportFactory : public TTransportFactory {
public:
THttpServerTransportFactory() {}
THttpServerTransportFactory(const std::string server_name, impala::MetricGroup* metrics,
bool has_ldap, bool has_kerberos, bool use_cookies);
virtual ~THttpServerTransportFactory() {}
virtual boost::shared_ptr<TTransport> getTransport(boost::shared_ptr<TTransport> trans) {
return boost::shared_ptr<TTransport>(new THttpServer(
trans, has_ldap_, has_kerberos_, use_cookies_, metrics_enabled_, &http_metrics_));
}
private:
bool has_ldap_ = false;
bool has_kerberos_ = false;
bool use_cookies_ = false;
// Metrics for every transport produced by this factory.
bool metrics_enabled_ = false;
HttpMetrics http_metrics_;
};
}
}
} // apache::thrift::transport
#endif // #ifndef IMPALA_TRANSPORT_THTTPSERVER_H