5 #include <boost/bind/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"
43 using namespace boost::placeholders;
47 #define METADATA_TRACE(obj, arg) \
49 std::ostringstream _str; \
51 Metadata##obj::TraceMsg(MetadataTraceBuf, __FILE__, __LINE__, _str.str()); \
54 std::map<uint16_t, std::string>
56 (404,
"404 Not Found")
57 (500,
"500 Internal Server Error")
58 (501,
"501 Not Implemented")
59 (502,
"502 Bad Gateway")
60 (503,
"503 Service Unavailable")
61 (504,
"504 Gateway Timeout");
70 static std::string
GetHmacSha256(
const std::string &key,
const std::string &data) {
71 #if defined(RHEL_MAJOR) && (RHEL_MAJOR >= 9)
74 unsigned int digestlen =
sizeof(digest);
75 isc_result_t result =
isc_hmac(md_type, (
const unsigned char *)key.c_str(), key.length(),
76 (
const unsigned char *)data.c_str(), data.length(),
78 if (result != ISC_R_SUCCESS) {
82 std::stringstream str;
83 for (
unsigned int i = 0; i < digestlen; i++) {
84 str << std::hex << std::setfill(
'0') << std::setw(2) << (int)digest[i];
87 isc_hmacsha256_t hmacsha256;
88 isc_hmacsha256_init(&hmacsha256, (
const unsigned char *)key.c_str(),
90 isc_hmacsha256_update(&hmacsha256, (
const isc_uint8_t *)data.c_str(),
93 isc_hmacsha256_sign(&hmacsha256, hmac_sha256_digest,
95 std::stringstream str;
97 str << std::hex << std::setfill(
'0') << std::setw(2)
98 << (int) hmac_sha256_digest[i];
107 const std::string &secret)
108 : services_(module), shared_secret_(secret),
109 http_server_(new
MetadataServer(services_->agent()->event_manager())),
110 http_server6_(new
MetadataServer(services_->agent()->event_manager())),
111 http_client_(new
MetadataClient(services_->agent()->event_manager())) {
135 SessionMap::iterator next = ++it;
167 bool conn_close =
false;
168 std::vector<std::string> header_options;
169 std::string vm_ip, vm_uuid, vm_project_uuid;
176 if (ip.to_string().find(
"fe80") == 0) {
177 int i_percent = ip.to_string().find(
'%');
178 std::string ip_str = ip.to_string().substr(0, i_percent);
179 ip = boost::asio::ip::address::from_string(ip_str);
184 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
186 <<
"; Request for VM : " << ip);
199 for (HttpRequest::HeaderMap::const_iterator it = req_header.begin();
200 it != req_header.end(); ++it) {
201 std::string option = boost::to_lower_copy(it->first);
202 if (option ==
"host") {
205 if (option ==
"connection") {
206 std::string val = boost::to_lower_copy(it->second);
211 header_options.push_back(std::string(it->first +
": " + it->second));
217 boost::replace_all(vm_project_uuid,
"-",
"");
218 header_options.push_back(std::string(
"X-Forwarded-For: " + vm_ip));
219 header_options.push_back(std::string(
"X-Instance-ID: " + vm_uuid));
220 header_options.push_back(std::string(
"X-Tenant-ID: " + vm_project_uuid));
221 header_options.push_back(std::string(
"X-Instance-ID-Signature: " +
224 std::string uri = request->
UrlPath();
227 const std::string &body = request->
Body();
229 std::string nova_hostname;
232 if (!nova_hostname.empty()) {
233 header_options.insert(header_options.begin(),
234 std::string(
"Host: " + nova_hostname));
240 conn->
HttpGet(uri,
true,
false,
true, header_options,
244 <<
" URL : " << uri);
249 conn->
HttpHead(uri,
true,
false,
true, header_options,
253 <<
" URL : " << uri);
258 conn->
HttpPost(body, uri,
true,
false,
true, header_options,
262 <<
" URL : " << uri);
267 conn->
HttpPut(body, uri,
true,
false,
true, header_options,
271 <<
" URL : " << uri);
276 conn->
HttpDelete(uri,
true,
false,
true, header_options,
280 <<
" URL : " << uri);
286 <<
"Request Method: " << request->
GetMethod()
287 <<
"; Request for VM: " << vm_ip);
300 <<
"Request Method: " << request->
GetMethod()
301 <<
"; Request for VM : " << vm_ip);
318 std::string &msg, boost::system::error_code &ec) {
319 bool delete_session =
false;
320 boost::asio::ip::address ip = session->remote_endpoint().address();
327 std::string vm_ip, vm_uuid, vm_project_uuid;
329 if (ip.to_string().find(
"fe80") == 0) {
330 int i_percent = ip.to_string().find(
'%');
331 std::string ip_str = ip.to_string().substr(0, i_percent);
332 ip = boost::asio::ip::address::from_string(ip_str);
336 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
337 LOG(ERROR,
"UUID was not found for ip=" << ip.to_string() <<
338 ", in MetadataProxy::HandleMetadataResponse" <<
345 session->Send(
reinterpret_cast<const u_int8_t *
>(msg.c_str()),
349 boost::system::system_error(ec).what());
352 delete_session =
true;
357 if (!ec && it->second.close_req) {
358 std::stringstream str(msg);
361 if (option ==
"Content-Length:") {
362 str >> it->second.content_len;
363 }
else if (msg ==
"\r\n") {
364 it->second.header_end =
true;
365 if (it->second.header_end && !it->second.content_len) {
368 delete_session =
true;
370 }
else if (it->second.header_end) {
371 it->second.data_sent += msg.length();
372 if (it->second.data_sent >= it->second.content_len) {
375 delete_session =
true;
382 if (delete_session) {
415 ConnectionSessionMap::iterator it =
438 std::string *nova_hostname) {
441 it->second.close_req = conn_close;
442 return it->second.conn;
445 uint16_t linklocal_port = session->
local_port();
449 std::string md_service_name;
451 if (linklocal_server.is_v4() &&
454 nova_hostname, &nova_server, &nova_port)) {
458 if (linklocal_server.is_v6() &&
461 nova_hostname, &nova_server, &nova_port)) {
465 HttpConnection *conn = (nova_hostname != 0 && !nova_hostname->empty()) ?
469 map<CURLoption, int> *curl_options = conn->
curl_options();
470 curl_options->insert(std::make_pair(CURLOPT_HTTP_TRANSFER_DECODING, 0L));
510 snprintf(body,
sizeof(body),
"<html>\n"
512 " <title>%s</title>\n"
514 "</html>\n", message.c_str());
516 snprintf(response,
sizeof(response),
518 "Content-Type: text/html; charset=UTF-8\n"
519 "Content-Length: %u\n"
520 "\n%s", message.c_str(), (
unsigned int) strlen(body), body);
521 session->
Send(
reinterpret_cast<const u_int8_t *
>(response),
522 strlen(response), NULL);
boost::asio::ip::address IpAddress
boost::asio::ip::address_v4 Ip4Address
std::string metadata_client_cert_type() const
const bool metadata_use_ssl() const
std::string metadata_client_key() const
uint16_t metadata_proxy_port() const
std::string metadata_ca_cert() const
std::string metadata_client_cert() const
InterfaceTable * interface_table() const
void set_metadata_server_port(uint16_t port)
AgentParam * params() const
Ip4Address router_id() const
static const std::string kMetadataService6
static const std::string kMetadataService
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.
HttpConnection * Connection()
HttpConnection * CreateConnection(boost::asio::ip::tcp::endpoint)
void RemoveConnection(HttpConnection *)
int HttpPut(const std::string &put_string, const std::string &path, HttpCb)
void set_ca_cert(const std::string &ca_cert)
int HttpGet(const std::string &path, HttpCb)
void set_client_cert(const std::string &client_cert)
void RegisterEventCb(HttpClientSession::SessionEventCb cb)
void set_use_ssl(bool ssl_flag)
int HttpPost(const std::string &post_string, const std::string &path, HttpCb)
void set_client_cert_type(const std::string &client_cert_type)
void set_client_key(const std::string &client_key)
int HttpHead(const std::string &path, bool header, bool short_timeout, bool reuse, std::vector< std::string > &hdr_options, HttpCb cb)
int HttpDelete(const std::string &path, HttpCb)
std::map< CURLoption, int > * curl_options()
const std::string & Body() const
http_method GetMethod() const
std::map< std::string, std::string > HeaderMap
std::string UrlPath() const
const HeaderMap & Headers() const
void RegisterHandler(const std::string &path, HttpHandlerFn handler)
GlobalVrouter * global_vrouter() const
static void DeleteServer(TcpServer *server)
virtual bool Initialize(unsigned short port)
virtual void DeleteSession(TcpSession *session)
Endpoint remote_endpoint() const
Endpoint local_endpoint() const
int32_t local_port() const
virtual bool Send(const uint8_t *data, size_t size, size_t *sent)
#define HTTP_WILDCARD_ENTRY
#define LOG(_Level, _Msg)
void RegisterEventCb(SessionEventCb cb)