Skip to content

Commit 9f60703

Browse files
Merge pull request #85 from XeryusTC/feature/179582_certbot_via_pip_installeren
Install certbot through pip
2 parents cfe5c5c + d3f7833 commit 9f60703

File tree

17 files changed

+222
-31
lines changed

17 files changed

+222
-31
lines changed

docs/README.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,17 @@ Available states
5555

5656
This is a shortcut for letsencrypt.install letsencrypt.config and letsencrypt.domains.
5757

58-
If `use_package` is `True` (the default), the formula will try to install the *certbot* package from your Distro's repo.
58+
if `install_method` is `package` (the default), the formula will try to install the *certbot* package from your Distro's repo.
5959
Keep in mind that most distros don't have a package available by default: Ie, previous stable Debian (Stretch) requires a backports repo installed.
6060
Centos 7 requires EPEL, etc. This formula **DOES NOT** manage these repositories. Use the `apt-formula <https://github.com/saltstack-formulas/apt-formula>`_
6161
or the `epel-formula <https://github.com/saltstack-formulas/epel-formula>`_ to manage them.
6262

63-
If `use_package` is `False` it installs and configures the letsencrypt cli from git, creates the requested certificates and installs renewal cron job.
63+
If `install_method` is `git` it installs and configures the letsencrypt cli from git, creates the requested certificates and installs renewal cron job.
64+
65+
If `install_method` is `pip` it installs and configures the letsencrypt cli from pip, creates the requested certificates and installs renewwal cron job. Allows plugin installation with `pip_pkgs`.
6466

6567
** WARNING **
66-
If you set `use_package` to `True`, it will:
68+
If you set `install_method` to `package`, it will:
6769

6870
* Delete all certbot's crons if they exist from a previous git-based installation (as the package uses a
6971
systemd's timer unit to renew all the certs)

kitchen.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,24 @@ suites:
390390
verifier:
391391
inspec_tests:
392392
- path: test/integration/git
393+
- name: pip
394+
provisioner:
395+
state_top:
396+
base:
397+
'*':
398+
- letsencrypt._mapdata
399+
- letsencrypt.install
400+
- letsencrypt.config
401+
pillars:
402+
top.sls:
403+
base:
404+
'*':
405+
- letsencrypt
406+
pillars_from_files:
407+
letsencrypt.sls: test/salt/pillar/pip.sls
408+
verifier:
409+
inspec_tests:
410+
- path: test/integration/pip
393411
- name: deb
394412
includes:
395413
- debian-11-tiamat-py3

letsencrypt/defaults.yaml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,30 @@
22
# vim: ft=yaml
33
---
44
letsencrypt:
5-
use_package: true
5+
install_method: package
66
pkgs: []
77
git_pkg: git
88
service: certbot.timer
9-
# Only used for the pkg install method (use_package: true), internal var
9+
# Only used for the pkg install method (install_method = package), internal var
1010
_cli_path: /usr/bin/certbot
11-
# Only used for the pkg install method (use_package: true), internal var
11+
# Only used for the pkg install method (install_method = package), internal var
1212
_default_pkg: certbot
13-
# Only used for the git install method (use_package: false)
13+
# Only used for the git or pip install methods (install_method = (git|pip))
1414
cli_install_dir: /opt/letsencrypt
15-
# Only used for the git install method (use_package: false). If you want to
16-
# have specific version of certbot you can enable it. The version value
17-
# should match a certbot/certbot branch
18-
# version: 0.30.x
15+
# Only used for the git or pip install methods (install_method = (git|pip)).
16+
# If you want to have specific version of certbot you can enable it. The
17+
# version value should match a certbot/certbot branch version: 0.30.x
1918
config_dir:
2019
path: /etc/letsencrypt
2120
user: root
2221
group: root
2322
mode: 755
23+
# Only used for the pip install method (install_method = pip). Can be used to
24+
# install plugins for certbot.
25+
pip_pkgs: []
26+
# Only used for the pip install method (install_method = pip), internal var
27+
virtualenv_pkg:
28+
- python3-virtualenv
2429
config:
2530
server: https://acme-v02.api.letsencrypt.org/directory
2631
agree-tos: true

