Skip to content

Commit

Permalink
Support for ssl connection to the api-server from analytics services
Browse files Browse the repository at this point in the history
Added api_server_use_ssl option to enable/disable ssl connection to the
api-server in contrail-collector, contrail-alarm-gen,
contrail-snmp-collector and contrail-topology.

Change-Id: I657ce76cc742e1e1c558803bb46c76c24b4c1dd5
Closes-Bug: #1671296
  • Loading branch information
Sundaresan Rajangam committed Mar 22, 2017
1 parent c00e33f commit f9b1f84
Show file tree
Hide file tree
Showing 18 changed files with 119 additions and 40 deletions.
8 changes: 4 additions & 4 deletions src/analytics/configdb_connection.cc
Expand Up @@ -19,8 +19,8 @@ ConfigDBConnection::ConfigDBConnection(EventManager *evm,
api_server_index_(-1) {
if (!api_server_list_.empty()) {
api_server_index_ = 0;
vnccfg_.cfg_srv_ip = api_server_list_[0].first;
vnccfg_.cfg_srv_port = api_server_list_[0].second;
vnccfg_.api_srv_ip = api_server_list_[0].first;
vnccfg_.api_srv_port = api_server_list_[0].second;
InitVnc();
}
}
Expand Down Expand Up @@ -48,8 +48,8 @@ ConfigDBConnection::RetryNextApi() {
if (++api_server_index_ == static_cast<int>(api_server_list_.size())) {
api_server_index_ = 0;
}
vnccfg_.cfg_srv_ip = api_server_list_[api_server_index_].first;
vnccfg_.cfg_srv_port = api_server_list_[api_server_index_].second;
vnccfg_.api_srv_ip = api_server_list_[api_server_index_].first;
vnccfg_.api_srv_port = api_server_list_[api_server_index_].second;
lock.release();
InitVnc();
}
Expand Down
1 change: 1 addition & 0 deletions src/analytics/contrail-collector.conf
Expand Up @@ -83,6 +83,7 @@ log_local=1
[API_SERVER]
# List of api-servers in ip:port format separated by space
# api_server_list=127.0.0.1:8082
# api_server_use_ssl=False

[DATABASE]
# disk usage percentage
Expand Down
@@ -1,5 +1,4 @@
[DEFAULTS]
#api_server=127.0.0.1:8082
#collectors=ip1:8086 ip2:8086
#fast_scan_frequency=60
#http_server_port=5920
Expand All @@ -12,6 +11,7 @@ log_file=/var/log/contrail/contrail-snmp-collector.log
[API_SERVER]
# List of api-servers in ip:port format separated by space
#api_server_list=127.0.0.1:8082
#api_server_use_ssl=False

[KEYSTONE]
#keystone parameters come from contrail-keystone-auth.conf
Expand Down
Expand Up @@ -86,14 +86,15 @@ def fom_file(filename):
return devices

@staticmethod
def get_vnc(usr, passwd, tenant, api_servers, auth_host=None,
auth_port=None, auth_protocol=None, notifycb=None):
def get_vnc(usr, passwd, tenant, api_servers, use_ssl=False,
auth_host=None, auth_port=None, auth_protocol=None, notifycb=None):
e = IOError('Api servers (%s) not reachable' % ','.join(api_servers))
while True:
for api_server in api_servers:
srv = api_server.split(':')
try:
vnc = VncApi(usr, passwd, tenant, srv[0], srv[1],
api_server_use_ssl=use_ssl,
auth_host=auth_host, auth_port=auth_port,
auth_protocol=auth_protocol)
if callable(notifycb):
Expand All @@ -107,13 +108,14 @@ def get_vnc(usr, passwd, tenant, api_servers, auth_host=None,
time.sleep(3)

@staticmethod
def fom_api_server(api_servers, usr, passwd, tenant, auth_host=None,
auth_port=None, auth_protocol=None, notifycb=None):
def fom_api_server(api_servers, usr, passwd, tenant, use_ssl=False,
auth_host=None, auth_port=None, auth_protocol=None, notifycb=None):
while True:
try:
vnc = DeviceConfig.get_vnc(usr, passwd, tenant, api_servers,
auth_host=auth_host, auth_port=auth_port,
auth_protocol=auth_protocol, notifycb=notifycb)
use_ssl=use_ssl, auth_host=auth_host,
auth_port=auth_port, auth_protocol=auth_protocol,
notifycb=notifycb)
devices = map(lambda e: DeviceDict(e['fq_name'][-1], vnc, **e),
vnc.physical_routers_list()[
'physical-routers'])
Expand Down
Expand Up @@ -90,7 +90,8 @@ def parse(self):
'cluster_id' :'',
}
api_opts = {
'api_server_list' : ['127.0.0.1:8082']
'api_server_list' : ['127.0.0.1:8082'],
'api_server_use_ssl' : False
}
ksopts = {
'auth_host': '127.0.0.1',
Expand Down Expand Up @@ -195,6 +196,8 @@ def parse(self):
parser.add_argument("--api_server_list",
help="List of api-servers in ip:port format separated by space",
nargs="+")
parser.add_argument("--api_server_use_ssl",
help="Use SSL to connect to api-server")
group = parser.add_mutually_exclusive_group(required=False)
group.add_argument("--device-config-file",
help="where to look for snmp credentials")
Expand All @@ -217,6 +220,7 @@ def devices(self):
self._args.api_server_list,
self._args.admin_user, self._args.admin_password,
self._args.admin_tenant_name,
self._args.api_server_use_ssl,
self._args.auth_host, self._args.auth_port,
self._args.auth_protocol, self._cb)
return self._devices
Expand Down
1 change: 1 addition & 0 deletions src/analytics/contrail-topology/contrail-topology.conf
Expand Up @@ -11,6 +11,7 @@ log_file=/var/log/contrail/contrail-topology.log
[API_SERVER]
# List of api-servers in ip:port format separated by space
#api_server_list=127.0.0.1:8082
#api_server_use_ssl=False

