diff --git a/portas/etc/portas-api-paste.ini b/portas/etc/portas-api-paste.ini index 9b1d990..7fd4361 100644 --- a/portas/etc/portas-api-paste.ini +++ b/portas/etc/portas-api-paste.ini @@ -1,5 +1,18 @@ [pipeline:portas-api] -pipeline = apiv1app +pipeline = authtoken context apiv1app [app:apiv1app] -paste.app_factory = portas.api.v1.router:API.factory \ No newline at end of file +paste.app_factory = portas.api.v1.router:API.factory + +[filter:context] +paste.filter_factory = portas.api.middleware.context:ContextMiddleware.factory + +[filter:authtoken] +paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory +auth_host = 172.18.79.72 +auth_port = 35357 +auth_protocol = http +admin_tenant_name = admin +admin_user = admin +admin_password = swordfish +signing_dir = /tmp/keystone-signing-portas \ No newline at end of file diff --git a/portas/portas/api/middleware/__init__.py b/portas/portas/api/middleware/__init__.py index 0a754b6..e69de29 100644 --- a/portas/portas/api/middleware/__init__.py +++ b/portas/portas/api/middleware/__init__.py @@ -1 +0,0 @@ -__author__ = 'sad' diff --git a/portas/portas/api/middleware/context.py b/portas/portas/api/middleware/context.py index 1d22b9e..1b3d7e9 100644 --- a/portas/portas/api/middleware/context.py +++ b/portas/portas/api/middleware/context.py @@ -16,24 +16,15 @@ # under the License. import json - from oslo.config import cfg + import webob.exc -from glance.common import wsgi -import glance.context -import glance.openstack.common.log as logging - - -context_opts = [ - cfg.BoolOpt('owner_is_tenant', default=True), - cfg.StrOpt('admin_role', default='admin'), - cfg.BoolOpt('allow_anonymous_access', default=False), -] +from portas.openstack.common import wsgi +import portas.context +import portas.openstack.common.log as logging CONF = cfg.CONF -CONF.register_opts(context_opts) - LOG = logging.getLogger(__name__) @@ -52,7 +43,7 @@ class ContextMiddleware(BaseContextMiddleware): def process_request(self, req): """Convert authentication information into a request context - Generate a glance.context.RequestContext object from the available + Generate a portas.context.RequestContext object from the available authentication headers and store on the 'context' attribute of the req object. @@ -62,61 +53,34 @@ class ContextMiddleware(BaseContextMiddleware): anonymous access is disallowed """ if req.headers.get('X-Identity-Status') == 'Confirmed': - req.context = self._get_authenticated_context(req) - elif CONF.allow_anonymous_access: - req.context = self._get_anonymous_context() + roles_header = req.headers.get('X-Roles', '') + roles = [r.strip().lower() for r in roles_header.split(',')] + + #NOTE(bcwaldon): This header is deprecated in favor of X-Auth-Token + deprecated_token = req.headers.get('X-Storage-Token') + + service_catalog = None + if req.headers.get('X-Service-Catalog') is not None: + try: + catalog_header = req.headers.get('X-Service-Catalog') + service_catalog = json.loads(catalog_header) + except ValueError: + raise webob.exc.HTTPInternalServerError( + _('Invalid service catalog json.')) + + kwargs = { + 'user': req.headers.get('X-User-Id'), + 'tenant': req.headers.get('X-Tenant-Id'), + 'roles': roles, + 'auth_tok': req.headers.get('X-Auth-Token', deprecated_token), + 'service_catalog': service_catalog, + } + req.context = portas.context.RequestContext(**kwargs) else: raise webob.exc.HTTPUnauthorized() - def _get_anonymous_context(self): - kwargs = { - 'user': None, - 'tenant': None, - 'roles': [], - 'is_admin': False, - 'read_only': True, - } - return glance.context.RequestContext(**kwargs) - - def _get_authenticated_context(self, req): - #NOTE(bcwaldon): X-Roles is a csv string, but we need to parse - # it into a list to be useful - roles_header = req.headers.get('X-Roles', '') - roles = [r.strip().lower() for r in roles_header.split(',')] - - #NOTE(bcwaldon): This header is deprecated in favor of X-Auth-Token - deprecated_token = req.headers.get('X-Storage-Token') - - service_catalog = None - if req.headers.get('X-Service-Catalog') is not None: - try: - catalog_header = req.headers.get('X-Service-Catalog') - service_catalog = json.loads(catalog_header) - except ValueError: - raise webob.exc.HTTPInternalServerError( - _('Invalid service catalog json.')) - - kwargs = { - 'user': req.headers.get('X-User-Id'), - 'tenant': req.headers.get('X-Tenant-Id'), - 'roles': roles, - 'is_admin': CONF.admin_role.strip().lower() in roles, - 'auth_tok': req.headers.get('X-Auth-Token', deprecated_token), - 'owner_is_tenant': CONF.owner_is_tenant, - 'service_catalog': service_catalog, - } - - return glance.context.RequestContext(**kwargs) - - -class UnauthenticatedContextMiddleware(BaseContextMiddleware): - def process_request(self, req): - """Create a context without an authorized user.""" - kwargs = { - 'user': None, - 'tenant': None, - 'roles': [], - 'is_admin': True, - } - - req.context = glance.context.RequestContext(**kwargs) + @classmethod + def factory(cls, global_conf, **local_conf): + def filter(app): + return cls(app) + return filter \ No newline at end of file diff --git a/portas/portas/context.py b/portas/portas/context.py index 8e3d9a4..43051f7 100644 --- a/portas/portas/context.py +++ b/portas/portas/context.py @@ -15,8 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. -from glance.openstack.common import local -from glance.openstack.common import uuidutils +from portas.openstack.common import uuidutils class RequestContext(object): @@ -25,22 +24,12 @@ class RequestContext(object): accesses the system, as well as additional request information. """ - def __init__(self, auth_tok=None, user=None, tenant=None, roles=None, - is_admin=False, read_only=False, show_deleted=False, - owner_is_tenant=True, service_catalog=None): + def __init__(self, auth_tok=None, user=None, tenant=None, roles=None): self.auth_tok = auth_tok self.user = user self.tenant = tenant self.roles = roles or [] - self.is_admin = is_admin - self.read_only = read_only - self._show_deleted = show_deleted - self.owner_is_tenant = owner_is_tenant self.request_id = uuidutils.generate_uuid() - self.service_catalog = service_catalog - - if not hasattr(local.store, 'context'): - self.update_store() def to_dict(self): # NOTE(ameade): These keys are named to correspond with the default @@ -57,28 +46,10 @@ class RequestContext(object): 'tenant_id': self.tenant, 'project_id': self.tenant, - 'is_admin': self.is_admin, - 'read_deleted': self.show_deleted, 'roles': self.roles, 'auth_token': self.auth_tok, - 'service_catalog': self.service_catalog, } @classmethod def from_dict(cls, values): - return cls(**values) - - def update_store(self): - local.store.context = self - - @property - def owner(self): - """Return the owner to correlate with an image.""" - return self.tenant if self.owner_is_tenant else self.user - - @property - def show_deleted(self): - """Admins can see deleted by default""" - if self._show_deleted or self.is_admin: - return True - return False + return cls(**values) \ No newline at end of file