letsencrypt/domains.sls

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
{% from "letsencrypt/map.jinja" import letsencrypt with context %}
55
6-
{% if letsencrypt.use_package %}
6+
{% if letsencrypt.install_method == 'package' %}
77
{% set check_cert_cmd = letsencrypt._cli_path ~ ' certificates --cert-name' %}
88
{% set renew_cert_cmd = letsencrypt._cli_path ~ ' renew' %}
99
{% set create_cert_cmd = letsencrypt._cli_path %}
@@ -15,7 +15,11 @@
1515
{% else %}
1616
{% set check_cert_cmd = '/usr/local/bin/check_letsencrypt_cert.sh' %}
1717
{% set renew_cert_cmd = '/usr/local/bin/renew_letsencrypt_cert.sh' %}
18-
{% set create_cert_cmd = letsencrypt.cli_install_dir ~ '/letsencrypt-auto' %}
18+
{% if letsencrypt.install_method == 'pip' %}
19+
{% set create_cert_cmd = letsencrypt.cli_install_dir ~ '/bin/certbot' %}
20+
{% else %}
21+
{% set create_cert_cmd = letsencrypt.cli_install_dir ~ '/letsencrypt-auto' %}
22+
{% endif %}
1923
2024
{% set old_check_cert_cmd_state = 'managed' %}
2125
{% set old_renew_cert_cmd_state = 'managed' %}
@@ -63,11 +67,11 @@ create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}:
6367
{{ installer }} \
6468
--cert-name {{ setname }} \
6569
-d {{ domainlist|join(' -d ') }}
66-
{% if not letsencrypt.use_package %}
70+
{% if letsencrypt.install_method != 'package' %}
6771
- cwd: {{ letsencrypt.cli_install_dir }}
6872
{% endif %}
6973
- unless:
70-
{% if letsencrypt.use_package %}
74+
{% if letsencrypt.install_method == 'package' %}
7175
- fun: cmd.run
7276
python_shell: true
7377
cmd: |
@@ -78,7 +82,7 @@ create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}:
7882
- {{ check_cert_cmd }} {{ setname }} {{ domainlist | join(' ') }}
7983
{% endif %}
8084
- require:
81-
{% if letsencrypt.use_package %}
85+
{% if letsencrypt.install_method == 'package' %}
8286
- pkg: letsencrypt-client
8387
{% else %}
8488
- file: {{ check_cert_cmd }}
@@ -95,7 +99,7 @@ letsencrypt-crontab-{{ setname }}-{{ domainlist[0] }}:
9599
- identifier: letsencrypt-{{ setname }}-{{ domainlist[0] }}
96100
- require:
97101
- cmd: create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}
98-
{% if letsencrypt.use_package %}
102+
{% if letsencrypt.install_method == 'package' %}
99103
- pkg: letsencrypt-client
100104
{% else %}
101105
- file: {{ renew_cert_cmd }}

letsencrypt/files/renew_letsencrypt_cert.sh.jinja

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
{% from "letsencrypt/map.jinja" import letsencrypt with context %}
33
COMMON_NAME="$1"
44

5+
{% if letsencrypt.install_method == 'pip' %}
6+
{{ letsencrypt.cli_install_dir }}/bin/certbot renew --non-interactive || exit 1
7+
{% else %}
58
{{ letsencrypt.cli_install_dir }}/letsencrypt-auto renew --non-interactive || exit 1
9+
{% endif %}
610
cat {{ letsencrypt.config_dir.path }}/live/${COMMON_NAME}/fullchain.pem \
711
{{ letsencrypt.config_dir.path }}/live/${COMMON_NAME}/privkey.pem \
812
> {{ letsencrypt.config_dir.path }}/live/${COMMON_NAME}/fullchain-privkey.pem || exit 1

