Support HTTP authentication

Change-Id: I7648d8a14ac7c0e65758c095fef8faf9094d9c5c
This commit is contained in:
Vitaliy Kharechko 2016-06-14 11:19:25 +03:00
parent 724700c104
commit 31dbf8e3a1
4 changed files with 151 additions and 25 deletions

View File

@ -21,6 +21,7 @@ class AgentAPI(object):
def __init__(self):
self.__httpMethod = "POST"
self.__feature = None
self.__auth = None
self.__host = None
self.__port = None
self.__payload = None
@ -64,7 +65,9 @@ class AgentAPI(object):
self.__payload["id"] = AgentAPI.__serial
AgentAPI.__serial = AgentAPI.__serial + 1
conn = AgentConnection(self.__host, self.__port, self.__feature, timeout)
return conn.makeRequest(self)
r = conn.makeRequest(self)
conn.close()
return r
def getjson(self):
x = json.dumps(OrderedDict(self.__payload))

View File

@ -21,6 +21,15 @@ import sys
import urllib
from xml.etree import ElementTree
import json
from sidauth import SIDAuth
from broadview_lib.config.broadviewconfig import BroadViewBSTSwitches
try:
from oslo_log import log as logging
except:
import logging
LOG = logging.getLogger(__name__)
class RequestObj():
pass
@ -39,11 +48,19 @@ class RequestFailed(Exception):
return repr((self._url, self._http_code, self._open_code, self._open_msg))
class AgentConnection():
def __init__(self, host, port, feature, timeout):
self.host = host
self.port = port
self.feature = feature # e.g., "bst"
self._timeout = timeout
self._swconfig = BroadViewBSTSwitches()
self._auth = None
def close(self):
if self._auth.logout:
self._auth.logout()
self._auth = None
def _is_ok(self, r):
return r.status_code == 200
@ -71,7 +88,27 @@ class AgentConnection():
raise RequestFailed(url, j["response_code"], j["error_code"], j["msg"])
def makeRequest(self, request):
def getAuth(self):
return self._auth
def getAuthConf(self):
auth = {}
auth["auth"] = None
auth["username"] = None
auth["password"] = None
conf = self._swconfig.getByIP(self.host)
if conf:
if "username" in conf:
auth["username"] = conf["username"]
if "password" in conf:
auth["password"] = conf["password"]
if "auth" in conf:
auth["auth"] = conf["auth"]
return auth
def __makeRequest(self, request):
headers = {"Content-Type": "application/json"}
timeout = False
@ -80,32 +117,23 @@ class AgentConnection():
if request.getHttpMethod() == "GET":
isGet = True
if False and isGet:
payload = request.getjson().encode("utf-8")
if self.feature:
url = "http://%s:%d/broadview/%s/%s%s%s" % (self.host, self.port, self.feature, request.getMethod(), "?req=", payload)
else:
url = "http://%s:%d/broadview/%s%s%s" % (self.host, self.port, request.getMethod(), "?req=", payload)
auth = self.getAuth()
payload = request.getjson().encode("utf-8")
if self.feature:
url = "http://%s:%d/broadview/%s/%s" % (self.host, self.port, self.feature, request.getMethod())
else:
url = "http://%s:%d/broadview/%s" % (self.host, self.port, request.getMethod())
if isGet:
try:
r = requests.get(url, timeout=self._timeout, headers=headers)
r = requests.get(url, timeout=self._timeout, data=payload, headers=headers, auth=auth)
except requests.exceptions.Timeout:
timeout = True
else:
payload = request.getjson().encode("utf-8")
if self.feature:
url = "http://%s:%d/broadview/%s/%s" % (self.host, self.port, self.feature, request.getMethod())
else:
url = "http://%s:%d/broadview/%s" % (self.host, self.port, request.getMethod())
if isGet:
try:
r = requests.get(url, timeout=self._timeout, data=payload, headers=headers)
except requests.exceptions.Timeout:
timeout = True
else:
try:
r = requests.post(url, timeout=self._timeout, data=payload, headers=headers)
except requests.exceptions.Timeout:
timeout = True
try:
r = requests.post(url, timeout=self._timeout, data=payload, headers=headers, auth=auth)
except requests.exceptions.Timeout:
timeout = True
json_data = {}
if timeout:
@ -122,6 +150,39 @@ class AgentConnection():
except:
pass
self._raise_fail_if(url, r, timeout)
return (r, json_data)
def makeRequest(self, request):
r, json_data = self.__makeRequest(request)
if r.status_code == 401:
conf = self.getAuthConf()
try:
auth_method = r.headers["WWW-Authenticate"]
except:
auth_method = None
if auth_method:
auth_method = auth_method.lower()
if auth_method == "basic":
self._auth = requests.HTTPBasicAuth(conf["username"], conf["password"])
elif auth_method == "digest":
self._auth[self.host] = requests.HTTPDigestAuth(conf["username"], conf["password"])
elif auth_method == "sidauth":
self._auth[self.host] = SIDAuth(self.host, self.port, conf["username"], conf["password"])
else:
LOG.info("unknown auth {}".format(auth_method))
return
else:
# RFC 2616 requires a WWW-Authenticate header in 401 responses. If
# we get here, it was missing. Check if there is configuration that
# declares an auth method and use that.
LOG.info("makeRequest: 401 but no WWW-Authenticate")
if conf["auth"] and conf["auth"].lower() == "sidauth":
self._auth = SIDAuth(self.host, self.port, conf["username"], conf["password"])
# try again
r, json_data = self.__makeRequest(request)
return (r.status_code, json_data)

View File

@ -35,6 +35,14 @@ class BroadViewBSTSwitches():
else:
return 0
def getByIP(self, ip):
ret = None
for x in range(self.__len__()):
if BroadViewBSTSwitches.bst_switches[x]["ip"] == ip:
ret = BroadViewBSTSwitches.bst_switches[x]
break
return ret
def get(self, i):
ret = None
if i >= 0 and i < len(BroadViewBSTSwitches.bst_switches):

View File

@ -0,0 +1,54 @@
#
# (C) Copyright Broadcom Corporation 2016
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import requests
class SIDAuth(requests.auth.AuthBase):
def __init__(self, host, port, username, password):
super(SIDAuth, self).__init__()
self._SID = None
self._host = host
self._port = port
self._username = username
self._password = password
self._login()
def _getCookie(self):
cookie = {}
if self._SID:
x = self._SID.split("=")
cookie[x[0]] = x[1]
return cookie
def _login(self):
url = "http://{}:{}/broadview/login?username={}&password={}".format(self._host, self._port, self._username, self._password)
r = requests.put(url)
code = r.status_code
if code == 200:
try:
self._SID = r.headers["Set-Cookie"]
except:
self._SID = None
def logout(self):
url = "http://{}:{}/broadview/logout".format(self._host, self._port)
r = requests.put(url, cookies=self._getCookie())
self._SID = None
def __call__(self, r):
if self._SID:
r.headers['Cookie'] = self._SID
return r