mirror of
				https://github.com/laurivosandi/certidude
				synced 2025-10-30 17:09:19 +00:00 
			
		
		
		
	Merge authority setup and production setup
This commit is contained in:
		
							
								
								
									
										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: | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										169
									
								
								certidude/cli.py
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								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,7 +283,6 @@ 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) | ||||||
| @@ -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,26 +1,11 @@ | |||||||
| 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; |  | ||||||
|     sendfile on; |  | ||||||
|     keepalive_timeout 65; |  | ||||||
|     gzip on; |  | ||||||
|  |  | ||||||
|     upstream certidude_api { |  | ||||||
|         server unix:///run/uwsgi/app/certidude/socket; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     server { |  | ||||||
|         server_name {{hostname}}; # TODO: FQDN, SSL |  | ||||||
|     listen 80 default_server; |     listen 80 default_server; | ||||||
|         listen [::]:80 default_server ipv6only=on; |  | ||||||
|     error_page 500 502 503 504 /50x.html; |     error_page 500 502 503 504 /50x.html; | ||||||
|  |  | ||||||
|     root {{static_path}}; |     root {{static_path}}; | ||||||
| @@ -49,6 +34,5 @@ http { | |||||||
|     } |     } | ||||||
|     {% endif %} |     {% 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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user