[SANDESH]
#sandesh_ssl_enable=False
Expand Down
6 changes: 5 additions & 1 deletion src/analytics/contrail-topology/contrail_topology/config.py
Expand Up @@ -80,7 +80,8 @@ def parse(self):
'cluster_id' : '',
}
api_opts = {
'api_server_list' : ['127.0.0.1:8082']
'api_server_list' : ['127.0.0.1:8082'],
'api_server_use_ssl' : False
}
ksopts = {
'auth_host': '127.0.0.1',
Expand Down Expand Up @@ -188,6 +189,8 @@ def parse(self):
parser.add_argument("--api_server_list",
help="List of api-servers in ip:port format separated by space",
nargs="+")
parser.add_argument("--api_server_use_ssl",
help="Use SSL to connect to api-server")

self._args = parser.parse_args(remaining_argv)
if type(self._args.collectors) is str:
Expand Down Expand Up @@ -270,6 +273,7 @@ def vnc_api(self, notifycb=None):
self._args.admin_password,
self._args.admin_tenant_name,
srv[0], srv[1],
api_server_use_ssl=self._args.api_server_use_ssl,
auth_host=self._args.auth_host,
auth_port=self._args.auth_port,
auth_protocol=self._args.auth_protocol)
Expand Down
12 changes: 8 additions & 4 deletions src/analytics/main.cc
Expand Up @@ -340,12 +340,16 @@ int main(int argc, char *argv[])
api_server_port));
}
VncApiConfig api_config;
api_config.api_use_ssl = options.api_server_use_ssl();
api_config.ks_srv_ip = options.auth_host();
api_config.ks_srv_port = options.auth_port();
api_config.protocol = options.auth_protocol();
api_config.user = options.auth_user();
api_config.password = options.auth_passwd();
api_config.tenant = options.auth_tenant();
api_config.ks_protocol = options.auth_protocol();
api_config.ks_user = options.auth_user();
api_config.ks_password = options.auth_passwd();
api_config.ks_tenant = options.auth_tenant();
api_config.ks_keyfile = options.keystone_keyfile();
api_config.ks_certfile = options.keystone_certfile();
api_config.ks_cafile = options.keystone_cafile();

