Skip to content
This repository has been archived by the owner on Jan 30, 2024. It is now read-only.

Commit

Permalink
As an installer user, I can configure Pulp
Browse files Browse the repository at this point in the history
to run with TLS enabled to install/renew using letsencrypt certificates

fixes: #6846
https://pulp.plan.io/issues/6846
  • Loading branch information
mikedep333 committed Aug 11, 2020
1 parent 07c99d9 commit 1bb2d24
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGES/6846.feature
@@ -0,0 +1 @@
Support Let's Encrypt and other ACME protocol CAs. Includes sharing out the `pulp_webserver_static_dir`/.well-known directory for HTTP-01 verification.
4 changes: 0 additions & 4 deletions molecule/release-static/molecule.yml
Expand Up @@ -32,10 +32,6 @@ platforms:
name: debian-10
image: pulp/molecule_debian10
command: /sbin/init
- <<: *platform_base
name: fedora-31
image: pulp/molecule_fedora31
command: /usr/sbin/init
provisioner:
name: ansible
config_options:
Expand Down
23 changes: 23 additions & 0 deletions playbooks/example-use-letsencrypt/group_vars/all
@@ -0,0 +1,23 @@
---
pulp_webserver_httpd_servername: "{{ inventory_hostname }}"
lets_encrypt_hostname: "{{ inventory_hostname }}"
lets_encrypt_directories_certs: "/etc/letsencrypt"
lets_encrypt_directories_data: "/var/lib/pulp/pulpcore_static"

pulp_default_admin_password: password
pulp_install_plugins:
# galaxy-ng: {}
# pulp-ansible: {}
# pulp-certguard: {}
# pulp-container: {}
# pulp-cookbook: {}
# pulp-deb: {}
pulp-file: {}
# pulp-gem: {}
# pulp-maven: {}
# pulp-npm: {}
# pulp-python: {}
# pulp-rpm: {}
pulp_settings:
secret_key: secret
content_origin: "https://{{ inventory_hostname }}"
27 changes: 27 additions & 0 deletions playbooks/example-use-letsencrypt/playbook.yml
@@ -0,0 +1,27 @@
---
- hosts: all
pre_tasks:
# The version string below is the highest of all those in roles' metadata:
# "min_ansible_version". It needs to be kept manually up-to-date.
- name: Verify Ansible meets min required version
assert:
that: "ansible_version.full is version_compare('2.8', '>=')"
msg: >
"You must update Ansible to at least 2.8 to use this version of Pulp 3 Installer."
roles:
# Includes running pulp_webserver. letsencrypt depends on a webserver
# that can host the .well-known directory.
- pulp_all_services
- role: lexa-uw.letsencrypt
become: true
tasks:
# Must be run via a task so that it can be run more than once.
- name: Run pulp_webserver a 2nd time to import the key
include_role:
name: pulp_webserver
vars:
pulp_webserver_tls_key: "/etc/letsencrypt/private_key.pem"
pulp_webserver_tls_cert: "/etc/letsencrypt/fullchain.pem"
pulp_webserver_tls_files_remote: true
environment:
DJANGO_SETTINGS_MODULE: pulpcore.app.settings
7 changes: 7 additions & 0 deletions roles/pulp_common/tasks/install.yml
Expand Up @@ -68,6 +68,13 @@
- name: Reset ssh conn to allow user changes to affect when ssh user and pulp user are the same
meta: reset_connection

# Needed for ngingx/apache to serve content at pulp_webserver_static_dir,
# which is the subdir pulpcore_static by default.
- name: Make {{ pulp_user_home }} world executable
file:
path: '{{ pulp_user_home }}'
mode: 'o+x'

- name: Create cache dir for Pulp
file:
path: '{{ pulp_cache_dir }}'
Expand Down
15 changes: 11 additions & 4 deletions roles/pulp_webserver/README.md
Expand Up @@ -20,12 +20,19 @@ Role Variables
* `pulp_webserver_disable_https`: Whether or not HTTPS should be disabled. Defaults to `false`.
* `pulp_webserver_tls_folder`: Path where to generate or drop the certificates. Defaults to
`pulp_config_dir`.
* `pulp_webserver_tls_cert`: Relative or absolute path to the TLS (SSL) certificate
one wants to import.
* `pulp_webserver_tls_key`: Relative or absolute path to the TLS (SSL) key
one wants to import.
* `pulp_webserver_tls_files_remote`: Whether or not `pulp_webserver_tls_cert` &
`pulp_webserver_tls_key` is on the webserver (`true`) or on the ansible management
node (`false`). Defaults to `false`.
* `pulp_webserver_httpd_servername`: Servername to use when deploying httpd. Defaults to
`ansible_fqdn`.
* `pulp_webserver_ssl_cert`: Relative or absolute path to the TLS certificate one wants to
import.
* `pulp_webserver_ssl_key`: Relative or absolute path to the TLS key one wants to
import.
- `pulp_webserver_static_dir` absolute path where to place static files, such as for the .well-known
directory for ACME (letsencrypt) files or SSL certs. This is not to be confused with the Pulp
application's setting `STATIC_ROOT`, which is a function of Pulp itself (not the webserver) and servces
a different set of files.

