aboutsummaryrefslogtreecommitdiffstats
path: root/external_policy_checker/external_policy_checker
diff options
context:
space:
mode:
authorThomas Duval <thomas.duval@orange.com>2018-03-07 10:53:41 +0100
committerThomas Duval <thomas.duval@orange.com>2018-03-07 10:57:14 +0100
commit9a2e6721376547244e53dbb92ea596f526a9c865 (patch)
tree0c9377c1af969864a740072fb442aa4847ca274e /external_policy_checker/external_policy_checker
parentdbd38cc0f28257772580d42905d2d398fc1d1705 (diff)
Add Moon stub for the tempest and patrole tests.
Change-Id: Icb3cc72f69636b3a99a3c7c19be3c4e407cb24dc
Diffstat (limited to 'external_policy_checker/external_policy_checker')
-rw-r--r--external_policy_checker/external_policy_checker/__init__.py1
-rw-r--r--external_policy_checker/external_policy_checker/__main__.py9
-rw-r--r--external_policy_checker/external_policy_checker/conf_installer.py83
-rw-r--r--external_policy_checker/external_policy_checker/server.py135
4 files changed, 228 insertions, 0 deletions
diff --git a/external_policy_checker/external_policy_checker/__init__.py b/external_policy_checker/external_policy_checker/__init__.py
new file mode 100644
index 00000000..a4e2017f
--- /dev/null
+++ b/external_policy_checker/external_policy_checker/__init__.py
@@ -0,0 +1 @@
+__version__ = "0.1"
diff --git a/external_policy_checker/external_policy_checker/__main__.py b/external_policy_checker/external_policy_checker/__main__.py
new file mode 100644
index 00000000..4499a96b
--- /dev/null
+++ b/external_policy_checker/external_policy_checker/__main__.py
@@ -0,0 +1,9 @@
+# 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 moon_bouchon.server
+
+moon_bouchon.server.main()
diff --git a/external_policy_checker/external_policy_checker/conf_installer.py b/external_policy_checker/external_policy_checker/conf_installer.py
new file mode 100644
index 00000000..ec45003b
--- /dev/null
+++ b/external_policy_checker/external_policy_checker/conf_installer.py
@@ -0,0 +1,83 @@
+import shutil
+import logging
+import argparse
+import os
+from uuid import uuid4
+import glob
+
+logger = logging.getLogger(__name__)
+
+COMPONENTS = (
+ "cinder",
+ "nova",
+ "neutron",
+ "glance",
+ "keystone"
+)
+
+
+def init():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--verbose", '-v', action='store_true', help='verbose mode')
+ parser.add_argument("--debug", '-d', action='store_true', help='debug mode')
+ parser.add_argument("--templates", '-t', help='set template directory', default="templates/")
+ parser.add_argument("--out-dir", '-o', help='if set, copy the files in this directory', default=None)
+ parser.add_argument("wrapper_url", help='Wrapper URL to use', nargs="*",
+ default=["http://127.0.0.1:8080/policy_checker"])
+ args = parser.parse_args()
+ logging_format = "%(levelname)s: %(message)s"
+ if args.verbose:
+ logging.basicConfig(level=logging.INFO, format=logging_format)
+ if args.debug:
+ logging.basicConfig(level=logging.DEBUG, format=logging_format)
+ return args
+
+
+def update_templates(templates_dir, wrapper_url):
+ tmp_dir = os.path.join("/tmp", str(uuid4()))
+ wrapper_url = wrapper_url[0].strip('"').strip("'")
+ os.mkdir(tmp_dir)
+ for comp in COMPONENTS:
+ input_file = os.path.join(templates_dir, comp + ".policy.json")
+ output_file = os.path.join(tmp_dir, comp + ".policy.json")
+ output_fd = open(output_file, "w")
+ for line in open(input_file):
+ output_fd.write(line.replace("{{wrapper}}", wrapper_url))
+ return tmp_dir
+
+
+def remove_tmp_files(tmp_dir):
+ for _filename in glob.glob(os.path.join(tmp_dir, "*")):
+ logger.debug("{} {}".format(_filename, os.path.isfile(_filename)))
+ if os.path.isfile(_filename):
+ logger.debug("Trying to delete {}".format(_filename))
+ os.remove(_filename)
+ logger.debug("Delete done")
+ os.removedirs(tmp_dir)
+
+
+def main(templates_dir, wrapper_url, out_dir=None):
+ logger.info("Moving configuration files")
+ tmp_dir = update_templates(templates_dir, wrapper_url)
+ if out_dir:
+ logger.info("Moving to {}".format(out_dir))
+ try:
+ os.mkdir(out_dir)
+ except FileExistsError:
+ logger.warning("Output directory exists, writing on it!")
+ for comp in COMPONENTS:
+ logger.info("Moving {}".format(comp))
+ shutil.copy(os.path.join(tmp_dir, comp + ".policy.json"),
+ os.path.join(out_dir, comp + ".policy.json"))
+ else:
+ logger.info("Moving to /etc")
+ for comp in COMPONENTS:
+ logger.info("Moving {}".format(comp))
+ shutil.copy(os.path.join(tmp_dir, comp + ".policy.json"),
+ os.path.join("etc", comp, "policy.json"))
+ remove_tmp_files(tmp_dir)
+
+
+if __name__ == "__main__":
+ args = init()
+ main(args.templates, args.wrapper_url, args.out_dir)
diff --git a/external_policy_checker/external_policy_checker/server.py b/external_policy_checker/external_policy_checker/server.py
new file mode 100644
index 00000000..cbb4a933
--- /dev/null
+++ b/external_policy_checker/external_policy_checker/server.py
@@ -0,0 +1,135 @@
+# Copyright 2018 Orange
+# 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 sys
+import flask
+from flask import Flask
+from flask import request
+import json
+import logging
+import random
+
+logger = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+app = Flask(__name__)
+
+
+def test_target(data, result):
+ if "resource_id" in data:
+ result["resource_id"] = data['object_id']
+ if "object_id" in data:
+ result["resource_id"] = data['object_id']
+ if 'project_id' in data:
+ result["project_id"] = data['project_id']
+ if 'user_id' in data:
+ result["user_id"] = data['user_id']
+
+
+def test_credentials(data, result):
+ if 'project_id' in data:
+ result["project_id"] = data['project_id']
+ if 'user_id' in data:
+ result["user_id"] = data['user_id']
+ if 'project_domain_id' in data:
+ result["domain_id"] = data['project_domain_id']
+
+
+def test_rule(data, result):
+ result['action_name'] = data
+
+
+def test_data():
+ data = request.form
+ result = {
+ "user_id": "",
+ "project_id": "",
+ "action_name": "",
+ "resource_id": "",
+ "domain_id": "",
+ }
+ if not dict(request.form):
+ data = json.loads(request.data.decode("utf-8"))
+ try:
+ target = json.loads(data.get('target', {}))
+ except Exception:
+ raise Exception("Error reading target")
+ try:
+ credentials = json.loads(data.get('credentials', {}))
+ except Exception:
+ raise Exception("Error reading credentials")
+ try:
+ rule = data.get('rule', "")
+ except Exception:
+ raise Exception("Error reading rule")
+ test_target(target, result)
+ test_credentials(credentials, result)
+ test_rule(rule, result)
+ return_value = True
+ logger.info("Analysing request with {}".format(rule))
+ for key in result:
+ if not result[key] and key != "domain_id":
+ return_value = False
+ logger.error("Attribute {} is absent".format(key))
+ if not result[key] and key == "domain_id":
+ logger.warning("Attribute {} is missing.".format(key))
+ return return_value
+
+
+@app.route("/policy_checker", methods=["POST"])
+def checker():
+ information_is_complete = False
+ try:
+ information_is_complete = test_data()
+ except Exception as e:
+ logger.exception(e)
+ if information_is_complete:
+ response = flask.make_response("True")
+ response.headers['content-type'] = 'application/octet-stream'
+ return response
+ else:
+ response = flask.make_response("False")
+ response.headers['content-type'] = 'application/octet-stream'
+ return response, 403
+
+
+def get_target():
+ data = request.form
+ if not dict(request.form):
+ data = json.loads(request.data.decode("utf-8"))
+ try:
+ return json.loads(data.get('target', {}))
+ except Exception:
+ raise Exception("Error reading target")
+
+
+@app.route("/authz/grant", methods=["POST"])
+def wrapper_grant():
+ logger.info("Requesting wrapper authz with {}".format(get_target()))
+ response = flask.make_response("True")
+ response.headers['content-type'] = 'application/octet-stream'
+ return response
+
+
+@app.route("/authz/deny", methods=["POST"])
+def wrapper_deny():
+ logger.info("Requesting wrapper authz with {}".format(get_target()))
+ response = flask.make_response("False")
+ response.headers['content-type'] = 'application/octet-stream'
+ return response, 403
+
+
+def main():
+ port = 8080
+ if len(sys.argv) > 1:
+ try:
+ port = int(sys.argv[1])
+ except ValueError:
+ logger.error("Argument for Port in command line is not an integer")
+ sys.exit(1)
+ app.run(host="0.0.0.0", port=port)
+
+
+if __name__ == "__main__":
+ main()