Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for CentOS 7 and 8 #79

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,18 @@ 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'}
pip-debian-10-tiamat-py3: {extends: '.test_instance'}
pip-ubuntu-2004-tiamat-py3: {extends: '.test_instance'}
pip-debian-11-master-py3: {extends: '.test_instance'}
pip-debian-10-master-py3: {extends: '.test_instance'}
pip-debian-9-master-py3: {extends: '.test_instance'}
pip-ubuntu-2004-master-py3: {extends: '.test_instance'}
pip-centos-8-master-py3: {extends: '.test_instance'}
pip-opensuse-leap-153-master-py3: {extends: '.test_instance'}
pip-opensuse-leap-152-master-py3: {extends: '.test_instance'}
pip-arch-base-latest-master-py3: {extends: '.test_instance'}
pip-gentoo-stage3-latest-master-py3: {extends: '.test_instance'}
pip-gentoo-stage3-systemd-master-py3: {extends: '.test_instance'}

###############################################################################
# `release` stage: `semantic-release`
Expand Down
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,18 @@ jobs:
# - env: INSTANCE=git-gentoo-stage3-systemd-3000-9-py3
# - env: INSTANCE=git-ubuntu-1804-3000-9-py2
# - env: INSTANCE=git-arch-base-latest-3000-9-py2
- env: INSTANCE=pip-debian-10-tiamat-py3
- env: INSTANCE=pip-ubuntu-2004-tiamat-py3
- env: INSTANCE=pip-debian-11-master-py3
- env: INSTANCE=pip-debian-10-master-py3
- env: INSTANCE=pip-debian-9-master-py3
- env: INSTANCE=pip-ubuntu-2004-master-py3
- env: INSTANCE=pip-centos-8-master-py3
- env: INSTANCE=pip-opensuse-leap-153-master-py3
- env: INSTANCE=pip-opensuse-leap-152-master-py3
- env: INSTANCE=pip-arch-base-latest-master-py3
- env: INSTANCE=pip-gentoo-stage-3-latest-master-py3
- env: INSTANCE=pip-gentoo-stage-3-systemd-master-py3

## Define the release stage that runs `semantic-release`
- stage: 'release'
Expand Down
8 changes: 5 additions & 3 deletions docs/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@ Available states

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

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

