summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZiad Sawalha <github@highbridgellc.com>2011-08-11 02:03:26 -0500
committerZiad Sawalha <github@highbridgellc.com>2011-08-11 02:41:57 -0500
commitd52cde680b2e968c60f59638ada9f651b4b4cab2 (patch)
tree60af19d0d81761ada25f4535ca2f7535ae32f7e4
parentb1fd6aac34a2e96d7e71f307f31f40fa3bf3fac1 (diff)
downloadkeystone-d52cde680b2e968c60f59638ada9f651b4b4cab2.tar.gz
keystone-d52cde680b2e968c60f59638ada9f651b4b4cab2.tar.xz
keystone-d52cde680b2e968c60f59638ada9f651b4b4cab2.zip
Correct 401, 305, and www-authenticate responses
Change-Id: I6205567e7b68917d5ecabcf336a4891802ab7381 Fixing memcache issues.Fixing pep8 changes. Change-Id: I4e941efec2fad4b945481072b43334bf6477580f
-rw-r--r--examples/echo/echo/echo.ini1
-rw-r--r--examples/echo/echo/echo_remote.ini2
-rw-r--r--examples/paste/auth_token.ini3
-rw-r--r--examples/paste/glance-api.conf1
-rw-r--r--examples/paste/glance-registry.conf1
-rw-r--r--examples/paste/nova-api-paste.ini1
-rwxr-xr-xkeystone/backends/memcache/api/token.py34
-rwxr-xr-xkeystone/middleware/auth_token.py40
-rw-r--r--keystone/middleware/remoteauth.py12
-rwxr-xr-xrun_tests.py2
10 files changed, 66 insertions, 31 deletions
diff --git a/examples/echo/echo/echo.ini b/examples/echo/echo/echo.ini
index aecb3f4b..b5647601 100644
--- a/examples/echo/echo/echo.ini
+++ b/examples/echo/echo/echo.ini
@@ -25,6 +25,7 @@ paste.filter_factory = keystone.middleware.auth_token:filter_factory
auth_host = 127.0.0.1
auth_port = 5001
auth_protocol = http
+auth_uri = http://localhost:5000/
;how to authenticate to the auth service for priviledged operations
;like validate token
admin_token = 999888777666
diff --git a/examples/echo/echo/echo_remote.ini b/examples/echo/echo/echo_remote.ini
index a429485d..ba5e4610 100644
--- a/examples/echo/echo/echo_remote.ini
+++ b/examples/echo/echo/echo_remote.ini
@@ -14,6 +14,6 @@ paste.filter_factory = keystone.middleware.remoteauth:filter_factory
; (otherwise we redirect call)
remote_auth_pass = dTpw
;where to redirect untrusted calls to
-auth_location = http://127.0.0.1:5001/
+proxy_location = http://127.0.0.1:8090/
diff --git a/examples/paste/auth_token.ini b/examples/paste/auth_token.ini
index b2899e36..bb37241b 100644
--- a/examples/paste/auth_token.ini
+++ b/examples/paste/auth_token.ini
@@ -6,9 +6,10 @@ paste.app_factory = auth_token:app_factory
auth_protocol = http
auth_host = 127.0.0.1
auth_port = 5001
+auth_uri = http://127.0.0.1:5000/
admin_token = 999888777666
-delay_auth_decision = 0
+delay_auth_decision = 1
service_protocol = http
service_host = 127.0.0.1
diff --git a/examples/paste/glance-api.conf b/examples/paste/glance-api.conf
index 6b1d8801..26dea5ee 100644
--- a/examples/paste/glance-api.conf
+++ b/examples/paste/glance-api.conf
@@ -82,6 +82,7 @@ service_port = 808
auth_host = 127.0.0.1
auth_port = 5001
auth_protocol = http
+auth_uri = http://127.0.0.1:5000/
admin_token = 999888777666
# Allows anonymous access
diff --git a/examples/paste/glance-registry.conf b/examples/paste/glance-registry.conf
index a66323cd..378705e5 100644
--- a/examples/paste/glance-registry.conf
+++ b/examples/paste/glance-registry.conf
@@ -46,6 +46,7 @@ service_port = 808
auth_host = 127.0.0.1
auth_port = 5001
auth_protocol = http
+auth_uri = http://127.0.0.1:5000/
admin_token = 999888777666
# Allows anonymous access
diff --git a/examples/paste/nova-api-paste.ini b/examples/paste/nova-api-paste.ini
index 7cc75ffe..bf7ae41f 100644
--- a/examples/paste/nova-api-paste.ini
+++ b/examples/paste/nova-api-paste.ini
@@ -90,6 +90,7 @@ service_port = 808
auth_host = 127.0.0.1
auth_port = 5001
auth_protocol = http
+auth_uri = http://127.0.0.1:5000/
admin_token = 999888777666
[filter:auth_shim]
diff --git a/keystone/backends/memcache/api/token.py b/keystone/backends/memcache/api/token.py
index a614eb33..c758a19b 100755
--- a/keystone/backends/memcache/api/token.py
+++ b/keystone/backends/memcache/api/token.py
@@ -14,39 +14,49 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-
+from keystone.backends.memcache import MEMCACHE_SERVER, models
from keystone.backends.api import BaseTokenAPI
class TokenAPI(BaseTokenAPI):
def create(self, token):
+ if not hasattr(token, 'tenant_id'):
+ token.tenant_id = None
if token.tenant_id != None:
tenant_user_key = token.tenant_id + "::" + token.user_id
else:
tenant_user_key = token.user_id
- #Setting them for a day.
+
MEMCACHE_SERVER.set(token.id, token)
MEMCACHE_SERVER.set(tenant_user_key, token)
- def get(self, id, session=None):
- return MEMCACHE_SERVER.get(id)
-
- def delete(self, id, session=None):
+ def get(self, id):
token = MEMCACHE_SERVER.get(id)
+ if token != None and not hasattr(token, 'tenant_id'):
+ token.tenant_id = None
+ return token
+
+ def delete(self, id):
+ token = self.get(id)
if token != None:
MEMCACHE_SERVER.delete(id)
-
if token.tenant_id != None:
MEMCACHE_SERVER.delete(token.tenant_id + "::" + token.user_id)
else:
MEMCACHE_SERVER.delete(token.id)
MEMCACHE_SERVER.delete(token.user_id)
- def get_for_user(self, user_id, session=None):
- return MEMCACHE_SERVER.get(user_id)
-
- def get_for_user_by_tenant(self, user_id, tenant_id, session=None):
- return MEMCACHE_SERVER.get(tenant_id + "::" + user_id)
+ def get_for_user(self, user_id):
+ token = MEMCACHE_SERVER.get(user_id)
+ if token != None and not hasattr(token, 'tenant_id'):
+ token.tenant_id = None
+ return token
+
+ def get_for_user_by_tenant(self, user_id, tenant_id):
+ token = MEMCACHE_SERVER.get(tenant_id + "::" + user_id)
+ if token != None and not hasattr(token, 'tenant_id'):
+ token.tenant_id = None
+ return token
def get():
diff --git a/keystone/middleware/auth_token.py b/keystone/middleware/auth_token.py
index 1dd3e21e..2b8fce5e 100755
--- a/keystone/middleware/auth_token.py
+++ b/keystone/middleware/auth_token.py
@@ -58,6 +58,7 @@ from paste.deploy import loadapp
from urlparse import urlparse
from webob.exc import HTTPUnauthorized, HTTPUseProxy
from webob.exc import Request, Response
+import tools.tracer # @UnusedImport # module runs on import
from keystone.common.bufferedhttp import http_connect_raw as http_connect
@@ -99,18 +100,22 @@ class AuthProtocol(object):
self.auth_host = conf.get('auth_host')
self.auth_port = int(conf.get('auth_port'))
self.auth_protocol = conf.get('auth_protocol', 'https')
- self.auth_location = "%s://%s:%s" % (self.auth_protocol,
- self.auth_host,
- self.auth_port)
+
+ # where to tell clients to find the auth service (default to url
+ # constructed based on endpoint we have for the service to use)
+ self.auth_location = conf.get('auth_uri',
+ "%s://%s:%s" % (self.auth_protocol,
+ self.auth_host,
+ self.auth_port))
# Credentials used to verify this component with the Auth service since
- # validating tokens is a priviledged call
+ # validating tokens is a privileged call
self.admin_token = conf.get('admin_token')
def __init__(self, app, conf):
""" Common initialization code """
- #TODO(ziad): maybe we rafactor this into a superclass
+ #TODO(ziad): maybe we refactor this into a superclass
self._init_protocol_common(app, conf) # Applies to all protocols
self._init_protocol(app, conf) # Specific to this protocol
@@ -174,8 +179,8 @@ class AuthProtocol(object):
# NOTE(todd): unused
self.expanded = True
- #Send request downstream
- return self._forward_request()
+ #Send request downstream
+ return self._forward_request()
# NOTE(todd): unused
def get_admin_auth_token(self, username, password, tenant):
@@ -203,8 +208,10 @@ class AuthProtocol(object):
def _reject_request(self):
"""Redirect client to auth server"""
- return HTTPUseProxy(location=self.auth_location)(self.env,
- self.start_response)
+ return HTTPUnauthorized("Authentication required",
+ [("WWW-Authenticate",
+ "Keystone uri='%s'" % self.auth_location)])(self.env,
+ self.start_response)
def _reject_claims(self):
"""Client sent bad claims"""
@@ -297,6 +304,7 @@ class AuthProtocol(object):
# We are forwarding to a remote service (no downstream WSGI app)
req = Request(self.proxy_headers)
parsed = urlparse(req.url)
+
conn = http_connect(self.service_host,
self.service_port,
req.method,
@@ -305,10 +313,20 @@ class AuthProtocol(object):
ssl=(self.service_protocol == 'https'))
resp = conn.getresponse()
data = resp.read()
+
#TODO(ziad): use a more sophisticated proxy
# we are rewriting the headers now
- return Response(status=resp.status, body=data)(self.proxy_headers,
- self.start_response)
+
+ if resp.status == 401 or resp.status == 305:
+ # Add our own headers to the list
+ headers = [("WWW_AUTHENTICATE",
+ "Keystone uri='%s'" % self.auth_location)]
+ return Response(status=resp.status, body=data,
+ headerlist=headers)(self.env,
+ self.start_response)
+ else:
+ return Response(status=resp.status, body=data)(self.env,
+ self.start_response)
def filter_factory(global_conf, **local_conf):
diff --git a/keystone/middleware/remoteauth.py b/keystone/middleware/remoteauth.py
index 5919abd6..70501807 100644
--- a/keystone/middleware/remoteauth.py
+++ b/keystone/middleware/remoteauth.py
@@ -69,8 +69,8 @@ class RemoteAuth(object):
# app is the next app in WSGI chain - eventually the OpenStack service
self.app = app
self.conf = conf
- # where to redirect untrusted requests to go and auth
- self.auth_location = conf.get('auth_location')
+ # where to redirect untrusted requests to
+ self.proxy_location = conf.get('proxy_location')
# secret that will tell us a request is coming from a trusted auth
# component
self.remote_auth_pass = conf.get('remote_auth_pass')
@@ -81,7 +81,10 @@ class RemoteAuth(object):
# Authenticate the Auth component itself.
headers = [('www-authenticate', 'Basic realm="API Auth"')]
if 'HTTP_AUTHORIZATION' not in env:
- return HTTPUnauthorized(headers=headers)(env, start_response)
+ # Redirect to proxy (auth component) and show that basic auth is
+ # required
+ return HTTPUseProxy(location=self.proxy_location,
+ headers=headers)(env, start_response)
else:
auth_type, encoded_creds = env['HTTP_AUTHORIZATION'].split(None, 1)
if encoded_creds != self.remote_auth_pass:
@@ -89,8 +92,7 @@ class RemoteAuth(object):
# Make sure that the user has been authenticated by the Auth Service
if 'HTTP_X_AUTHORIZATION' not in env:
- return HTTPUseProxy(location=self.auth_location)(env,
- start_response)
+ return HTTPUnauthorized()(env, start_response)
return self.app(env, start_response)
diff --git a/run_tests.py b/run_tests.py
index 3816fcd5..6d10f9ee 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -12,7 +12,7 @@ TEST_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)),
CONFIG_FILES = (
'sql.conf.template',
- #'memcache.conf.template',
+ # not passing 'memcache.conf.template',
'ldap.conf.template')
TEST_FILES = (