From 7735b776101987176c0b435bd15dc86734ef7b15 Mon Sep 17 00:00:00 2001 From: aviau Date: Fri, 1 May 2015 16:00:29 -0400 Subject: [PATCH] Implemented token authentication Change-Id: If5b84a12b3e489f3fcbe91222ac7d6edb8f54de8 --- README.rst | 10 +++--- requirements.txt | 3 +- surveilclient/common/http.py | 42 +++++++++++++++++++++++-- surveilclient/tests/common/test_http.py | 2 +- surveilclient/tests/test_client.py | 9 ++++-- surveilclient/v1_0/client.py | 2 +- surveilclient/v2_0/client.py | 27 ++++++++++++++-- 7 files changed, 81 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index 934e72d..9bbe009 100644 --- a/README.rst +++ b/README.rst @@ -14,6 +14,7 @@ You'll need to provide the Surveil API URL. You can do this with the variable:: export SURVEIL_API_URL=http://localhost:8080/v2 + export SURVEIL_AUTH_URL=http://localhost:8080/v2/auth You'll find complete documentation on the shell by running ``surveil help``. @@ -29,7 +30,8 @@ Python API To use the python API, simply create a client with the endpoint:: - from surveilclient import client - c = client.Client('http://localhost:8080/v2', version='2_0') - hosts = c.config.hosts.list() - + from surveilclient import client + c = client.Client('http://localhost:8080/v2', + auth_url='http://localhost:8080/v2/auth', + version='2_0') + hosts = c.config.hosts.list() diff --git a/requirements.txt b/requirements.txt index 76d2338..b9e1ac6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ oslo.serialization prettytable -pbr==0.10.4 +pbr six +requests diff --git a/surveilclient/common/http.py b/surveilclient/common/http.py index 980681a..794631a 100644 --- a/surveilclient/common/http.py +++ b/surveilclient/common/http.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import requests from six.moves import http_client as httplib from surveilclient import exc @@ -27,19 +28,51 @@ USER_AGENT = 'python-surveilclient' class HTTPClient(object): - def __init__(self, endpoint): + def __init__(self, + endpoint, + username=None, + password=None, + tenant_name=None, + auth_url=None, + authenticated=True): endpoint_parts = urlutils.urlparse(endpoint) self.endpoint_hostname = endpoint_parts.hostname self.endpoint_port = endpoint_parts.port self.endpoint_path = endpoint_parts.path + self.authenticated = authenticated + if self.authenticated: + self.auth_username = username + self.auth_password = password + self.tenant_name = tenant_name + self.auth_url = auth_url + self.auth_token = {} + + def _token_valid(self): + if self.auth_token.get('id', None) is None: + return False + # TODO(aviau): Check expiration date on token. + return True + + def _get_auth_token(self): + """Returns an auth token.""" + + if self._token_valid(): + return self.auth_token + + auth_url = self.auth_url + '/tokens' + credentials = {} + resp = requests.post(auth_url, data=json.dumps(credentials)) + access = resp.json() + self.auth_token = access['access']['token'] + return self.auth_token['id'] + def get_connection(self): # TODO(aviau): https con = httplib.HTTPConnection( self.endpoint_hostname, self.endpoint_port ) - return con def _http_request(self, url, method, **kwargs): @@ -50,6 +83,11 @@ class HTTPClient(object): """ kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {})) kwargs['headers'].setdefault('User-Agent', USER_AGENT) + + if self.authenticated: + kwargs['headers'].setdefault('X-Auth-Token', + self._get_auth_token()) + conn = self.get_connection() conn.request(method, self.endpoint_path + url, **kwargs) resp = conn.getresponse() diff --git a/surveilclient/tests/common/test_http.py b/surveilclient/tests/common/test_http.py index dfefb27..507ecd2 100644 --- a/surveilclient/tests/common/test_http.py +++ b/surveilclient/tests/common/test_http.py @@ -24,7 +24,7 @@ class TestHttp(unittest.TestCase): def setUp(self): self.surveil_url = 'http://surveil:8080/v1' - self.client = http.HTTPClient(self.surveil_url) + self.client = http.HTTPClient(self.surveil_url, authenticated=False) @httpretty.activate def test_json_request_get(self): diff --git a/surveilclient/tests/test_client.py b/surveilclient/tests/test_client.py index 2bb5d15..36daaad 100644 --- a/surveilclient/tests/test_client.py +++ b/surveilclient/tests/test_client.py @@ -22,7 +22,8 @@ from surveilclient.v2_0 import client as v2_0_client class TestClient(unittest.TestCase): def test_client_default_version(self): - sc = client.Client('http://localhost:8080/sdf') + sc = client.Client('http://localhost:8080/sdf', + auth_url='http://localhost:8080/v2/auth') self.assertTrue(isinstance(sc, v2_0_client.Client)) def test_client_init_v1(self): @@ -30,5 +31,7 @@ class TestClient(unittest.TestCase): self.assertTrue(isinstance(sc, v1_0_client.Client)) def test_client_init_v2(self): - sc = client.Client('http://localhost:8080/v2', version='2_0') - self.assertTrue(isinstance(sc, v2_0_client.Client)) \ No newline at end of file + sc = client.Client('http://localhost:8080/v2', + auth_url='http://localhost:8080/v2/auth', + version='2_0') + self.assertTrue(isinstance(sc, v2_0_client.Client)) diff --git a/surveilclient/v1_0/client.py b/surveilclient/v1_0/client.py index ff77f42..587f069 100644 --- a/surveilclient/v1_0/client.py +++ b/surveilclient/v1_0/client.py @@ -25,7 +25,7 @@ class Client(object): """ def __init__(self, endpoint): - self.http_client = http.HTTPClient(endpoint) + self.http_client = http.HTTPClient(endpoint, authenticated=False) self.hosts = hosts.HostsManager(self.http_client) self.services = services.ServicesManager(self.http_client) diff --git a/surveilclient/v2_0/client.py b/surveilclient/v2_0/client.py index 8316133..4be5c15 100644 --- a/surveilclient/v2_0/client.py +++ b/surveilclient/v2_0/client.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import os + from surveilclient.common import http from surveilclient.v2_0 import actions from surveilclient.v2_0 import config @@ -25,8 +27,29 @@ class Client(object): :param string endpoint: The url of the surveil API """ - def __init__(self, endpoint): - self.http_client = http.HTTPClient(endpoint) + def __init__(self, + endpoint, + username=os.environ.get('OS_USERNAME', None), + password=os.environ.get('OS_PASSWORD', None), + tenant_name=os.environ.get('OS_TENANT_NAME', None), + auth_url=None): + + if auth_url is None: + auth_url = os.environ.get( + 'SURVEIL_AUTH_URL', + os.environ.get('OS_AUTH_URL', None) + ) + if auth_url is None: + raise Exception("Must specify auth url") + + self.http_client = http.HTTPClient( + endpoint, + username=username, + password=password, + tenant_name=tenant_name, + auth_url=auth_url, + ) + self.config = config.ConfigManager(self.http_client) self.status = status.StatusManager(self.http_client) self.actions = actions.ActionsManager(self.http_client)