From 2465d3eebc3ae8b951305972ed6fd9210ce286d3 Mon Sep 17 00:00:00 2001 From: Biswajit Mandal Date: Tue, 26 Jul 2016 23:10:05 +0530 Subject: [PATCH] Closes-Bug: #1606646 Post node version 0.9.1, tls, https: validate server certificate by default. So in case self signed certificate, UI will not work with https request to openstack services. https://github.com/mscdex/node-imap/issues/181#issuecomment-14781480 Fix: Added rejectUnauthorized flag. In node post v0.11.14, we have custom checkServerIdentity in options to have more control. UT Results: +++++++++++ contrail-web-controller: ------------------------ PhantomJS 1.9.8 (Mac OS X 10.9.5): Executed 376 of 376 SUCCESS (1 min 41.645 secs / 1 min 39.143 secs) Done, without errors. contrail-web-server-manager: ---------------------------- PhantomJS 1.9.8 (Mac OS X 10.9.5): Executed 89 of 89 SUCCESS (11.9 secs / 11.643 secs) Done, without errors. contrail-web-storage: -------------------- PhantomJS 1.9.8 (Mac OS X 0.0.0): Executed 84 of 84 SUCCESS (20.301 secs / 18.748 secs) Done, without errors. Change-Id: Iec589a59b5ae153c3b6a57ad1e96a025c8a9280e (cherry picked from commit 60c214946aa0ceb34e668a212a41036b693e63df) Avoid passing an empty 'data' object to restler.get calls. Restler changes Content-Type to 'application/x-www-form-urlencoded' even for GET requests, as long as data is not a string. That breaks some nova API calls when Mitaka nova-api is used, as it now expects to get "application/json" for all queries. Make sure we pass data object only for POST and PUT calls. Change-Id: Ieaf1622dec703404d9672681a9cd0d35199326d7 Closes-Bug: 1591393 (cherry picked from commit f10620ede1f9f28858a9b418ec26093c57f00c41) Closes-Bug: #1605163 This is side effect of the below fix: https://github.com/Juniper/contrail-web-core/commit/f10620ede1f9f28858a9b418ec26093c57f00c41 Comuting data before Content-Length header assignement. Change-Id: I100ab66856595688e97a74a54ce534fcdc201a36 (cherry picked from commit 15ba7405f1a000dcf3537cef7c2191f91a1c0fb5) --- src/serverroot/common/httpsoptions.api.js | 7 ++-- src/serverroot/common/rest.api.js | 41 +++++++++++++++++++---- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/serverroot/common/httpsoptions.api.js b/src/serverroot/common/httpsoptions.api.js index 7e15a423a..e049d3b50 100644 --- a/src/serverroot/common/httpsoptions.api.js +++ b/src/serverroot/common/httpsoptions.api.js @@ -143,12 +143,11 @@ function updateHttpsSecureOptions (apiType, options) logutils.logger.error('readFileSync error for ca file' + e); } } - /* If strictSSL is set to false, then if response.client.authorized - * is set as false, a secure connection is established. - */ + /* https://github.com/mscdex/node-imap/issues/181 */ + options['rejectUnauthorized'] = false; var strictSSL = getHttpsOptionsByAPIType(apiType, 'strictSSL'); if (null != strictSSL) { - options['strictSSL'] = strictSSL; + options['rejectUnauthorized'] = strictSSL; } } return options; diff --git a/src/serverroot/common/rest.api.js b/src/serverroot/common/rest.api.js index e141f16de..885e88a0f 100644 --- a/src/serverroot/common/rest.api.js +++ b/src/serverroot/common/rest.api.js @@ -3,6 +3,7 @@ */ var http = require('http'), + https = require('https'), config = process.mainModule.exports.config, logutils = require('../utils/log.utils'), messages = require('./messages'), @@ -133,9 +134,31 @@ APIServer.prototype.updateDiscoveryServiceParams = function (params) APIServer.prototype.makeHttpsRestCall = function (options, callback) { - request(options, function(err, response, data) { - callback(err, data, response); + var method = options['method']; + var req = https.request(options, function (res) { + var result = ''; + res.on('data', function (chunk) { + result += chunk; + }); + res.on('end', function () { + callback(null, result, res); + }); + res.on('error', function (err) { + callback(err); + }) }); + + // req error + req.on('error', function (err) { + logutils.logger.error(err.stack); + callback(err); + }); + + //send request with the postData form + if (('POST' == method) || ('PUT' == method)) { + req.write(options['data']); + } + req.end(); } /** Retry the REST API Call, once it fails @@ -222,11 +245,10 @@ APIServer.prototype.makeCall = function (restApi, params, callback, isRetry) var self = this; var reqUrl = null; var options = {}; - var data = commonUtils.getApiPostData(params['path'], params['data']); var method = params['method']; var xml2jsSettings = params['xml2jsSettings']; + var data = commonUtils.getApiPostData(params['path'], params['data']); options['headers'] = params['headers'] || {}; - options['data'] = data || {}; options['method'] = method; options['headers']['Content-Length'] = (data) ? data.toString().length : 0; @@ -235,24 +257,29 @@ APIServer.prototype.makeCall = function (restApi, params, callback, isRetry) we need to specify the Content-Type as App/JSON with JSON.stringify of the data, otherwise, restler treats it as application/x-www-form-urlencoded as Content-Type and encodes - the data accordingly + the data accordingly. Restler also changes Content-Type when + an empty data object is passed for GET queries, so make sure + we are don't pass it. */ + options['data'] = data || {}; options['headers']['Content-Type'] = 'application/json'; } params = self.updateDiscoveryServiceParams(params); - options['parser'] = restler.parsers.auto; options = httpsOp.updateHttpsSecureOptions(self.name, options); if ((null != options['headers']) && (null != options['headers']['protocol']) && (global.PROTOCOL_HTTPS == options['headers']['protocol'])) { delete options['headers']['protocol']; reqUrl = global.HTTPS_URL + params.url + ':' + params.port + params.path; - options['uri'] = reqUrl; options['body'] = options['data']; if (('POST' != method) && ('PUT' != method)) { delete options['data']; delete options['body']; } + options['hostname'] = params.url; + options['port'] = params.port; + options['path'] = params.path; + self.makeHttpsRestCall(options, function(err, data, response) { if (null != err) { try {