mirror of
				https://github.com/laurivosandi/certidude
				synced 2025-10-31 01:19:11 +00:00 
			
		
		
		
	Merge pull request #4 from plaes/wip
Refactoring and making sure things actually work
This commit is contained in:
		| @@ -1,18 +1,16 @@ | |||||||
| import re | import re | ||||||
| import falcon | import falcon | ||||||
| import ipaddress | import ipaddress | ||||||
|  | import mimetypes | ||||||
| import os | import os | ||||||
| import json | import json | ||||||
| import types | import types | ||||||
| import urllib.request |  | ||||||
| import click | import click | ||||||
| from time import sleep | from time import sleep | ||||||
| from certidude.wrappers import Request, Certificate | from certidude.wrappers import Request, Certificate, CertificateAuthorityConfig | ||||||
| from certidude.auth import login_required | from certidude.auth import login_required | ||||||
| from certidude.mailer import Mailer |  | ||||||
| from pyasn1.codec.der import decoder | from pyasn1.codec.der import decoder | ||||||
| from datetime import datetime, date | from datetime import datetime, date | ||||||
| from OpenSSL import crypto |  | ||||||
| from jinja2 import Environment, PackageLoader, Template | from jinja2 import Environment, PackageLoader, Template | ||||||
|  |  | ||||||
| env = Environment(loader=PackageLoader("certidude", "templates")) | env = Environment(loader=PackageLoader("certidude", "templates")) | ||||||
| @@ -356,3 +354,44 @@ class ApplicationConfigurationResource(CertificateAuthorityBase): | |||||||
|         resp.append_header("Content-Disposition", "attachment; filename=%s.ovpn" % cn) |         resp.append_header("Content-Disposition", "attachment; filename=%s.ovpn" % cn) | ||||||
|         resp.body = Template(open("/etc/openvpn/%s.template" % ca.slug).read()).render(ctx) |         resp.body = Template(open("/etc/openvpn/%s.template" % ca.slug).read()).render(ctx) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class StaticResource(object): | ||||||
|  |     def __init__(self, root): | ||||||
|  |         self.root = os.path.realpath(root) | ||||||
|  |  | ||||||
|  |     def __call__(self, req, resp): | ||||||
|  |  | ||||||
|  |         path = os.path.realpath(os.path.join(self.root, req.path[1:])) | ||||||
|  |         if not path.startswith(self.root): | ||||||
|  |             raise falcon.HTTPForbidden | ||||||
|  |  | ||||||
|  |         print("Serving:", path) | ||||||
|  |         if os.path.exists(path): | ||||||
|  |             content_type, content_encoding = mimetypes.guess_type(path) | ||||||
|  |             if content_type: | ||||||
|  |                 resp.append_header("Content-Type", content_type) | ||||||
|  |             if content_encoding: | ||||||
|  |                 resp.append_header("Content-Encoding", content_encoding) | ||||||
|  |             resp.append_header("Content-Disposition", "attachment") | ||||||
|  |             resp.stream = open(path, "rb") | ||||||
|  |         else: | ||||||
|  |             resp.status = falcon.HTTP_404 | ||||||
|  |             resp.body = "File '%s' not found" % req.path | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def certidude_app(): | ||||||
|  |     config = CertificateAuthorityConfig() | ||||||
|  |  | ||||||
|  |     app = falcon.API() | ||||||
|  |     app.add_route("/api/{ca}/ocsp/", CertificateStatusResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/signed/{cn}/openvpn", ApplicationConfigurationResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/certificate/", CertificateAuthorityResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/revoked/", RevocationListResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/signed/{cn}/", SignedCertificateDetailResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/signed/", SignedCertificateListResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/request/{cn}/", RequestDetailResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/request/", RequestListResource(config)) | ||||||
|  |     app.add_route("/api/{ca}/", IndexResource(config)) | ||||||
|  |  | ||||||
|  |     return app | ||||||
|   | |||||||
| @@ -3,9 +3,7 @@ | |||||||
|  |  | ||||||
| import asyncore | import asyncore | ||||||
| import click | import click | ||||||
| import falcon |  | ||||||
| import logging | import logging | ||||||
| import mimetypes |  | ||||||
| import netifaces | import netifaces | ||||||
| import os | import os | ||||||
| import pwd | import pwd | ||||||
| @@ -761,30 +759,6 @@ def certidude_sign(common_name, overwrite, lifetime): | |||||||
|             click.echo("Added extension %s: %s" % (key, value)) |             click.echo("Added extension %s: %s" % (key, value)) | ||||||
|         click.echo() |         click.echo() | ||||||
|  |  | ||||||
| class StaticResource(object): |  | ||||||
|     def __init__(self, root): |  | ||||||
|         self.root = os.path.realpath(root) |  | ||||||
|         click.echo("Serving static from: %s" % self.root) |  | ||||||
|  |  | ||||||
|     def __call__(self, req, resp): |  | ||||||
|  |  | ||||||
|         path = os.path.realpath(os.path.join(self.root, req.path[1:])) |  | ||||||
|         if not path.startswith(self.root): |  | ||||||
|             raise falcon.HTTPForbidden |  | ||||||
|  |  | ||||||
|         print("Serving:", path) |  | ||||||
|         if os.path.exists(path): |  | ||||||
|             content_type, content_encoding = mimetypes.guess_type(path) |  | ||||||
|             if content_type: |  | ||||||
|                 resp.append_header("Content-Type", content_type) |  | ||||||
|             if content_encoding: |  | ||||||
|                 resp.append_header("Content-Encoding", content_encoding) |  | ||||||
|             resp.append_header("Content-Disposition", "attachment") |  | ||||||
|             resp.stream = open(path, "rb") |  | ||||||
|         else: |  | ||||||
|             resp.status = falcon.HTTP_404 |  | ||||||
|             resp.body = "File '%s' not found" % req.path |  | ||||||
|  |  | ||||||
| @click.command("serve", help="Run built-in HTTP server") | @click.command("serve", help="Run built-in HTTP server") | ||||||
| @click.option("-u", "--user", default="certidude", help="Run as user") | @click.option("-u", "--user", default="certidude", help="Run as user") | ||||||
| @click.option("-p", "--port", default=80, help="Listen port") | @click.option("-p", "--port", default=80, help="Listen port") | ||||||
| @@ -798,34 +772,27 @@ def certidude_serve(user, port, listen, enable_signature): | |||||||
|  |  | ||||||
|     click.echo("Serving API at %s:%d" % (listen, port)) |     click.echo("Serving API at %s:%d" % (listen, port)) | ||||||
|     import pwd |     import pwd | ||||||
|     import falcon |  | ||||||
|     from wsgiref.simple_server import make_server, WSGIServer |     from wsgiref.simple_server import make_server, WSGIServer | ||||||
|     from socketserver import ThreadingMixIn |     from socketserver import ThreadingMixIn | ||||||
|     from certidude.api import CertificateAuthorityResource, \ |     from certidude.api import certidude_app, StaticResource | ||||||
|         RequestDetailResource, RequestListResource, \ |  | ||||||
|         SignedCertificateDetailResource, SignedCertificateListResource, \ |  | ||||||
|         RevocationListResource, IndexResource, ApplicationConfigurationResource, \ |  | ||||||
|         CertificateStatusResource |  | ||||||
|  |  | ||||||
|     class ThreadingWSGIServer(ThreadingMixIn, WSGIServer): |     class ThreadingWSGIServer(ThreadingMixIn, WSGIServer): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     click.echo("Listening on %s:%d" % (listen, port)) |     click.echo("Listening on %s:%d" % (listen, port)) | ||||||
|  |  | ||||||
|     app = falcon.API() |     app = certidude_app() | ||||||
|     app.add_route("/api/{ca}/ocsp/", CertificateStatusResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/signed/{cn}/openvpn", ApplicationConfigurationResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/certificate/", CertificateAuthorityResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/revoked/", RevocationListResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/signed/{cn}/", SignedCertificateDetailResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/signed/", SignedCertificateListResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/request/{cn}/", RequestDetailResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/request/", RequestListResource(config)) |  | ||||||
|     app.add_route("/api/{ca}/", IndexResource(config)) |  | ||||||
|  |  | ||||||
|     app.add_sink(StaticResource(os.path.join(os.path.dirname(__file__), "static"))) |     app.add_sink(StaticResource(os.path.join(os.path.dirname(__file__), "static"))) | ||||||
|  |  | ||||||
|     httpd = make_server(listen, port, app, ThreadingWSGIServer) |     httpd = make_server(listen, port, app, ThreadingWSGIServer) | ||||||
|  |  | ||||||
|     if user: |     if user: | ||||||
|  |         # Load required utils which cannot be imported from chroot | ||||||
|  |         # TODO: Figure out better approach | ||||||
|  |         from jinja2.debug import make_traceback as _make_traceback | ||||||
|  |         "".encode("charmap") | ||||||
|  |  | ||||||
|         _, _, uid, gid, gecos, root, shell = pwd.getpwnam(user) |         _, _, uid, gid, gecos, root, shell = pwd.getpwnam(user) | ||||||
|         if uid == 0: |         if uid == 0: | ||||||
|             click.echo("Please specify unprivileged user") |             click.echo("Please specify unprivileged user") | ||||||
| @@ -835,7 +802,7 @@ def certidude_serve(user, port, listen, enable_signature): | |||||||
|         os.setuid(uid) |         os.setuid(uid) | ||||||
|         os.umask(0o007) |         os.umask(0o007) | ||||||
|     elif os.getuid() == 0: |     elif os.getuid() == 0: | ||||||
|         click.echo("Warning: running as root, this is not reccommended!") |         click.echo("Warning: running as root, this is not recommended!") | ||||||
|     httpd.serve_forever() |     httpd.serve_forever() | ||||||
|  |  | ||||||
| @click.group("strongswan", help="strongSwan helpers") | @click.group("strongswan", help="strongSwan helpers") | ||||||
|   | |||||||
| @@ -1,29 +1,14 @@ | |||||||
|  | """ | ||||||
|  |     certidude.wsgi | ||||||
|  |     ~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  |     Certidude web app factory for WSGI-compatible web servers | ||||||
|  | """ | ||||||
| import os | import os | ||||||
| import falcon | from certidude.api import certidude_app | ||||||
| from certidude.wrappers import CertificateAuthorityConfig |  | ||||||
| from certidude.api import CertificateAuthorityResource, \ |  | ||||||
|     RequestDetailResource, RequestListResource, \ |  | ||||||
|     SignedCertificateDetailResource, SignedCertificateListResource, \ |  | ||||||
|     RevocationListResource, IndexResource, ApplicationConfigurationResource, \ |  | ||||||
|     CertificateStatusResource |  | ||||||
|  |  | ||||||
| # TODO: deduplicate routing code |  | ||||||
| # TODO: set up /run/certidude/api paths and permissions | # TODO: set up /run/certidude/api paths and permissions | ||||||
|  |  | ||||||
| config = CertificateAuthorityConfig() |  | ||||||
|  |  | ||||||
| assert os.getenv("PUSH_SUBSCRIBE"), "Please set PUSH_SUBSCRIBE to your web server's subscription URL" | assert os.getenv("PUSH_SUBSCRIBE"), "Please set PUSH_SUBSCRIBE to your web server's subscription URL" | ||||||
| assert os.getenv("PUSH_PUBLISH"), "Please set PUSH_PUBLISH to your web server's publishing URL" | assert os.getenv("PUSH_PUBLISH"), "Please set PUSH_PUBLISH to your web server's publishing URL" | ||||||
|  |  | ||||||
| app = falcon.API() | app = certidude_app() | ||||||
| app.add_route("/api/{ca}/ocsp/", CertificateStatusResource(config)) |  | ||||||
| app.add_route("/api/{ca}/signed/{cn}/openvpn", ApplicationConfigurationResource(config)) |  | ||||||
| app.add_route("/api/{ca}/certificate/", CertificateAuthorityResource(config)) |  | ||||||
| app.add_route("/api/{ca}/revoked/", RevocationListResource(config)) |  | ||||||
| app.add_route("/api/{ca}/signed/{cn}/", SignedCertificateDetailResource(config)) |  | ||||||
| app.add_route("/api/{ca}/signed/", SignedCertificateListResource(config)) |  | ||||||
| app.add_route("/api/{ca}/request/{cn}/", RequestDetailResource(config)) |  | ||||||
| app.add_route("/api/{ca}/request/", RequestListResource(config)) |  | ||||||
| app.add_route("/api/{ca}/", IndexResource(config)) |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user