6 #include <boost/bind/bind.hpp>
7 #include <boost/asio/ip/host_name.hpp>
8 #include <boost/foreach.hpp>
9 #include <boost/tokenizer.hpp>
10 #include <boost/assign/list_of.hpp>
12 #if defined(RHEL_MAJOR) && (RHEL_MAJOR >= 9)
17 #include <isc/hmacmd5.h>
18 #include <isc/hmacsha.h>
35 #include "services/services_types.h"
44 using namespace boost::placeholders;
48 #define METADATA_TRACE(obj, arg) \
50 std::ostringstream _str; \
52 Metadata##obj::TraceMsg(MetadataTraceBuf, __FILE__, __LINE__, _str.str()); \
55 std::map<uint16_t, std::string>
57 (404,
"404 Not Found")
58 (500,
"500 Internal Server Error")
59 (501,
"501 Not Implemented")
60 (502,
"502 Bad Gateway")
61 (503,
"503 Service Unavailable")
62 (504,
"504 Gateway Timeout");
71 static std::string
GetHmacSha256(
const std::string &key,
const std::string &data) {
72 #if defined(RHEL_MAJOR) && (RHEL_MAJOR >= 9)
75 unsigned int digestlen =
sizeof(digest);
76 isc_result_t result =
isc_hmac(md_type, (
const unsigned char *)key.c_str(), key.length(),
77 (
const unsigned char *)data.c_str(), data.length(),
79 if (result != ISC_R_SUCCESS) {
83 std::stringstream str;
84 for (
unsigned int i = 0; i < digestlen; i++) {
85 str << std::hex << std::setfill(
'0') << std::setw(2) << (int)digest[i];
88 isc_hmacsha256_t hmacsha256;
89 isc_hmacsha256_init(&hmacsha256, (
const unsigned char *)key.c_str(),
91 isc_hmacsha256_update(&hmacsha256, (
const isc_uint8_t *)data.c_str(),
94 isc_hmacsha256_sign(&hmacsha256, hmac_sha256_digest,
96 std::stringstream str;
98 str << std::hex << std::setfill(
'0') << std::setw(2)
99 << (int) hmac_sha256_digest[i];
108 const std::string &secret)
109 : services_(module), shared_secret_(secret),
110 http_server_(new
MetadataServer(services_->agent()->event_manager())),
111 http_server6_(new
MetadataServer(services_->agent()->event_manager())),
112 http_client_(new
MetadataClient(services_->agent()->event_manager())) {
136 SessionMap::iterator next = ++it;
168 bool conn_close =
false;
169 std::vector<std::string> header_options;
170 std::string vm_ip, vm_uuid, vm_project_uuid;
177 if (ip.to_string().find(
"fe80") == 0) {
178 int i_percent = ip.to_string().find(
'%');
179 std::string ip_str = ip.to_string().substr(0, i_percent);
180 ip = boost::asio::ip::address::from_string(ip_str);
185 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
187 <<
"; Request for VM : " << ip);
200 for (HttpRequest::HeaderMap::const_iterator it = req_header.begin();
201 it != req_header.end(); ++it) {
202 std::string option = boost::to_lower_copy(it->first);
203 if (option ==
"host") {
206 if (option ==
"connection") {
207 std::string val = boost::to_lower_copy(it->second);
212 header_options.push_back(std::string(it->first +
": " + it->second));
218 boost::replace_all(vm_project_uuid,
"-",
"");
219 header_options.push_back(std::string(
"X-Forwarded-For: " + vm_ip));
220 header_options.push_back(std::string(
"X-Instance-ID: " + vm_uuid));
221 header_options.push_back(std::string(
"X-Tenant-ID: " + vm_project_uuid));
222 header_options.push_back(std::string(
"X-Instance-ID-Signature: " +
225 std::string uri = request->
UrlPath();
228 const std::string &body = request->
Body();
230 std::string nova_hostname;
233 if (!nova_hostname.empty()) {
234 header_options.insert(header_options.begin(),
235 std::string(
"Host: " + nova_hostname));
241 conn->
HttpGet(uri,
true,
false,
true, header_options,
245 <<
" URL : " << uri);
250 conn->
HttpHead(uri,
true,
false,
true, header_options,
254 <<
" URL : " << uri);
259 conn->
HttpPost(body, uri,
true,
false,
true, header_options,
263 <<
" URL : " << uri);
268 conn->
HttpPut(body, uri,
true,
false,
true, header_options,
272 <<
" URL : " << uri);
277 conn->
HttpDelete(uri,
true,
false,
true, header_options,
281 <<
" URL : " << uri);
287 <<
"Request Method: " << request->
GetMethod()
288 <<
"; Request for VM: " << vm_ip);
301 <<
"Request Method: " << request->
GetMethod()
302 <<
"; Request for VM : " << vm_ip);
319 std::string &msg, boost::system::error_code &ec) {
320 bool delete_session =
false;
321 boost::asio::ip::address ip = session->remote_endpoint().address();
328 std::string vm_ip, vm_uuid, vm_project_uuid;
330 if (ip.to_string().find(
"fe80") == 0) {
331 int i_percent = ip.to_string().find(
'%');
332 std::string ip_str = ip.to_string().substr(0, i_percent);
333 ip = boost::asio::ip::address::from_string(ip_str);
337 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
338 LOG(ERROR,
"UUID was not found for ip=" << ip.to_string() <<
339 ", in MetadataProxy::HandleMetadataResponse" <<
346 session->Send(
reinterpret_cast<const u_int8_t *
>(msg.c_str()),
350 boost::system::system_error(ec).what());
353 delete_session =
true;
358 if (!ec && it->second.close_req) {
359 std::stringstream str(msg);
362 if (option ==
"Content-Length:") {
363 str >> it->second.content_len;
364 }
else if (msg ==
"\r\n") {
365 it->second.header_end =
true;
366 if (it->second.header_end && !it->second.content_len) {
369 delete_session =
true;
371 }
else if (it->second.header_end) {
372 it->second.data_sent += msg.length();
373 if (it->second.data_sent >= it->second.content_len) {
376 delete_session =
true;
383 if (delete_session) {
416 ConnectionSessionMap::iterator it =
439 std::string *nova_hostname) {
442 it->second.close_req = conn_close;
443 return it->second.conn;
446 uint16_t linklocal_port = session->
local_port();
450 std::string md_service_name;
452 if (linklocal_server.is_v4() &&
455 nova_hostname, &nova_server, &nova_port)) {
459 if (linklocal_server.is_v6() &&
462 nova_hostname, &nova_server, &nova_port)) {
466 HttpConnection *conn = (nova_hostname != 0 && !nova_hostname->empty()) ?
470 map<CURLoption, int> *curl_options = conn->
curl_options();
471 curl_options->insert(std::make_pair(CURLOPT_HTTP_TRANSFER_DECODING, 0L));
511 snprintf(body,
sizeof(body),
"<html>\n"
513 " <title>%s</title>\n"
515 "</html>\n", message.c_str());
517 snprintf(response,
sizeof(response),
519 "Content-Type: text/html; charset=UTF-8\n"
520 "Content-Length: %u\n"
521 "\n%s", message.c_str(), (
unsigned int) strlen(body), body);
522 session->
Send(
reinterpret_cast<const u_int8_t *
>(response),
523 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)