diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 06ad6be..3dcf638 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -229,6 +229,7 @@ rpm-rockylinux-8-master-py3: {extends: '.test_instance'} # git-gentoo-stage3-systemd-3000-9-py3: {extends: '.test_instance'} # git-ubuntu-1804-3000-9-py2: {extends: '.test_instance'} # git-arch-base-latest-3000-9-py2: {extends: '.test_instance'} +domains-debian-10-3003-1-py3: {extends: '.test_instance'} ############################################################################### # `release` stage: `semantic-release` diff --git a/kitchen.yml b/kitchen.yml index 314a295..5156f81 100644 --- a/kitchen.yml +++ b/kitchen.yml @@ -526,3 +526,29 @@ suites: verifier: inspec_tests: - path: test/integration/rpm + - name: domains + includes: + - debian-10-3003-1-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 diff --git a/letsencrypt/defaults.yaml b/letsencrypt/defaults.yaml index a483736..6fe7e68 100644 --- a/letsencrypt/defaults.yaml +++ b/letsencrypt/defaults.yaml @@ -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 diff --git a/letsencrypt/domains.sls b/letsencrypt/domains.sls index 240b640..50c55e2 100644 --- a/letsencrypt/domains.sls +++ b/letsencrypt/domains.sls @@ -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('+') }}: @@ -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 %} diff --git a/pillar.example b/pillar.example index cd758e3..72460f9 100644 --- a/pillar.example +++ b/pillar.example @@ -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 @@ -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 diff --git a/test/integration/domains/README.md b/test/integration/domains/README.md new file mode 100644 index 0000000..ca35b92 --- /dev/null +++ b/test/integration/domains/README.md @@ -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). diff --git a/test/integration/domains/controls/domains_spec.rb b/test/integration/domains/controls/domains_spec.rb new file mode 100644 index 0000000..9ce18e1 --- /dev/null +++ b/test/integration/domains/controls/domains_spec.rb @@ -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 diff --git a/test/integration/domains/inspec.yml b/test/integration/domains/inspec.yml new file mode 100644 index 0000000..f566fab --- /dev/null +++ b/test/integration/domains/inspec.yml @@ -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 diff --git a/test/salt/pillar/domains.sls b/test/salt/pillar/domains.sls new file mode 100644 index 0000000..a7111ca --- /dev/null +++ b/test/salt/pillar/domains.sls @@ -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 diff --git a/test/salt/states/install_letsencrypt_test_server.sls b/test/salt/states/install_letsencrypt_test_server.sls new file mode 100644 index 0000000..02737fc --- /dev/null +++ b/test/salt/states/install_letsencrypt_test_server.sls @@ -0,0 +1,190 @@ +# This state is used to prepare environment for formula testing +# To KISS, testing only on Debian + +# Download the LE test server (pebble) and configure it + +# Download pebble binary +test-salt-states-install-letsencrypt-test-server-pebble-file-managed: + file.managed: + - name: /usr/local/bin/pebble + - source: https://github.com/letsencrypt/pebble/releases/download/v2.3.1/pebble_linux-amd64 + - source_hash: sha256=60a401159d5132411c88e93ff03ba3322d4ecc7fdba78503da552018f3f98230 + - mode: 755 + +# Write pebble config based on +# https://github.com/letsencrypt/pebble/blob/master/test/config/pebble-config.json +test-salt-states-install-letsencrypt-test-server-pebble-config-file-managed: + file.managed: + - name: /usr/local/etc/pebble-config.json + - contents: | + { + "pebble": { + "listenAddress": "0.0.0.0:14000", + "managementListenAddress": "0.0.0.0:15000", + "certificate": "/etc/ssl/certs/pebble-cert.pem", + "privateKey": "/etc/ssl/private/pebble-key.pem", + "httpPort": 5002, + "tlsPort": 5001, + "ocspResponderURL": "", + "externalAccountBindingRequired": false + } + } + - mode: 644 + - require: + - file: test-salt-states-install-letsencrypt-test-server-pebble-file-managed + +test-salt-states-install-letsencrypt-test-server-dependencies-pkg-installed: + pkg.installed: + - pkgs: + - cron + - openssl + - ca-certificates + +# Download certs files required for pebble to work (unless we want to generate them) +# https://github.com/letsencrypt/pebble/blob/master/test/certs/pebble.minica.pem +test-salt-states-install-letsencrypt-test-server-pebble-minica-crt-file-managed: + file.managed: + - name: /usr/local/share/ca-certificates/pebble-minica-cert.crt + - contents: | + -----BEGIN CERTIFICATE----- + MIIDCTCCAfGgAwIBAgIIJOLbes8sTr4wDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE + AxMVbWluaWNhIHJvb3QgY2EgMjRlMmRiMCAXDTE3MTIwNjE5NDIxMFoYDzIxMTcx + MjA2MTk0MjEwWjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSAyNGUyZGIwggEi + MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5WgZNoVJandj43kkLyU50vzCZ + alozvdRo3OFiKoDtmqKPNWRNO2hC9AUNxTDJco51Yc42u/WV3fPbbhSznTiOOVtn + Ajm6iq4I5nZYltGGZetGDOQWr78y2gWY+SG078MuOO2hyDIiKtVc3xiXYA+8Hluu + 9F8KbqSS1h55yxZ9b87eKR+B0zu2ahzBCIHKmKWgc6N13l7aDxxY3D6uq8gtJRU0 + toumyLbdzGcupVvjbjDP11nl07RESDWBLG1/g3ktJvqIa4BWgU2HMh4rND6y8OD3 + Hy3H8MY6CElL+MOCbFJjWqhtOxeFyZZV9q3kYnk9CAuQJKMEGuN4GU6tzhW1AgMB + AAGjRTBDMA4GA1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB + BQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQsFAAOCAQEAF85v + d40HK1ouDAtWeO1PbnWfGEmC5Xa478s9ddOd9Clvp2McYzNlAFfM7kdcj6xeiNhF + WPIfaGAi/QdURSL/6C1KsVDqlFBlTs9zYfh2g0UXGvJtj1maeih7zxFLvet+fqll + xseM4P9EVJaQxwuK/F78YBt0tCNfivC6JNZMgxKF59h0FBpH70ytUSHXdz7FKwix + Mfn3qEb9BXSk0Q3prNV5sOV3vgjEtB4THfDxSz9z3+DepVnW3vbbqwEbkXdk3j82 + 2muVldgOUgTwK8eT+XdofVdntzU/kzygSAtAQwLJfn51fS1GvEcYGBc1bDryIqmF + p9BI7gVKtWSZYegicA== + -----END CERTIFICATE----- + - require: + - pkg: test-salt-states-install-letsencrypt-test-server-dependencies-pkg-installed + +#test-salt-states-install-letsencrypt-test-server-pebble-minica-key-file-managed: +# file.managed: + +test-salt-states-install-letsencrypt-test-server-pebble-update-ca-certs-cmd-run: + cmd.run: + - name: /usr/sbin/update-ca-certificates + - require: + - file: test-salt-states-install-letsencrypt-test-server-pebble-minica-crt-file-managed + - unless: + - test -f /etc/ssl/certs/pebble-minica-cert.pem + - require_in: + - service: test-salt-states-install-letsencrypt-test-server-pebble-service-running + +test-salt-states-install-letsencrypt-test-server-pebble-ca-crt-file-managed: + file.managed: + - name: /etc/ssl/certs/pebble-cert.pem + - contents: | + -----BEGIN CERTIFICATE----- + MIIDGzCCAgOgAwIBAgIIbEfayDFsBtwwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE + AxMVbWluaWNhIHJvb3QgY2EgMjRlMmRiMCAXDTE3MTIwNjE5NDIxMFoYDzIxMDcx + MjA2MTk0MjEwWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB + AQUAA4IBDwAwggEKAoIBAQCbFMW3DXXdErvQf2lCZ0qz0DGEWadDoF0O2neM5mVa + VQ7QGW0xc5Qwvn3Tl62C0JtwLpF0pG2BICIN+DHdVaIUwkf77iBS2doH1I3waE1I + 8GkV9JrYmFY+j0dA1SwBmqUZNXhLNwZGq1a91nFSI59DZNy/JciqxoPX2K++ojU2 + FPpuXe2t51NmXMsszpa+TDqF/IeskA9A/ws6UIh4Mzhghx7oay2/qqj2IIPjAmJj + i73kdUvtEry3wmlkBvtVH50+FscS9WmPC5h3lDTk5nbzSAXKuFusotuqy3XTgY5B + PiRAwkZbEY43JNfqenQPHo7mNTt29i+NVVrBsnAa5ovrAgMBAAGjYzBhMA4GA1Ud + DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0T + AQH/BAIwADAiBgNVHREEGzAZgglsb2NhbGhvc3SCBnBlYmJsZYcEfwAAATANBgkq + hkiG9w0BAQsFAAOCAQEAYIkXff8H28KS0KyLHtbbSOGU4sujHHVwiVXSATACsNAE + D0Qa8hdtTQ6AUqA6/n8/u1tk0O4rPE/cTpsM3IJFX9S3rZMRsguBP7BSr1Lq/XAB + 7JP/CNHt+Z9aKCKcg11wIX9/B9F7pyKM3TdKgOpqXGV6TMuLjg5PlYWI/07lVGFW + /mSJDRs8bSCFmbRtEqc4lpwlrpz+kTTnX6G7JDLfLWYw/xXVqwFfdengcDTHCc8K + wtgGq/Gu6vcoBxIO3jaca+OIkMfxxXmGrcNdseuUCa3RMZ8Qy03DqGu6Y6XQyK4B + W8zIG6H9SVKkAznM2yfYhW8v2ktcaZ95/OBHY97ZIw== + -----END CERTIFICATE----- + +test-salt-states-install-letsencrypt-test-server-pebble-ca-key-file-managed: + file.managed: + - name: /etc/ssl/private/pebble-key.pem + - contents: | + -----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEAmxTFtw113RK70H9pQmdKs9AxhFmnQ6BdDtp3jOZlWlUO0Blt + MXOUML5905etgtCbcC6RdKRtgSAiDfgx3VWiFMJH++4gUtnaB9SN8GhNSPBpFfSa + 2JhWPo9HQNUsAZqlGTV4SzcGRqtWvdZxUiOfQ2TcvyXIqsaD19ivvqI1NhT6bl3t + redTZlzLLM6Wvkw6hfyHrJAPQP8LOlCIeDM4YIce6Gstv6qo9iCD4wJiY4u95HVL + 7RK8t8JpZAb7VR+dPhbHEvVpjwuYd5Q05OZ280gFyrhbrKLbqst104GOQT4kQMJG + WxGONyTX6np0Dx6O5jU7dvYvjVVawbJwGuaL6wIDAQABAoIBAGW9W/S6lO+DIcoo + PHL+9sg+tq2gb5ZzN3nOI45BfI6lrMEjXTqLG9ZasovFP2TJ3J/dPTnrwZdr8Et/ + 357YViwORVFnKLeSCnMGpFPq6YEHj7mCrq+YSURjlRhYgbVPsi52oMOfhrOIJrEG + ZXPAwPRi0Ftqu1omQEqz8qA7JHOkjB2p0i2Xc/uOSJccCmUDMlksRYz8zFe8wHuD + XvUL2k23n2pBZ6wiez6Xjr0wUQ4ESI02x7PmYgA3aqF2Q6ECDwHhjVeQmAuypMF6 + IaTjIJkWdZCW96pPaK1t+5nTNZ+Mg7tpJ/PRE4BkJvqcfHEOOl6wAE8gSk5uVApY + ZRKGmGkCgYEAzF9iRXYo7A/UphL11bR0gqxB6qnQl54iLhqS/E6CVNcmwJ2d9pF8 + 5HTfSo1/lOXT3hGV8gizN2S5RmWBrc9HBZ+dNrVo7FYeeBiHu+opbX1X/C1HC0m1 + wJNsyoXeqD1OFc1WbDpHz5iv4IOXzYdOdKiYEcTv5JkqE7jomqBLQk8CgYEAwkG/ + rnwr4ThUo/DG5oH+l0LVnHkrJY+BUSI33g3eQ3eM0MSbfJXGT7snh5puJW0oXP7Z + Gw88nK3Vnz2nTPesiwtO2OkUVgrIgWryIvKHaqrYnapZHuM+io30jbZOVaVTMR9c + X/7/d5/evwXuP7p2DIdZKQKKFgROm1XnhNqVgaUCgYBD/ogHbCR5RVsOVciMbRlG + UGEt3YmUp/vfMuAsKUKbT2mJM+dWHVlb+LZBa4pC06QFgfxNJi/aAhzSGvtmBEww + xsXbaceauZwxgJfIIUPfNZCMSdQVIVTi2Smcx6UofBz6i/Jw14MEwlvhamaa7qVf + kqflYYwelga1wRNCPopLaQKBgQCWsZqZKQqBNMm0Q9yIhN+TR+2d7QFjqeePoRPl + 1qxNejhq25ojE607vNv1ff9kWUGuoqSZMUC76r6FQba/JoNbefI4otd7x/GzM9uS + 8MHMJazU4okwROkHYwgLxxkNp6rZuJJYheB4VDTfyyH/ng5lubmY7rdgTQcNyZ5I + majRYQKBgAMKJ3RlII0qvAfNFZr4Y2bNIq+60Z+Qu2W5xokIHCFNly3W1XDDKGFe + CCPHSvQljinke3P9gPt2HVdXxcnku9VkTti+JygxuLkVg7E0/SWwrWfGsaMJs+84 + fK+mTZay2d3v24r9WKEKwLykngYPyZw5+BdWU0E+xx5lGUd3U4gG + -----END RSA PRIVATE KEY----- + +test-salt-states-install-letsencrypt-test-server-pebble-env-vars-service-file-managed: + file.managed: + - name: /etc/default/pebble + - contents: | + PEBBLE_VA_NOSLEEP=1 + PEBBLE_VA_ALWAYS_VALID=1 + +test-salt-states-install-letsencrypt-test-server-pebble-systemd-service-file-managed: + file.managed: + - name: /etc/systemd/system/pebble.service + - contents: | + [Unit] + Description=Pebble Service + + [Service] + ExecStart=/usr/local/bin/pebble -config /usr/local/etc/pebble-config.json + User=root + Group=root + StandardInput=null + StandardOutput=append:/var/log/pebble.log + StandardError=append:/var/log/pebble.log + EnvironmentFile=-/etc/default/pebble + - require: + - file: test-salt-states-install-letsencrypt-test-server-pebble-config-file-managed + - file: test-salt-states-install-letsencrypt-test-server-pebble-env-vars-service-file-managed + +test-salt-states-install-letsencrypt-test-server-systemd-service-cmd-wait: + cmd.wait: + - name: systemctl daemon-reload + - runas: root + - watch: + - file: test-salt-states-install-letsencrypt-test-server-pebble-systemd-service-file-managed + - require_in: + - service: test-salt-states-install-letsencrypt-test-server-pebble-service-running + +test-salt-states-install-letsencrypt-test-server-pebble-service-running: + service.running: + - name: pebble + +# test-salt-states-install-letsencrypt-test-server-pebble-service-running: +# cmd.run: +# - env: +# - PEBBLE_VA_NOSLEEP: 1 +# - PEBBLE_VA_ALWAYS_VALID: 1 +# - bg: true +# - name: /usr/local/bin/pebble -config /usr/local/etc/pebble-config.json +# - require: +# - file: test-salt-states-install-letsencrypt-test-server-pebble-config-file-managed +# - file: test-salt-states-install-letsencrypt-test-server-pebble-minica-crt-file-managed +# - file: test-salt-states-install-letsencrypt-test-server-pebble-ca-crt-file-managed +# - file: test-salt-states-install-letsencrypt-test-server-pebble-ca-key-file-managed