mirror of
				https://github.com/laurivosandi/certidude
				synced 2025-10-31 01:19:11 +00:00 
			
		
		
		
	api: Added signed certificate tagging mechanism
This commit is contained in:
		| @@ -79,6 +79,7 @@ def certidude_app(): | ||||
|     from .lease import LeaseResource | ||||
|     from .whois import WhoisResource | ||||
|     from .log import LogResource | ||||
|     from .tag import TagResource, TagDetailResource | ||||
|  | ||||
|     app = falcon.API() | ||||
|  | ||||
| @@ -91,6 +92,8 @@ def certidude_app(): | ||||
|     app.add_route("/api/request/{cn}/", RequestDetailResource()) | ||||
|     app.add_route("/api/request/", RequestListResource()) | ||||
|     app.add_route("/api/log/", LogResource()) | ||||
|     app.add_route("/api/tag/", TagResource()) | ||||
|     app.add_route("/api/tag/{identifier}/", TagDetailResource()) | ||||
|     app.add_route("/api/", SessionResource()) | ||||
|  | ||||
|     # Gateway API calls, should this be moved to separate project? | ||||
| @@ -128,12 +131,13 @@ def certidude_app(): | ||||
|         logger.addHandler(push_handler) | ||||
|  | ||||
|  | ||||
|     logging.getLogger("cli").info("Started Certidude at %s", socket.getaddrinfo(socket.gethostname(), 0, flags=socket.AI_CANONNAME)[0][3]) | ||||
|     logging.getLogger("cli").debug("Started Certidude at %s", | ||||
|         socket.getaddrinfo(socket.gethostname(), 0, flags=socket.AI_CANONNAME)[0][3]) | ||||
|  | ||||
|     import atexit | ||||
|  | ||||
|     def exit_handler(): | ||||
|         logging.getLogger("cli").info("Shutting down Certidude") | ||||
|         logging.getLogger("cli").debug("Shutting down Certidude") | ||||
|  | ||||
|     atexit.register(exit_handler) | ||||
|  | ||||
|   | ||||
| @@ -73,7 +73,7 @@ class RequestListResource(object): | ||||
|             raise falcon.HTTPConflict( | ||||
|                 "CSR with such CN already exists", | ||||
|                 "Will not overwrite existing certificate signing request, explicitly delete CSR and try again") | ||||
|         push.publish("request_submitted", csr.common_name) | ||||
|         push.publish("request-submitted", csr.common_name) | ||||
|  | ||||
|         # Wait the certificate to be signed if waiting is requested | ||||
|         if req.get_param("wait"): | ||||
|   | ||||
| @@ -1,9 +1,12 @@ | ||||
|  | ||||
| import falcon | ||||
| import logging | ||||
| from certidude import authority | ||||
| from certidude.auth import login_required, authorize_admin | ||||
| from certidude.decorators import serialize | ||||
|  | ||||
| logger = logging.getLogger("api") | ||||
|  | ||||
| class SignedCertificateListResource(object): | ||||
|     @serialize | ||||
|     @authorize_admin | ||||
| @@ -26,13 +29,17 @@ class SignedCertificateDetailResource(object): | ||||
|     @serialize | ||||
|     def on_get(self, req, resp, cn): | ||||
|         try: | ||||
|             logger.info("Served certificate %s to %s", cn, req.env["REMOTE_ADDR"]) | ||||
|             resp.set_header("Content-Disposition", "attachment; filename=%s.crt" % cn) | ||||
|             return authority.get_signed(cn) | ||||
|         except FileNotFoundError: | ||||
|             logger.warning("Failed to serve non-existant certificate %s to %s", cn, req.env["REMOTE_ADDR"]) | ||||
|             resp.body = "No certificate CN=%s found" % cn | ||||
|             raise falcon.HTTPNotFound() | ||||
|  | ||||
|     @login_required | ||||
|     @authorize_admin | ||||
|     def on_delete(self, req, resp, cn): | ||||
|         logger.info("Revoked certificate %s by %s from %s", cn, req.context["user"], req.env["REMOTE_ADDR"]) | ||||
|         authority.revoke_certificate(cn) | ||||
|  | ||||
|   | ||||
							
								
								
									
										90
									
								
								certidude/api/tag.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								certidude/api/tag.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
