laurivosandi / certidude Goto Github PK
View Code? Open in Web Editor NEWEasy to use Certificate Authority web service for OpenVPN, StrongSwan and HTTPS
License: MIT License
Easy to use Certificate Authority web service for OpenVPN, StrongSwan and HTTPS
License: MIT License
Currently activities at CA leave trace in:
Auditing tool would have to fetch all the bits and pieces and verify that data hasn't been tampered with.
Since we are authenticating Certidude server users against Kerberos anyway, it would be relatively easy to authenticate machines as well. This way we can leverage the system keytab which is already in place once computer is joined to domain. See examples how to make requests on behalf of a computer account instead of a regular user.
Currently following directories are not created on the fly:
https://nchan.slact.net/ is a nice competitor to the streaming push module we're using currently. It properly forwards content type to long polling request and deleting the channel causes 404 to be returned.
Currently the certidude serve
spawns signer processes as root and then switches to user certitude
to serve HTTP API. In order to use Kerberos authentication on the server we could serve the API on UNIX domain socket and let the web server do the heavy lifting. Currently there is no elegant way to start API as root and then have it's privileges dropped (UNIX domain socket binding is done once event loop starts), moreover FastCGI implementations seem to be somwhat behind for Python3. It might make sense to modify code to permit uWSGI usage from web server context (as user www-data), this assumes the certidude spawn
is run during boot.
Currently Kerberos authenticated machines are assigned to roadwarriors OU, but this should be in fact customizable:
https://github.com/laurivosandi/certidude/blob/master/certidude/api/request.py#L104
One of the systemd service files is being generated with incorrect contents:
Unknown lvalue 'Before' in section 'Service' for certidude-ldap-kinit.service
To even get started with Python3 port some things need to be clarified first - what is the current status of following dependencies:
Currently the domain admins group membership check is not performed within Python code. AD-compatible domain controllers also supply PAC, which can be used to check group membership avoiding additional LDAP query.
Currently insecure
flag in /etc/certidude/client.conf
specifies whether CA should be contacted over HTTP or HTTPS. Instead of such static configuration we should support HSTS.
Possible implementation on the client side would perform first request over HTTP and if server redirects to HTTPS and returns with HSTS headers create a file eg /var/lib/certidude/ca.example.com/secure. If such file exists further requests would be performed over HTTPS by default.
This would allow auotmatically obtaining certificate for a server with certbot
Windows reports hostname in upper case and this will fail:
https://github.com/laurivosandi/certidude/blob/master/certidude/api/request.py#L83
If the user is authenticated via LDAP, it would be useful to publish the newly created certificate to the corresponding certificate attribute in Active Directory.
Clock skew issues are common, it would be convenient to supply client timestamp with CSR so server could inform CA administrator about the clock skew on client side eg. simply via log entry.
HTTP request header Date should be suitable for this purpose.
A cron job could be scheduled 2 weeks before the certificate expiration so Certidude could also perform certificate renewal. Certidude server could automatic allow certificate renewal in certain timeframe, exact implementation details need more investigation.
Since OCSP responses and CRL-s can basically be queried by anyone it would be a good idea to use keypair other than CA-s to sign them, so CA keypair wouldn't be exposed too much (consider timing attacks)
Hi,
I've hit an error when trying to provision with sudo -H /usr/local/bin/certidude provision authority
:
Traceback (most recent call last):
File "/usr/local/bin/certidude", line 6, in <module>
exec(compile(open(__file__).read(), __file__, 'exec'))
File "/srv/certidude/misc/certidude", line 6, in <module>
entry_point()
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/srv/certidude/certidude/cli.py", line 1193, in certidude_provision_authority
verbose_render_systemd_service("snippets/nginx-ocsp-cache.service", "certidude-ocsp-cache.service", vars())
File "/srv/certidude/certidude/cli.py", line 1179, in verbose_render_systemd_service
buf = env.get_template(template).render(context)
File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 989, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 754, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python3/dist-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "/srv/certidude/certidude/templates/snippets/nginx-ocsp-cache.service", line 7, in top-level template code
ExecStart=-/usr/bin/curl --cert-status https://{{ common_name }}:8443/ --cacert /etc/certidude/authority/{{ session.authority.hostname }}/ca_cert.pem
File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 408, in getattr
return getattr(obj, attribute)
jinja2.exceptions.UndefinedError: 'session' is undefined
I haven't found this error on the net, so after a bit digging I think this is related to nginx not starting, this is the output from sudo systemctl status nginx.service
:
nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled)
Active: failed (Result: exit-code) since vie 2018-09-21 10:53:08 CEST; 11s ago
Docs: man:nginx(8)
Process: 29186 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
sep 21 10:53:07 soporte systemd[1]: Starting A high performance web server and a reverse proxy server...
sep 21 10:53:08 soporte nginx[29186]: nginx: [emerg] BIO_new_file("/var/lib/certidude/signed/ca.mainsip.com.pem") failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/var/lib/certidude/signed/ca.mainsip.com.pemsep 21 10:53:08 soporte nginx[29186]: nginx: configuration file /etc/nginx/nginx.conf test failed
sep 21 10:53:08 soporte systemd[1]: nginx.service: Control process exited, code=exited status=1
sep 21 10:53:08 soporte systemd[1]: Failed to start A high performance web server and a reverse proxy server.
sep 21 10:53:08 soporte systemd[1]: nginx.service: Unit entered failed state.
sep 21 10:53:08 soporte systemd[1]: nginx.service: Failed with result 'exit-code'.
So it seems it doesn't find a certificate on /var/lib/certidude/signed/ca.mainsip.com.pem
but /var/lib/certidude/
doesn't even exists. Is there anything I'm missing?
Migrate whole certificate renewal procedure to mutually authenticated TLS connection.
New port assignment:
80 - Certidude API-s over HTTP
443 - Certidude API-s over HTTPS, no client auth
8443 - Certidude API-s over HTTPS with mandatory client auth
To make adoption easier, Certidude server could be wrapped up as a Docker image.
Currently hashing algorithm is used for tokening systems. Not having to save stuff to database is a pro of this approach, but if server's secrets are compromised attacker can generate a valid token. Also such token can be reused.
Certidude should support a database backed token system where token identifier is genuinely random and relevant information is looked up on the server side from the database.
Currently log spinner will stay there if /api/log returns 404 (not enabled), instead relevant information should be showed in the user interface.
Currently CSR submission originating IP address is not saved. It could be saved in the filesystem attributes and shown in the user interface as well.
When certidude client places certificates and keys under /var/lib/certidude NetworkManager/OpenVPN/Fedora combo doesn't like it. A quick hack right now seems to be following:
chcon -Rv --type=home_cert_t /var/lib/certidude
Impementing Simple Certificate Enrollment Protocol would add compatibility with existing devices that make use of X.509 infrastructure. A software based client application can be found here. It might be possible to add long poll support, but that would have to be investigated
Trying to install Certidude on CentOS 7, in a virtual env. The install went fine, but provisioning fails with
[root@rad ~]# /opt/certidude/bin/certidude provision authority
Traceback (most recent call last):
File "/opt/certidude/bin/certidude", line 4, in <module>
__import__('pkg_resources').run_script('certidude==0.1.21', 'certidude')
File "/opt/certidude/lib/python2.7/site-packages/pkg_resources/__init__.py", line 743, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/opt/certidude/lib/python2.7/site-packages/pkg_resources/__init__.py", line 1498, in run_script
exec(code, namespace, namespace)
File "/opt/certidude/lib/python2.7/site-packages/certidude-0.1.21-py2.7.egg/EGG-INFO/scripts/certidude", line 6, in <module>
entry_point()
File "/opt/certidude/lib/python2.7/site-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/opt/certidude/lib/python2.7/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/opt/certidude/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/opt/certidude/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/opt/certidude/lib/python2.7/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/opt/certidude/lib/python2.7/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/opt/certidude/lib/python2.7/site-packages/certidude-0.1.21-py2.7.egg/certidude/cli.py", line 1024, in certidude_provision_authority
assert subprocess.check_output(["/usr/bin/lsb_release", "-cs"]) in (b"trusty\n", b"xenial\n", b"bionic\n"), "Only Ubuntu 16.04 supported at the moment"
File "/usr/lib64/python2.7/subprocess.py", line 568, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
I only Ubuntu trusty, xenial or bionic supported ? It should be made more clear in the doc in that case
Certidude client could be packaged as MSI for Windows, installed as a service and it could allow automatic installation of OpenVPN as a service once the certificates are in place. Graphical user interface can be omitted at first.
strongSwan support is almost there so adding OpenVPN support using strongSwan snippets is pretty trivial.
GN or SN containing unicode characters breaks Android client
Currently window title in the certidude web server view is simply Certidude server, instead it could be something more descripive and specific to organization, hence it should be configurable via /etc/certidude/server.conf
for example by placing title = Foo Bar LLC VPN certificates
under [authority]
section.
Similarily description = /var/lib/certidude/ca.example.com/help.md
could be used to specify Markdown formatted file which gets rendered to HTML and displayed as landing page.
Current approach is pretty naive - all signed certificates and accompanying metadata and code snippets are inserted into DOM tree which makes even Chrome choke.
For development/testing run this with autosign allowed from localhost:
for j in $(seq 1 500); do
openssl genrsa -out /tmp/host_key.pem 1024
openssl req -new -sha384 -subj "/CN=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 15 | head -n 1)" \
-key /tmp/host_key.pem \
-out /tmp/host_req.pem
curl --cert-status -f -L -H "Content-type: application/pkcs10" \
--data-binary @/tmp/host_req.pem \
-o /tmp/host_cert.pem \
'http://127.0.1.1:8080/api/request/?wait=yes\&autosign=yes'
done
Currently if .ovpn or .p12 bundle is downloaded the RSA private key is generated on the server and served for the web browser.
To do it technically correctly the private key would have to be generated on the client side. Using WebCrypto and pki.js we should be able to generate RSA keypair and bundle file in the browser and have it signed by server since the user is already logged in.
The .ovpn could be generated using JavaScript blobs.
File "/usr/lib/python2.7/site-packages/certidude-0.1.21-py2.7.egg/certidude/helpers.py", line 73, in certidude_request_certificate
for revocation in revocation_list.get_revoked():
TypeError: 'NoneType' object is not iterable
Minimal user interface could be implemented to check the current status of the certificates of a client machine. Bundling with Windows MSI should be considered.
In the beginning we tried to configure services with certidude setup service-blah
, this approach failed because bits and pieces of the information has to be persistent for example for certificate renewal and in some cases request has to be initiated later (when interface goes up or machine is joined to domain).
Instead now we're using /etc/certidude/client.conf
and /etc/certidude/services.conf
configuration files. This makes it more manageable also with configuration management software.
In fact in the future we should migrate to /etc/certidude/client.d/blah.conf
and /etc/certidude/service.d/blah.conf
schema. This makes it easier to reconfigure services with a simple copypastable command instead of having to update fragments of an .ini style file.
So - certidude setup service-blah
command either should be removed completely or refactored to generate /etc/certidude/serivced/blah.conf
files
Currently only non-sensitive data is pushed over event source which is followed by an API call to fetch relevant information. To reduce roundtrips we could use authenticated channels instead https://nchan.io/#request-authorization
When certificate is going to be signed UI could show a popup where following can be adjusted:
/etc/certidude/server.conf
When automatic enrollment is possible certificate expiration policy could be defined in /etc/certidude/server.conf
.
Cronjob for automatically revoking certificates for disabled/deleted computer/user accounts should be added. To consistently map users to certificates perhaps SID should be added into the certificate somehow?
Hi, I'm trying to use this to manage my certificates for Samba domain controllers and OpenVPN. I have followed the source install steps for a source install, but get an error 404 page when loading the https page.
The logs show no error:
Aug 25 16:01:31 ca certidude[7615]: Executing log_insert_entry.sql with (datetime.datetime(2019, 8, 25, 16, 1, 31, 519141), 'certidude.api.session', 20, 'info', 'Served CA certificate to 192.168.48.69', 'session', 'on_get', 17, '', 7623, 139841744570176, 'MainThread') Aug 25 16:01:31 ca certidude[7615]: Publishing log-entry event '{"created": "2019-08-25T16:01:31.519Z", "message": "Served CA certificate to 192.168.48.69", "severity": "info"}' on http://localhost/ev/pub/lidJVVGSKNSEgV5cJ5YzmFjIYLSBatKk
Is there something obvious that I am missing ?
Thanks very much
Example stack trace:
Mar 31 06:26:02 ca certidude[16379]: Connecing to ldap://dc1.example.com using Kerberos ticket cache from /run/certidude/krb5cc
Mar 31 06:26:02 ca /usr/bin/python[17271]: python /usr/local/bin/certidude serve -l 0.0.0.0 -p 80: GSSAPI client step 1
Mar 31 06:26:02 ca /usr/bin/python[17271]: python /usr/local/bin/certidude serve -l 0.0.0.0 -p 80: GSSAPI client step 1
Mar 31 06:26:02 ca /usr/bin/python[17271]: python /usr/local/bin/certidude serve -l 0.0.0.0 -p 80: GSSAPI client step 1
Mar 31 06:26:02 ca /usr/bin/python[17271]: python /usr/local/bin/certidude serve -l 0.0.0.0 -p 80: GSSAPI client step 2
Mar 31 06:26:02 ca certidude[16379]: Sending e-mail certificate-renewed.md to Lauri Võsandi <[email protected]>
Mar 31 06:26:03 ca certidude[16379]: Traceback (most recent call last):
Mar 31 06:26:03 ca certidude[16379]: File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
Mar 31 06:26:03 ca certidude[16379]: self.result = application(self.environ, self.start_response)
Mar 31 06:26:03 ca certidude[16379]: File "/usr/local/lib/python2.7/dist-packages/falcon/api.py", line 209, in __call__
Mar 31 06:26:03 ca certidude[16379]: responder(req, resp, **params)
Mar 31 06:26:03 ca certidude[16379]: File "/root/certidude/certidude/auth.py", line 50, in kerberos_authenticate
Mar 31 06:26:03 ca certidude[16379]: return func(resource, req, resp, *args, **kwargs)
Mar 31 06:26:03 ca certidude[16379]: File "/root/certidude/certidude/firewall.py", line 24, in wrapped
Mar 31 06:26:03 ca certidude[16379]: return func(self, req, resp, *args, **kwargs)
Mar 31 06:26:03 ca certidude[16379]: File "/root/certidude/certidude/firewall.py", line 33, in wrapped
Mar 31 06:26:03 ca certidude[16379]: return func(self, req, resp, *args, **kwargs)
Mar 31 06:26:03 ca certidude[16379]: File "/root/certidude/certidude/api/request.py", line 100, in on_post
Mar 31 06:26:03 ca certidude[16379]: _, resp.body = authority._sign(csr, body, overwrite=True)
Mar 31 06:26:03 ca certidude[16379]: File "/root/certidude/certidude/authority.py", line 351, in _sign
Mar 31 06:26:03 ca certidude[16379]: certificate=cert,
Mar 31 06:26:03 ca certidude[16379]: File "/root/certidude/certidude/mailer.py", line 96, in send
Mar 31 06:26:03 ca certidude[16379]: conn.sendmail(config.OUTBOX_MAIL, recipients, msg.as_string())
Mar 31 06:26:03 ca certidude[16379]: File "/usr/lib/python2.7/smtplib.py", line 747, in sendmail
Mar 31 06:26:03 ca certidude[16379]: raise SMTPRecipientsRefused(senderrs)
Mar 31 06:26:03 ca certidude[16379]: SMTPRecipientsRefused: {u'Lauri V\xf5sandi <[email protected]>': (451, '4.3.5 <[email protected]>: Recipient address rejected: Server configuration error')}
Mar 31 06:26:03 ca certidude[16379]: 192.168.12.1 - - [31/Mar/2017 06:26:03] "POST /api/request/?autosign=true&wait=30 HTTP/1.1" 500 59
When uploading a CSR, all custom extensions are removed.
There should be a feature that if the adminstrator approves, the extensions are included in the certificate. For example, this software can't currently be used to issue certificates for smart cards for windows logon, as they require special attributes to be set (certidude removes them on issuance).
Even if these weren't exposed in the GUI, it would be great if this was an option for advanced users (e.g. adding multiple SANs).
On the VPN gateway interesting traffic could be logged to syslog and then forwarded to Certidude:
Certidude could have another syslog server facilities, possibly use already deployed certificates to authenticate TLS tunnel for syslog and parse the messages coming in.
Parsed messages could be stored in SQL database with all relevant metadata decoded - who was the user/computer initiating the connections etc
Right now there are no e-mails sent about certificates that are going to expire. The notification machinery could also distinguish server certs from client certs.
Currently OCSP responder returns ok regardless of user account status in AD. Certidude should have config to handle this
Some ideas for malformed CSR-s:
On Ubuntu 16.04 NetworkManager seems to shut down VPN connection after certain time of inactivity. Quick fix is to add ping option.
Currently confguration file gets generated with TAP interface but we should switch to TUN.
Currently LDAP server down results in HTTP error 500 on the web browser side
To automate VPN setup even more the server could export basically the client's services.conf file which tells clients which services to configure once the certificates have been deployed to basically make it possible to acquire the certificate and configure related services with single command:
certidude bootstrap ca.example.lan
By default assume clients to have sort of dumb config which accepts anything that eg VPN gateway suggests during negotiation.
However in certain cases it makes sense to constrain config on the client side:
On UNIX requests Kerberos module allows using force_preemptive=True, which tells the client to immideately send GSSAPI headers. On Windows this is not currently supported, perhaps this is possible from PowerShell?
https://github.com/laurivosandi/certidude/blob/master/certidude/cli.py#L439
Currently adduser
command fails during certidude setup authority
on Fedora. This should be replaced with something more universal - useradd
perhaps
Certidude server could be set up so it would fetch certidude@hostname mailbox content automatically. Preliminary implementation could avoid IMAP altogether and simply parse /var/mail contents directly. Sending mail could be implemented with smtplib
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.