letsencrypt/install.sls

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{%- from "letsencrypt/map.jinja" import letsencrypt with context %}
44
55
{#- Use empty default for `grains.osfinger`, which isn't available in all distros #}
6-
{%- if letsencrypt.use_package and
6+
{%- if letsencrypt.install_method == 'package' and
77
grains.osfinger|d('') == 'Amazon Linux-2' %}
88
{%- set rhel_ver = '7' %}
99
letsencrypt_external_repo:
@@ -20,11 +20,11 @@ letsencrypt_external_repo:
2020
{%- endif %}
2121
2222
letsencrypt-client:
23-
{%- if letsencrypt.use_package %}
23+
{%- if letsencrypt.install_method == 'package' %}
2424
{%- set pkgs = letsencrypt.pkgs or [letsencrypt._default_pkg] %}
2525
pkg.installed:
2626
- pkgs: {{ pkgs | json }}
27-
{%- else %}
27+
{%- elif letsencrypt.install_method == 'git' %}
2828
pkg.installed:
2929
- name: {{ letsencrypt.git_pkg }}
3030
{%- if letsencrypt.version is defined and letsencrypt.version|length %}
@@ -38,5 +38,20 @@ letsencrypt-client:
3838
- target: {{ letsencrypt.cli_install_dir }}
3939
- force_reset: True
4040
{%- endif %}
41+
{%- elif letsencrypt.install_method == 'pip' %}
42+
pkg.installed:
43+
- pkgs: {{ letsencrypt.virtualenv_pkg | json }}
44+
virtualenv.managed:
45+
- name: {{ letsencrypt.cli_install_dir }}
46+
- python: python3
47+
- pip_pkgs:
48+
{%- if letsencrypt.version is defined and letsencrypt.version|length %}
49+
- certbot=={{ letsencrypt.version }}
50+
{%- else %}
51+
- certbot
52+
{%- endif %}
53+
{%- for pkg in letsencrypt.pip_pkgs %}
54+
- {{ pkg }}
55+
{%- endfor %}
4156
{%- endif %}
4257
- reload_modules: True

letsencrypt/map.jinja

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,12 @@
2424
),
2525
base='letsencrypt')
2626
%}
27+
28+
{# Make backwards compatible with use_package #}
29+
{% if letsencrypt.use_package is defined %}
30+
{% if letsencrypt.use_package %}
31+
{{ letsencrypt | set_dict_key_value('install_method', 'package') }}
32+
{% else %}
33+
{{ letsencrypt | set_dict_key_value('install_method', 'git') }}
34+
{% endif %}
35+
{% endif %}

letsencrypt/osfamilymap.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@
44
RedHat:
55
service: certbot-renew.timer
66
FreeBSD:
7-
# Only used for the pkg install method (use_package: true), internal var
7+
# Only used for the pkg install method (install_method: package), internal var
88
_cli_path: /usr/local/bin/certbot
99
Gentoo:
1010
git_pkg: dev-vcs/git
11+
virtualenv_pkg:
12+
- dev-python/virtualenv
13+
Debian:
14+
virtualenv_pkg:
15+
- virtualenv
16+
Arch:
17+
virtualenv_pkg:
18+
- python-virtualenv

letsencrypt/service.sls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
{% from "letsencrypt/map.jinja" import letsencrypt with context %}
55
6-
{% if letsencrypt.use_package %}
6+
{% if letsencrypt.install_method == 'package' %}
77
letsencrypt-service-timer:
88
service.running:
99
- name: {{ letsencrypt.service }}

pillar.example

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# vim: ft=yaml
33
---
44
letsencrypt:
5-
# Install using packages instead of git
6-
use_package: true
5+
# Install using package, git or pip
6+
install_method: package
77
# A list of package/s to install. To find the correct name for the variant
88
# you want to use, check https://certbot.eff.org/all-instructions
99
# Usually, you'll need a single one, but you can also add other plugins here.
@@ -13,12 +13,17 @@ letsencrypt:
1313
- python3-certbot-apache
1414
# - python3-certbot-nginx
1515
# - python3-dns-route53
16-
# Only used for the git install method (use_package: false)
16+
# Only used for the git or pip install methods (install_method = (git|pip))
1717
cli_install_dir: /opt/letsencrypt
18-
# Only used for the git install method (use_package: false). If you want to
19-
# have specific version of certbot you can enable it. The version value
20-
# should match a certbot/certbot branch.
18+
# Only used for the git or pip install methods (install_method = git|pip)).
19+
# If you want to have specific version of certbot you can enable it. The
20+
# version value should match a certbot/certbot branch.
2121
version: 0.30.x
22+
# Only used for the pip install method (install_method = pip). Can be used to
23+
# install plugins for certbot. Default: []
24+
pip_pkgs:
25+
- certbot-dns-azure
26+
- certbot-dns-powerdns
2227
# Subcommand used for certificates' first generation cmd ( run | certonly | renew )
2328
create_init_cert_subcmd: certonly
2429
# Any parameter from the cli can be specified in the config file

test/integration/pip/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# InSpec Profile: `git`
2+
3+
This shows the implementation of the `pip` InSpec [profile](https://github.com/inspec/inspec/blob/master/docs/profiles.md).
4+
5+
## Verify a profile
6+
7+
InSpec ships with built-in features to verify a profile structure.
8+
9+
```bash
10+
$ inspec check git
11+
Summary
12+
-------
13+
Location: git
14+
Profile: profile
15+
Controls: 4
16+
Timestamp: 2019-06-24T23:09:01+00:00
17+
Valid: true
18+
19+
Errors
20+
------
21+
22+
Warnings
23+
--------
24+
```
25+
26+
## Execute a profile
27+
28+
To run all **supported** controls on a local machine use `inspec exec /path/to/profile`.
29+
30+
```bash
31+
$ inspec exec git
32+
..
33+
34+
Finished in 0.0025 seconds (files took 0.12449 seconds to load)
35+
8 examples, 0 failures
36+
```
37+
38+
## Execute a specific control from a profile
39+
40+
To run one control from the profile use `inspec exec /path/to/profile --controls name`.
41+
42+
```bash
43+
$ inspec exec git --controls package
44+
.
45+
46+
Finished in 0.0025 seconds (files took 0.12449 seconds to load)
47+
1 examples, 0 failures
48+
```
49+
50+
See an [example control here](https://github.com/inspec/inspec/blob/master/examples/profile/controls/example.rb).
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
describe file('/opt/letsencrypt') do
4+
it { should be_directory }
5+
it { should be_owned_by 'root' }
6+
it { should be_grouped_into 'root' }
7+
it { should be_readable }
8+
its('size') { should be > 25 }
9+
end
10+
11+
describe file('/etc/letsencrypt/cli.ini') do
12+
it { should be_file }
13+
it { should be_owned_by 'root' }
14+
it { should be_grouped_into 'root' }
15+
it { should be_readable }
16+
its('size') { should be > 1 }
17+
its('content') do
18+
should match 'server = https://acme-staging.api.letsencrypt.org/directory'
19+
end
20+
its('content') { should match 'authenticator = standalone' }
21+
its('content') { should match 'File managed by Salt' }
22+
end
23+
24+
describe command('/opt/letsencrypt/bin/certbot plugins') do
25+
its('stdout') { should match(/dns-powerdns/) }
26+
end

test/integration/pip/inspec.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# -*- coding: utf-8 -*-
2+
# vim: ft=yaml
3+
---
4+
name: pip
5+
title: letsencrypt formula
6+
maintainer: SaltStack Formulas
7+
license: Apache-2.0
8+
# yamllint disable-line rule:line-length
9+
summary: Verify that the letsencrypt formula is setup and configured correctly using `pip`
10+
depends:
11+
- name: share
12+
path: test/integration/share
13+
supports:
14+
- platform-name: debian
15+
- platform-name: ubuntu
16+
- platform-name: centos
17+
- platform-name: fedora
18+
- platform-name: opensuse
19+
- platform-name: suse
20+
- platform-name: freebsd
21+
- platform-name: openbsd
22+
- platform-name: amazon
23+
- platform-name: oracle
24+
- platform-name: arch
25+
- platform-name: gentoo
26+
- platform-name: almalinux
27+
- platform-name: rocky
28+
- platform: windows

test/salt/pillar/deb.sls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# vim: ft=yaml
33
---
44
letsencrypt:
5-
use_package: true
5+
install_method: package
66
config: |
77
server = https://acme-staging.api.letsencrypt.org/directory
88

test/salt/pillar/git.sls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# vim: ft=yaml
33
---
44
letsencrypt:
5-
use_package: false
5+
install_method: git
66
version: 0.26.x
77
config: |
88
server = https://acme-staging.api.letsencrypt.org/directory

0 commit comments

Comments
 (0)