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 #include <isc/hmacmd5.h>
12 #include <isc/hmacsha.h>
28 #include "services/services_types.h"
39 #define METADATA_TRACE(obj, arg) \
41 std::ostringstream _str; \
43 Metadata##obj::TraceMsg(MetadataTraceBuf, __FILE__, __LINE__, _str.str()); \
46 std::map<uint16_t, std::string>
48 (404,
"404 Not Found")
49 (500,
"500 Internal Server Error")
50 (501,
"501 Not Implemented")
51 (502,
"502 Bad Gateway")
52 (503,
"503 Service Unavailable")
53 (504,
"504 Gateway Timeout");
65 isc_hmacsha256_t hmacsha256;
66 isc_hmacsha256_init(&hmacsha256, (
const unsigned char *)key.c_str(),
68 isc_hmacsha256_update(&hmacsha256, (
const isc_uint8_t *)data.c_str(),
70 unsigned char hmac_sha256_digest[ISC_SHA512_DIGESTLENGTH];
71 isc_hmacsha256_sign(&hmacsha256, hmac_sha256_digest,
72 ISC_SHA256_DIGESTLENGTH);
73 std::stringstream str;
74 for (
unsigned int i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) {
75 str << std::hex << std::setfill(
'0') << std::setw(2)
76 << (int) hmac_sha256_digest[i];
84 const std::string &secret)
85 : services_(module), shared_secret_(secret),
86 http_server_(new
MetadataServer(services_->agent()->event_manager())),
87 http_server6_(new
MetadataServer(services_->agent()->event_manager())),
88 http_client_(new
MetadataClient(services_->agent()->event_manager())) {
112 SessionMap::iterator next = ++it;
144 bool conn_close =
false;
145 std::vector<std::string> header_options;
146 std::string vm_ip, vm_uuid, vm_project_uuid;
153 if (ip.to_string().find(
"fe80") == 0) {
154 int i_percent = ip.to_string().find(
'%');
155 std::string ip_str = ip.to_string().substr(0, i_percent);
156 ip = boost::asio::ip::address::from_string(ip_str);
161 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
163 <<
"; Request for VM : " << ip);
176 for (HttpRequest::HeaderMap::const_iterator it = req_header.begin();
177 it != req_header.end(); ++it) {
178 std::string option = boost::to_lower_copy(it->first);
179 if (option ==
"host") {
182 if (option ==
"connection") {
183 std::string val = boost::to_lower_copy(it->second);
188 header_options.push_back(std::string(it->first +
": " + it->second));
194 boost::replace_all(vm_project_uuid,
"-",
"");
195 header_options.push_back(std::string(
"X-Forwarded-For: " + vm_ip));
196 header_options.push_back(std::string(
"X-Instance-ID: " + vm_uuid));
197 header_options.push_back(std::string(
"X-Tenant-ID: " + vm_project_uuid));
198 header_options.push_back(std::string(
"X-Instance-ID-Signature: " +
201 std::string uri = request->
UrlPath();
204 const std::string &body = request->
Body();
206 std::string nova_hostname;
209 if (!nova_hostname.empty()) {
210 header_options.insert(header_options.begin(),
211 std::string(
"Host: " + nova_hostname));
217 conn->
HttpGet(uri,
true,
false,
true, header_options,
221 <<
" URL : " << uri);
226 conn->
HttpHead(uri,
true,
false,
true, header_options,
230 <<
" URL : " << uri);
235 conn->
HttpPost(body, uri,
true,
false,
true, header_options,
239 <<
" URL : " << uri);
244 conn->
HttpPut(body, uri,
true,
false,
true, header_options,
248 <<
" URL : " << uri);
253 conn->
HttpDelete(uri,
true,
false,
true, header_options,
257 <<
" URL : " << uri);
263 <<
"Request Method: " << request->
GetMethod()
264 <<
"; Request for VM: " << vm_ip);
277 <<
"Request Method: " << request->
GetMethod()
278 <<
"; Request for VM : " << vm_ip);
295 std::string &msg, boost::system::error_code &ec) {
296 bool delete_session =
false;
297 boost::asio::ip::address ip = session->remote_endpoint().address();
304 std::string vm_ip, vm_uuid, vm_project_uuid;
306 if (ip.to_string().find(
"fe80") == 0) {
307 int i_percent = ip.to_string().find(
'%');
308 std::string ip_str = ip.to_string().substr(0, i_percent);
309 ip = boost::asio::ip::address::from_string(ip_str);
313 FindVmUuidFromMetadataIp(ip, &vm_ip, &vm_uuid, &vm_project_uuid)) {
314 LOG(ERROR,
"UUID was not found for ip=" << ip.to_string() <<
315 ", in MetadataProxy::HandleMetadataResponse" <<
322 session->Send(reinterpret_cast<const u_int8_t *>(msg.c_str()),
326 boost::system::system_error(ec).what());
329 delete_session =
true;
334 if (!ec && it->second.close_req) {
335 std::stringstream str(msg);
338 if (option ==
"Content-Length:") {
339 str >> it->second.content_len;
340 }
else if (msg ==
"\r\n") {
341 it->second.header_end =
true;
342 if (it->second.header_end && !it->second.content_len) {
345 delete_session =
true;
347 }
else if (it->second.header_end) {
348 it->second.data_sent += msg.length();
349 if (it->second.data_sent >= it->second.content_len) {
352 delete_session =
true;
359 if (delete_session) {
392 ConnectionSessionMap::iterator it =
415 std::string *nova_hostname) {
418 it->second.close_req = conn_close;
419 return it->second.conn;
422 uint16_t linklocal_port = session->
local_port();
426 std::string md_service_name;
428 if (linklocal_server.is_v4() &&
431 nova_hostname, &nova_server, &nova_port)) {
435 if (linklocal_server.is_v6() &&
438 nova_hostname, &nova_server, &nova_port)) {
442 HttpConnection *conn = (nova_hostname != 0 && !nova_hostname->empty()) ?
446 map<CURLoption, int> *curl_options = conn->
curl_options();
447 curl_options->insert(std::make_pair(CURLOPT_HTTP_TRANSFER_DECODING, 0L));
487 snprintf(body,
sizeof(body),
"<html>\n"
489 " <title>%s</title>\n"
491 "</html>\n", message.c_str());
493 snprintf(response,
sizeof(response),
495 "Content-Type: text/html; charset=UTF-8\n"
496 "Content-Length: %u\n"
497 "\n%s", message.c_str(), (
unsigned int) strlen(body), body);
498 session->
Send(reinterpret_cast<const u_int8_t *>(response),
499 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)