Plugin Webserver Configs
------------------------
Expand Down
4 changes: 4 additions & 0 deletions roles/pulp_webserver/defaults/main.yml
Expand Up @@ -7,3 +7,7 @@ pulp_configure_firewall: auto
pulp_webserver_disable_https: false
pulp_webserver_tls_folder: '{{ pulp_config_dir }}'
pulp_webserver_httpd_servername: '{{ ansible_fqdn }}'
# The "static" dir is used by Pulp 2, and has conflicting SELinux policies.
# https://pulp.plan.io/issues/5995
pulp_webserver_static_dir: "{{ pulp_user_home | regex_replace('\\/$', '') }}/pulpcore_static/"
pulp_webserver_tls_files_remote: false
6 changes: 4 additions & 2 deletions roles/pulp_webserver/tasks/import_certificates.yml
@@ -1,18 +1,20 @@
---
- name: Import specified TLS certificate
copy:
src: "{{ pulp_webserver_ssl_cert }}"
src: "{{ pulp_webserver_tls_cert }}"
dest: "{{ pulp_webserver_tls_folder }}/pulp_webserver.crt"
owner: root
group: "{{ pulp_group }}"
mode: 0600
remote_src: "{{ pulp_webserver_tls_files_remote }}"
notify: reload {{ pulp_webserver_server }}

- name: Import specified TLS private key
copy:
src: "{{ pulp_webserver_ssl_key }}"
src: "{{ pulp_webserver_tls_key }}"
dest: "{{ pulp_webserver_tls_folder }}/pulp_webserver.key"
owner: root
group: "{{ pulp_group }}"
mode: 0600
remote_src: "{{ pulp_webserver_tls_files_remote }}"
notify: reload {{ pulp_webserver_server }}
39 changes: 26 additions & 13 deletions roles/pulp_webserver/tasks/main.yml
Expand Up @@ -15,10 +15,10 @@

- name: Ensure that if we have web cert, we also have key
fail:
msg: "If you give one of pulp_webserver_ssl_cert and pulp_webserver_ssl_key, you must also give the other."
msg: "If you give one of pulp_webserver_tls_cert and pulp_webserver_tls_key, you must also give the other."
when:
- "pulp_webserver_ssl_cert is defined or pulp_webserver_ssl_key is defined"
- "pulp_webserver_ssl_cert is not defined or pulp_webserver_ssl_key is not defined"
- "pulp_webserver_tls_cert is defined or pulp_webserver_tls_key is defined"
- "pulp_webserver_tls_cert is not defined or pulp_webserver_tls_key is not defined"

- debug:
msg: >
Expand All @@ -37,17 +37,21 @@
changed_when: false
check_mode: false

- import_tasks: generate_tls_certificates.yml
become: true
- include_tasks: generate_tls_certificates.yml
args:
apply:
become: true
when:
- pulp_webserver_ssl_cert is undefined
- pulp_webserver_ssl_key is undefined
- pulp_webserver_tls_cert is undefined
- pulp_webserver_tls_key is undefined

- import_tasks: import_certificates.yml
become: true
- include_tasks: import_certificates.yml
args:
apply:
become: true
when:
- pulp_webserver_ssl_cert is defined
- pulp_webserver_ssl_key is defined
- pulp_webserver_tls_cert is defined
- pulp_webserver_tls_key is defined

- name: Copy custom CA cert
copy:
Expand All @@ -60,8 +64,17 @@
become: true
notify: update ca trust

- import_tasks: nginx.yml
when: pulp_webserver_server == 'nginx'
- name: Create ACME dirs
file:
path: "{{ item }}"
state: directory
mode: 0755
owner: "{{ pulp_user }}"
group: "{{ pulp_group }}"
become: true
with_items:
- "{{ pulp_webserver_static_dir }}"
- "{{ pulp_webserver_static_dir }}/.well-known"

- include_tasks: "{{ pulp_webserver_server }}.yml"

Expand Down
15 changes: 13 additions & 2 deletions roles/pulp_webserver/templates/nginx.conf.j2
Expand Up @@ -49,7 +49,7 @@ http {
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;

{% if pulp_webserver_ssl_cert is defined %}
{% if pulp_webserver_tls_cert is defined %}
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
{% endif %}
Expand All @@ -63,6 +63,10 @@ http {
# Gunicorn docs suggest this value.
keepalive_timeout 5;

# static files that can change dynamically, or are needed for TLS
# purposes are served through the webserver.
root {{ pulp_webserver_static_dir }};

location /pulp/content/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
Expand Down Expand Up @@ -103,8 +107,15 @@ http {
# redirects, we set the Host: header above already.
proxy_redirect off;
proxy_pass http://pulp-api;
# static files are served through whitenoise - http://whitenoise.evans.io/en/stable/
# most pulp static files are served through whitenoise
# http://whitenoise.evans.io/en/stable/
}

# ACME http-01 tokens, i.e, for Let's Encrypt
location /.well-known/ {
try_files $uri $uri/ =404;
}

}

{% if not pulp_webserver_disable_https | bool %}
Expand Down
2 changes: 1 addition & 1 deletion roles/pulp_webserver/templates/pulp-vhost.conf.j2
Expand Up @@ -47,7 +47,7 @@ Define pulp-api {{ pulp_api_bind }}
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder on

{% if pulp_webserver_ssl_cert is defined %}
{% if pulp_webserver_tls_cert is defined %}
# HSTS (15768000 seconds = 6 months)
Header always set Strict-Transport-Security "max-age=15768000;; includeSubDomains; preload"
{% endif %}
Expand Down

0 comments on commit 1bb2d24

Please sign in to comment.