mirror of
				https://github.com/laurivosandi/certidude
				synced 2025-10-30 17:09:19 +00:00 
			
		
		
		
	Add API call for rendering scripts, bugfixes
This commit is contained in:
		| @@ -172,7 +172,7 @@ def certidude_app(log_handlers=[]): | ||||
|     from .signed import SignedCertificateDetailResource | ||||
|     from .request import RequestListResource, RequestDetailResource | ||||
|     from .lease import LeaseResource, LeaseDetailResource | ||||
|     from .cfg import ConfigResource, ScriptResource | ||||
|     from .script import ScriptResource | ||||
|     from .tag import TagResource, TagDetailResource | ||||
|     from .attrib import AttributeResource | ||||
|     from .bootstrap import BootstrapResource | ||||
| @@ -194,6 +194,7 @@ def certidude_app(log_handlers=[]): | ||||
|  | ||||
|     # Extended attributes for scripting etc. | ||||
|     app.add_route("/api/signed/{cn}/attr/", AttributeResource()) | ||||
|     app.add_route("/api/signed/{cn}/script/", ScriptResource()) | ||||
|  | ||||
|     # API calls used by pushed events on the JS end | ||||
|     app.add_route("/api/signed/{cn}/tag/", TagResource()) | ||||
|   | ||||
| @@ -4,7 +4,6 @@ from ipaddress import ip_address | ||||
| from datetime import datetime | ||||
| from certidude import config, authority | ||||
| from certidude.decorators import serialize | ||||
| from xattr import getxattr, listxattr | ||||
|  | ||||
| logger = logging.getLogger(__name__) | ||||
|  | ||||
| @@ -18,24 +17,10 @@ class AttributeResource(object): | ||||
|         Results made available only to lease IP address. | ||||
|         """ | ||||
|         try: | ||||
|             path, buf, cert = authority.get_signed(cn) | ||||
|             path, buf, cert, attribs = authority.get_attributes(cn) | ||||
|         except IOError: | ||||
|             raise falcon.HTTPNotFound() | ||||
|         else: | ||||
|             attribs = dict() | ||||
|             for key in listxattr(path): | ||||
|                 if not key.startswith("user."): | ||||
|                     continue | ||||
|                 value = getxattr(path, key) | ||||
|                 current = attribs | ||||
|                 if "." in key: | ||||
|                     namespace, key = key.rsplit(".", 1) | ||||
|                     for component in namespace.split("."): | ||||
|                         if component not in current: | ||||
|                             current[component] = dict() | ||||
|                         current = current[component] | ||||
|                 current[key] = value | ||||
|  | ||||
|             try: | ||||
|                 whitelist = ip_address(attribs.get("user").get("lease").get("address").decode("ascii")) | ||||
|             except AttributeError: # TODO: probably race condition | ||||
|   | ||||
| @@ -1,110 +0,0 @@ | ||||
| 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(__name__) | ||||
| 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 | ||||
							
								
								
									
										21
									
								
								certidude/api/script.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								certidude/api/script.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| import falcon | ||||
| import logging | ||||
| from certidude import config, authority | ||||
| from certidude.decorators import serialize | ||||
| from jinja2 import Environment, FileSystemLoader | ||||
|  | ||||
| logger = logging.getLogger(__name__) | ||||
| env = Environment(loader=FileSystemLoader(config.SCRIPT_DIR), trim_blocks=True) | ||||
|  | ||||
| class ScriptResource(): | ||||
|     def on_get(self, req, resp, cn): | ||||
|  | ||||
|         try: | ||||
|             path, buf, cert, attribs = authority.get_attributes(cn) | ||||
|         except IOError: | ||||
|             raise falcon.HTTPNotFound() | ||||
|         else: | ||||
|             resp.set_header("Content-Type", "text/x-shellscript") | ||||
|             resp.body = env.get_template(config.SCRIPT_DEFAULT).render(attributes=attribs) | ||||
|  | ||||
|         # TODO: Assert time is within reasonable range | ||||
		Reference in New Issue
	
	Block a user