import falcon import logging import ipaddress import string from random import choice from certidude import config from certidude.auth import login_required, authorize_admin from certidude.decorators import serialize from certidude.relational import RelationalMixin from jinja2 import Environment, FileSystemLoader logger = logging.getLogger("api") env = Environment(loader=FileSystemLoader("/etc/certidude/scripts"), trim_blocks=True) SQL_SELECT_INHERITED = """ select `key`, `value` from tag_inheritance where tag_id in (select tag.id from device_tag join tag on device_tag.tag_id = tag.id join device on device_tag.device_id = device.id where device.cn = %s) """ SQL_SELECT_TAGS = """ select tag.`key` as `key`, tag.`value` as `value` from device_tag join tag on device_tag.tag_id = tag.id join device on device_tag.device_id = device.id """ SQL_SELECT_RULES = """ select tag.cn as `cn`, tag.key as `tag_key`, tag.value as `tag_value`, tag_properties.property_key as `property_key`, tag_properties.property_value as `property_value` from tag_properties join tag on tag.key = tag_properties.tag_key and tag.value = tag_properties.tag_value """ class ConfigResource(RelationalMixin): @serialize @login_required @authorize_admin def on_get(self, req, resp): return self.iterfetch(SQL_SELECT_TAGS) class ScriptResource(RelationalMixin): def on_get(self, req, resp): from certidude.api.whois import address_to_identity node = address_to_identity( self.connect(), req.context.get("remote_addr") ) if not node: resp.body = "Could not map IP address: %s" % req.context.get("remote_addr") resp.status = falcon.HTTP_404 return address, acquired, identity = node key, common_name = identity.split("=") assert "=" not in common_name conn = self.connect() cursor = conn.cursor() resp.set_header("Content-Type", "text/x-shellscript") args = common_name, ctx = dict() for query in SQL_SELECT_INHERITED, SQL_SELECT_TAGS: cursor.execute(query, args) for key, value in cursor: current = ctx if "." in key: path, key = key.rsplit(".", 1) for component in path.split("."): if component not in current: current[component] = dict() current = current[component] current[key] = value cursor.close() conn.close() resp.body = env.get_template("uci.sh").render(ctx) # TODO: Assert time is within reasonable range