summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorCerberus <matt.dietz@rackspace.com>2010-09-16 14:41:51 -0500
committerCerberus <matt.dietz@rackspace.com>2010-09-16 14:41:51 -0500
commit11b934f75ac4359b75f246fd9babfc3363a9a396 (patch)
tree98ae7309d2b08131d4f5471e8cb908f35b2b9ea8 /nova/api
parentc2c113917d3e354f85d473a6d646688b59abad17 (diff)
Replaced the existing Rackspace Auth Mechanism with one that mirrors the implementation in the design document.
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/rackspace/__init__.py52
-rw-r--r--nova/api/rackspace/auth.py37
2 files changed, 78 insertions, 11 deletions
diff --git a/nova/api/rackspace/__init__.py b/nova/api/rackspace/__init__.py
index b4d666d63..dbba97107 100644
--- a/nova/api/rackspace/__init__.py
+++ b/nova/api/rackspace/__init__.py
@@ -26,8 +26,10 @@ import time
import routes
import webob.dec
import webob.exc
+import webob
from nova import flags
+from nova import utils
from nova import wsgi
from nova.api.rackspace import flavors
from nova.api.rackspace import images
@@ -36,6 +38,10 @@ from nova.api.rackspace import sharedipgroups
from nova.auth import manager
+FLAGS = flags.FLAGS
+flags.DEFINE_string('nova_api_auth', 'nova.api.rackspace.auth.FakeAuth',
+ 'The auth mechanism to use for the Rackspace API implemenation')
+
class API(wsgi.Middleware):
"""WSGI entry point for all Rackspace API requests."""
@@ -47,23 +53,47 @@ class API(wsgi.Middleware):
class AuthMiddleware(wsgi.Middleware):
"""Authorize the rackspace API request or return an HTTP Forbidden."""
- #TODO(gundlach): isn't this the old Nova API's auth? Should it be replaced
- #with correct RS API auth?
+ def __init__(self, application):
+ self.auth_driver = utils.import_class(FLAGS.nova_api_auth)()
+ super(AuthMiddleware, self).__init__(application)
@webob.dec.wsgify
def __call__(self, req):
- context = {}
- if "HTTP_X_AUTH_TOKEN" in req.environ:
- context['user'] = manager.AuthManager().get_user_from_access_key(
- req.environ['HTTP_X_AUTH_TOKEN'])
- if context['user']:
- context['project'] = manager.AuthManager().get_project(
- context['user'].name)
- if "user" not in context:
- return webob.exc.HTTPForbidden()
+ if not req.headers.has_key("X-Auth-Token"):
+ return self.authenticate(req)
+
+ user = self.auth_driver.authorize_token(req.headers["X-Auth-Token"])
+
+ if not user:
+ return webob.exc.HTTPUnauthorized()
+ 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):
"""
diff --git a/nova/api/rackspace/auth.py b/nova/api/rackspace/auth.py
new file mode 100644
index 000000000..d2b5193c3
--- /dev/null
+++ b/nova/api/rackspace/auth.py
@@ -0,0 +1,37 @@
+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
+
+ 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
+ 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')
+