|
@@ -225,21 +225,96 @@ First of all, let's set-up some basic directory structure and configuration:
|
|
|
[backup]
|
|
|
bak.example.com
|
|
|
|
|
|
4. Create a number of directories for storing playbooks, group variables, SSH
|
|
|
keys, and GnuPG keyring (we'll get to this later)::
|
|
|
4. Create a number of directories for storing playbooks, group
|
|
|
variables, SSH keys, X.509 artefacts (for TLS), and GnuPG keyring
|
|
|
(we'll get to this later)::
|
|
|
|
|
|
mkdir ~/mysite/playbooks/
|
|
|
mkdir ~/mysite/group_vars/
|
|
|
mkdir ~/mysite/ssh/
|
|
|
mkdir ~/mysite/gnupg/
|
|
|
|
|
|
5. Before moving ahead, we should also create SSH private/public key pair that
|
|
|
will be used by Ansible for connecting to destination servers, as well as
|
|
|
for some roles::
|
|
|
5. Create SSH private/public key pair that will be used by Ansible for
|
|
|
connecting to destination servers, as well as for some roles::
|
|
|
|
|
|
ssh-keygen -f ~/.ssh/id_rsa -N ''
|
|
|
|
|
|
|
|
|
Protecting communications using TLS
|
|
|
-----------------------------------
|
|
|
|
|
|
In order to protect the communications between users and servers, as
|
|
|
well as between servers themselves, it is important to set-up and
|
|
|
properly configure TLS for each role.
|
|
|
|
|
|
*Majic Ansible Roles* mandates use of TLS wherever possible. In other
|
|
|
words, *you must* have TLS private keys and certificates issued by
|
|
|
some CA for all servers in order to be able to use most of the
|
|
|
roles. The private keys and certificates are primarily meant to be
|
|
|
generated *per service*, and that is the approach we will pursue here
|
|
|
as well.
|
|
|
|
|
|
TLS private keys should be ideally generated locally and kept in a
|
|
|
safe environment (possibly encrypted until needed), while the X.509
|
|
|
certificates should be issued by a relevant certification
|
|
|
authority. You can choose to roll-out your own CA, use one of the
|
|
|
public CAs, or perhaps go for a mix of both.
|
|
|
|
|
|
For the purpose of this guide, we'll set-up a small simple local CA to
|
|
|
issue all the necessary certificates, and we'll generate the private
|
|
|
keys and issue server certificates on the go as needed.
|
|
|
|
|
|
So, let us make a slight detour to create a CA of our own:
|
|
|
|
|
|
1. First off, install a couple more tools on the Ansible server. We
|
|
|
will be using ``certtool`` for our improvised CA needs (run this as
|
|
|
``root``)::
|
|
|
|
|
|
apt-get install -y gnutls-bin
|
|
|
|
|
|
2. Create directory where the private keys and certificates will be
|
|
|
stored at (you can switch back to the ``ansible`` user now)::
|
|
|
|
|
|
mkdir ~/mysite/tls/
|
|
|
|
|
|
3. Create a template for the ``certtool`` so it would know what
|
|
|
extensions and content to have in the CA certificate:
|
|
|
|
|
|
:file:`~/mysite/tls/ca.cfg`
|
|
|
::
|
|
|
|
|
|
organization = "Example Inc."
|
|
|
country = "SE"
|
|
|
cn = "Example Inc. Test Site CA"
|
|
|
expiration_days = 1825
|
|
|
ca
|
|
|
cert_signing_key
|
|
|
crl_signing_key
|
|
|
|
|
|
4. Almost there... Now let us generate the CA private key and
|
|
|
self-signed certificate::
|
|
|
|
|
|
certtool --sec-param high --generate-privkey --outfile ~/mysite/tls/ca.key
|
|
|
certtool --template ~/mysite/tls/ca.cfg --generate-self-signed --load-privkey ~/mysite/tls/ca.key --outfile ~/mysite/tls/ca.pem
|
|
|
|
|
|
5. And just one more small tweak - we need to provide a truststore PEM
|
|
|
file containing all CA certificates in the chain for services to be
|
|
|
able to connect to each-other (where necessary). In this particular
|
|
|
case we have a super-simple hierarchy (root CA is also issuing the
|
|
|
end entity certificates), so simply make a copy of the ``ca.pem``::
|
|
|
|
|
|
cp ~/mysite/tls/ca.pem ~/mysite/tls/truststore.pem
|
|
|
|
|
|
.. note::
|
|
|
A useful feature that all roles implement is a check to see if
|
|
|
certificates will expire within the next 30 days. This check is
|
|
|
performed via cronjob at midnight, and failing results will end-up
|
|
|
being delivered to the ``root`` user on local server. Later on,
|
|
|
once you have configured the mail server, you should be able to
|
|
|
set-up the necessary aliases to have the mails delivered to
|
|
|
non-local accounts too.
|
|
|
|
|
|
|
|
|
Preseed files
|
|
|
-------------
|
|
|
|
|
@@ -478,11 +553,22 @@ Let's take care of this common configuration right away:
|
|
|
common_packages:
|
|
|
- emacs25-nox
|
|
|
|
|
|
ca_certificates:
|
|
|
truststore: "{{ lookup('file', '~/mysite/tls/truststore.pem') }}"
|
|
|
|
|
|
.. note::
|
|
|
The ``common`` role comes with ability to set-up time
|
|
|
synchronisation using NTP. This is not done by default. For
|
|
|
details see the role parameter ``ntp_servers``.
|
|
|
|
|
|
.. note::
|
|
|
The ``ca_certificates`` parameter lets us deploy custom CA
|
|
|
certificates on servers. The name we pick (in this case
|
|
|
``truststore``) can be set to anything. In this particular case,
|
|
|
we want to deploy our own CA certificate for use as truststore,
|
|
|
since this is what the services will use to validate server
|
|
|
certificates when connecting to each-other.
|
|
|
|
|
|
6. That's all for configuration, time to apply the changes::
|
|
|
|
|
|
workon mysite && ansible-playbook playbooks/site.yml
|
|
@@ -546,12 +632,16 @@ one up first. This includes both the LDAP *server* and *client* configuration.
|
|
|
|
|
|
ldap_admin_password: admin
|
|
|
ldap_server_organization: "Example Inc."
|
|
|
ldap_server_tls_certificate: "{{ lookup('file', 'tls/comms.example.com_ldap.pem') }}"
|
|
|
ldap_server_tls_key: "{{ lookup('file', 'tls/comms.example.com_ldap.key') }}"
|
|
|
|
|
|
4. Phew. That was... Well, actually, easy :) Technically, only the LDAP admin
|
|
|
password *must* be set, but it's nice to have better organisation specified
|
|
|
than the default one. Let's add the LDAP client configuration next. We will
|
|
|
start off with global LDAP client configuration. In case of LDAP client,
|
|
|
we've got to be a bit more explicit.
|
|
|
4. Phew. That was... Well, actually, easy :) Technically, only the
|
|
|
LDAP admin password and TLS certificate/key *must* be set, but it
|
|
|
is nice to have organisation explicitly specified as well (instead
|
|
|
of using whatever Debian picks as default). Let us add the LDAP
|
|
|
client configuration next. We will start off with global LDAP
|
|
|
client configuration. In case of the LDAP client role, we have got
|
|
|
to be a bit more explicit.
|
|
|
|
|
|
:file:`~/mysite/group_vars/all.yml`
|
|
|
::
|
|
@@ -598,48 +688,11 @@ one up first. This includes both the LDAP *server* and *client* configuration.
|
|
|
value: demand
|
|
|
|
|
|
6. Ok, time to re-run the playbooks again... Wait a minute, something
|
|
|
is missing here... Oh, right, I forgot to mention one thing - Majic
|
|
|
Ansible Roles use TLS throughout wherever possible. In other words,
|
|
|
you *must* have TLS private keys and certificates issued by some CA
|
|
|
for all servers in order to be able to use most of the roles
|
|
|
(actually, you need them issued per *service*). This includes
|
|
|
``ldap_server`` too. So, let's make a slight detour to create a CA
|
|
|
of our own, plus the necessary server certificate for the LDAP
|
|
|
service...
|
|
|
|
|
|
.. note::
|
|
|
Another useful feature the roles implement is a check to see if
|
|
|
certificates will expire within the next 30 days. This check is
|
|
|
performed via cronjob at midnight, and failing results will
|
|
|
end-up being delivered to the ``root`` user on local
|
|
|
server. Later on, once you have configured the mail server, you
|
|
|
should be able to set-up the necessary aliases to have the mails
|
|
|
delivered to non-local accounts too.
|
|
|
is missing here... Ah, right, we have to generate the TLS private
|
|
|
key and issue the X.509 certificate.
|
|
|
|
|
|
1. Let's first install a couple of more tools on the Ansible server, since we
|
|
|
will be using ``certtool`` for our improvised CA needs (run this as
|
|
|
``root``)::
|
|
|
|
|
|
apt-get install -y gnutls-bin
|
|
|
|
|
|
2. Create directory where the private keys and certificates will be stored
|
|
|
at (you can switch back to the ``ansible`` user now)::
|
|
|
|
|
|
mkdir ~/mysite/tls/
|
|
|
|
|
|
3. It is time to create a couple of templates for the ``certtool`` so it
|
|
|
would know what extensions and content to have in the certificates:
|
|
|
|
|
|
:file:`~/mysite/tls/ca.cfg`
|
|
|
::
|
|
|
|
|
|
organization = "Example Inc."
|
|
|
country = "SE"
|
|
|
cn = "Example Inc. Test Site CA"
|
|
|
expiration_days = 1825
|
|
|
ca
|
|
|
cert_signing_key
|
|
|
crl_signing_key
|
|
|
1. Create template for the ``certtool`` so it would know what
|
|
|
extensions and content to have in the certificate:
|
|
|
|
|
|
:file:`~/mysite/tls/comms.example.com_ldap.cfg`
|
|
|
::
|
|
@@ -653,35 +706,12 @@ one up first. This includes both the LDAP *server* and *client* configuration.
|
|
|
signing_key
|
|
|
encryption_key
|
|
|
|
|
|
4. Almost there... Now let's generate the keys and certificates::
|
|
|
2. Almost there... Now let us generate the key and issue the certificate::
|
|
|
|
|
|
certtool --sec-param high --generate-privkey --outfile ~/mysite/tls/ca.key
|
|
|
certtool --template ~/mysite/tls/ca.cfg --generate-self-signed --load-privkey ~/mysite/tls/ca.key --outfile ~/mysite/tls/ca.pem
|
|
|
certtool --sec-param normal --generate-privkey --outfile ~/mysite/tls/comms.example.com_ldap.key
|
|
|
certtool --generate-certificate --load-ca-privkey ~/mysite/tls/ca.key --load-ca-certificate ~/mysite/tls/ca.pem --template ~/mysite/tls/comms.example.com_ldap.cfg --load-privkey ~/mysite/tls/comms.example.com_ldap.key --outfile ~/mysite/tls/comms.example.com_ldap.pem
|
|
|
|
|
|
5. And just one more small tweak - we need to provide a truststore PEM file
|
|
|
containing all CA certificates in the chain. In this particular case we
|
|
|
have a super-simple hierarchy (root CA is also issuing the end entity
|
|
|
certificates), so simply make a copy of the ``ca.pem``. The
|
|
|
``truststore.pem`` file is picked-up automatically by many other roles::
|
|
|
|
|
|
cp ~/mysite/tls/ca.pem ~/mysite/tls/truststore.pem
|
|
|
|
|
|
7. With private keys and certificates in place, we are almost ready to re-run
|
|
|
the playbooks! Now, just a *small* tweak to the general configuration to set
|
|
|
where the TLS private keys and certificates can be found at, and all should
|
|
|
be fine.
|
|
|
|
|
|
:file:`~/mysite/group_vars/all.yml`
|
|
|
::
|
|
|
|
|
|
tls_private_key_dir: "~/mysite/tls/"
|
|
|
tls_certificate_dir: "~/mysite/tls/"
|
|
|
ca_certificates:
|
|
|
truststore: "{{ lookup('file', '~/mysite/tls/truststore.pem') }}"
|
|
|
|
|
|
8. And now, for the finishing touch, just run the playbooks again::
|
|
|
7. And now, for the finishing touch, just run the playbooks again::
|
|
|
|
|
|
workon mysite && ansible-playbook playbooks/site.yml
|
|
|
|