aboutsummaryrefslogtreecommitdiffstats
path: root/keystonemiddleware-moon/keystonemiddleware/moon_agent.py
diff options
context:
space:
mode:
Diffstat (limited to 'keystonemiddleware-moon/keystonemiddleware/moon_agent.py')
-rw-r--r--keystonemiddleware-moon/keystonemiddleware/moon_agent.py310
1 files changed, 0 insertions, 310 deletions
diff --git a/keystonemiddleware-moon/keystonemiddleware/moon_agent.py b/keystonemiddleware-moon/keystonemiddleware/moon_agent.py
deleted file mode 100644
index fd878fea..00000000
--- a/keystonemiddleware-moon/keystonemiddleware/moon_agent.py
+++ /dev/null
@@ -1,310 +0,0 @@
-# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
-# This software is distributed under the terms and conditions of the 'Apache-2.0'
-# license which can be found in the file 'LICENSE' in this package distribution
-# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
-
-import webob
-import logging
-import json
-import re
-import httplib
-
-from cStringIO import StringIO
-from oslo_config import cfg
-from keystonemiddleware.i18n import _, _LC, _LE, _LI, _LW
-
-
-_OPTS = [
- cfg.StrOpt('auth_uri',
- default="http://127.0.0.1:35357/v3",
- help='Complete public Identity API endpoint.'),
- cfg.StrOpt('auth_version',
- default=None,
- help='API version of the admin Identity API endpoint.'),
- cfg.StrOpt('authz_login',
- default="admin",
- help='Name of the administrator who will connect to the Keystone Moon backends.'),
- cfg.StrOpt('authz_password',
- default="nomoresecrete",
- help='Password of the administrator who will connect to the Keystone Moon backends.'),
- cfg.StrOpt('logfile',
- default="/tmp/authz.log",
- help='File where logs goes.'),
- ]
-
-_MOON_KEYSTONEMIDDLEWARE_AGENT_GROUP = 'moon_keystonemiddleware_agent'
-CONF = cfg.CONF
-CONF.register_opts(_OPTS, group=_MOON_KEYSTONEMIDDLEWARE_AGENT_GROUP)
-CONF.debug = True
-
-# from http://developer.openstack.org/api-ref-objectstorage-v1.html
-SWIFT_API = (
- ("^/v1/(?P<account>[\w_-]+)$", "GET", "get_account_details"),
- ("^/v1/(?P<account>[\w_-]+)$", "POST", "modify_account"),
- ("^/v1/(?P<account>[\w_-]+)$", "HEAD", "get_account"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "GET", "get_container"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "PUT", "create_container"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "POST", "update_container_metadata"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "DELETE", "delete_container"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)$", "HEAD", "get_container_metadata"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "GET", "get_object"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "PUT", "create_object"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "COPY", "copy_object"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "POST", "update_object_metadata"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "DELETE", "delete_object"),
- ("^/v1/(?P<account>[\w_-]+)/(?P<container>[\w-]+)/(?P<object>.+)$", "HEAD", "get_object_metadata"),
-)
-
-
-class MoonAgentKeystoneMiddleware(object):
- """Moon's agent for KeystoneMiddleware to interact calls."""
-
- post_data = {
- "auth": {
- "identity": {
- "methods": [
- "password"
- ],
- "password": {
- "user": {
- "domain": {
- "id": "Default"
- },
- "name": "admin",
- "password": "nomoresecrete"
- }
- }
- }
- }
- }
-
- def __init__(self, app, conf):
- self.conf = conf
- self._LOG = logging.getLogger(conf.get('log_name', __name__))
- # FIXME: events are duplicated in log file
- moon_agent_fh = logging.FileHandler(self.conf.get('logfile', "/tmp/keystonemiddleware.log"))
- self._LOG.setLevel(logging.DEBUG)
- self._LOG.addHandler(moon_agent_fh)
- self._LOG.info(_LI('Starting Moon KeystoneMiddleware Agent'))
- self._conf = conf
- self._app = app
-
- # Auth
- self.auth_host = conf.get('auth_host', "127.0.0.1")
- self.auth_port = int(conf.get('auth_port', 35357))
- auth_protocol = conf.get('auth_protocol', 'http')
- self._conf["_request_uri"] = '%s://%s:%s' % (auth_protocol, self.auth_host, # TODO: ??? for auth or authz
- self.auth_port)
-
- # SSL
- insecure = conf.get('insecure', False)
- cert_file = conf.get('certfile')
- key_file = conf.get('keyfile')
-
- if insecure:
- self._conf["_verify"] = False
- elif cert_file and key_file:
- self._conf["_verify"] = (cert_file, key_file)
- elif cert_file:
- self._conf["_verify"] = cert_file
- else:
- self._conf["_verify"] = None
-
- # Moon registered mgrs
- self.local_registered_mgr_dict = dict() # TODO: load from the sql backend
- from keystonemiddleware.moon_mgrs.authz_mgr.authz_mgr import AuthzMgr
- self.local_registered_mgr_dict["authz_mgr"] = AuthzMgr(self._conf)
-
- def __set_token(self):
- self.post_data["auth"]["identity"]["password"]["user"]["name"] = self.conf.get('authz_login', "admin")
- self.post_data["auth"]["identity"]["password"]["user"]["password"] = self.conf.get('authz_password', "nomoresecrete")
- data = self.get_url("/v3/auth/tokens", post_data=self.post_data)
- if "token" not in data:
- raise Exception("Authentication problem ({})".format(data))
- self.token = data["token"]
-
- def __unset_token(self):
- data = self.get_url("/v3/auth/tokens", method="DELETE", authtoken=True)
- if "content" in data and len(data["content"]) > 0:
- self._LOG.error("Error while unsetting token {}".format(data["content"]))
- self.token = None
-
- def get_url(self, url, post_data=None, delete_data=None, method="GET", authtoken=None):
- if post_data:
- method = "POST"
- if delete_data:
- method = "DELETE"
- self._LOG.debug("\033[32m{} {}\033[m".format(method, url))
- conn = httplib.HTTPConnection(self.auth_host, self.auth_port)
- headers = {
- "Content-type": "application/x-www-form-urlencoded",
- "Accept": "text/plain,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
- }
- if authtoken:
- if self.x_subject_token:
- if method == "DELETE":
- headers["X-Subject-Token"] = self.x_subject_token
- headers["X-Auth-Token"] = self.x_subject_token
- else:
- headers["X-Auth-Token"] = self.x_subject_token
- if post_data:
- method = "POST"
- headers["Content-type"] = "application/json"
- post_data = json.dumps(post_data)
- conn.request(method, url, post_data, headers=headers)
- elif delete_data:
- method = "DELETE"
- conn.request(method, url, json.dumps(delete_data), headers=headers)
- else:
- conn.request(method, url, headers=headers)
- resp = conn.getresponse()
- headers = resp.getheaders()
- try:
- self.x_subject_token = dict(headers)["x-subject-token"]
- except KeyError:
- pass
- content = resp.read()
- conn.close()
- try:
- return json.loads(content)
- except ValueError:
- return {"content": content}
-
- def _find_openstack_component(self, env):
- if "nova.context" in env.keys():
- return "nova"
- elif "swift.authorize" in env.keys():
- return "swift"
- else:
- self._LOG.debug(env.keys())
- return "unknown"
-
- def _get_action(self, env, component):
- """ Find and return the action of the request
- Actually, find only Nova action (start, destroy, pause, unpause, ...)
-
- :param env: the request
- :return: the action or ""
- """
- action = ""
- self.input = ""
- if component == "nova":
- length = int(env.get('CONTENT_LENGTH', '0'))
- # TODO (dthom): compute for Nova, Cinder, Neutron, ...
- action = ""
- if length > 0:
- try:
- sub_action_object = env['wsgi.input'].read(length)
- self.input = sub_action_object
- action = json.loads(sub_action_object).keys()[0]
- body = StringIO(sub_action_object)
- env['wsgi.input'] = body
- except ValueError:
- self._LOG.error("Error in decoding sub-action")
- except Exception as e:
- self._LOG.error(str(e))
- if not action or len(action) == 0 and "servers/detail" in env["PATH_INFO"]:
- return "list"
- if component == "swift":
- path = env["PATH_INFO"]
- method = env["REQUEST_METHOD"]
- for api in SWIFT_API:
- if re.match(api[0], path) and method == api[1]:
- action = api[2]
- length = int(env.get('CONTENT_LENGTH', '0'))
- # TODO (dthom): compute for Nova, Cinder, Neutron, ...
- _action = ""
- if length > 0:
- try:
- sub_action_object = env['wsgi.input'].read(length)
- self.input = sub_action_object
- _action = json.loads(sub_action_object).keys()[0]
- body = StringIO(sub_action_object)
- env['wsgi.input'] = body
- self._LOG.debug("wsgi.input={}".format(_action))
- except ValueError:
- self._LOG.error("Error in decoding sub-action")
- except Exception as e:
- self._LOG.error(str(e))
- return action
-
- @staticmethod
- def _get_resource(env, component):
- if component == "nova":
- # http://developer.openstack.org/api-ref-compute-v2.1.html
- # nova URLs:
- # /<tenant_id>/servers/<server_id>
- # list details for server_id
- # /<tenant_id>/servers/<server_id>/action
- # execute action to server_id
- # /<tenant_id>/servers/<server_id>/metadata
- # show metadata from server_id
- # /<tenant_id>/servers/details
- # list servers
- url = env.get("PATH_INFO").split("/")
- if url[-1] == "detail":
- return "servers"
- try:
- return url[3]
- except IndexError:
- return
- elif component == "swift":
- # remove the "/v1/" part of the URL
- return env.get("PATH_INFO").split("/", 2)[-1].replace("/", "-").replace(".", "-")
- return "unknown"
-
- def __call__(self, env, start_response):
- req = webob.Request(env)
- agent_data = dict()
-
- agent_data['user_id'] = env.get("HTTP_X_USER_ID")
- if not agent_data['user_id']:
- self._LOG.warning("No user_id found for {}".format(env.get("PATH_INFO")))
- return self._app(env, start_response)
-
- agent_data['tenant_id'] = env.get("HTTP_X_TENANT_ID")
- if not agent_data['tenant_id']:
- self._LOG.warning("No tenant_id found for {}".format(env.get("PATH_INFO")))
- return self._app(env, start_response)
-
- agent_data['OS_component'] = self._find_openstack_component(env)
-
- agent_data['action_id'] = self._get_action(env, agent_data['OS_component'])
- if not agent_data['action_id']:
- self._LOG.warning("No action_id found for {}".format(env.get("PATH_INFO")))
- # If action is not found, we can't raise an exception because a lots of action is missing
- # in function self._get_action, it is not possible to get them all.
- return self._app(env, start_response)
-
- agent_data['resource_id'] = self._get_resource(env, agent_data['OS_component'])
- if not agent_data['resource_id'] :
- self._LOG.warning("No resource_id found for {}".format(env.get("PATH_INFO")))
- return self._app(env, start_response)
- else:
- self._LOG.debug("resource_id={}".format(agent_data['resource_id']))
-
- self.__set_token()
- for _mgr in self.local_registered_mgr_dict: # TODO: update from the sql backend
- self.local_registered_mgr_dict[_mgr].response_content = \
- json.loads(self.local_registered_mgr_dict[_mgr].treat_request(self.x_subject_token, agent_data).content)
- self.__unset_token()
-
- aggregate_result = 1
- for _mgr in self.local_registered_mgr_dict:
- if not self.local_registered_mgr_dict[_mgr].response_content:
- aggregate_result = 0
-
- if aggregate_result:
- return self._app(env, 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 moon_agent_filter(app):
- return MoonAgentKeystoneMiddleware(app, conf)
- return moon_agent_filter
-
-