mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-23 00:25:18 +00:00
Merge authority setup and production setup
This commit is contained in:
parent
a094db794b
commit
d2a259b887
188
README.rst
188
README.rst
@ -74,23 +74,14 @@ To install Certidude:
|
|||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
apt-get install -y python python-pip python-dev cython python-configparser \
|
apt-get install -y python python-pip python-dev cython \
|
||||||
|
python-cffi python-configparser \
|
||||||
python-pysqlite2 python-mysql.connector python-ldap \
|
python-pysqlite2 python-mysql.connector python-ldap \
|
||||||
build-essential libffi-dev libssl-dev libkrb5-dev \
|
build-essential libffi-dev libssl-dev libkrb5-dev \
|
||||||
ldap-utils krb5-user \
|
ldap-utils krb5-user \
|
||||||
libsasl2-modules-gssapi-mit
|
libsasl2-modules-gssapi-mit
|
||||||
pip install certidude
|
pip install certidude
|
||||||
|
|
||||||
Make sure you're running PyOpenSSL 0.15+ from PyPI,
|
|
||||||
not the outdated one provided by APT.
|
|
||||||
|
|
||||||
Create a system user for ``certidude``:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
adduser --system --no-create-home --group certidude
|
|
||||||
mkdir /etc/certidude
|
|
||||||
|
|
||||||
|
|
||||||
Setting up authority
|
Setting up authority
|
||||||
--------------------
|
--------------------
|
||||||
@ -103,27 +94,46 @@ You can check it with:
|
|||||||
|
|
||||||
hostname -f
|
hostname -f
|
||||||
|
|
||||||
The command should return ca.example.com
|
The command should return ``ca.example.com``.
|
||||||
|
|
||||||
Certidude can set up certificate authority relatively easily,
|
If necessary tweak machine's fully qualified hostname in ``/etc/hosts``:
|
||||||
following will set up certificate authority in /var/lib/certidude/hostname.domain.tld:
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
127.0.0.1 localhost
|
||||||
|
127.0.1.1 ca.example.com ca
|
||||||
|
|
||||||
|
Then proceed to install `nchan <https://nchan.slact.net/>`_ and ``uwsgi``:
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
wget https://nchan.slact.net/download/nginx-common.deb https://nchan.slact.net/download/nginx-extras.deb
|
||||||
|
dpkg -i nginx-common.deb nginx-extras.deb
|
||||||
|
apt-get install nginx uwsgi uwsgi-plugin-python
|
||||||
|
|
||||||
|
Certidude can set up certificate authority relatively easily.
|
||||||
|
Following will set up certificate authority in ``/var/lib/certidude/hostname.domain.tld``,
|
||||||
|
configure uWSGI in ``/etc/uwsgi/apps-available/certidude.ini``,
|
||||||
|
nginx in ``/etc/nginx/sites-available/certidude.conf``,
|
||||||
|
cronjobs in ``/etc/cron.hourly/certidude`` and much more:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
certidude setup authority
|
certidude setup authority
|
||||||
|
|
||||||
Tweak the configuration in /etc/certidude/server.conf until you meet your requirements and
|
Tweak the configuration in ``/etc/certidude/server.conf`` until you meet your requirements and
|
||||||
spawn the signer process:
|
spawn the signer process:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
certidude signer spawn
|
certidude signer spawn
|
||||||
|
|
||||||
Finally serve the certificate authority via web:
|
Finally restart services:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
certidude serve
|
service nginx restart
|
||||||
|
service uwsgi restart
|
||||||
|
|
||||||
|
|
||||||
Certificate management
|
Certificate management
|
||||||
@ -148,137 +158,6 @@ Use web interface or following to sign a certificate on server:
|
|||||||
certidude sign client-hostname-or-common-name
|
certidude sign client-hostname-or-common-name
|
||||||
|
|
||||||
|
|
||||||
Production deployment
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Install ``nginx`` and ``uwsgi``:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
apt-get install nginx uwsgi uwsgi-plugin-python
|
|
||||||
|
|
||||||
For easy setup following is reccommended:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
certidude setup production
|
|
||||||
|
|
||||||
Otherwise manually configure ``uwsgi`` application in ``/etc/uwsgi/apps-available/certidude.ini``:
|
|
||||||
|
|
||||||
.. code:: ini
|
|
||||||
|
|
||||||
[uwsgi]
|
|
||||||
master = true
|
|
||||||
processes = 1
|
|
||||||
vaccum = true
|
|
||||||
uid = certidude
|
|
||||||
gid = certidude
|
|
||||||
plugins = python
|
|
||||||
chdir = /tmp
|
|
||||||
module = certidude.wsgi
|
|
||||||
callable = app
|
|
||||||
chmod-socket = 660
|
|
||||||
chown-socket = certidude:www-data
|
|
||||||
buffer-size = 32768
|
|
||||||
env = LANG=C.UTF-8
|
|
||||||
env = LC_ALL=C.UTF-8
|
|
||||||
env = KRB5_KTNAME=/etc/certidude/server.keytab
|
|
||||||
env = KRB5CCNAME=/run/certidude/krb5cc
|
|
||||||
|
|
||||||
Also enable the application:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
ln -s ../apps-available/certidude.ini /etc/uwsgi/apps-enabled/certidude.ini
|
|
||||||
|
|
||||||
We support `nchan <https://nchan.slact.net/>`_,
|
|
||||||
configure the site in /etc/nginx/sites-available/certidude:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
upstream certidude_api {
|
|
||||||
server unix:///run/uwsgi/app/certidude/socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
server_name localhost;
|
|
||||||
listen 80 default_server;
|
|
||||||
listen [::]:80 default_server ipv6only=on;
|
|
||||||
root /usr/local/lib/python2.7/dist-packages/certidude/static;
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
include uwsgi_params;
|
|
||||||
uwsgi_pass certidude_api;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add following three if you wish to enable push server on this machine
|
|
||||||
location /pub {
|
|
||||||
allow 127.0.0.1;
|
|
||||||
nchan_publisher http;
|
|
||||||
nchan_store_messages off;
|
|
||||||
nchan_channel_id $arg_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ "^/lp/(.*)" {
|
|
||||||
nchan_subscriber longpoll;
|
|
||||||
nchan_channel_id $1;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ "^/ev/(.*)" {
|
|
||||||
nchan_subscriber eventsource;
|
|
||||||
nchan_channel_id $1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Enable the site:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
ln -s ../sites-available/certidude /etc/nginx/sites-enabled/certidude
|
|
||||||
|
|
||||||
Also adjust ``/etc/nginx/nginx.conf``:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
user www-data;
|
|
||||||
worker_processes 4;
|
|
||||||
pid /run/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 768;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
sendfile on;
|
|
||||||
tcp_nopush on;
|
|
||||||
tcp_nodelay on;
|
|
||||||
keepalive_timeout 65;
|
|
||||||
types_hash_max_size 2048;
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
access_log /var/log/nginx/access.log;
|
|
||||||
error_log /var/log/nginx/error.log;
|
|
||||||
gzip on;
|
|
||||||
gzip_disable "msie6";
|
|
||||||
include /etc/nginx/conf.d/*;
|
|
||||||
include /etc/nginx/sites-enabled/*;
|
|
||||||
}
|
|
||||||
|
|
||||||
In your Certidude server's /etc/certidude/server.conf make sure Certidude
|
|
||||||
is aware of your nginx setup:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
push_server = http://push.example.com/
|
|
||||||
|
|
||||||
Restart the services:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
service uwsgi restart
|
|
||||||
service nginx restart
|
|
||||||
|
|
||||||
|
|
||||||
Setting up Active Directory authentication
|
Setting up Active Directory authentication
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
@ -291,13 +170,6 @@ Install dependencies:
|
|||||||
|
|
||||||
apt-get install samba-common-bin krb5-user ldap-utils
|
apt-get install samba-common-bin krb5-user ldap-utils
|
||||||
|
|
||||||
Make sure Certidude machine's fully qualified hostname is correct in ``/etc/hosts``:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
127.0.0.1 localhost
|
|
||||||
127.0.1.1 ca.example.lan ca
|
|
||||||
|
|
||||||
Reset Samba client configuration in ``/etc/samba/smb.conf``:
|
Reset Samba client configuration in ``/etc/samba/smb.conf``:
|
||||||
|
|
||||||
.. code:: ini
|
.. code:: ini
|
||||||
@ -306,7 +178,7 @@ Reset Samba client configuration in ``/etc/samba/smb.conf``:
|
|||||||
security = ads
|
security = ads
|
||||||
netbios name = CA
|
netbios name = CA
|
||||||
workgroup = EXAMPLE
|
workgroup = EXAMPLE
|
||||||
realm = EXAMPLE.LAN
|
realm = EXAMPLE.COM
|
||||||
kerberos method = system keytab
|
kerberos method = system keytab
|
||||||
|
|
||||||
Reset Kerberos configuration in ``/etc/krb5.conf``:
|
Reset Kerberos configuration in ``/etc/krb5.conf``:
|
||||||
@ -314,7 +186,7 @@ Reset Kerberos configuration in ``/etc/krb5.conf``:
|
|||||||
.. code:: ini
|
.. code:: ini
|
||||||
|
|
||||||
[libdefaults]
|
[libdefaults]
|
||||||
default_realm = EXAMPLE.LAN
|
default_realm = EXAMPLE.COM
|
||||||
dns_lookup_realm = true
|
dns_lookup_realm = true
|
||||||
dns_lookup_kdc = true
|
dns_lookup_kdc = true
|
||||||
|
|
||||||
@ -417,7 +289,7 @@ To run from source tree:
|
|||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
PYTHONPATH=. KRB5_KTNAME=/etc/certidude/server.keytab LANG=C.UTF-8 python misc/certidude
|
PYTHONPATH=. KRB5CCNAME=/run/certidude/krb5cc KRB5_KTNAME=/etc/certidude/server.keytab LANG=C.UTF-8 python misc/certidude
|
||||||
|
|
||||||
To install the package from the source:
|
To install the package from the source:
|
||||||
|
|
||||||
|
185
certidude/cli.py
185
certidude/cli.py
@ -236,10 +236,9 @@ def certidude_request_spawn(fork):
|
|||||||
os.unlink(pid_path)
|
os.unlink(pid_path)
|
||||||
|
|
||||||
|
|
||||||
@click.command("spawn", help="Run privilege isolated signer process")
|
@click.command("spawn", help="Restart privilege isolated signer process")
|
||||||
@click.option("-k", "--kill", default=False, is_flag=True, help="Kill previous instance")
|
|
||||||
@click.option("-n", "--no-interaction", default=True, is_flag=True, help="Don't load password protected keys")
|
@click.option("-n", "--no-interaction", default=True, is_flag=True, help="Don't load password protected keys")
|
||||||
def certidude_signer_spawn(kill, no_interaction):
|
def certidude_signer_spawn(no_interaction):
|
||||||
"""
|
"""
|
||||||
Spawn privilege isolated signer process
|
Spawn privilege isolated signer process
|
||||||
"""
|
"""
|
||||||
@ -284,15 +283,14 @@ def certidude_signer_spawn(kill, no_interaction):
|
|||||||
pid = 0
|
pid = 0
|
||||||
|
|
||||||
if pid > 0:
|
if pid > 0:
|
||||||
if kill:
|
try:
|
||||||
try:
|
click.echo("Killing %d" % pid)
|
||||||
click.echo("Killing %d" % pid)
|
os.kill(pid, signal.SIGTERM)
|
||||||
os.kill(pid, signal.SIGTERM)
|
sleep(1)
|
||||||
sleep(1)
|
os.kill(pid, signal.SIGKILL)
|
||||||
os.kill(pid, signal.SIGKILL)
|
sleep(1)
|
||||||
sleep(1)
|
except EnvironmentError:
|
||||||
except EnvironmentError:
|
pass
|
||||||
pass
|
|
||||||
|
|
||||||
child_pid = os.fork()
|
child_pid = os.fork()
|
||||||
|
|
||||||
@ -693,71 +691,19 @@ def certidude_setup_openvpn_networkmanager(server, email_address, common_name, o
|
|||||||
services.set(endpoint, "service", "network-manager/openvpn")
|
services.set(endpoint, "service", "network-manager/openvpn")
|
||||||
services.write(open("/etc/certidude/services.conf", "w"))
|
services.write(open("/etc/certidude/services.conf", "w"))
|
||||||
|
|
||||||
@click.command("production", help="Set up nginx, uwsgi and cron")
|
|
||||||
|
@click.command("authority", help="Set up Certificate Authority in a directory")
|
||||||
@click.option("--username", default="certidude", help="Service user account, created if necessary, 'certidude' by default")
|
@click.option("--username", default="certidude", help="Service user account, created if necessary, 'certidude' by default")
|
||||||
@click.option("--hostname", default=HOSTNAME, help="nginx hostname, '%s' by default" % HOSTNAME)
|
@click.option("--static-path", default=os.path.join(os.path.dirname(__file__), "static"), help="Path to Certidude's static JS/CSS/etc")
|
||||||
@click.option("--static-path", default=os.path.join(os.path.dirname(__file__), "static"), help="Static files")
|
@click.option("--kerberos-keytab", default="/etc/certidude/server.keytab", help="Kerberos keytab for using 'kerberos' authentication backend, /etc/certidude/server.keytab by default")
|
||||||
@click.option("--kerberos-keytab", default="/etc/certidude/server.keytab", help="Specify Kerberos keytab")
|
|
||||||
@click.option("--push-server", default=None, help="Push server URL")
|
|
||||||
@click.option("--nginx-config", "-n",
|
@click.option("--nginx-config", "-n",
|
||||||
default="/etc/nginx/nginx.conf",
|
default="/etc/nginx/sites-available/certidude.conf",
|
||||||
type=click.File(mode="w", atomic=True, lazy=True),
|
type=click.File(mode="w", atomic=True, lazy=True),
|
||||||
help="nginx configuration, /etc/nginx/nginx.conf by default")
|
help="nginx site config for serving Certidude, /etc/nginx/sites-available/certidude by default")
|
||||||
@click.option("--uwsgi-config", "-u",
|
@click.option("--uwsgi-config", "-u",
|
||||||
default="/etc/uwsgi/apps-available/certidude.ini",
|
default="/etc/uwsgi/apps-available/certidude.ini",
|
||||||
type=click.File(mode="w", atomic=True, lazy=True),
|
type=click.File(mode="w", atomic=True, lazy=True),
|
||||||
help="uwsgi configuration, /etc/uwsgi/ by default")
|
help="uwsgi configuration for serving Certidude API, /etc/uwsgi/apps-available/certidude.ini by default")
|
||||||
def certidude_setup_production(username, hostname, push_server, nginx_config, uwsgi_config, static_path, kerberos_keytab):
|
|
||||||
try:
|
|
||||||
pwd.getpwnam(username)
|
|
||||||
click.echo("Username '%s' already exists, excellent!" % username)
|
|
||||||
except KeyError:
|
|
||||||
cmd = "adduser", "--system", "--no-create-home", "--group", username
|
|
||||||
subprocess.check_call(cmd)
|
|
||||||
|
|
||||||
if subprocess.call("net ads testjoin", shell=True):
|
|
||||||
click.echo("Domain membership check failed, 'net ads testjoin' returned non-zero value", err=True)
|
|
||||||
exit(255)
|
|
||||||
|
|
||||||
if not os.path.exists(kerberos_keytab):
|
|
||||||
subprocess.call("KRB5_KTNAME=FILE:" + kerberos_keytab + " net ads keytab add HTTP -P")
|
|
||||||
click.echo("Created service principal in Kerberos keytab '%s'" % kerberos_keytab)
|
|
||||||
|
|
||||||
if os.path.exists("/etc/krb5.keytab") and os.path.exists("/etc/samba/smb.conf"):
|
|
||||||
# Fetch Kerberos ticket for system account
|
|
||||||
cp = ConfigParser()
|
|
||||||
cp.read("/etc/samba/smb.conf")
|
|
||||||
domain = cp.get("global", "realm").lower()
|
|
||||||
base = ",".join(["dc=" + j for j in domain.split(".")])
|
|
||||||
with open("/etc/cron.hourly/certidude", "w") as fh:
|
|
||||||
fh.write("#!/bin/bash\n")
|
|
||||||
fh.write("KRB5CCNAME=/run/certidude/krb5cc-new kinit -k %s$\n" % cp.get("global", "netbios name"))
|
|
||||||
fh.write("chown certidude /run/certidude/krb5cc-new\n")
|
|
||||||
fh.write("mv /run/certidude/krb5cc-new /run/certidude/krb5cc\n")
|
|
||||||
os.chmod("/etc/cron.hourly/certidude", 0o755)
|
|
||||||
click.echo("Created /etc/cron.hourly/certidude for automatic Kerberos TGT renewal")
|
|
||||||
else:
|
|
||||||
click.echo("Warning: cronjob for Kerberos ticket renewal not created, LDAP with GSSAPI will not be available!")
|
|
||||||
|
|
||||||
|
|
||||||
if not static_path.endswith("/"):
|
|
||||||
static_path += "/"
|
|
||||||
|
|
||||||
nginx_config.write(env.get_template("nginx.conf").render(vars()))
|
|
||||||
click.echo("Generated: %s" % nginx_config.name)
|
|
||||||
uwsgi_config.write(env.get_template("uwsgi.ini").render(vars()))
|
|
||||||
click.echo("Generated: %s" % uwsgi_config.name)
|
|
||||||
|
|
||||||
if os.path.exists("/etc/uwsgi/apps-enabled/certidude.ini"):
|
|
||||||
os.unlink("/etc/uwsgi/apps-enabled/certidude.ini")
|
|
||||||
os.symlink(uwsgi_config.name, "/etc/uwsgi/apps-enabled/certidude.ini")
|
|
||||||
click.echo("Symlinked %s -> /etc/uwsgi/apps-enabled/certidude.ini" % uwsgi_config.name)
|
|
||||||
|
|
||||||
if not push_server:
|
|
||||||
click.echo("Remember to install nchan instead of regular nginx!")
|
|
||||||
|
|
||||||
|
|
||||||
@click.command("authority", help="Set up Certificate Authority in a directory")
|
|
||||||
@click.option("--parent", "-p", help="Parent CA, none by default")
|
@click.option("--parent", "-p", help="Parent CA, none by default")
|
||||||
@click.option("--common-name", "-cn", default=FQDN, help="Common name, fully qualified hostname by default")
|
@click.option("--common-name", "-cn", default=FQDN, help="Common name, fully qualified hostname by default")
|
||||||
@click.option("--country", "-c", default=None, help="Country, none by default")
|
@click.option("--country", "-c", default=None, help="Country, none by default")
|
||||||
@ -775,7 +721,70 @@ def certidude_setup_production(username, hostname, push_server, nginx_config, uw
|
|||||||
@click.option("--directory", default=os.path.join("/var/lib/certidude", FQDN), help="Directory for authority files, /var/lib/certidude/%s/ by default" % FQDN)
|
@click.option("--directory", default=os.path.join("/var/lib/certidude", FQDN), help="Directory for authority files, /var/lib/certidude/%s/ by default" % FQDN)
|
||||||
@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" % constants.DOMAIN, help="SMTP server, smtp://smtp.%s by default" % constants.DOMAIN)
|
@click.option("--outbox", default="smtp://smtp.%s" % constants.DOMAIN, help="SMTP server, smtp://smtp.%s by default" % constants.DOMAIN)
|
||||||
def certidude_setup_authority(parent, country, state, locality, organization, organizational_unit, common_name, directory, certificate_lifetime, authority_lifetime, revocation_list_lifetime, revoked_url, certificate_url, push_server, email_address, outbox, server_flags):
|
def certidude_setup_authority(username, static_path, kerberos_keytab, nginx_config, uwsgi_config, parent, country, state, locality, organization, organizational_unit, common_name, directory, certificate_lifetime, authority_lifetime, revocation_list_lifetime, revoked_url, certificate_url, push_server, email_address, outbox, server_flags):
|
||||||
|
|
||||||
|
# Expand variables
|
||||||
|
ca_key = os.path.join(directory, "ca_key.pem")
|
||||||
|
ca_crt = os.path.join(directory, "ca_crt.pem")
|
||||||
|
if not static_path.endswith("/"):
|
||||||
|
static_path += "/"
|
||||||
|
certidude_conf = os.path.join("/etc/certidude/server.conf")
|
||||||
|
|
||||||
|
try:
|
||||||
|
pwd.getpwnam("certidude")
|
||||||
|
except KeyError:
|
||||||
|
cmd = "adduser", "--system", "--no-create-home", "--group", "certidude"
|
||||||
|
if subprocess.call(cmd):
|
||||||
|
click.echo("Failed to create system user 'certidude'")
|
||||||
|
return 255
|
||||||
|
|
||||||
|
if not os.path.exists("/etc/certidude"):
|
||||||
|
click.echo("Creating /etc/certidude")
|
||||||
|
os.makedirs("/etc/certidude")
|
||||||
|
|
||||||
|
if os.path.exists(kerberos_keytab):
|
||||||
|
click.echo("Service principal keytab found in '%s'" % kerberos_keytab)
|
||||||
|
else:
|
||||||
|
click.echo("To use 'kerberos' authentication backend create service principal with:")
|
||||||
|
click.echo()
|
||||||
|
click.echo(" KRB5_KTNAME=FILE:%s net ads keytab add HTTP -P" % kerberos_keytab)
|
||||||
|
click.echo(" chown %s %s" % (username, kerberos_keytab))
|
||||||
|
click.echo()
|
||||||
|
|
||||||
|
if os.path.exists("/etc/krb5.keytab") and os.path.exists("/etc/samba/smb.conf"):
|
||||||
|
|
||||||
|
# Fetch Kerberos ticket for system account
|
||||||
|
cp = ConfigParser()
|
||||||
|
cp.read("/etc/samba/smb.conf")
|
||||||
|
domain = cp.get("global", "realm").lower()
|
||||||
|
base = ",".join(["dc=" + j for j in domain.split(".")])
|
||||||
|
with open("/etc/cron.hourly/certidude", "w") as fh:
|
||||||
|
fh.write("#!/bin/bash\n")
|
||||||
|
fh.write("KRB5CCNAME=/run/certidude/krb5cc-new kinit -k %s$\n" % cp.get("global", "netbios name"))
|
||||||
|
fh.write("chown certidude /run/certidude/krb5cc-new\n")
|
||||||
|
fh.write("mv /run/certidude/krb5cc-new /run/certidude/krb5cc\n")
|
||||||
|
os.chmod("/etc/cron.hourly/certidude", 0o755)
|
||||||
|
click.echo("Created /etc/cron.hourly/certidude for automatic Kerberos TGT renewal")
|
||||||
|
else:
|
||||||
|
click.echo("Warning: /etc/krb5.keytab or /etc/samba/smb.conf not found, Kerberos unconfigured")
|
||||||
|
|
||||||
|
nginx_config.write(env.get_template("nginx.conf").render(vars()))
|
||||||
|
click.echo("Generated: %s" % nginx_config.name)
|
||||||
|
uwsgi_config.write(env.get_template("uwsgi.ini").render(vars()))
|
||||||
|
click.echo("Generated: %s" % uwsgi_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_config.name)
|
||||||
|
if not os.path.exists("/etc/uwsgi/apps-enabled/certidude.ini"):
|
||||||
|
os.symlink("../apps-available/certidude.ini", "/etc/uwsgi/apps-enabled/certidude.ini")
|
||||||
|
click.echo("Symlinked %s -> /etc/uwsgi/apps-enabled/" % uwsgi_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!")
|
||||||
|
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
|
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
|
||||||
@ -783,16 +792,19 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
|||||||
from cryptography.hazmat.primitives import hashes, serialization
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
|
||||||
# Make sure common_name is valid
|
_, _, uid, gid, gecos, root, shell = pwd.getpwnam("certidude")
|
||||||
if not re.match(r"^[\.\-_a-zA-Z0-9]+$", common_name):
|
os.setgid(gid)
|
||||||
raise click.ClickException("CA name can contain only alphanumeric, '_' and '-' characters")
|
|
||||||
|
if os.path.exists(certidude_conf):
|
||||||
|
click.echo("Configuration file %s already exists, remove to regenerate" % certidude_conf)
|
||||||
|
else:
|
||||||
|
os.umask(0o137)
|
||||||
|
with open(certidude_conf, "w") as fh:
|
||||||
|
fh.write(env.get_template("certidude.conf").render(vars()))
|
||||||
|
click.echo("Generated %s" % certidude_conf)
|
||||||
|
|
||||||
if os.path.lexists(directory):
|
if os.path.lexists(directory):
|
||||||
raise click.ClickException("Output directory {} already exists.".format(directory))
|
raise click.ClickException("CA directory %s already exists, remove to regenerate" % directory)
|
||||||
|
|
||||||
certidude_conf = os.path.join("/etc/certidude/server.conf")
|
|
||||||
if os.path.exists(certidude_conf):
|
|
||||||
raise click.ClickException("Configuration file %s already exists" % certidude_conf)
|
|
||||||
|
|
||||||
click.echo("CA configuration files are saved to: {}".format(directory))
|
click.echo("CA configuration files are saved to: {}".format(directory))
|
||||||
|
|
||||||
@ -809,11 +821,6 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
|||||||
if not certificate_url:
|
if not certificate_url:
|
||||||
certificate_url = "http://%s/api/certificate/" % common_name
|
certificate_url = "http://%s/api/certificate/" % common_name
|
||||||
|
|
||||||
# File paths
|
|
||||||
ca_key = os.path.join(directory, "ca_key.pem")
|
|
||||||
ca_crt = os.path.join(directory, "ca_crt.pem")
|
|
||||||
|
|
||||||
|
|
||||||
subject = issuer = x509.Name([
|
subject = issuer = x509.Name([
|
||||||
x509.NameAttribute(o, value) for o, value in (
|
x509.NameAttribute(o, value) for o, value in (
|
||||||
(NameOID.COUNTRY_NAME, country),
|
(NameOID.COUNTRY_NAME, country),
|
||||||
@ -867,9 +874,6 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
|||||||
|
|
||||||
click.echo("Signing %s..." % cert.subject)
|
click.echo("Signing %s..." % cert.subject)
|
||||||
|
|
||||||
_, _, uid, gid, gecos, root, shell = pwd.getpwnam("certidude")
|
|
||||||
os.setgid(gid)
|
|
||||||
|
|
||||||
# Create authority directory with 750 permissions
|
# Create authority directory with 750 permissions
|
||||||
os.umask(0o027)
|
os.umask(0o027)
|
||||||
if not os.path.exists(directory):
|
if not os.path.exists(directory):
|
||||||
@ -883,8 +887,6 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
|||||||
|
|
||||||
# Set permission bits to 640
|
# Set permission bits to 640
|
||||||
os.umask(0o137)
|
os.umask(0o137)
|
||||||
with open(certidude_conf, "w") as fh:
|
|
||||||
fh.write(env.get_template("certidude.conf").render(vars()))
|
|
||||||
with open(ca_crt, "wb") as fh:
|
with open(ca_crt, "wb") as fh:
|
||||||
fh.write(cert.public_bytes(serialization.Encoding.PEM))
|
fh.write(cert.public_bytes(serialization.Encoding.PEM))
|
||||||
|
|
||||||
@ -906,7 +908,7 @@ def certidude_setup_authority(parent, country, state, locality, organization, or
|
|||||||
click.echo()
|
click.echo()
|
||||||
click.echo("Use following to launch privilege isolated signer processes:")
|
click.echo("Use following to launch privilege isolated signer processes:")
|
||||||
click.echo()
|
click.echo()
|
||||||
click.echo(" certidude signer spawn -k")
|
click.echo(" certidude signer spawn")
|
||||||
click.echo()
|
click.echo()
|
||||||
click.echo("Use following command to serve CA read-only:")
|
click.echo("Use following command to serve CA read-only:")
|
||||||
click.echo()
|
click.echo()
|
||||||
@ -1157,7 +1159,6 @@ certidude_setup.add_command(certidude_setup_authority)
|
|||||||
certidude_setup.add_command(certidude_setup_openvpn)
|
certidude_setup.add_command(certidude_setup_openvpn)
|
||||||
certidude_setup.add_command(certidude_setup_strongswan)
|
certidude_setup.add_command(certidude_setup_strongswan)
|
||||||
certidude_setup.add_command(certidude_setup_client)
|
certidude_setup.add_command(certidude_setup_client)
|
||||||
certidude_setup.add_command(certidude_setup_production)
|
|
||||||
certidude_setup.add_command(certidude_setup_nginx)
|
certidude_setup.add_command(certidude_setup_nginx)
|
||||||
certidude_request.add_command(certidude_request_spawn)
|
certidude_request.add_command(certidude_request_spawn)
|
||||||
certidude_signer.add_command(certidude_signer_spawn)
|
certidude_signer.add_command(certidude_signer_spawn)
|
||||||
|
@ -32,7 +32,7 @@ posix admin group = sudo
|
|||||||
;backend = ldap
|
;backend = ldap
|
||||||
ldap computer filter = (&(objectclass=user)(objectclass=computer)(samaccountname=%s))
|
ldap computer filter = (&(objectclass=user)(objectclass=computer)(samaccountname=%s))
|
||||||
ldap user filter = (&(objectclass=user)(objectclass=person)(samaccountname=%s))
|
ldap user filter = (&(objectclass=user)(objectclass=person)(samaccountname=%s))
|
||||||
ldap admin filter = (&(memberOf=cn=Domain Admins,cn=Users,dc=example,dc=com)(samaccountname=%s))
|
ldap admin filter = (&(memberOf=cn=Domain Admins,cn=Users,{% if base %}{{ base }}{% else %}dc=example,dc=com{% endif %})(samaccountname=%s))
|
||||||
|
|
||||||
# Users are allowed to log in from user subnets
|
# Users are allowed to log in from user subnets
|
||||||
user subnets = 0.0.0.0/0
|
user subnets = 0.0.0.0/0
|
||||||
|
@ -1,54 +1,38 @@
|
|||||||
user www-data;
|
|
||||||
worker_processes 4;
|
|
||||||
pid /run/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
upstream certidude_api {
|
||||||
worker_connections 1024;
|
server unix:///run/uwsgi/app/certidude/socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
http {
|
server {
|
||||||
include mime.types;
|
server_name {{ common_name }};
|
||||||
default_type application/octet-stream;
|
listen 80 default_server;
|
||||||
sendfile on;
|
error_page 500 502 503 504 /50x.html;
|
||||||
keepalive_timeout 65;
|
|
||||||
gzip on;
|
|
||||||
|
|
||||||
upstream certidude_api {
|
root {{static_path}};
|
||||||
server unix:///run/uwsgi/app/certidude/socket;
|
|
||||||
|
location /api/ {
|
||||||
|
include uwsgi_params;
|
||||||
|
uwsgi_pass certidude_api;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
{% if not push_server %}
|
||||||
server_name {{hostname}}; # TODO: FQDN, SSL
|
location /pub {
|
||||||
listen 80 default_server;
|
allow 127.0.0.1;
|
||||||
listen [::]:80 default_server ipv6only=on;
|
nchan_publisher http;
|
||||||
error_page 500 502 503 504 /50x.html;
|
nchan_store_messages off;
|
||||||
|
nchan_channel_id $arg_id;
|
||||||
root {{static_path}};
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
include uwsgi_params;
|
|
||||||
uwsgi_pass certidude_api;
|
|
||||||
}
|
|
||||||
|
|
||||||
{% if not push_server %}
|
|
||||||
location /pub {
|
|
||||||
allow 127.0.0.1;
|
|
||||||
nchan_publisher http;
|
|
||||||
nchan_store_messages off;
|
|
||||||
nchan_channel_id $arg_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ "^/lp/(.*)" {
|
|
||||||
nchan_subscriber longpoll;
|
|
||||||
nchan_channel_id $1;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ "^/ev/(.*)" {
|
|
||||||
nchan_subscriber eventsource;
|
|
||||||
nchan_channel_id $1;
|
|
||||||
}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location ~ "^/lp/(.*)" {
|
||||||
|
nchan_subscriber longpoll;
|
||||||
|
nchan_channel_id $1;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ "^/ev/(.*)" {
|
||||||
|
nchan_subscriber eventsource;
|
||||||
|
nchan_channel_id $1;
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[uwsgi]
|
[uwsgi]
|
||||||
exec-as-root = /usr/local/bin/certidude signer spawn -k
|
exec-as-root = /usr/local/bin/certidude signer spawn
|
||||||
master = true
|
master = true
|
||||||
processes = 1
|
processes = 1
|
||||||
vacuum = true
|
vacuum = true
|
||||||
|
Loading…
Reference in New Issue
Block a user