From 52d35012a4261ba0fee9bb1d8ce8ea266a600933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Thu, 13 Apr 2017 20:30:28 +0000 Subject: [PATCH] Various fixes --- certidude/api/__init__.py | 4 ++-- certidude/api/attrib.py | 3 +-- certidude/authority.py | 5 ++--- certidude/cli.py | 18 ++++++++++-------- certidude/const.py | 7 ++++++- certidude/helpers.py | 2 +- certidude/templates/nginx.conf | 30 +++++++++++++++++++++++++++--- setup.py | 8 -------- 8 files changed, 49 insertions(+), 28 deletions(-) diff --git a/certidude/api/__init__.py b/certidude/api/__init__.py index f04c2d2..65534aa 100644 --- a/certidude/api/__init__.py +++ b/certidude/api/__init__.py @@ -6,7 +6,6 @@ import logging import os import click import hashlib -import xattr from datetime import datetime from time import sleep from certidude import authority, mailer @@ -46,6 +45,8 @@ class SessionResource(object): @login_required @event_source def on_get(self, req, resp): + import xattr + def serialize_requests(g): for common_name, path, buf, obj, server in g(): yield dict( @@ -126,7 +127,6 @@ class SessionResource(object): requests=serialize_requests(authority.list_requests), signed=serialize_certificates(authority.list_signed), revoked=serialize_certificates(authority.list_revoked), - users=User.objects.all(), admin_users = User.objects.filter_admins(), user_subnets = config.USER_SUBNETS, autosign_subnets = config.AUTOSIGN_SUBNETS, diff --git a/certidude/api/attrib.py b/certidude/api/attrib.py index 9186a5d..740f8c6 100644 --- a/certidude/api/attrib.py +++ b/certidude/api/attrib.py @@ -1,11 +1,10 @@ - import falcon import logging from ipaddress import ip_address -from xattr import getxattr, listxattr from datetime import datetime from certidude import config, authority from certidude.decorators import serialize +from xattr import getxattr, listxattr logger = logging.getLogger(__name__) diff --git a/certidude/authority.py b/certidude/authority.py index 73d236a..cbdee51 100644 --- a/certidude/authority.py +++ b/certidude/authority.py @@ -15,7 +15,6 @@ from cryptography.hazmat.primitives import hashes, serialization from certidude import config, push, mailer, const from certidude import errors from jinja2 import Template -from xattr import getxattr, listxattr, setxattr RE_HOSTNAME = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])(@(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))?$" @@ -297,6 +296,8 @@ def sign(common_name, overwrite=False): def _sign(csr, buf, overwrite=False): assert buf.startswith("-----BEGIN CERTIFICATE REQUEST-----\n") assert isinstance(csr, x509.CertificateSigningRequest) + from xattr import getxattr, listxattr, setxattr + common_name, = csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME) cert_path = os.path.join(config.SIGNED_DIR, common_name.value + ".pem") renew = False @@ -375,5 +376,3 @@ def _sign(csr, buf, overwrite=False): push.publish("request-signed", common_name.value) return cert, cert_buf - - diff --git a/certidude/cli.py b/certidude/cli.py index 857f9ce..26975a7 100755 --- a/certidude/cli.py +++ b/certidude/cli.py @@ -8,7 +8,6 @@ import os import pwd import random import re -import requests import signal import socket import string @@ -67,6 +66,8 @@ ExecStart=%s request @click.option("-r", "--renew", default=False, is_flag=True, help="Renew now") @click.option("-f", "--fork", default=False, is_flag=True, help="Fork to background") def certidude_request(fork, renew): + import requests + if not os.path.exists(const.CLIENT_CONFIG_PATH): click.echo("No %s!" % const.CLIENT_CONFIG_PATH) return 1 @@ -741,7 +742,7 @@ def certidude_setup_openvpn_networkmanager(authority, remote): @click.option("--authority-lifetime", default=20*365, help="Authority certificate lifetime in days, 20 years by default") @click.option("--organization", "-o", default=None, help="Company or organization name") @click.option("--organizational-unit", "-ou", default=None) -@click.option("--push-server", default="http://" + const.FQDN, help="Push server, by default http://%s" % const.FQDN) +@click.option("--push-server", help="Push server, by default http://%s" % const.FQDN) @click.option("--directory", help="Directory for authority files") @click.option("--server-flags", is_flag=True, help="Add TLS Server and IKE Intermediate extended key usage flags") @click.option("--outbox", default="smtp://smtp.%s" % const.DOMAIN, help="SMTP server, smtp://smtp.%s by default" % const.DOMAIN) @@ -799,8 +800,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, country, else: click.echo("Warning: /etc/krb5.keytab or /etc/samba/smb.conf not found, Kerberos unconfigured") - - working_directory = os.path.realpath(os.path.dirname(__file__)) + static_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), "static") certidude_path = sys.argv[0] # Push server config generation @@ -809,15 +809,16 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, country, listen = "0.0.0.0" port = "80" else: - nginx_client_config.write(env.get_template("nginx.conf").render(vars())) - click.echo("Generated: %s" % nginx_client_config.name) + port = "8080" + nginx_config.write(env.get_template("nginx.conf").render(vars())) + click.echo("Generated: %s" % nginx_config.name) if not os.path.exists("/etc/nginx/sites-enabled/certidude.conf"): os.symlink("../sites-available/certidude.conf", "/etc/nginx/sites-enabled/certidude.conf") - click.echo("Symlinked %s -> /etc/nginx/sites-enabled/" % nginx_client_config.name) + click.echo("Symlinked %s -> /etc/nginx/sites-enabled/" % nginx_config.name) if os.path.exists("/etc/nginx/sites-enabled/default"): os.unlink("/etc/nginx/sites-enabled/default") if not push_server: - click.echo("Remember to install nchan instead of regular nginx!") + click.echo("Remember to install nchan capable nginx instead of regular nginx!") if os.path.exists("/etc/systemd"): if os.path.exists("/etc/systemd/system/certidude.service"): @@ -1231,6 +1232,7 @@ def certidude_serve(port, listen, fork): @click.option("-s", "--slot", default="9a", help="Yubikey slot to use, 9a by default") @click.option("-u", "--username", default=os.getenv("USER"), help="Username to use, %s by default" % os.getenv("USER")) def certidude_setup_yubikey(authority, slot, username, pin): + import requests cmd = "ykinfo", "-q", "-s" click.echo("Executing: %s" % " ".join(cmd)) serial = subprocess.check_output(cmd).strip() diff --git a/certidude/const.py b/certidude/const.py index 5d2bb62..22a35b0 100644 --- a/certidude/const.py +++ b/certidude/const.py @@ -2,6 +2,7 @@ import click import os import socket +import sys CONFIG_DIR = os.path.expanduser("~/.certidude") if os.getuid() else "/etc/certidude" CONFIG_PATH = os.path.join(CONFIG_DIR, "server.conf") @@ -18,7 +19,11 @@ SIGNER_LOG_PATH = os.path.join(CONFIG_DIR, "signer.log") if os.getuid() else "/v if os.getenv("TRAVIS"): FQDN = "buildbot" else: - FQDN = socket.getaddrinfo(socket.gethostname(), 0, socket.AF_INET, 0, 0, socket.AI_CANONNAME)[0][3] + try: + FQDN = socket.getaddrinfo(socket.gethostname(), 0, socket.AF_INET, 0, 0, socket.AI_CANONNAME)[0][3] + except socket.gaierror: + click.echo("Failed to resolve fully qualified hostname of this machine, make sure hostname -f works") + sys.exit(254) if "." in FQDN: HOSTNAME, DOMAIN = FQDN.split(".", 1) diff --git a/certidude/helpers.py b/certidude/helpers.py index bcaa15a..fa71392 100644 --- a/certidude/helpers.py +++ b/certidude/helpers.py @@ -1,7 +1,6 @@ import click import os -import requests import subprocess import tempfile from base64 import b64encode @@ -30,6 +29,7 @@ def certidude_request_certificate(server, key_path, request_path, certificate_pa """ Exchange CSR for certificate using Certidude HTTP API server """ + import requests # Create directories for path in key_path, request_path, certificate_path, authority_path, revocations_path: diff --git a/certidude/templates/nginx.conf b/certidude/templates/nginx.conf index 9a52aaa..7c97df1 100644 --- a/certidude/templates/nginx.conf +++ b/certidude/templates/nginx.conf @@ -1,13 +1,29 @@ +# To set up SSL certificates using Let's Encrypt run: +# +# apt install letsencrypt +# certbot certonly -d {{common_name}} --webroot /var/www/html/ +# +# Also uncomment URL rewriting and SSL configuration below server { server_name {{ common_name }}; listen 80 default_server; +# rewrite ^ https://$server_name$request_uri? permanent; +#} + +#server { +# server_name {{ common_name }}; +# listen 443 ssl http2 default_server; +# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;"; +# ssl_certificate /etc/letsencrypt/live/{{common_name}}/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/{{common_name}}/privkey.pem; + error_page 500 502 503 504 /50x.html; root {{static_path}}; location /api/ { - proxy_pass http://127.0.0.1{% if listen != 80 }:{{ listen }}{% endif %}/api/; + proxy_pass http://127.0.0.1{% if port != 80 %}:{{ port }}{% endif %}/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 600; @@ -16,7 +32,15 @@ server { send_timeout 600; } - {% if not push_server %} + # This is for Let's Encrypt + location /.well-known/ { + alias /var/www/html/.well-known/; + } + + +{% if not push_server %} + # This only works with nchan, for Debian 9 just apt install libnginx-mod-nchan + # For Ubuntu and older Debian releases install nchan from https://nchan.io/ location ~ "^/lp/pub/(.*)" { allow 127.0.0.1; nchan_publisher; @@ -40,7 +64,7 @@ server { nchan_channel_id $1; nchan_subscriber eventsource; } - {% endif %} +{% endif %} } diff --git a/setup.py b/setup.py index 7a75ae7..4884ee6 100644 --- a/setup.py +++ b/setup.py @@ -18,14 +18,6 @@ setup( ], long_description=open("README.rst").read(), install_requires=[ - "setproctitle", - "click", - "falcon", - "jinja2", - "pyopenssl", - "humanize", - "cryptography", - "markupsafe", ], scripts=[ "misc/certidude"