summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorCerberus <matt.dietz@rackspace.com>2010-09-20 18:04:57 -0500
committerCerberus <matt.dietz@rackspace.com>2010-09-20 18:04:57 -0500
commit64dd3000c4a9b88719e86d1090097e35398d3838 (patch)
tree3ae84cad82cef59c7c1b3eabe9c2b784d70e82f5 /nova/api
parent11b934f75ac4359b75f246fd9babfc3363a9a396 (diff)
Refactored the auth branch based on review feedback
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/rackspace/__init__.py33
-rw-r--r--nova/api/rackspace/auth.py117
2 files changed, 88 insertions, 62 deletions
diff --git a/nova/api/rackspace/__init__.py b/nova/api/rackspace/__init__.py
index dbba97107..f62ddc1c7 100644
--- a/nova/api/rackspace/__init__.py
+++ b/nova/api/rackspace/__init__.py
@@ -39,7 +39,8 @@ from nova.auth import manager
FLAGS = flags.FLAGS
-flags.DEFINE_string('nova_api_auth', 'nova.api.rackspace.auth.FakeAuth',
+flags.DEFINE_string('nova_api_auth',
+ 'nova.api.rackspace.auth.BasicApiAuthManager',
'The auth mechanism to use for the Rackspace API implemenation')
class API(wsgi.Middleware):
@@ -49,7 +50,6 @@ class API(wsgi.Middleware):
app = AuthMiddleware(APIRouter())
super(API, self).__init__(app)
-
class AuthMiddleware(wsgi.Middleware):
"""Authorize the rackspace API request or return an HTTP Forbidden."""
@@ -60,41 +60,16 @@ class AuthMiddleware(wsgi.Middleware):
@webob.dec.wsgify
def __call__(self, req):
if not req.headers.has_key("X-Auth-Token"):
- return self.authenticate(req)
+ return self.auth_driver.authenticate(req)
user = self.auth_driver.authorize_token(req.headers["X-Auth-Token"])
if not user:
return webob.exc.HTTPUnauthorized()
- context = {'user':user}
+ context = {'user': user}
req.environ['nova.context'] = context
return self.application
- def authenticate(self, req):
- # Unless the request is explicitly made against /<version>/ don't
- # honor it
- path_info = req.environ['wsgiorg.routing_args'][1]['path_info']
- if path_info:
- return webob.exc.HTTPUnauthorized()
-
- if req.headers.has_key("X-Auth-User") and \
- req.headers.has_key("X-Auth-Key"):
- username, key = req.headers['X-Auth-User'], req.headers['X-Auth-Key']
- token, user = self.auth_driver.authorize_user(username, key)
- if user and token:
- res = webob.Response()
- res.headers['X-Auth-Token'] = token
- res.headers['X-Server-Management-Url'] = \
- user['server_management_url']
- res.headers['X-Storage-Url'] = user['storage_url']
- res.headers['X-CDN-Management-Url'] = user['cdn_management_url']
- res.content_type = 'text/plain'
- res.status = '204'
- return res
- else:
- return webob.exc.HTTPUnauthorized()
- return webob.exc.HTTPUnauthorized()
-
class APIRouter(wsgi.Router):
"""
Routes requests on the Rackspace API to the appropriate controller
diff --git a/nova/api/rackspace/auth.py b/nova/api/rackspace/auth.py
index d2b5193c3..b29596880 100644
--- a/nova/api/rackspace/auth.py
+++ b/nova/api/rackspace/auth.py
@@ -1,37 +1,88 @@
+import datetime
import json
-from hashlib import sha1
-from nova import datastore
-
-class FakeAuth(object):
- def __init__(self, store=datastore.Redis.instance):
- self._store = store()
- self.auth_hash = 'rs_fake_auth'
- self._store.hsetnx(self.auth_hash, 'rs_last_id', 0)
-
- def authorize_token(self, token):
- user = self._store.hget(self.auth_hash, token)
- if user:
- return json.loads(user)
- return None
+import time
+import webob.exc
+import webob.dec
+import hashlib
+
+from nova import auth
+from nova import manager
+from nova import db
+
+class Context(object):
+ pass
+
+class BasicApiAuthManager(manager.Manager):
+ """ Implements a somewhat rudimentary version of Rackspace Auth"""
+
+ def __init__(self):
+ self.auth = auth.manager.AuthManager()
+ self.context = Context()
+ super(BasicApiAuthManager, self).__init__()
+
+ def authenticate(self, req):
+ # Unless the request is explicitly made against /<version>/ don't
+ # honor it
+ path_info = req.path_info
+ if len(path_info) > 1:
+ return webob.exc.HTTPUnauthorized()
+
+ try:
+ username, key = req.headers['X-Auth-User'], \
+ req.headers['X-Auth-Key']
+ except KeyError:
+ return webob.exc.HTTPUnauthorized()
- def authorize_user(self, user, key):
- token = sha1("%s_%s" % (user, key)).hexdigest()
- user = self._store.hget(self.auth_hash, token)
- if not user:
- return None, None
+ username, key = req.headers['X-Auth-User'], req.headers['X-Auth-Key']
+ token, user = self._authorize_user(username, key)
+ if user and token:
+ res = webob.Response()
+ res.headers['X-Auth-Token'] = token['token_hash']
+ res.headers['X-Server-Management-Url'] = \
+ token['server_management_url']
+ res.headers['X-Storage-Url'] = token['storage_url']
+ res.headers['X-CDN-Management-Url'] = token['cdn_management_url']
+ res.content_type = 'text/plain'
+ res.status = '204'
+ return res
else:
- return token, json.loads(user)
-
- def add_user(self, user, key):
- last_id = self._store.hget(self.auth_hash, 'rs_last_id')
- token = sha1("%s_%s" % (user, key)).hexdigest()
- user = {
- 'id':last_id,
- 'cdn_management_url':'cdn_management_url',
- 'storage_url':'storage_url',
- 'server_management_url':'server_management_url'
- }
- new_user = self._store.hsetnx(self.auth_hash, token, json.dumps(user))
- if new_user:
- self._store.hincrby(self.auth_hash, 'rs_last_id')
+ return webob.exc.HTTPUnauthorized()
+
+ def authorize_token(self, token_hash):
+ """ retrieves user information from the datastore given a token
+
+ If the token has expired, returns None
+ If the token is not found, returns None
+ Otherwise returns the token
+
+ This method will also remove the token if the timestamp is older than
+ 2 days ago.
+ """
+ token = self.db.auth_get_token(self.context, token_hash)
+ if token:
+ delta = datetime.datetime.now() - token['created_at']
+ if delta.days >= 2:
+ self.db.auth_destroy_token(self.context, token)
+ else:
+ user = self.auth.get_user(self.context, token['user_id'])
+ return { 'id':user['id'] }
+ return None
+
+ def _authorize_user(self, username, key):
+ """ Generates a new token and assigns it to a user """
+ user = self.auth.get_user_from_access_key(key)
+ if user and user['name'] == username:
+ token_hash = hashlib.sha1('%s%s%f' % (username, key,
+ time.time())).hexdigest()
+ token = {}
+ token['token_hash'] = token_hash
+ token['cdn_management_url'] = ''
+ token['server_management_url'] = self._get_server_mgmt_url()
+ token['storage_url'] = ''
+ self.db.auth_create_token(self.context, token, user['id'])
+ return token, user
+ return None, None
+
+ def _get_server_mgmt_url(self):
+ return 'https://%s/v1.0/' % self.host