-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Http and Https default site detection #71
Comments
I'm afraid the above solutions aren't the correct ones in this problem, because problem is completely elsewhere. But if I tell you that it's just lack of a default certificates that So instead let me tell you how these different pieces fit together. It will be a long read (got the tl;dr above), but I hope it will clear up some things for you and others about how I imagine and design stuff in DebOps. Let's start at the top, in this case, But why? It's simple - we are living in 2015, not 1990. Everybody is doing HTTPS these days, there's huge movement all over the Internet to switch everything to HTTPS. Let's Encrypt, HTTPS Everywhere, Mozilla wants to deprecate HTTP entirely, others do similar things. So it's basically not a choice if a site should or shouldn't run HTTPS. You do it, end of story. But there's a problem - if you want to offer HTTPS, you need to have SSL certificates. Unfortunately, webservers like In fact, Debian and Ubuntu provide ssl-cert package which handles this - it creates a set of "SnakeOil" certificates and keys for other applications to use. Unfortunately, nobody trusts them, because they are self-signed, so nobody trusts them. In other words, they are useless for production purposes. OK, so let's create our own pair of self-seigned certificatest instead, exactly what you just did in your own playbook. Actually, let's go back even further - in fact, first public commit of "ansible-aiua" project, with over time became DebOps, used the very same concept of generating self-signed certificates on each host so that they could be used by other services. Going further, lots of places over the Web with examples how to setup a HTTPS site describe in detail how to setup your own pair of private key and self-signed certificate. Seems that this is the go-to way of providing HTTPS encryption on the Web these days. Unfortunately, our own self-signed certificate still is not trusted by anyone or anything else. This isn't an issue we can easily fix, this is mathematics. The way more smarter people than me found a workaround for this problem long time ago - create a third party that is trusted both by a client and a server - if the certificate a client receives from a server is signed by a third party (a Certificate Authority) that the client trusts, the connection is accepted without issues. Otherwise - the resolution is dependent on the application. Web browsers display a warning and let you skip it, which you can decide yourself as a human. But other clients like various services don't have that option. They either drop the connection entirely, or can be instructed using an option to implicitly trust untrusted certificates, which is unacceptable in a production environment. But why should we care? Because DebOps is meant to be used in a distributed environment, on multiple hosts at once. Sure, different services could be used over plaintext communication channel, but again - it's 2015, not 1990. We want everything that is coming over the wire to be encrypted, thus providing secure channel for the server and client to exchange data. Without encryption, you risk getting hacked when you try to set up LDAP for all of your servers, especially in the "cloud" environment. But again, all of this requires certificates and we are back to square one. Self-signed certificates won't work, because they would need to be distributed p2p style to all of the concerned hosts. The solution to this problem is to go to a Certificate Authority and get yourself a certificate that is trusted by all involved parties. But alas, that is both expensive and not automated - and remember, we want So, what to do? Here's an idea - create our own Certificate Authority which all hosts trust implicitly (for the moment forget about external clients, we will come back to them later). We could get a Certificate Signing Request from each of the hosts managed by us, sign them, and send that certificate back. And after installing our own Root CA certificate on all of the hosts, they trust us as the third party and communication between various services can be done without issues, and over a secure channel. I've looked at various solutions to this available at the time, but none were fit for the function I wanted them to perform. Most of the available solutions used either a graphical interface, or were not automated enough and required human interaction which wasn't satisfactory. More automated solutions like FreeIPA / DogTag weren't available in the Debian repositories at the time. So I've decided to create my own PKI. It would be automated (after all we trust ourselves implictly, and hopefully Ansible Controller that the CA runs on is trusted as well), would allow for management of both internal, free and strong certificates, as well as custom certificates signed somewhere else and provided by the user after a time. It would have to be centralized, both in the sense that it should run on Ansible Controller, and other roles and applications would be designed to use certificates managed by that PKI in one central place in the filesystem, instead of custom solution for each application. A set of defaults would be provided so that users could setup their own PKI with minimal changes in the role itself. But I guess, I failed by choosing to base the whole PKI concept around a DNS domain which would be used by all of the involved hosts. The concept of a domain which binds all of the hosts in a shared DNS space is useful - you can put a host in a domain and it can use services easily via subdomains - for example LDAP queries can be automatically directed to But it seems that this concept fails miserably when confronted with reality. Because of that, the PKI used by DebOps would have to be redesigned a third time. But it's fine, I planned for this from the beginning. When I wrote this iteration of But let's go back to the topic of our discussion. When the Because of that, But then, the This is exactly what happens in the example playbook you provided above. First Now, the fix you are proposing is to check essentially "out of band" to see if any of the But hold on - Could this be solved without using the |
Thanks for the background and explanation. I just want to clear a few things from my previous post. I was not proposing any sort of solutions, but rather discussion the issue as I understood it, in hopes to come to a resolution. I understand debops use case and your reasoning to create a central authority. I guess that puts me in a bind, because I don't share the same use case as you, or need the overhead of a central authority right now. I am currently using debops in a few different projects, and this particular one needs an https site on ubuntu. I don't want a distributed environment, lots of dependencies or overhead, etc. I just want to generate a CSR, purchase a cert, install the cert on nginx, and keep it automated as possible. I came to realize that I actually did use I completely believe what you are saying and have no intention to argue a week later. I was more interested in discussing the problem to better understand it, to ultimately come to a resolution. So we have outlined the problem as the lack of global certificates and |
I assume that you have each environment in a separate DebOps project directory. Ansible Controller is your laptop, and a webserver is somewhere in the cloud. Here's how you could handle the case of Create new DebOps project directory, cd into it. In
This tells the Create new webserver host on your hosting provider, let's say it's clean Debian netinstall with only Add
When you make sure that you can connect to
This will generate
When you get Run command:
This will configure the host to make it suitable for DebOps roles. Among other things, PKI will be created in Now you can configure the host to display your webpage, and When you have bought the "signed" certificate and you want to start using them instead of the ones provided by DebOps, go to the When you switch the default certificates from the internal ones to provided by you, |
We started talking about this on IRC. The problem seems to stem from the fact that debops picks an http or https site and stores it in facts. In subsequent runs, using tags, or using roles with
debops.nginx
as a dependency has issues because the fact is no longer accurate. Nginx can only setipv6only=off
once per listen, so debops has attempted to use the fact to detect the default site for http and https and set this value. I am creating this issue as a placeholder to discuss further.I created a test environment https://github.com/patrickheeney/ansible-nginx-test which uses my bug fix in #70 because
debops.nginx
currently does not detect the right site without it. In this version you can run different tags and see whatdebops.nginx
picks as the default, as well as what is stored in the facts. The facts are also cleared on each run. (You can uncommentdebops.nginx
in therequirements.yml
file and comment out my version to test with stock debops and the bug in #70).Some workarounds:
debops.nginx
in the main playbook and include all of your sites in a role withdebops.nginx
as a dependency. This waydebops.nginx
only executes once and with the fix in SSL detection improvements #70 will determine the right defaults. The facts will need to be cleared if any sites change.Ideas:
This seems like a difficult issue to solve. The role is not aware of the global state and has no idea the master list of all sites. We can't assume the server will have a default site, any https sites, or any sites in general.
One idea is to set the facts on first run like normal, but then validate those facts on subsequent runs. For example, if a second run of
debops.nginx
adds an https site, it will need to save that fact. If a third run adds another https site, the fact is no longerdefault
so it will not be set. However, what happens when sites are removed or de-activated in all of these scenarios, how will it know which to pick next and re-configure. So it seems like this will not work with all scenarios.A second idea is to run a shell or python script at the end of
debops.nginx
that is responsible for setting the default sites and saving the facts. The script would essentially check if there is an http site, set the first one it finds as default. It would do the same for https perhaps usingfind
and aregex
. It would then have to do a shell equivalent oflineinfile
to addipv6only=off
which is far from ideal. It would then save the sites in the facts, on subsequent runs if the sites still exists, it would exit immediately.A third idea is to just be explicit. Add some documentation that explains that the default ssl site has to be specified in the config
default_site_ssl: 'test.com'
. Perhaps even on the nginx configuration likeitem.default_https: True
. It would be up to the user to specify this only once, or maybe the first one it comes across gets saved as a fact. This is almost how it works now, but perhaps we can write some troubleshooting information for detecting the issue that comes up when this is not set (connection refused).The text was updated successfully, but these errors were encountered: