5 #include <boost/bind.hpp>
6 #include <boost/asio/ip/host_name.hpp>
7 #include <boost/foreach.hpp>
8 #include <boost/tokenizer.hpp>
9 #include <boost/assign/list_of.hpp>
11 #if defined(RHEL_MAJOR) && (RHEL_MAJOR >= 9)
16 #include <isc/hmacmd5.h>
17 #include <isc/hmacsha.h>
34 #include "services/services_types.h"
45 #define METADATA_TRACE(obj, arg) \
47 std::ostringstream _str; \
49 Metadata##obj::TraceMsg(MetadataTraceBuf, __FILE__, __LINE__, _str.str()); \
52 std::map<uint16_t, std::string>
54 (404,
"404 Not Found")
55 (500,
"500 Internal Server Error")
56 (501,
"501 Not Implemented")
57 (502,
"502 Bad Gateway")
58 (503,
"503 Service Unavailable")
59 (504,
"504 Gateway Timeout");
68 static std::string
GetHmacSha256(
const std::string &key,
const std::string &data) {
69 #if defined(RHEL_MAJOR) && (RHEL_MAJOR >= 9)
72 unsigned int digestlen =
sizeof(digest);
73 isc_result_t result =
isc_hmac(md_type, (
const unsigned char *)key.c_str(), key.length(),
74 (
const unsigned char *)data.c_str(), data.length(),
76 if (result != ISC_R_SUCCESS) {
80 std::stringstream str;
81 for (
unsigned int i = 0; i < digestlen; i++) {
82 str << std::hex << std::setfill(
'0') << std::setw(2) << (int)digest[i];
85 isc_hmacsha256_t hmacsha256;
86 isc_hmacsha256_init(&hmacsha256, (
const unsigned char *)key.c_str(),
88 isc_hmacsha256_update(&hmacsha256, (
const isc_uint8_t *)data.c_str(),
91 isc_hmacsha256_sign(&hmacsha256, hmac_sha256_digest,
93 std::stringstream str;
95 str << std::hex << std::setfill(
'0') << std::setw(2)
96 << (int) hmac_sha256_digest[i];
105 const std::string &secret)
106 : services_(module), shared_secret_(secret),
107 http_server_(new
MetadataServer(services_->agent()->event_manager())),
108 http_server6_(new
MetadataServer(services_->agent()->event_manager())),
109 http_client_(new
MetadataClient(services_->agent()->event_manager())) {
133 SessionMap::iterator next = ++it;
165 bool conn_close =
false;
166 std::vector<std::string> header_options;
167 std::string vm_ip, vm_uuid, vm_project_uuid;
174 if (ip.to_string().find(
"fe80") == 0) {
175 int i_percent = ip.to_string().find(
'%');
176 std::string ip_str = ip.to_string().substr(0, i_percent);
177 ip = boost::asio::ip::address::from_string(ip_str);
182 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
184 <<
"; Request for VM : " << ip);
197 for (HttpRequest::HeaderMap::const_iterator it = req_header.begin();
198 it != req_header.end(); ++it) {
199 std::string option = boost::to_lower_copy(it->first);
200 if (option ==
"host") {
203 if (option ==
"connection") {
204 std::string val = boost::to_lower_copy(it->second);
209 header_options.push_back(std::string(it->first +
": " + it->second));
215 boost::replace_all(vm_project_uuid,
"-",
"");
216 header_options.push_back(std::string(
"X-Forwarded-For: " + vm_ip));
217 header_options.push_back(std::string(
"X-Instance-ID: " + vm_uuid));
218 header_options.push_back(std::string(
"X-Tenant-ID: " + vm_project_uuid));
219 header_options.push_back(std::string(
"X-Instance-ID-Signature: " +
222 std::string uri = request->
UrlPath();
225 const std::string &body = request->
Body();
227 std::string nova_hostname;
230 if (!nova_hostname.empty()) {
231 header_options.insert(header_options.begin(),
232 std::string(
"Host: " + nova_hostname));
238 conn->
HttpGet(uri,
true,
false,
true, header_options,
242 <<
" URL : " << uri);
247 conn->
HttpHead(uri,
true,
false,
true, header_options,
251 <<
" URL : " << uri);
256 conn->
HttpPost(body, uri,
true,
false,
true, header_options,
260 <<
" URL : " << uri);
265 conn->
HttpPut(body, uri,
true,
false,
true, header_options,
269 <<
" URL : " << uri);
274 conn->
HttpDelete(uri,
true,
false,
true, header_options,
278 <<
" URL : " << uri);
284 <<
"Request Method: " << request->
GetMethod()
285 <<
"; Request for VM: " << vm_ip);
298 <<
"Request Method: " << request->
GetMethod()
299 <<
"; Request for VM : " << vm_ip);
316 std::string &msg, boost::system::error_code &ec) {
317 bool delete_session =
false;
318 boost::asio::ip::address ip = session->remote_endpoint().address();
325 std::string vm_ip, vm_uuid, vm_project_uuid;
327 if (ip.to_string().find(
"fe80") == 0) {
328 int i_percent = ip.to_string().find(
'%');
329 std::string ip_str = ip.to_string().substr(0, i_percent);
330 ip = boost::asio::ip::address::from_string(ip_str);
334 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
335 LOG(ERROR,
"UUID was not found for ip=" << ip.to_string() <<
336 ", in MetadataProxy::HandleMetadataResponse" <<
343 session->Send(reinterpret_cast<const u_int8_t *>(msg.c_str()),
347 boost::system::system_error(ec).what());
350 delete_session =
true;
355 if (!ec && it->second.close_req) {
356 std::stringstream str(msg);
359 if (option ==
"Content-Length:") {
360 str >> it->second.content_len;
361 }
else if (msg ==
"\r\n") {
362 it->second.header_end =
true;
363 if (it->second.header_end && !it->second.content_len) {
366 delete_session =
true;
368 }
else if (it->second.header_end) {
369 it->second.data_sent += msg.length();
370 if (it->second.data_sent >= it->second.content_len) {
373 delete_session =
true;
380 if (delete_session) {
413 ConnectionSessionMap::iterator it =
436 std::string *nova_hostname) {
439 it->second.close_req = conn_close;
440 return it->second.conn;
443 uint16_t linklocal_port = session->
local_port();
447 std::string md_service_name;
449 if (linklocal_server.is_v4() &&
452 nova_hostname, &nova_server, &nova_port)) {
456 if (linklocal_server.is_v6() &&
459 nova_hostname, &nova_server, &nova_port)) {
463 HttpConnection *conn = (nova_hostname != 0 && !nova_hostname->empty()) ?
467 map<CURLoption, int> *curl_options = conn->
curl_options();
468 curl_options->insert(std::make_pair(CURLOPT_HTTP_TRANSFER_DECODING, 0L));
508 snprintf(body,
sizeof(body),
"<html>\n"
510 " <title>%s</title>\n"
512 "</html>\n", message.c_str());
514 snprintf(response,
sizeof(response),
516 "Content-Type: text/html; charset=UTF-8\n"
517 "Content-Length: %u\n"
518 "\n%s", message.c_str(), (
unsigned int) strlen(body), body);
519 session->
Send(reinterpret_cast<const u_int8_t *>(response),
520 strlen(response), NULL);
Endpoint local_endpoint() const
virtual void DeleteSession(TcpSession *session)
int HttpGet(const std::string &path, HttpCb)
uint16_t metadata_proxy_port() const
HttpConnection * CreateConnection(boost::asio::ip::tcp::endpoint)
boost::asio::ip::address IpAddress
const std::string & Body() const
InterfaceTable * interface_table() const
const bool metadata_use_ssl() const
virtual bool Send(const uint8_t *data, size_t size, size_t *sent)
int HttpPost(const std::string &post_string, const std::string &path, HttpCb)
int32_t local_port() const
bool FindLinkLocalService(const std::string &service_name, IpAddress *service_ip, uint16_t *service_port, std::string *fabric_hostname, Ip4Address *fabric_ip, uint16_t *fabric_port) const
Get link local service configuration info, for a given service name.
int HttpDelete(const std::string &path, HttpCb)
const HeaderMap & Headers() const
void set_use_ssl(bool ssl_flag)
void set_ca_cert(const std::string &ca_cert)
GlobalVrouter * global_vrouter() const
std::map< CURLoption, int > * curl_options()
Ip4Address router_id() const
HttpConnection * Connection()
std::string metadata_client_key() const
void RemoveConnection(HttpConnection *)
void set_client_cert(const std::string &client_cert)
static const std::string kMetadataService6
static void DeleteServer(TcpServer *server)
std::map< std::string, std::string > HeaderMap
AgentParam * params() const
boost::asio::ip::address_v4 Ip4Address
http_method GetMethod() const
std::string metadata_ca_cert() const
void set_client_key(const std::string &client_key)
#define HTTP_WILDCARD_ENTRY
void set_client_cert_type(const std::string &client_cert_type)
static const std::string kMetadataService
int HttpHead(const std::string &path, bool header, bool short_timeout, bool reuse, std::vector< std::string > &hdr_options, HttpCb cb)
Endpoint remote_endpoint() const
std::string metadata_client_cert_type() const
int HttpPut(const std::string &put_string, const std::string &path, HttpCb)
#define LOG(_Level, _Msg)
virtual bool Initialize(unsigned short port)
void set_metadata_server_port(uint16_t port)
std::string metadata_client_cert() const
void RegisterHandler(const std::string &path, HttpHandlerFn handler)
std::string UrlPath() const
void RegisterEventCb(SessionEventCb cb)
void RegisterEventCb(HttpClientSession::SessionEventCb cb)