Skip to content

Commit

Permalink
feat(domains): allow to specify different authenticators/installers
Browse files Browse the repository at this point in the history
Allow to specify different authenticators or installers for each domainset.

Also, added a `pebble` ACME CA to test that the domainsets can be obtained
and installed correctly.

Added tests to verify the certificates are installed.
  • Loading branch information
javierbertoli committed Jul 2, 2021
1 parent 75b7466 commit 87456a1
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 0 deletions.
26 changes: 26 additions & 0 deletions kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -526,3 +526,29 @@ suites:
verifier:
inspec_tests:
- path: test/integration/rpm
- name: domains
includes:
- debian-10-3003-0-py3
provisioner:
dependencies:
- name: apt
repo: git
source: https://github.com/saltstack-formulas/apt-formula.git
- name: states
path: ./test/salt
state_top:
base:
'*':
- letsencrypt._mapdata
- states.install_letsencrypt_test_server
- letsencrypt
pillars:
top.sls:
base:
'*':
- letsencrypt
pillars_from_files:
letsencrypt.sls: test/salt/pillar/domains.sls
verifier:
inspec_tests:
- path: test/integration/domains
2 changes: 2 additions & 0 deletions letsencrypt/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ letsencrypt:
keep-until-expiring: true
expand: true
max-log-backups: 0
authenticators: {}
installers: {}
# The post_renew cmds are executed via renew_letsencrypt_cert.sh after every
# run. For more fine grain control, consider placing scripts in the pre,
# post, and/or deploy directories within /etc/letsencrypt/renewal-hooks/. For
Expand Down
14 changes: 14 additions & 0 deletions letsencrypt/domains.sls
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,20 @@
{% endif %}
{%- set default_authenticator = '--authenticator ' ~ letsencrypt.authenticators['default']
if letsencrypt.authenticators['default'] is defined else '' %}
{%- set default_installer = '--installer ' ~ letsencrypt.installers['default']
if letsencrypt.installers['default'] is defined else '' %}
{% for setname, domainlist in letsencrypt.domainsets.items() %}
# Set an authenticator and a installer for the domainset or use defaults set above
{%- set authenticator = '--authenticator ' ~ letsencrypt.authenticators[setname]
if letsencrypt.authenticators[setname] is defined else default_authenticator %}
{%- set installer = '--installer ' ~ letsencrypt.installers[setname]
if letsencrypt.installers[setname] is defined else default_installer %}
# domainlist[0] represents the "CommonName", and the rest
# represent SubjectAlternativeNames
create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}:
Expand All @@ -47,6 +59,8 @@ create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}:
{{ create_cert_cmd }} {{ letsencrypt.create_init_cert_subcmd }} \
--quiet \
--non-interactive \
{{ authenticator }} \
{{ installer }} \
--cert-name {{ setname }} \
-d {{ domainlist|join(' -d ') }}
{% if not letsencrypt.use_package %}
Expand Down
21 changes: 21 additions & 0 deletions pillar.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ letsencrypt:
config:
server: https://acme-v02.api.letsencrypt.org/directory
email: webmaster@example.com
# Don't add an authenticator here if you need (or expect) to mix authentication
# methods.
# In such case, use authenticators below
authenticator: webroot
webroot-path: /var/lib/www
agree-tos: true
Expand All @@ -47,6 +50,24 @@ letsencrypt:
user: root
group: root
mode: 755
# If you need to manage certificates for a few domainsets on the same node, but
# the authentication for each of these vary, you need to specify
# an authenticator for each of the domainsets instead of setting it in cli.ini
# Set them in this parameter. You can use the reserved name `default` to set
# the authenticator that will be used in case no other is specified for a
# particular domainset.
# Default: authenticators: {}

authenticators:
default: nginx
mail: route53
# As with `authenticators` above, you can specify different install methods for
# your different certificates. The installer set as `default` will be used to
# all the domainsets with no particular installer
# Default: installers: {}
installers:
default: nginx

domainsets:
www:
- example.com
Expand Down
50 changes: 50 additions & 0 deletions test/integration/domains/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# InSpec Profile: `domains`

This shows the implementation of the `domains` InSpec [profile](https://github.com/inspec/inspec/blob/master/docs/profiles.md).

## Verify a profile

InSpec ships with built-in features to verify a profile structure.

```bash
$ inspec check domains
Summary
-------
Location: domains
Profile: profile
Controls: 4
Timestamp: 2019-06-24T23:09:01+00:00
Valid: true

Errors
------

Warnings
--------
```

## Execute a profile

To run all **supported** controls on a local machine use `inspec exec /path/to/profile`.

```bash
$ inspec exec domains
..

Finished in 0.0025 seconds (files took 0.12449 seconds to load)
8 examples, 0 failures
```

## Execute a specific control from a profile

To run one control from the profile use `inspec exec /path/to/profile --controls name`.

```bash
$ inspec exec domains --controls package
.

Finished in 0.0025 seconds (files took 0.12449 seconds to load)
1 examples, 0 failures
```

See an [example control here](https://github.com/inspec/inspec/blob/master/examples/profile/controls/example.rb).
27 changes: 27 additions & 0 deletions test/integration/domains/controls/domains_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

%w[
cert
chain
fullchain
privkey
].each do |f|
describe file("/etc/letsencrypt/archive/www/#{f}1.pem") do
it { should be_file }
it { should be_owned_by 'root' }
it { should be_grouped_into 'root' }
it { should be_readable }
its('size') { should be > 1 }
end

describe file("/etc/letsencrypt/live/www/#{f}.pem") do
it { should be_symlink }
end
end
describe file('/etc/letsencrypt/live/www/fullchain-privkey.pem') do
it { should be_file }
it { should be_owned_by 'root' }
it { should be_grouped_into 'root' }
it { should be_readable }
its('size') { should be > 1 }
end
14 changes: 14 additions & 0 deletions test/integration/domains/inspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# vim: ft=yaml
---
name: domains
title: letsencrypt formula
maintainer: SaltStack Formulas
license: Apache-2.0
summary: Verify that certificates can be requested/issued correctly
depends:
- name: share
path: test/integration/share
supports:
- platform-name: debian
- platform-name: ubuntu
16 changes: 16 additions & 0 deletions test/salt/pillar/domains.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# vim: ft=yaml
---
## Pebble does not work correctly with certbot < 0.30,
## so don't test it with stretch-backports
letsencrypt:
config:
server: https://localhost:14000/dir
agree-tos: true
renew-by-default: true
email: saltstack-letsencrypt-formula@example.com
authenticators:
default: standalone
domainsets:
www:
- letsencrypt-formula.example.com
Loading

0 comments on commit 87456a1

Please sign in to comment.