VizCollector analytics(a_evm,
options.collector_port(),
Expand Down
5 changes: 5 additions & 0 deletions src/analytics/options.cc
Expand Up @@ -416,6 +416,9 @@ void Options::Initialize(EventManager &evm,
opt::value<vector<string> >()->default_value(
default_api_server_list, default_api_server),
"Api-Server list")
("API_SERVER.api_server_use_ssl",
opt::bool_switch(&api_server_use_ssl_),
"Use ssl for connecting to Api-Server")
;

config_file_options_.add(config).add(cassandra_config)
Expand Down Expand Up @@ -707,4 +710,6 @@ void Options::Process(int argc, char *argv[],

GetOptValue< vector<string> >(var_map, api_server_list_,
"API_SERVER.api_server_list");
GetOptValue<bool>(var_map, api_server_use_ssl_,
"API_SERVER.api_server_use_ssl");
}
5 changes: 5 additions & 0 deletions src/analytics/options.h
Expand Up @@ -210,10 +210,14 @@ class Options {
const std::string auth_user() const { return ks_user_; }
const std::string auth_passwd() const { return ks_password_; }
const std::string auth_tenant() const { return ks_tenant_; }
const std::string keystone_keyfile() const { return ks_key_; }
const std::string keystone_certfile() const { return ks_cert_; }
const std::string keystone_cafile() const { return ks_ca_; }
const SandeshConfig &sandesh_config() const { return sandesh_config_; }
const std::vector<std::string> api_server_list() const {
return api_server_list_;
}
const bool api_server_use_ssl() const { return api_server_use_ssl_; }

private:
template <typename ValueType>
Expand Down Expand Up @@ -297,6 +301,7 @@ class Options {
std::string ks_ca_;
SandeshConfig sandesh_config_;
std::vector<std::string> api_server_list_;
bool api_server_use_ssl_;

boost::program_options::options_description config_file_options_;
DbWriteOptions db_write_options_;
Expand Down
46 changes: 39 additions & 7 deletions src/http/client/vncapi.cc
Expand Up @@ -5,6 +5,7 @@
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include "base/util.h"
#include "base/logging.h"
#include "base/test/task_test_util.h"
#include <iomanip>
#include <ctype.h>
Expand All @@ -16,6 +17,8 @@
#include <rapidjson/stringbuffer.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include "vncapi.h"

Expand Down Expand Up @@ -112,12 +115,19 @@ void
VncApi::Reauthenticate(RespBlock *orb)
{
if (client_) {
RespBlock *rb = new RespBlock(client_->CreateConnection(ks_ep_),
"v2.0/tokens", 0);
HttpConnection *conn = client_->CreateConnection(ks_ep_);
if (cfg_->ks_protocol == "https") {
conn->set_use_ssl(true);
conn->set_client_cert(cfg_->ks_certfile);
conn->set_client_cert_type("PEM");
conn->set_client_key(cfg_->ks_keyfile);
conn->set_ca_cert(cfg_->ks_cafile);
}
RespBlock *rb = new RespBlock(conn, "v2.0/tokens", 0);
std::ostringstream pstrm;
pstrm << "{\"auth\": {\"passwordCredentials\": {\"username\": \"" <<
cfg_->user << "\", \"password\": \"" << cfg_->password <<
"\"}, \"tenantName\": \"" << cfg_->tenant << "\"}}";
cfg_->ks_user << "\", \"password\": \"" << cfg_->ks_password <<
"\"}, \"tenantName\": \"" << cfg_->ks_tenant << "\"}}";
rb->GetConnection()->HttpPost(pstrm.str(), rb->GetUri(), false, false,
true, kshdr_, boost::bind(&VncApi::KsRespHandler,
shared_from_this(), rb, orb, _1, _2));
Expand Down Expand Up @@ -240,14 +250,28 @@ VncApi::VncApi(EventManager *evm, VncApiConfig *cfg) : evm_(evm), cfg_(cfg),
SetApiServerAddress();
ks_ep_.address(boost::asio::ip::address::from_string(cfg_->ks_srv_ip, ec));
ks_ep_.port(cfg_->ks_srv_port);
if (cfg_->api_use_ssl) {
boost::property_tree::ptree pt;
try {
boost::property_tree::ini_parser::read_ini(
"/etc/contrail/vnc_api_lib.ini", pt);
} catch (const boost::property_tree::ptree_error &e) {
LOG(ERROR, "Failed to parse /etc/contrail/vnc_api_lib.ini : " <<
e.what());
exit(1);
}
cfg_->api_keyfile = pt.get<std::string>("global.keyfile", "");
cfg_->api_certfile = pt.get<std::string>("global.certfile", "");
cfg_->api_cafile = pt.get<std::string>("global.cafile", "");
}
}

void
VncApi::SetApiServerAddress() {
boost::system::error_code ec;
api_ep_.address(boost::asio::ip::address::from_string(cfg_->cfg_srv_ip,
api_ep_.address(boost::asio::ip::address::from_string(cfg_->api_srv_ip,
ec));
api_ep_.port(cfg_->cfg_srv_port);
api_ep_.port(cfg_->api_srv_port);
}

void
Expand All @@ -272,7 +296,15 @@ VncApi::GetConfig(std::string type, std::vector<std::string> ids,
std::map<std::string, std::string> *headers)> cb)
{
if (client_) {
RespBlock *rb = new RespBlock(client_->CreateConnection(api_ep_),
HttpConnection *conn = client_->CreateConnection(api_ep_);
if (cfg_->api_use_ssl) {
conn->set_use_ssl(true);
conn->set_client_cert(cfg_->api_certfile);
conn->set_client_cert_type("PEM");
conn->set_client_key(cfg_->api_keyfile);
conn->set_ca_cert(cfg_->api_cafile);
}
RespBlock *rb = new RespBlock(conn,
MakeUri(type, ids, filters, parents, refs, fields), cb);
rb->GetConnection()->HttpGet(rb->GetUri(), false, false, true, hdr_,
boost::bind(&VncApi::RespHandler, shared_from_this(),
Expand Down
19 changes: 13 additions & 6 deletions src/http/client/vncapi.h
Expand Up @@ -15,14 +15,21 @@
#include <boost/enable_shared_from_this.hpp>

struct VncApiConfig {
std::string cfg_srv_ip;
int cfg_srv_port;
std::string api_srv_ip;
int api_srv_port;
bool api_use_ssl;
std::string api_keyfile;
std::string api_certfile;
std::string api_cafile;
std::string ks_srv_ip;
int ks_srv_port;
std::string protocol;
std::string user;
std::string password;
std::string tenant;
std::string ks_protocol;
std::string ks_user;
std::string ks_password;
std::string ks_tenant;
std::string ks_keyfile;
std::string ks_certfile;
std::string ks_cafile;
};

class RespBlock {
Expand Down
2 changes: 1 addition & 1 deletion src/opserver/alarmgen.py
Expand Up @@ -995,7 +995,7 @@ def __init__(self, conf, test_logger=None):
rabbitmq_params = self._conf.rabbitmq_params()
self._config_handler = AlarmGenConfigHandler(self._sandesh,
self._moduleid, self._instance_id, self.config_log,
self._conf.api_server_list(), self._conf.keystone_params(),
self._conf.api_server_config(), self._conf.keystone_params(),
rabbitmq_params, self.mgrs, self.alarm_config_change_callback)
if rabbitmq_params['servers']:
self._config_handler.start()
Expand Down
12 changes: 9 additions & 3 deletions src/opserver/alarmgen_cfg.py
Expand Up @@ -77,7 +77,8 @@ def parse(self):
}

api_opts = {
'api_server_list' : ['127.0.0.1:8082']
'api_server_list' : ['127.0.0.1:8082'],
'api_server_use_ssl' : False
}

redis_opts = {
Expand Down Expand Up @@ -226,6 +227,8 @@ def parse(self):
parser.add_argument("--api_server_list",
help="List of api-servers in ip:port format separated by space",
nargs="+")
parser.add_argument("--api_server_use_ssl",
help="Use SSL to connect to api-server")
self._args = parser.parse_args(remaining_argv)
if type(self._args.collectors) is str:
self._args.collectors = self._args.collectors.split()
Expand Down Expand Up @@ -264,8 +267,11 @@ def kafka_broker_list(self):
def zk_list(self):
return self._args.zk_list;

def api_server_list(self):
return self._args.api_server_list
def api_server_config(self):
return {
'api_server_list': self._args.api_server_list,
'api_server_use_ssl': self._args.api_server_use_ssl
}

def log_local(self):
return self._args.log_local
Expand Down
4 changes: 2 additions & 2 deletions src/opserver/alarmgen_config_handler.py
Expand Up @@ -23,12 +23,12 @@
class AlarmGenConfigHandler(ConfigHandler):

def __init__(self, sandesh_instance, module_id, instance_id, logger,
api_server_list, keystone_info, rabbitmq_info,
api_server_config, keystone_info, rabbitmq_info,
alarm_plugins, alarm_config_change_callback):
service_id = socket.gethostname()+':'+module_id+':'+instance_id
config_types = ['global-system-config', 'alarm']
super(AlarmGenConfigHandler, self).__init__(service_id, logger,
api_server_list, keystone_info, rabbitmq_info, config_types)
api_server_config, keystone_info, rabbitmq_info, config_types)
self._sandesh_instance = sandesh_instance
self._alarm_plugins = alarm_plugins
self._alarm_config_change_callback = alarm_config_change_callback
Expand Down

0 comments on commit f9b1f84

Please sign in to comment.