|  | ||||
| import falcon | ||||
| import logging | ||||
| from certidude import config | ||||
| from certidude.auth import login_required, authorize_admin | ||||
| from certidude.decorators import serialize | ||||
|  | ||||
| logger = logging.getLogger("api") | ||||
|  | ||||
| class TagResource(object): | ||||
|     @serialize | ||||
|     @login_required | ||||
|     @authorize_admin | ||||
|     def on_get(self, req, resp): | ||||
|         conn = config.DATABASE_POOL.get_connection() | ||||
|         cursor = conn.cursor(dictionary=True) | ||||
|         cursor.execute("select * from tag") | ||||
|  | ||||
|         def g(): | ||||
|             for row in cursor: | ||||
|                 yield row | ||||
|             cursor.close() | ||||
|             conn.close() | ||||
|         return tuple(g()) | ||||
|  | ||||
|     @serialize | ||||
|     @login_required | ||||
|     @authorize_admin | ||||
|     def on_post(self, req, resp): | ||||
|         from certidude import push | ||||
|         conn = config.DATABASE_POOL.get_connection() | ||||
|         cursor = conn.cursor() | ||||
|         args = req.get_param("cn"), req.get_param("key"), req.get_param("value") | ||||
|         cursor.execute( | ||||
|             "insert into tag (`cn`, `key`, `value`) values (%s, %s, %s)", args) | ||||
|         push.publish("tag-added", str(cursor.lastrowid)) | ||||
|         logger.debug("Tag cn=%s, key=%s, value=%s added" % args) | ||||
|         conn.commit() | ||||
|         cursor.close() | ||||
|         conn.close() | ||||
|  | ||||
|  | ||||
| class TagDetailResource(object): | ||||
|     @serialize | ||||
|     @login_required | ||||
|     @authorize_admin | ||||
|     def on_get(self, req, resp, identifier): | ||||
|         conn = config.DATABASE_POOL.get_connection() | ||||
|         cursor = conn.cursor(dictionary=True) | ||||
|         cursor.execute("select * from tag where `id` = %s", (identifier,)) | ||||
|         for row in cursor: | ||||
|             cursor.close() | ||||
|             conn.close() | ||||
|             return row | ||||
|         cursor.close() | ||||
|         conn.close() | ||||
|         raise falcon.HTTPNotFound() | ||||
|  | ||||
|     @serialize | ||||
|     @login_required | ||||
|     @authorize_admin | ||||
|     def on_put(self, req, resp, identifier): | ||||
|         from certidude import push | ||||
|         conn = config.DATABASE_POOL.get_connection() | ||||
|         cursor = conn.cursor() | ||||
|         cursor.execute("update tag set `value` = %s where `id` = %s limit 1", | ||||
|             (req.get_param("value"), identifier)) | ||||
|         conn.commit() | ||||
|         cursor.close() | ||||
|         conn.close() | ||||
|         logger.debug("Tag %s updated, value set to %s", | ||||
|             identifier, req.get_param("value")) | ||||
|         push.publish("tag-updated", identifier) | ||||
|  | ||||
|  | ||||
|     @serialize | ||||
|     @login_required | ||||
|     @authorize_admin | ||||
|     def on_delete(self, req, resp, identifier): | ||||
|         from certidude import push | ||||
|         conn = config.DATABASE_POOL.get_connection() | ||||
|         cursor = conn.cursor() | ||||
|         cursor.execute("delete from tag where tag.id = %s", (identifier,)) | ||||
|         conn.commit() | ||||
|         cursor.close() | ||||
|         conn.close() | ||||
|         push.publish("tag-removed", identifier) | ||||
|         logger.debug("Tag %s removed" % identifier) | ||||
|  | ||||
|  | ||||
| @@ -1,8 +1,10 @@ | ||||
|  | ||||
| import falcon | ||||
| import ipaddress | ||||
| from datetime import datetime | ||||
| from certidude import config | ||||
| from certidude.decorators import serialize | ||||
| from certidude.api.lease import parse_dn | ||||
|  | ||||
| def address_to_identity(cnx, addr): | ||||
|     """ | ||||
| @@ -10,19 +12,19 @@ def address_to_identity(cnx, addr): | ||||
|     """ | ||||
|  | ||||
|     SQL_LEASES = """ | ||||
|         SELECT | ||||
|         select | ||||
|             acquired, | ||||
|             released, | ||||
|             identities.data as identity | ||||
|         FROM | ||||
|         from | ||||
|             addresses | ||||
|         RIGHT JOIN | ||||
|         right join | ||||
|             identities | ||||
|         ON | ||||
|         on | ||||
|             identities.id = addresses.identity | ||||
|         WHERE | ||||
|             address = %s AND | ||||
|             released IS NOT NULL | ||||
|         where | ||||
|             address = %s and | ||||
|             released is not null | ||||
|     """ | ||||
|  | ||||
|     cursor = cnx.cursor() | ||||
| @@ -31,6 +33,7 @@ def address_to_identity(cnx, addr): | ||||
|  | ||||
|     for acquired, released, identity in cursor: | ||||
|         return { | ||||
|             "address": addr, | ||||
|             "acquired": datetime.utcfromtimestamp(acquired), | ||||
|             "identity": parse_dn(bytes(identity)) | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user