[pipeline:heat-api-keystone]
pipeline = versionnegotiation authtoken context apiv1app
+# Use the following pipeline for custom cloud backends
+# i.e. in heat-api.conf:
+# [paste_deploy]
+# flavor = custombackend
+#
+[pipeline:heat-api-custombackend]
+pipeline = versionnegotiation context custombackendauth apiv1app
+
# Use the following pipeline to enable transparent caching of image files
# i.e. in heat-api.conf:
# [paste_deploy]
[filter:auth-context]
paste.filter_factory = heat.common.wsgi:filter_factory
heat.filter_factory = keystone.middleware.heat_auth_token:KeystoneContextMiddleware
+
+[filter:custombackendauth]
+paste.filter_factory = heat.common.custom_backend_auth:filter_factory
\ No newline at end of file
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (C) 2012, Red Hat, Inc.
+#
+# 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.
+
+"""
+Middleware for authenticating against custom backends.
+"""
+
+import logging
+
+from heat.openstack.common import local
+from heat.rpc import client as rpc_client
+import webob.exc
+
+
+LOG = logging.getLogger(__name__)
+
+
+class AuthProtocol(object):
+ def __init__(self, app, conf):
+ self.conf = conf
+ self.app = app
+
+ def __call__(self, env, start_response):
+ """
+ Handle incoming request.
+
+ Authenticate send downstream on success. Reject request if
+ we can't authenticate.
+ """
+ LOG.debug('Authenticating user token')
+ context = local.store.context
+ engine = rpc_client.EngineClient()
+ authenticated = engine.authenticated_to_backend(context)
+ if authenticated:
+ return self.app(env, start_response)
+ else:
+ return self._reject_request(env, start_response)
+
+ def _reject_request(self, env, start_response):
+ """
+ Redirect client to auth server.
+
+ :param env: wsgi request environment
+ :param start_response: wsgi response callback
+ :returns HTTPUnauthorized http response
+ """
+ resp = webob.exc.HTTPUnauthorized("Backend authentication failed", [])
+ return resp(env, start_response)
+
+
+def filter_factory(global_conf, **local_conf):
+ conf = global_conf.copy()
+ conf.update(local_conf)
+
+ def auth_filter(app):
+ return AuthProtocol(app, conf)
+ return auth_filter
from heat.common import context
from heat.db import api as db_api
from heat.engine import api
+from heat.engine import clients
from heat.engine.event import Event
from heat.common import exception
from heat.common import identifier
}
return result
+ @request_context
+ def authenticated_to_backend(self, context):
+ """
+ Verify that the credentials in the RPC context are valid for the
+ current cloud backend.
+ """
+ return clients.Clients(context).authenticated()
+
@request_context
def get_template(self, context, stack_identity):
"""
template=template),
topic=_engine_topic(self.topic, ctxt, None))
+ def authenticated_to_backend(self, ctxt):
+ """
+ Verify that the credentials in the RPC context are valid for the
+ current cloud backend.
+
+ :param ctxt: RPC context.
+ """
+ return self.call(ctxt, self.make_msg('authenticated_to_backend'),
+ topic=_engine_topic(self.topic, ctxt, None))
+
def get_template(self, ctxt, stack_identity):
"""
Get the template.