Various fixes

This commit is contained in:
Lauri Võsandi 2017-04-13 20:30:28 +00:00
parent d91e12942d
commit 52d35012a4
8 changed files with 49 additions and 28 deletions

View File

@ -6,7 +6,6 @@ import logging
import os import os
import click import click
import hashlib import hashlib
import xattr
from datetime import datetime from datetime import datetime
from time import sleep from time import sleep
from certidude import authority, mailer from certidude import authority, mailer
@ -46,6 +45,8 @@ class SessionResource(object):
@login_required @login_required
@event_source @event_source
def on_get(self, req, resp): def on_get(self, req, resp):
import xattr
def serialize_requests(g): def serialize_requests(g):
for common_name, path, buf, obj, server in g(): for common_name, path, buf, obj, server in g():
yield dict( yield dict(
@ -126,7 +127,6 @@ class SessionResource(object):
requests=serialize_requests(authority.list_requests), requests=serialize_requests(authority.list_requests),
signed=serialize_certificates(authority.list_signed), signed=serialize_certificates(authority.list_signed),
revoked=serialize_certificates(authority.list_revoked), revoked=serialize_certificates(authority.list_revoked),
users=User.objects.all(),
admin_users = User.objects.filter_admins(), admin_users = User.objects.filter_admins(),
user_subnets = config.USER_SUBNETS, user_subnets = config.USER_SUBNETS,
autosign_subnets = config.AUTOSIGN_SUBNETS, autosign_subnets = config.AUTOSIGN_SUBNETS,

View File

@ -1,11 +1,10 @@
import falcon import falcon
import logging import logging
from ipaddress import ip_address from ipaddress import ip_address
from xattr import getxattr, listxattr
from datetime import datetime from datetime import datetime
from certidude import config, authority from certidude import config, authority
from certidude.decorators import serialize from certidude.decorators import serialize
from xattr import getxattr, listxattr
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -15,7 +15,6 @@ from cryptography.hazmat.primitives import hashes, serialization
from certidude import config, push, mailer, const from certidude import config, push, mailer, const
from certidude import errors from certidude import errors
from jinja2 import Template 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]))?$" 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): def _sign(csr, buf, overwrite=False):
assert buf.startswith("-----BEGIN CERTIFICATE REQUEST-----\n") assert buf.startswith("-----BEGIN CERTIFICATE REQUEST-----\n")
assert isinstance(csr, x509.CertificateSigningRequest) assert isinstance(csr, x509.CertificateSigningRequest)
from xattr import getxattr, listxattr, setxattr
common_name, = csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME) common_name, = csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)
cert_path = os.path.join(config.SIGNED_DIR, common_name.value + ".pem") cert_path = os.path.join(config.SIGNED_DIR, common_name.value + ".pem")
renew = False renew = False
@ -375,5 +376,3 @@ def _sign(csr, buf, overwrite=False):
push.publish("request-signed", common_name.value) push.publish("request-signed", common_name.value)
return cert, cert_buf return cert, cert_buf

View File

@ -8,7 +8,6 @@ import os
import pwd import pwd
import random import random
import re import re
import requests
import signal import signal
import socket import socket
import string import string
@ -67,6 +66,8 @@ ExecStart=%s request
@click.option("-r", "--renew", default=False, is_flag=True, help="Renew now") @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") @click.option("-f", "--fork", default=False, is_flag=True, help="Fork to background")
def certidude_request(fork, renew): def certidude_request(fork, renew):
import requests
if not os.path.exists(const.CLIENT_CONFIG_PATH): if not os.path.exists(const.CLIENT_CONFIG_PATH):
click.echo("No %s!" % const.CLIENT_CONFIG_PATH) click.echo("No %s!" % const.CLIENT_CONFIG_PATH)
return 1 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("--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("--organization", "-o", default=None, help="Company or organization name")
@click.option("--organizational-unit", "-ou", default=None) @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("--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("--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) @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: else:
click.echo("Warning: /etc/krb5.keytab or /etc/samba/smb.conf not found, Kerberos unconfigured") click.echo("Warning: /etc/krb5.keytab or /etc/samba/smb.conf not found, Kerberos unconfigured")
static_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), "static")
working_directory = os.path.realpath(os.path.dirname(__file__))
certidude_path = sys.argv[0] certidude_path = sys.argv[0]
# Push server config generation # Push server config generation
@ -809,15 +809,16 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, country,
listen = "0.0.0.0" listen = "0.0.0.0"
port = "80" port = "80"
else: else:
nginx_client_config.write(env.get_template("nginx.conf").render(vars())) port = "8080"
click.echo("Generated: %s" % nginx_client_config.name) 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"): if not os.path.exists("/etc/nginx/sites-enabled/certidude.conf"):
os.symlink("../sites-available/certidude.conf", "/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"): if os.path.exists("/etc/nginx/sites-enabled/default"):
os.unlink("/etc/nginx/sites-enabled/default") os.unlink("/etc/nginx/sites-enabled/default")
if not push_server: 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"):
if os.path.exists("/etc/systemd/system/certidude.service"): 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("-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")) @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): def certidude_setup_yubikey(authority, slot, username, pin):
import requests
cmd = "ykinfo", "-q", "-s" cmd = "ykinfo", "-q", "-s"
click.echo("Executing: %s" % " ".join(cmd)) click.echo("Executing: %s" % " ".join(cmd))
serial = subprocess.check_output(cmd).strip() serial = subprocess.check_output(cmd).strip()

View File

@ -2,6 +2,7 @@
import click import click
import os import os
import socket import socket
import sys
CONFIG_DIR = os.path.expanduser("~/.certidude") if os.getuid() else "/etc/certidude" CONFIG_DIR = os.path.expanduser("~/.certidude") if os.getuid() else "/etc/certidude"
CONFIG_PATH = os.path.join(CONFIG_DIR, "server.conf") 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"): if os.getenv("TRAVIS"):
FQDN = "buildbot" FQDN = "buildbot"
else: 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: if "." in FQDN:
HOSTNAME, DOMAIN = FQDN.split(".", 1) HOSTNAME, DOMAIN = FQDN.split(".", 1)

View File

@ -1,7 +1,6 @@
import click import click
import os import os
import requests
import subprocess import subprocess
import tempfile import tempfile
from base64 import b64encode 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 Exchange CSR for certificate using Certidude HTTP API server
""" """
import requests
# Create directories # Create directories
for path in key_path, request_path, certificate_path, authority_path, revocations_path: for path in key_path, request_path, certificate_path, authority_path, revocations_path:

View File

@ -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 {
server_name {{ common_name }}; server_name {{ common_name }};
listen 80 default_server; 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; error_page 500 502 503 504 /50x.html;
root {{static_path}}; root {{static_path}};
location /api/ { 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 Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 600; proxy_connect_timeout 600;
@ -16,7 +32,15 @@ server {
send_timeout 600; 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/(.*)" { location ~ "^/lp/pub/(.*)" {
allow 127.0.0.1; allow 127.0.0.1;
nchan_publisher; nchan_publisher;
@ -40,7 +64,7 @@ server {
nchan_channel_id $1; nchan_channel_id $1;
nchan_subscriber eventsource; nchan_subscriber eventsource;
} }
{% endif %} {% endif %}
} }

View File

@ -18,14 +18,6 @@ setup(
], ],
long_description=open("README.rst").read(), long_description=open("README.rst").read(),
install_requires=[ install_requires=[
"setproctitle",
"click",
"falcon",
"jinja2",
"pyopenssl",
"humanize",
"cryptography",
"markupsafe",
], ],
scripts=[ scripts=[
"misc/certidude" "misc/certidude"