On May 13, Hartmut Goebel wrote:
> If you still have trouble understanding the DebOps PKI/ACME setup
after
> reading the documentation, then I suppose that the docs need some
> improvements. Any idea about what could be added to make this setup easier to
> understand is welcome. :-)
Indeed I still do not really get this realm thing.
I suppose the explanations below could be included in the docs at some point,
or improve existing documentation.
A "PKI realm" is just a placeholder name for a bunle of the private key, X.509
certificate and Root CA certificate. This bundle has a certain directory
structure, rules for naming files and what symlinks are present. It's designed
so that from the outside of the 'debops.pki', other Ansible roles or services
they manage have a standardized, uniform location where they can find X.509
certificates and private keys.
In different guides that describe setting up TLS for different services like
webservers, mail servers, databases, etc. you can find that people put the
private keys and X.509 certificates in different directories - for example
/etc/nginx/ssl/, /etc/postfix/certs/, /etc/ssl/certs/, and so on. The
'debops.pki' role turns this around by setting up an uniform set of
directories split into "PKI realms", so that a host can have multiple sets of
certificates, each for different purposes. Then, various services can be
configured to get the private key and certificate files from those specific
directories, including privileged access to the private keys when needed.
I suggest to extend pki-realms.rst to explain how to choose
realm-names,
including some examples. Questions this should answer are e.g.:
* Why is the default realm "domain" and what is the idea behind?
Usually when you set up a cluster of DebOps hosts, they share a DNS domain
together, like '*.example.org'. Thats essentially the "domain" the
default PKI
realm refers to. The "domain" PKI realm is supposed to be used for internal
communication between cluster nodes, where you don't need to worry about
services exposed to the public which would probably rather use publicly-signed
certificates, from Let's Encrypt or other Certificate Authorities.
You have full control over the internal CA which signes the "domain"
certificates, they also have multiple levels of wildcards to make internal
service deployment easier. The "domain" PKI realm has the ACME support
explicitly disabled in case you are deploying the hosts on a private network
to which Let's Encrypt might not have access.
The 'debops.pki' is designed in such a way that the whole PKI realm is either
generated dynamically by the role via scripts, or all of its important details
like private keys, externally-signed X.509 certificates, etc. come from the
Ansible Controller. To recreate a PKI realm all you need to do is to remove it
from the remote host (rm -rf /etc/pki/realms/<realm>) and re-run the
'debops.pki' role - it should recreate a given realm automatically based on
its Ansible inventory configuration and contents of the 'secret/' directory.
* Does the realm-name just a name or does it have another meaning?
(Could the realm be named e.g. "xxxxaaaayyyy"?)
Originally the 'pki-realm' script supports different naming schemes for PKI
realms:
- the single string name, like "domain", "xxxxaaaayyyy" or whatever
you want.
These PKI realm names can be thought of as "handles" and they don't have
any
impact on the domains stored in the X.509 certificates. IIRC, the role will
by default use the host's FQDN and DNS domain name to generate such realms,
but you can override that. So, you could easily setup multiple "domain",
"domain2", "domainX" PKI realms that way, for testing or otherwise.
- the DNS-based name, which contains dots, like "example.com",
"host.example.com" and the like. These PKI realms base their X.509
certificates after the realm name by default. This is also the reason the
default PKI realm is named "domain" and not "{{ ansible_domain }}" -
you can
create a new PKI realm for your DNS domain on hosts that are reachable
publicly and they will automatically get the Let's Encrypt certificates when
possible, or will let you easily use external certificates grabbed from some
other CA.
Some DebOps roles like 'debops.nginx' can check the list of available PKI
realms via the local facts and use some other PKI realm rather than the
default one automatically. For example, if you create an "example.com" PKI
realm and then use the "example.com" DNS domain, standalone or with
a subdomain like "sub.example.com", the 'debops.nginx' will check if a
PKI
realm named after a given FQDN or DNS domain exist and will use it instead
of the "domain" PKI realm used by default. You can think of it as a shortcut
to easily manage X.509 certificates for multiple websites, each one with its
own FQDN domain name.
- the mail-based name, like "user(a)example.org" - any PKI realm name which
contains the '@' character qualifies as one. These PKI realms were meant to
host the client certificates used to authenticate to services, but this idea
was not developed further, so far.
o If this is different for ACME realms, this should be stated,
too.
PKI realms have a concept of multiple certificate authorities - there's one
set of private keys which can be signed by different CAs - internal CA,
external CA, ACME CA and self-signed when everything else is disabled. You can
have an "example.org" PKI realm which has certificates signed by both internal
CA and the Let's Encrypt CA (via ACME), and the 'pki-realm' script will
automatically switch between them after checking the validity of their X.509
certificates.
So, you can name your PKI realms that are meant to be used to hold ACME
certificates however you want, but naming them after a DNS domain name could
make things a bit easier, both when creating the certificate requests, and
when interfacing with other roles like 'debops.nginx'.
* Is is a good idea to name the realm just "host", and if
not, why?
You can name a PKI realm "host", without any further configuration it should
use the DNS domain of the host as a base of its X.509 certificate requests. If
you plan to set up an nginx webserver that uses this PKI realm, you will have
to point to it specifically via the 'item.pki_realm' parameter, because the
'debops.nginx' role will not detect it as a valid server name.
* The remaining questions might only be relevant if the realm-name
has
some meaning:
o How shall I name the realm when
o a) hosting a web-server with virtual domains from other apex
domains (
www.myngo.org,
www.mycorp.com),
I would go with:
pki_realms:
- name: 'myngo.org'
acme_subdomains: [ 'www' ]
- name: 'mycorp.com'
acme_subdomains: [ 'www' ]
Assuming that you want to rely on Let's Encrypt to get the certificates for
these domains. If you plan to get them elsewhere, for example from a different
public CA, I would go with:
pki_realms:
- name: 'myngo.org'
acme: False
- name: 'mycorp.com'
acme: False
And put the external private key and certificate files in the 'secret/'
directory (see the documentation about external certificates for details).
o b) hosting a nginx-server and e.g. a postfix-server for
different domains.
Here I assume that you mean the nginx server hosts a single service with
multiple separate DNS domains, with Postfix doing the same, which requires
that multiple domains are embedded in a single X.509 certificate. In that
case I would name the PKI realm with a single string, and point the respective
nginx server and Postfix to that particular PKI realm, for example:
pki_realms:
- name: 'multiple-certs'
subject: [ 'o=My Org', 'CN=myorg.com' ]
domains:
- 'myorg.org'
- 'myorg.net'
You could test the resulting X.509 certificates a few times to come up with
the best version, then send the generated certificate request to a CA (or
eanble ACME support).
* Best-practice for configuring realms if different servers (e.g.
nginx, postfix) server different domains, esp. how and in which
yml-file to define the pki realms.
I would name the PKI realms based on the DNS domains you use for these
services, optionally including additional subdomains like 'www' if you don't
use wildcard certificates. This again, assuming that you want either Let's
Encrypt certificates, or external certificates from some other CA. You can
define PKI realms in the inventory of a given host, for example
'ansible/inventory/host_vars/<hostname>/pki.yml', or put the common ones in
'ansible/inventory/group_vars/all/pki.yml'.
If this sounds like a "big" setup, IMHO it is not. For
example, on my
personal server I'm serving one of my web-sites, the web-sited for some
friends and not want to set up a prosody server for some club I'm a
member of.
Sure, the number of different services doesn't really matter here, all that
matters is how many DNS domains you want to use to point to these services. At
the end of the day services don't care what set of private key and X.509
certificate they use, usually it's only important that the service has access
to some kind of certs, otherwise TLS doesn't work at all, or a service refuses
to start.
>> * Changing the pki_system_realm has no effect on the
prosody
>> configuration. I assume since the debops.pki role is not used.
> First check if the /etc/ansible/facts.d/pki.fact has the correct realm you
> specified as the default one. Next, er-run the debops.prosody role, it should
> pick the new realm up from the local facts and modify the Prosody
> configuration.
What I did:
* run services/prosody
* found the wrong real is in the prosody config-file
* changed pki_system_realm the host
* run services/prosody again
Now since debops.prosody does not run debops.pki, pki.fact was not
updated. Thus the prosody config-file was still wrong. Worth a bug-report?
Did you change the 'pki_system_realm' in the inventory? You would have to
apply the 'debops.pki' role on the host before running the
'debops.prosody'
role, so that it updated its own local facts.
I dodn't want to create a precedent where 'debops.pki' is used as a
dependency
of another role in a playbook. It's used in the common playbook, and at least
in my case certificates are not changed all that often. Otherwise you would
have to add it as a dependency of 'debops.nginx', and this quickly snowballs
to all of the different applications that use debops.nginx as a dependency,
etc.
Cheers,
Maciej