If `use_package` is `False` it installs and configures the letsencrypt cli from git, creates the requested certificates and installs renewal cron job.
If `install_method` is `git` it installs and configures the letsencrypt cli from git, creates the requested certificates and installs renewal cron job.

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`.

** WARNING **
If you set `use_package` to `True`, it will:
If you set `install_method` to `package`, it will:

* Delete all certbot's crons if they exist from a previous git-based installation (as the package uses a
systemd's timer unit to renew all the certs)
Expand Down
18 changes: 18 additions & 0 deletions kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,24 @@ suites:
verifier:
inspec_tests:
- path: test/integration/git
- name: pip
provisioner:
state_top:
base:
'*':
- letsencrypt._mapdata
- letsencrypt.install
- letsencrypt.config
pillars:
top.sls:
base:
'*':
- letsencrypt
pillars_from_files:
letsencrypt.sls: test/salt/pillar/pip.sls
verifier:
inspec_tests:
- path: test/integration/pip
- name: deb
includes:
- debian-11-tiamat-py3
Expand Down
21 changes: 13 additions & 8 deletions letsencrypt/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,30 @@
# vim: ft=yaml
---
letsencrypt:
use_package: true
install_method: package
pkgs: []
git_pkg: git
service: certbot.timer
# Only used for the pkg install method (use_package: true), internal var
# Only used for the pkg install method (install_method = package), internal var
_cli_path: /usr/bin/certbot
# Only used for the pkg install method (use_package: true), internal var
# Only used for the pkg install method (install_method = package), internal var
_default_pkg: certbot
# Only used for the git install method (use_package: false)
# Only used for the git or pip install methods (install_method = (git|pip))
cli_install_dir: /opt/letsencrypt
# Only used for the git install method (use_package: false). If you want to
# have specific version of certbot you can enable it. The version value
# should match a certbot/certbot branch
# version: 0.30.x
# Only used for the git or pip install methods (install_method = (git|pip)).
# If you want to have specific version of certbot you can enable it. The
# version value should match a certbot/certbot branch version: 0.30.x
config_dir:
path: /etc/letsencrypt
user: root
group: root
mode: 755
# Only used for the pip install method (install_method = pip). Can be used to
# install plugins for certbot.
pip_pkgs: []
# Only used for the pip install method (install_method = pip), internal var
virtualenv_pkg:
- python3-virtualenv
config:
server: https://acme-v02.api.letsencrypt.org/directory
agree-tos: true
Expand Down
16 changes: 10 additions & 6 deletions letsencrypt/domains.sls
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{% from "letsencrypt/map.jinja" import letsencrypt with context %}

{% if letsencrypt.use_package %}
{% if letsencrypt.install_method == 'package' %}
{% set check_cert_cmd = letsencrypt._cli_path ~ ' certificates --cert-name' %}
{% set renew_cert_cmd = letsencrypt._cli_path ~ ' renew' %}
{% set create_cert_cmd = letsencrypt._cli_path %}
Expand All @@ -15,7 +15,11 @@
{% else %}
{% set check_cert_cmd = '/usr/local/bin/check_letsencrypt_cert.sh' %}
{% set renew_cert_cmd = '/usr/local/bin/renew_letsencrypt_cert.sh' %}
{% set create_cert_cmd = letsencrypt.cli_install_dir ~ '/letsencrypt-auto' %}
{% if letsencrypt.install_method == 'pip' %}
{% set create_cert_cmd = letsencrypt.cli_install_dir ~ '/bin/certbot' %}
{% else %}
{% set create_cert_cmd = letsencrypt.cli_install_dir ~ '/letsencrypt-auto' %}
{% endif %}

{% set old_check_cert_cmd_state = 'managed' %}
{% set old_renew_cert_cmd_state = 'managed' %}
Expand Down Expand Up @@ -63,11 +67,11 @@ create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}:
{{ installer }} \
--cert-name {{ setname }} \
-d {{ domainlist|join(' -d ') }}
{% if not letsencrypt.use_package %}
{% if letsencrypt.install_method != 'package' %}
- cwd: {{ letsencrypt.cli_install_dir }}
{% endif %}
- unless:
{% if letsencrypt.use_package %}
{% if letsencrypt.install_method == 'package' %}
- fun: cmd.run
python_shell: true
cmd: |
Expand All @@ -78,7 +82,7 @@ create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}:
- {{ check_cert_cmd }} {{ setname }} {{ domainlist | join(' ') }}
{% endif %}
- require:
{% if letsencrypt.use_package %}
{% if letsencrypt.install_method == 'package' %}
- pkg: letsencrypt-client
{% else %}
- file: {{ check_cert_cmd }}
Expand All @@ -95,7 +99,7 @@ letsencrypt-crontab-{{ setname }}-{{ domainlist[0] }}:
- identifier: letsencrypt-{{ setname }}-{{ domainlist[0] }}
- require:
- cmd: create-initial-cert-{{ setname }}-{{ domainlist | join('+') }}
{% if letsencrypt.use_package %}
{% if letsencrypt.install_method == 'package' %}
- pkg: letsencrypt-client
{% else %}
- file: {{ renew_cert_cmd }}
Expand Down
4 changes: 4 additions & 0 deletions letsencrypt/files/renew_letsencrypt_cert.sh.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
{% from "letsencrypt/map.jinja" import letsencrypt with context %}
COMMON_NAME="$1"

{% if letsencrypt.install_method == 'pip' %}
{{ letsencrypt.cli_install_dir }}/bin/certbot renew --non-interactive || exit 1
{% else %}
{{ letsencrypt.cli_install_dir }}/letsencrypt-auto renew --non-interactive || exit 1
{% endif %}
cat {{ letsencrypt.config_dir.path }}/live/${COMMON_NAME}/fullchain.pem \
{{ letsencrypt.config_dir.path }}/live/${COMMON_NAME}/privkey.pem \
> {{ letsencrypt.config_dir.path }}/live/${COMMON_NAME}/fullchain-privkey.pem || exit 1
Expand Down
30 changes: 27 additions & 3 deletions letsencrypt/install.sls
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{%- from "letsencrypt/map.jinja" import letsencrypt with context %}

{#- Use empty default for `grains.osfinger`, which isn't available in all distros #}
{%- if letsencrypt.use_package and
{%- if letsencrypt.install_method == 'package' and
grains.osfinger|d('') == 'Amazon Linux-2' %}
{%- set rhel_ver = '7' %}
letsencrypt_external_repo:
Expand All @@ -19,12 +19,21 @@ letsencrypt_external_repo:
- pkg: letsencrypt-client
{%- endif %}

{%- if letsencrypt.install_method == 'package' and grains.os|d('') == 'CentOS' %}
letsencrypt-epel-releasehttps://github.com/XeryusTC/letsencrypt-formula.git:
pkg.installed:
- pkgs:
- epel-release
- require_in:
- pkg: letsencrypt-client
{%- endif %}

letsencrypt-client:
{%- if letsencrypt.use_package %}
{%- if letsencrypt.install_method == 'package' %}
{%- set pkgs = letsencrypt.pkgs or [letsencrypt._default_pkg] %}
pkg.installed:
- pkgs: {{ pkgs | json }}
{%- else %}
{%- elif letsencrypt.install_method == 'git' %}
pkg.installed:
- name: {{ letsencrypt.git_pkg }}
{%- if letsencrypt.version is defined and letsencrypt.version|length %}
Expand All @@ -38,5 +47,20 @@ letsencrypt-client:
- target: {{ letsencrypt.cli_install_dir }}
- force_reset: True
{%- endif %}
{%- elif letsencrypt.install_method == 'pip' %}
pkg.installed:
- pkgs: {{ letsencrypt.virtualenv_pkg | json }}
virtualenv.managed:
- name: {{ letsencrypt.cli_install_dir }}
- python: python3
- pip_pkgs:
{%- if letsencrypt.version is defined and letsencrypt.version|length %}
- certbot=={{ letsencrypt.version }}
{%- else %}
- certbot
{%- endif %}
{%- for pkg in letsencrypt.pip_pkgs %}
- {{ pkg }}
{%- endfor %}
{%- endif %}
- reload_modules: True
11 changes: 10 additions & 1 deletion letsencrypt/map.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,18 @@
merge=salt['grains.filter_by'](
osfingermap,
grain='osfinger',
merge = salt['pillar.get']('letsencrypt', {}),
merge=salt['config.get']('letsencrypt', merge='recurse'),
),
),
),
base='letsencrypt')
%}

{# Make backwards compatible with use_package #}
{% if letsencrypt.use_package is defined %}
{% if letsencrypt.use_package %}
{{ letsencrypt | set_dict_key_value('install_method', 'package') }}
{% else %}
{{ letsencrypt | set_dict_key_value('install_method', 'git') }}
{% endif %}
{% endif %}
10 changes: 9 additions & 1 deletion letsencrypt/osfamilymap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@
RedHat:
service: certbot-renew.timer
FreeBSD:
# Only used for the pkg install method (use_package: true), internal var
# Only used for the pkg install method (install_method: package), internal var
_cli_path: /usr/local/bin/certbot
Gentoo:
git_pkg: dev-vcs/git
virtualenv_pkg:
- dev-python/virtualenv
Debian:
virtualenv_pkg:
- virtualenv
Arch:
virtualenv_pkg:
- python-virtualenv
2 changes: 1 addition & 1 deletion letsencrypt/service.sls
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{% from "letsencrypt/map.jinja" import letsencrypt with context %}

{% if letsencrypt.use_package %}
{% if letsencrypt.install_method == 'package' %}
letsencrypt-service-timer:
service.running:
- name: {{ letsencrypt.service }}
Expand Down
17 changes: 11 additions & 6 deletions pillar.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# vim: ft=yaml
---
letsencrypt:
# Install using packages instead of git
use_package: true
# Install using package, git or pip
install_method: package
# A list of package/s to install. To find the correct name for the variant
# you want to use, check https://certbot.eff.org/all-instructions
# Usually, you'll need a single one, but you can also add other plugins here.
Expand All @@ -13,12 +13,17 @@ letsencrypt:
- python3-certbot-apache
# - python3-certbot-nginx
# - python3-dns-route53
# Only used for the git install method (use_package: false)
# Only used for the git or pip install methods (install_method = (git|pip))
cli_install_dir: /opt/letsencrypt
# Only used for the git install method (use_package: false). If you want to
# have specific version of certbot you can enable it. The version value
# should match a certbot/certbot branch.
# Only used for the git or pip install methods (install_method = git|pip)).
# If you want to have specific version of certbot you can enable it. The
# version value should match a certbot/certbot branch.
version: 0.30.x
# Only used for the pip install method (install_method = pip). Can be used to
# install plugins for certbot. Default: []
pip_pkgs:
- certbot-dns-azure
- certbot-dns-powerdns
# Subcommand used for certificates' first generation cmd ( run | certonly | renew )
create_init_cert_subcmd: certonly
# Any parameter from the cli can be specified in the config file
Expand Down
50 changes: 50 additions & 0 deletions test/integration/pip/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# InSpec Profile: `git`

This shows the implementation of the `pip` 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 git
Summary
-------
Location: git
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 git
..

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 git --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).
26 changes: 26 additions & 0 deletions test/integration/pip/controls/letsencrypt_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

describe file('/opt/letsencrypt') do
it { should be_directory }
it { should be_owned_by 'root' }
it { should be_grouped_into 'root' }
it { should be_readable }
its('size') { should be > 25 }
end

describe file('/etc/letsencrypt/cli.ini') 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 }
its('content') do
should match 'server = https://acme-staging.api.letsencrypt.org/directory'
end
its('content') { should match 'authenticator = standalone' }
its('content') { should match 'File managed by Salt' }
end

describe command('/opt/letsencrypt/bin/certbot plugins') do
its('stdout') { should match(/dns-powerdns/) }
end
Loading