From 372e71c17588f302aa25cd6cc7a71c8a8fa60d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Thu, 26 Jan 2017 12:55:26 +0200 Subject: [PATCH 1/4] Use TUN for network-manager/openvpn service --- certidude/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certidude/cli.py b/certidude/cli.py index 17e5b69..61bb77f 100755 --- a/certidude/cli.py +++ b/certidude/cli.py @@ -239,7 +239,7 @@ def certidude_request(fork): nm_config.set("vpn", "connection-type", "tls") nm_config.set("vpn", "comp-lzo", "yes") nm_config.set("vpn", "cert-pass-flags", "0") - nm_config.set("vpn", "tap-dev", "yes") + nm_config.set("vpn", "tap-dev", "no") nm_config.set("vpn", "remote-cert-tls", "server") # Assert TLS Server flag of X.509 certificate nm_config.set("vpn", "remote", service_config.get(endpoint, "remote")) nm_config.set("vpn", "key", endpoint_key_path) From 93abceb9bdd18707b92a25457b0941d2459a7ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Thu, 26 Jan 2017 12:57:41 +0200 Subject: [PATCH 2/4] Update README --- README.rst | 152 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 48 deletions(-) diff --git a/README.rst b/README.rst index c613bc7..a0a45ea 100644 --- a/README.rst +++ b/README.rst @@ -17,9 +17,10 @@ eventually support PKCS#11 and in far future WebCrypto. .. figure:: doc/usecase-diagram.png -Certidude is mainly designed for VPN gateway operators to make -desktop/laptop VPN setup as easy as possible. -User certificate management eg. for HTTPS is also made reasonably simple. +Certidude is mainly designed for StrongSwan and OpenVPN gateway operators to make +VPN client setup on laptops, desktops and mobile devices as painless as possible. +Certidude can also be used to manage HTTPS client certificates for +eg. maintaining an extra layer of protection for intranet websites. For a full-blown CA you might want to take a look at `EJBCA `_ or `OpenCA `_. @@ -105,18 +106,29 @@ TODO Install ------- -To install Certidude server: +To install Certidude server you need certain system libraries in addition to +regular Python dependencies. + +System dependencies for Ubuntu 16.04: .. code:: bash - apt-get install -y python python-pip python-dev cython \ + apt install -y python python-pip python-dev cython \ python-cffi python-configparser \ python-pysqlite2 python-mysql.connector python-ldap \ build-essential libffi-dev libssl-dev libkrb5-dev \ ldap-utils krb5-user \ libsasl2-modules-gssapi-mit \ libsasl2-dev libldap2-dev - pip install simplepam pykerberos certidude + +System dependencies for Fedora 24+: + +.. code:: bash + + yum install redhat-rpm-config python-devel openssl-devel openldap-devel + +At the moment package at PyPI is rather outdated. +Please proceed down to Development section to install Certidude from source. Setting up authority @@ -139,15 +151,6 @@ If necessary tweak machine's fully qualified hostname in ``/etc/hosts``: 127.0.0.1 localhost 127.0.1.1 ca.example.com ca -Then proceed to install `nchan `_: - -.. 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 -f install - Certidude can set up certificate authority relatively easily. Following will set up certificate authority in ``/var/lib/certidude/hostname.domain.tld``, configure systemd service for your platform, @@ -166,27 +169,27 @@ and start the services: systemctl restart certidude -Certificate management ----------------------- +Setting up PAM authentication +----------------------------- -Use following command to request a certificate on a machine: +Following assumes the OS user accounts are used to authenticate users. +This means users can be easily managed with OS tools such as ``adduser``, ``usermod``, ``userdel`` etc. -.. code:: +Make sure you insert `AllowUsers administrator-account-username` +to SSH server configuration if you have SSH server installed on the machine +to prevent regular users from accessing the command line of certidude. +Note that in future we're planning to add command-line interaction +in which case SSH access makes sense. - certidude setup client ca.example.com +If you're planning to use PAM for authentication you need to install corresponding +Python modules: -Use following to list signing requests, certificates and revoked certificates on server: +.. code:: bash -.. code:: - - certidude list - -Use web interface or following to sign a certificate on server: - -.. code:: - - certidude sign client-hostname-or-common-name + pip install simplepam +The default configuration generated by ``certidude setup`` should make use of the +PAM. Setting up Active Directory authentication ------------------------------------------ @@ -199,6 +202,7 @@ Install dependencies: .. code:: bash apt-get install samba-common-bin krb5-user ldap-utils + pip install pykerberos Reset Samba client configuration in ``/etc/samba/smb.conf``, adjust workgroup and realm accordingly: @@ -274,33 +278,58 @@ Common pitfalls: the CA machine to domain, eg when you're running CA behind SSL terminating web server: Bad credentials: Unspecified GSS failure. Minor code may provide more information (851968) -Automating certificate setup ----------------------------- -Ubuntu 14.04 based desktops come with NetworkManager installed. -Create ``/etc/NetworkManager/dispatcher.d/certidude`` with following content: +Setting up services +------------------- + +Set up services as usual (OpenVPN, Strongswan, etc), when setting up certificates +generate signing request with TLS server flag set. +Paste signing request into the Certidude web interface and hit the submit button. + +Since signing requests with custom flags are not allowed to be signed +from the interface due to security concerns, sign the certificate at Certidude command line: .. code:: bash - #!/bin/sh -e - # Set up certificates for IPSec connection + certidude sign gateway.example.com - case "$2" in - up) - LANG=C.UTF-8 /usr/local/bin/certidude request spawn -k - ;; - esac +Download signed certificate from the web interface or ``wget`` it into the service machine. +Fetch also CA certificate and finish configuring the service. -Finally make it executable: + +Setting up clients +------------------ + +This example works for Ubuntu 16.04 desktop with corresponding plugins installed +for NetworkManager. + +Configure Certidude client in ``/etc/certidude/client.conf``: + +.. code:: ini + + [ca.example.com] + insecure = true + trigger = interface up + +Configure services in ``/etc/certidude/services.conf``: .. code:: bash - chmod +x /etc/NetworkManager/dispatcher.d/certidude + [gateway.example.com] + authority = ca.example.com + service = network-manager/openvpn + remote = gateway.example.com -Whenever a wired or wireless connection is brought up, -the dispatcher invokes ``certidude`` in order to generate RSA keys, -submit CSR, fetch signed certificate, -create NetworkManager configuration for the VPN connection. +To request certificate: + +.. code:: bash + + certidude request + +The keys, signing requests, certificates and CRL-s are placed under +/var/lib/certidude/ca.example.com/ + +The VPN connection should immideately become available under network connections. Development @@ -323,7 +352,7 @@ To generate templates: .. code:: bash - apt-get install npm nodejs + apt install npm nodejs sudo ln -s nodejs /usr/bin/node # Fix 'env node' on Ubuntu 14.04 npm install -g nunjucks@2.5.2 nunjucks-precompile --include "\\.html$" --include "\\.svg$" certidude/static/ > certidude/static/js/templates.js @@ -340,3 +369,30 @@ To install the package from the source: .. code:: bash python setup.py install --single-version-externally-managed --root / + +To uninstall: + + pip uninstall certidude + + +Certificate attributes +---------------------- + +Certificates have a lot of fields that can be filled in. +In any case country, state, locality, organization, organizational unit are not filled in +as this information will already exist in AD and duplicating it in the certificate management +doesn't make sense. Additionally the information will get out of sync if +attributes are changed in AD but certificates won't be updated. + +If machine is enrolled, eg by running certidude request: + +* If Kerberos credentials are presented machine is automatically enrolled +* Common name is set to short hostname/machine name in AD +* E-mail is not filled in (maybe we can fill in something from AD?) +* Given name and surname are not filled in + +If user enrolls, eg by clicking generate bundle button in the web interface: + +* Common name is either set to username or username@device-identifier depending on the 'user certificate enrollment' setting +* Given name and surname are filled in based on LDAP attributes of the user +* E-mail not filled in (should it be filled in? Can we even send mail to user if it's in external domain?) From ef72cb70cd2e86e2851602787a89597fb769deed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Thu, 26 Jan 2017 15:11:04 +0200 Subject: [PATCH 3/4] Fixes for testing server as regular user --- certidude/auth.py | 2 +- certidude/cli.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/certidude/auth.py b/certidude/auth.py index 5a2c60b..a2a7919 100644 --- a/certidude/auth.py +++ b/certidude/auth.py @@ -1,7 +1,6 @@ import click import falcon -import kerberos # If this fails pip install kerberos import logging import os import re @@ -13,6 +12,7 @@ from certidude import config, const logger = logging.getLogger("api") if "kerberos" in config.AUTHENTICATION_BACKENDS: + import kerberos # If this fails pip install kerberos ktname = os.getenv("KRB5_KTNAME") if not ktname: diff --git a/certidude/cli.py b/certidude/cli.py index 61bb77f..94f63f1 100755 --- a/certidude/cli.py +++ b/certidude/cli.py @@ -1174,10 +1174,11 @@ def certidude_serve(port, listen): from certidude import config # Fetch UID, GID of certidude user - import pwd - _, _, uid, gid, gecos, root, shell = pwd.getpwnam("certidude") - restricted_groups = [] - restricted_groups.append(gid) + if os.getuid() == 0: + import pwd + _, _, uid, gid, gecos, root, shell = pwd.getpwnam("certidude") + restricted_groups = [] + restricted_groups.append(gid) """ Spawn signer process From 6221fe9c00a2f2b3a6a834fa18699aa741c91314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20V=C3=B5sandi?= Date: Thu, 26 Jan 2017 15:22:02 +0200 Subject: [PATCH 4/4] Prompt for password when invalid password is entered --- certidude/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/certidude/auth.py b/certidude/auth.py index a2a7919..6972416 100644 --- a/certidude/auth.py +++ b/certidude/auth.py @@ -186,7 +186,7 @@ def authenticate(optional=False): if not simplepam.authenticate(user, passwd, "sshd"): logger.critical(u"Basic authentication failed for user %s from %s", repr(user), req.context.get("remote_addr")) - raise falcon.HTTPForbidden("Forbidden", "Invalid password") + raise falcon.HTTPUnauthorized("Forbidden", "Invalid password", ("Basic",)) req.context["user"] = User.objects.get(user) return func(resource, req, resp, *args, **kwargs)