diff options
author | Alessandro Pilotti <apilotti@cloudbasesolutions.com> | 2017-01-20 19:31:59 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-20 19:31:59 +0300 |
commit | 431022a60c1657db1ee6d0f6ef7607c2172dae10 (patch) | |
tree | ff9f48abef1bb68ad802ea4bcd4cd5dc471ddac5 | |
parent | 88ef086ba4f0c395dc48badab7868dba3ac285de (diff) | |
parent | e4492a23041aeb27f2031b9ce418a9205e9d8ea1 (diff) |
Merge pull request #157 from c64cosmin/master
Added Keystone v3 API
-rw-r--r-- | wsgate/nova_token_auth.cpp | 176 | ||||
-rw-r--r-- | wsgate/nova_token_auth.hpp | 7 | ||||
-rw-r--r-- | wsgate/wsgate.ini.sample.in | 3 | ||||
-rw-r--r-- | wsgate/wsgateEHS.cpp | 14 | ||||
-rw-r--r-- | wsgate/wsgateEHS.hpp | 2 |
5 files changed, 168 insertions, 34 deletions
diff --git a/wsgate/nova_token_auth.cpp b/wsgate/nova_token_auth.cpp index 5008e1e..7c5cd06 100644 --- a/wsgate/nova_token_auth.cpp +++ b/wsgate/nova_token_auth.cpp @@ -20,6 +20,7 @@ #include <cpprest/json.h> #include "nova_token_auth.hpp" +#include <iostream> using namespace pplx; using namespace std; @@ -27,36 +28,44 @@ using namespace web; using namespace wsgate; using namespace utility::conversions; - class nova_console_token_auth_impl : public nova_console_token_auth { private: - web::json::value execute_request_and_get_json_value( + web::http::http_response execute_request_and_get_response( web::http::client::http_client& client, web::http::http_request& request); - web::json::value get_auth_token_data(std::string osAuthUrl, - std::string osUserName, - std::string osPassword, - std::string osTenantName); + web::json::value get_json_from_response(web::http::http_response response); + + std::pair<std::string, std::string> get_auth_token_data_v2(std::string osAuthUrl, + std::string osUserName, + std::string osPassword, + std::string osTenantName, + std::string osRegion); + + std::pair<std::string, std::string> get_auth_token_data_v3(std::string osAuthUrl, + std::string osUserName, + std::string osPassword, + std::string osTenantName, + std::string osRegion); web::json::value get_console_token_data(std::string authToken, std::string novaUrl, std::string consoleToken); - utility::string_t get_nova_url(web::json::value token_data); - public: virtual nova_console_info get_console_info(std::string osAuthUrl, std::string osUserName, std::string osPassword, std::string osTenantName, - std::string consoleToken); + std::string consoleToken, + std::string keystoneVersion, + std::string osRegion); }; -json::value nova_console_token_auth_impl::execute_request_and_get_json_value( +http::http_response nova_console_token_auth_impl::execute_request_and_get_response( http::client::http_client& client, http::http_request& request) { @@ -69,15 +78,22 @@ json::value nova_console_token_auth_impl::execute_request_and_get_json_value( throw http_exception(response.status_code(), to_utf8string(response.reason_phrase())); } + return response; +} + +json::value nova_console_token_auth_impl::get_json_from_response( + http::http_response response) +{ auto json_task = response.extract_json(); json_task.wait(); return json_task.get(); } -json::value nova_console_token_auth_impl::get_auth_token_data( +std::pair<std::string, std::string> nova_console_token_auth_impl::get_auth_token_data_v2( string osAuthUrl, string osUserName, - string osPassword, string osTenantName) + string osPassword, string osTenantName, + string osRegion) { auto jsonRequestBody = json::value::object(); auto auth = json::value::object(); @@ -94,7 +110,95 @@ json::value nova_console_token_auth_impl::get_auth_token_data( request.set_body(jsonRequestBody); http::client::http_client client(to_string_t(osAuthUrl)); - return execute_request_and_get_json_value(client, request); + auto response_json = get_json_from_response(execute_request_and_get_response(client, request)); + + utility::string_t authToken; + utility::string_t novaUrl; + //get the authentication token + authToken = response_json[U("access")][U("token")][U("id")].as_string(); + + //get the nova api endpoint + for (auto serviceCatalog : response_json[U("access")][U("serviceCatalog")].as_array()) + if (serviceCatalog[U("name")].as_string() == U("nova")){ + if (osRegion.empty()){ + novaUrl = serviceCatalog[U("endpoints")][0][U("adminURL")].as_string(); + } + else{ + for (auto endpoint : serviceCatalog[U("endpoints")].as_array()){ + if (endpoint[U("region")].as_string() == to_string_t(osRegion)){ + novaUrl = endpoint[U("adminURL")].as_string(); + } + } + } + } + + + return std::pair<std::string, std::string>( + to_utf8string(authToken), + to_utf8string(novaUrl)); +} + +std::pair<std::string, std::string> nova_console_token_auth_impl::get_auth_token_data_v3( + string osAuthUrl, string osUserName, + string osPassword, string osTenantName, + string osRegion) +{ + auto jsonRequestBody = json::value::object(); + auto auth = json::value::object(); + auto identity = json::value::object(); + auto methods = json::value::array(); + methods[0] = json::value::string(to_string_t("password")); + + auto password = json::value::object(); + auto user = json::value::object(); + user[U("name")] = json::value::string(to_string_t(osUserName)); + user[U("password")] = json::value::string(to_string_t(osPassword)); + + auto domain = json::value::object(); + domain[U("id")] = json::value::string(to_string_t("default")); + + user[U("domain")] = domain; + password[U("user")] = user; + identity[U("methods")] = methods; + identity[U("password")] = password; + + auto scope = json::value::object(); + auto project = json::value::object(); + project[U("name")] = json::value::string(to_string_t(osTenantName)); + project[U("domain")] = domain; + scope[U("project")] = project; + + auth[U("identity")] = identity; + auth[U("scope")] = scope; + jsonRequestBody[U("auth")] = auth; + + http::http_request request(http::methods::POST); + request.set_request_uri(U("auth/tokens")); + request.headers().add(http::header_names::accept, U("application/json")); + request.headers().set_content_type(U("application/json")); + request.set_body(jsonRequestBody); + + http::client::http_client client(to_string_t(osAuthUrl)); + auto response = execute_request_and_get_response(client, request); + auto response_json = get_json_from_response(response); + + utility::string_t authToken; + utility::string_t novaUrl; + //get the authentication token + authToken = response.headers()[U("X-Subject-Token")]; + + //get the nova api endpoint + for (auto serviceCatalog : response_json[U("token")][U("catalog")].as_array()) + if (serviceCatalog[U("name")].as_string() == U("nova")) + for (auto endpoint : serviceCatalog[U("endpoints")].as_array()) + if (endpoint[U("interface")].as_string() == U("admin") && + (endpoint[U("region")].as_string() == to_string_t(osRegion) || osRegion.empty())){ + novaUrl = endpoint[U("url")].as_string(); + } + + return std::pair<std::string, std::string>( + to_utf8string(authToken), + to_utf8string(novaUrl)); } json::value nova_console_token_auth_impl::get_console_token_data( @@ -111,35 +215,43 @@ json::value nova_console_token_auth_impl::get_console_token_data( request.headers().add(http::header_names::accept, U("application/json")); request.headers().set_content_type(U("application/json")); - return execute_request_and_get_json_value(client, request); -} - -utility::string_t nova_console_token_auth_impl::get_nova_url(web::json::value token_data) -{ - for (auto serviceCatalog : token_data[U("access")][U("serviceCatalog")].as_array()) - if (serviceCatalog[U("name")].as_string() == U("nova")) - return serviceCatalog[U("endpoints")][0][U("adminURL")].as_string(); + return get_json_from_response(execute_request_and_get_response(client, request)); } nova_console_info nova_console_token_auth_impl::get_console_info( std::string osAuthUrl, std::string osUserName, std::string osPassword, std::string osTenantName, - std::string consoleToken) + std::string consoleToken, std::string keystoneVersion, + std::string osRegion) { - auto token_data = get_auth_token_data(osAuthUrl, osUserName, - osPassword, osTenantName); - - auto novaUrl = get_nova_url(token_data); + std::string authToken; + std::string novaUrl; + + if (keystoneVersion == KEYSTONE_V2){ + std::tie(authToken, novaUrl) = get_auth_token_data_v2(osAuthUrl, + osUserName, + osPassword, + osTenantName, + osRegion); + } + else if (keystoneVersion == KEYSTONE_V3){ + std::tie(authToken, novaUrl) = get_auth_token_data_v3(osAuthUrl, + osUserName, + osPassword, + osTenantName, + osRegion); + } + else{ + throw std::invalid_argument("Unknown Keystone version"); + } - auto authToken = token_data[U("access")][U("token")] - [U("id")].as_string(); + nova_console_info info; - auto consoleTokenData = get_console_token_data(to_utf8string(authToken), - to_utf8string(novaUrl), + auto consoleTokenData = get_console_token_data( + authToken, + novaUrl, consoleToken); - nova_console_info info; - info.host = to_utf8string(consoleTokenData[U("console")][U("host")].as_string()); auto portValue = consoleTokenData[U("console")][U("port")]; diff --git a/wsgate/nova_token_auth.hpp b/wsgate/nova_token_auth.hpp index 45fd9c8..d8f4332 100644 --- a/wsgate/nova_token_auth.hpp +++ b/wsgate/nova_token_auth.hpp @@ -21,6 +21,9 @@ #include <exception> #include <string> +#define KEYSTONE_V2 "v2.0" +#define KEYSTONE_V3 "v3" + namespace wsgate { class http_exception: public std::exception { @@ -66,7 +69,9 @@ namespace wsgate { std::string osUserName, std::string osPassword, std::string osTenantName, - std::string consoleToken) = 0; + std::string consoleToken, + std::string keystoneVersion, + std::string osRegion) = 0; }; diff --git a/wsgate/wsgate.ini.sample.in b/wsgate/wsgate.ini.sample.in index 8b9a80f..c4a9c93 100644 --- a/wsgate/wsgate.ini.sample.in +++ b/wsgate/wsgate.ini.sample.in @@ -151,9 +151,12 @@ nofullwindowdrag = true [openstack] #authurl = http://10.0.0.1:5000/v2.0 +#Specify the version for keystone +#keystoneversion = v2.0 or v3 #username = admin #password = secret #tenantname = admin +#region = optional region [hyperv] diff --git a/wsgate/wsgateEHS.cpp b/wsgate/wsgateEHS.cpp index fd4998c..bd75806 100644 --- a/wsgate/wsgateEHS.cpp +++ b/wsgate/wsgateEHS.cpp @@ -287,7 +287,7 @@ namespace wsgate{ nova_console_info info = token_auth->get_console_info(m_sOpenStackAuthUrl, m_sOpenStackUsername, m_sOpenStackPassword, m_sOpenStackTenantName, - tokenId); + tokenId, m_sOpenStackKeystoneVersion, m_sOpenStackRegion); log::info << "Host: " << info.host << " Port: " << info.port << " Internal access path: " << info.internal_access_path @@ -919,6 +919,18 @@ namespace wsgate{ } else { m_sOpenStackTenantName.clear(); } + if (pt.get_optional<std::string>("openstack.keystoneversion")) { + m_sOpenStackKeystoneVersion.assign(pt.get<std::string>("openstack.keystoneversion")); + } + else { + m_sOpenStackKeystoneVersion = KEYSTONE_V2; + } + if (pt.get_optional<std::string>("openstack.region")) { + m_sOpenStackRegion.assign(pt.get<std::string>("openstack.region")); + } + else { + m_sOpenStackRegion.clear(); + } if (pt.get_optional<std::string>("hyperv.hostusername")) { m_sHyperVHostUsername.assign(pt.get<std::string>("hyperv.hostusername")); } else { diff --git a/wsgate/wsgateEHS.hpp b/wsgate/wsgateEHS.hpp index ef72cef..27499e5 100644 --- a/wsgate/wsgateEHS.hpp +++ b/wsgate/wsgateEHS.hpp @@ -115,6 +115,8 @@ namespace wsgate{ string m_sOpenStackUsername; string m_sOpenStackPassword; string m_sOpenStackTenantName; + string m_sOpenStackKeystoneVersion; + string m_sOpenStackRegion; string m_sHyperVHostUsername; string m_sHyperVHostPassword; |