summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorge L. Williams <jorge.williams@rackspace.com>2011-04-21 16:53:57 -0500
committerJorge L. Williams <jorge.williams@rackspace.com>2011-04-21 16:53:57 -0500
commit8bb4887abf9a56291fe38bd43ece5d5cbc8aebd5 (patch)
tree94eb7749de1e374d61310bfd83c7cf22e0cec21c
parentc03f897ce59b437f0fea5c00671997d8a1cab9a0 (diff)
parent35fb99ec78f3c30a13036b550284b9f26de2bca0 (diff)
downloadkeystone-8bb4887abf9a56291fe38bd43ece5d5cbc8aebd5.tar.gz
keystone-8bb4887abf9a56291fe38bd43ece5d5cbc8aebd5.tar.xz
keystone-8bb4887abf9a56291fe38bd43ece5d5cbc8aebd5.zip
Merge branch 'master' of github.com:khussein/keystone
-rw-r--r--docs/guide/src/docbkx/samples/auth.json2
-rw-r--r--echo/echo/echo.ini7
-rw-r--r--keystone/auth_protocol/__init__.py0
-rw-r--r--keystone/auth_protocol/auth_protocol_token.py73
-rw-r--r--keystone/common/__init__.py0
-rw-r--r--keystone/common/bufferedhttp.py165
-rw-r--r--keystone/identity.py1
-rw-r--r--setup.py1
8 files changed, 247 insertions, 2 deletions
diff --git a/docs/guide/src/docbkx/samples/auth.json b/docs/guide/src/docbkx/samples/auth.json
index 697c4664..fa56c131 100644
--- a/docs/guide/src/docbkx/samples/auth.json
+++ b/docs/guide/src/docbkx/samples/auth.json
@@ -13,7 +13,7 @@
}
]},
"username": "jqsmith",
- "tenantId": "1234",
+ "tenantId": "1234"
}
}
}
diff --git a/echo/echo/echo.ini b/echo/echo/echo.ini
index 10e09712..020198b5 100644
--- a/echo/echo/echo.ini
+++ b/echo/echo/echo.ini
@@ -6,6 +6,7 @@ use = egg:echo
[pipeline:main]
pipeline =
+ auth
papiauth
echo
@@ -14,3 +15,9 @@ use = egg:keystone#papiauth
auth_ip = 127.0.0.1
auth_port = 8080
auth_pass = dTpw
+
+[filter:auth]
+use = egg:keystone#tokenauth
+auth_ip = 127.0.0.1
+auth_port = 8080
+auth_pass = dTpw
diff --git a/keystone/auth_protocol/__init__.py b/keystone/auth_protocol/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone/auth_protocol/__init__.py
diff --git a/keystone/auth_protocol/auth_protocol_token.py b/keystone/auth_protocol/auth_protocol_token.py
new file mode 100644
index 00000000..1c8ab7cf
--- /dev/null
+++ b/keystone/auth_protocol/auth_protocol_token.py
@@ -0,0 +1,73 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright (c) 2010-2011 OpenStack, LLC.
+#
+# 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.
+# Not Yet PEP8 standardized
+
+import simplejson as json
+from webob.exc import HTTPUnauthorized, Request
+
+from keystone.common.bufferedhttp import http_connect_raw as http_connect
+
+class TokenAuth(object):
+ """Auth Middleware that uses the dev auth server."""
+
+ def __init__(self, app, conf):
+ print "Starting the new one"
+ self.app = app
+ self.conf = conf
+ self.auth_host = conf.get('auth_ip', '127.0.0.1')
+ self.auth_port = int(conf.get('auth_port', 8080))
+ self.auth_pass = conf.get('auth_pass', 'dTpw')
+ self.delegated = int(conf.get('delegated', 0))
+
+ def __call__(self, env, start_response):
+
+ def custom_start_response(status, headers):
+ if self.delegated:
+ headers.append(('WWW-Authenticate', "Basic realm='API Realm'"))
+ return start_response(status, headers)
+
+ token = env.get('HTTP_X_AUTH_TOKEN', env.get('HTTP_X_STORAGE_TOKEN'))
+ if token:
+ #conn = http_connect(self.auth_host, self.auth_port, 'GET',
+ # '/token/%s' % token)
+ #resp = conn.getresponse()
+ path = 'http://%s:%s/token/%s' % \
+ (self.auth_host, self.auth_port, token)
+ resp = Request.blank(path).get_response(self.app)
+ user = json.loads(resp.body)
+ #resp.read()
+ #conn.close()
+ if not resp.status.startswith('20'):
+ if self.delegated:
+ env['HTTP_X_IDENTITY_STATUS'] = "Invalid"
+ else:
+ env['HTTP_X_AUTHORIZATION'] = "Proxy " + user
+ if self.delegated:
+ env['HTTP_X_IDENTITY_STATUS'] = "Confirmed"
+ return HTTPUnauthorized()(env, custom_start_response)
+
+ env['HTTP_AUTHORIZATION'] = "Basic dTpw"
+ return self.app(env, custom_start_response)
+
+
+def filter_factory(global_conf, **local_conf):
+ """Returns a WSGI filter app for use with paste.deploy."""
+ conf = global_conf.copy()
+ conf.update(local_conf)
+
+ def auth_filter(app):
+ return TokenAuth(app, conf)
+ return auth_filter
diff --git a/keystone/common/__init__.py b/keystone/common/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone/common/__init__.py
diff --git a/keystone/common/bufferedhttp.py b/keystone/common/bufferedhttp.py
new file mode 100644
index 00000000..fdb35ee6
--- /dev/null
+++ b/keystone/common/bufferedhttp.py
@@ -0,0 +1,165 @@
+# Copyright (c) 2010-2011 OpenStack, LLC.
+#
+# 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.
+
+"""
+Monkey Patch httplib.HTTPResponse to buffer reads of headers. This can improve
+performance when making large numbers of small HTTP requests. This module
+also provides helper functions to make HTTP connections using
+BufferedHTTPResponse.
+
+.. warning::
+
+ If you use this, be sure that the libraries you are using do not access
+ the socket directly (xmlrpclib, I'm looking at you :/), and instead
+ make all calls through httplib.
+"""
+
+from urllib import quote
+import logging
+import time
+
+from eventlet.green.httplib import CONTINUE, HTTPConnection, HTTPMessage, \
+ HTTPResponse, HTTPSConnection, _UNKNOWN
+
+
+class BufferedHTTPResponse(HTTPResponse):
+ """HTTPResponse class that buffers reading of headers"""
+
+ def __init__(self, sock, debuglevel=0, strict=0,
+ method=None): # pragma: no cover
+ self.sock = sock
+ self.fp = sock.makefile('rb')
+ self.debuglevel = debuglevel
+ self.strict = strict
+ self._method = method
+
+ self.msg = None
+
+ # from the Status-Line of the response
+ self.version = _UNKNOWN # HTTP-Version
+ self.status = _UNKNOWN # Status-Code
+ self.reason = _UNKNOWN # Reason-Phrase
+
+ self.chunked = _UNKNOWN # is "chunked" being used?
+ self.chunk_left = _UNKNOWN # bytes left to read in current chunk
+ self.length = _UNKNOWN # number of bytes left in response
+ self.will_close = _UNKNOWN # conn will close at end of response
+
+ def expect_response(self):
+ self.fp = self.sock.makefile('rb', 0)
+ version, status, reason = self._read_status()
+ if status != CONTINUE:
+ self._read_status = lambda: (version, status, reason)
+ self.begin()
+ else:
+ self.status = status
+ self.reason = reason.strip()
+ self.version = 11
+ self.msg = HTTPMessage(self.fp, 0)
+ self.msg.fp = None
+
+
+class BufferedHTTPConnection(HTTPConnection):
+ """HTTPConnection class that uses BufferedHTTPResponse"""
+ response_class = BufferedHTTPResponse
+
+ def connect(self):
+ self._connected_time = time.time()
+ return HTTPConnection.connect(self)
+
+ def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0):
+ self._method = method
+ self._path = url
+ return HTTPConnection.putrequest(self, method, url, skip_host,
+ skip_accept_encoding)
+
+ def getexpect(self):
+ response = BufferedHTTPResponse(self.sock, strict=self.strict,
+ method=self._method)
+ response.expect_response()
+ return response
+
+ def getresponse(self):
+ response = HTTPConnection.getresponse(self)
+ logging.debug(("HTTP PERF: %(time).5f seconds to %(method)s "
+ "%(host)s:%(port)s %(path)s)"),
+ {'time': time.time() - self._connected_time, 'method': self._method,
+ 'host': self.host, 'port': self.port, 'path': self._path})
+ return response
+
+
+def http_connect(ipaddr, port, device, partition, method, path,
+ headers=None, query_string=None, ssl=False):
+ """
+ Helper function to create an HTTPConnection object. If ssl is set True,
+ HTTPSConnection will be used. However, if ssl=False, BufferedHTTPConnection
+ will be used, which is buffered for backend Swift services.
+
+ :param ipaddr: IPv4 address to connect to
+ :param port: port to connect to
+ :param device: device of the node to query
+ :param partition: partition on the device
+ :param method: HTTP method to request ('GET', 'PUT', 'POST', etc.)
+ :param path: request path
+ :param headers: dictionary of headers
+ :param query_string: request query string
+ :param ssl: set True if SSL should be used (default: False)
+ :returns: HTTPConnection object
+ """
+ if ssl:
+ conn = HTTPSConnection('%s:%s' % (ipaddr, port))
+ else:
+ conn = BufferedHTTPConnection('%s:%s' % (ipaddr, port))
+ path = quote('/' + device + '/' + str(partition) + path)
+ if query_string:
+ path += '?' + query_string
+ conn.path = path
+ conn.putrequest(method, path)
+ if headers:
+ for header, value in headers.iteritems():
+ conn.putheader(header, value)
+ conn.endheaders()
+ return conn
+
+
+def http_connect_raw(ipaddr, port, method, path, headers=None,
+ query_string=None, ssl=False):
+ """
+ Helper function to create an HTTPConnection object. If ssl is set True,
+ HTTPSConnection will be used. However, if ssl=False, BufferedHTTPConnection
+ will be used, which is buffered for backend Swift services.
+
+ :param ipaddr: IPv4 address to connect to
+ :param port: port to connect to
+ :param method: HTTP method to request ('GET', 'PUT', 'POST', etc.)
+ :param path: request path
+ :param headers: dictionary of headers
+ :param query_string: request query string
+ :param ssl: set True if SSL should be used (default: False)
+ :returns: HTTPConnection object
+ """
+ if ssl:
+ conn = HTTPSConnection('%s:%s' % (ipaddr, port))
+ else:
+ conn = BufferedHTTPConnection('%s:%s' % (ipaddr, port))
+ if query_string:
+ path += '?' + query_string
+ conn.path = path
+ conn.putrequest(method, path)
+ if headers:
+ for header, value in headers.iteritems():
+ conn.putheader(header, value)
+ conn.endheaders()
+ return conn
diff --git a/keystone/identity.py b/keystone/identity.py
index 434e7fa6..bc9415fb 100644
--- a/keystone/identity.py
+++ b/keystone/identity.py
@@ -22,7 +22,6 @@ from bottle import request
from bottle import debug
from bottle import abort
from bottle import Bottle
-from bottle import EventletServer
import ConfigParser
from datetime import datetime
from datetime import timedelta
diff --git a/setup.py b/setup.py
index a85d32ea..6c9078b4 100644
--- a/setup.py
+++ b/setup.py
@@ -36,6 +36,7 @@ setup(
'paste.app_factory': ['main=identity:app_factory'],
'paste.filter_factory': [
'papiauth=keystone.middleware.papiauth:filter_factory',
+ 'tokenauth=keystone.auth_protocol.auth_protocol_token:filter_factory',
],
},
)