From e451856aeeff1b953f3dcb427c7df2faee2a9a96 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 12:11:09 +0200 Subject: [PATCH 01/65] Update CHANGES format --- CHANGES.rst | 19 +++++++------------ docs/includes/all.rst | 1 + 2 files changed, 8 insertions(+), 12 deletions(-) create mode 100644 docs/includes/all.rst diff --git a/CHANGES.rst b/CHANGES.rst index a22819d..61a46ee 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,18 +1,14 @@ Changelog ========= -**debops.pki** - -This project adheres to `Semantic Versioning `_ -and `human-readable changelog `_. +.. include:: includes/all.rst +**debops.pki** -Contributors ------------- +This project adheres to `Semantic Versioning `__ +and `human-readable changelog `__. -- [drybjed] - `Maciej Delmanowski `_ (role maintainer) -- [ypid] - `Robin Schneider `_ -- [yuvadm] - `Yuval Adam `_ +The current role maintainer_ is drybjed_. `debops.pki master`_ - unreleased @@ -30,7 +26,7 @@ Fixed ~~~~~ - Fix an error where certain versions of GnuTLS ``certtool`` did not support - the "URI" SubjectAltName which resulted in an abort and certificate requrests + the "URI" SubjectAltName which resulted in an abort and certificate requests not being generated correctly. The "URI" SANs will only be added when correct version of the ``certtool`` is available. [drybjed] @@ -39,7 +35,7 @@ Fixed ``0007``, which resulted in the web server not being able to serve ACME challenge responses. Now, correct ``umask`` will be set for the ``acme-tiny`` script, so that ACME responses are world-readable. [drybjed] - + - Fix an error in ``pki-authority`` script which invoked a Python print call that was unsupported in modern Python versions, the call is now supported on both 2.x and 3.x. [yuvadm] @@ -382,4 +378,3 @@ Removed - Remove Diffie-Hellman parameter support from the role, it's now managed by a separate ``debops.dhparam`` Ansible role. Existing hosts won't be affected. [drybjed] - diff --git a/docs/includes/all.rst b/docs/includes/all.rst new file mode 100644 index 0000000..73b2598 --- /dev/null +++ b/docs/includes/all.rst @@ -0,0 +1 @@ +.. include:: includes/global.rst From 1d15b219f83ee617d45a622fa60ce6fb6d94dd62 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 12:12:03 +0200 Subject: [PATCH 02/65] Fix docs about `pki_internal` --- defaults/main.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 909e7a7..dd976f1 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -22,7 +22,7 @@ pki_enabled: '{{ (True # .. envvar:: pki_internal # # Enable or disable support for internal certificates. If the support is -# disabled, the PKI realm will generate its own set of self-signed +# enabled, the PKI realm will generate its own set of self-signed # certificates. pki_internal: '{{ (True if pki_default_domain @@ -55,7 +55,10 @@ pki_inventory_groups: [ 'debops_service_pki' ] # :file:`/etc` is not tracked by default by a version control system so this # definition exists preliminary in case you decide to use :program:`etckeeper` for # example to track changes in :file:`/etc`. In case you want to track -# sensitive files by version control system specific:: +# sensitive files by a version control system specify: +# +# .. code-block:: yaml +# :linenos: # # pki_vcs_ignore_patterns_role: [] # From b7f51b70094ed8bc55f530f9eb26071c4d10d1af Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 12:12:46 +0200 Subject: [PATCH 03/65] Be more precise in docs when referring to ACME and Let's Encrypt --- .gitignore | 5 +++++ docs/acme-integration.rst | 8 ++++---- docs/introduction.rst | 4 +++- docs/pki-realms.rst | 16 ++++++++-------- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 7ac6fe5..56eb1fa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,8 @@ docs/Makefile docs/_build/ docs/conf.py docs/defaults.rst +docs/includes/global.rst +docs/_templates/page.html +docs/_templates/.gitkeep +docs/_static/custom.css +docs/_static/.gitkeep diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index b37d4fc..a537b47 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -3,11 +3,12 @@ ACME Integration ================ -The `Automated Certificate Management Environment `_ +.. include:: includes/all.rst + +`Automated Certificate Management Environment (ACME) `_ is a protocol that allows automated certificate requests, retrieval of signed certificates and certificate renewal. It was designed to enable easy deployment -of TLS/SSL certificates by the `Let's Encrypt `_ -project. +of TLS/SSL certificates by the `Let's Encrypt`_ project. The ``debops.pki`` Ansible role provides support for the ACME protocol which is used by default with the Let's Encrypt service (there is a possibility to @@ -239,4 +240,3 @@ can have several parameters related to the ACME certificates: ``item.acme_subject`` List of Distinguished Name entries which define the ACME certificate Subject. - diff --git a/docs/introduction.rst b/docs/introduction.rst index 38c050f..1b67c29 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -1,6 +1,8 @@ Introduction ============ +.. include:: includes/all.rst + The ``debops.pki`` role provides a standardized management of the X.509 certificates on hosts controlled by Ansible. Other Ansible roles can utilize the environment created by ``debops.pki`` to automatically enable TLS/SSL @@ -10,7 +12,7 @@ Using this role, you can bootstrap a Public Key Infrastructure in your environment using an internal Certificate Authority, easily switch the active set of certificates between internal and external Certificate Authorities, or use the ACME protocol to automatically obtain signed certificates from CA that -support it (currently, `Let's Encrypt `_). +support it (for example `Let's Encrypt`_). Installation ~~~~~~~~~~~~ diff --git a/docs/pki-realms.rst b/docs/pki-realms.rst index 16ede4b..76289db 100644 --- a/docs/pki-realms.rst +++ b/docs/pki-realms.rst @@ -3,6 +3,8 @@ PKI realms structure ==================== +.. include:: includes/all.rst + The concept of PKI realms is designed to provide a standardized way for various applications to access X.509 certificates and private keys. The management of the keys and certificates is moved outside of the application into a fixed @@ -247,21 +249,20 @@ data files for different Certificate Authorities. Each CA is described in more detail in a separate document, here is a brief overview: :file:`acme/` - This is directory used by the ACME Certificate Authority (currently only the - `Let's Encrypt `_ CA supports this protocol). + This directory is for certificates issued using ACME support (for example `Let's Encrypt`_). It will be activated and used automatically when a host has a public IP address and the :program:`nginx` webserver is installed and configured to support ACME Challenges (see the ``debops.nginx`` role for more details). :file:`external/` This directory is used to manage certificates signed by an external - Certificate Authority. To do this, you need to provide a special ``script`` + Certificate Authority. To do this, you need to provide a special :file:`script` file, which will be executed with a set of environment variables. This can be - used to request a certificate in and external CA, like Active Directory or - FreeIPA, or download a signed certificate from external location. + used to request a certificate from an external CA, like Active Directory or + FreeIPA, or download a signed certificate from an external location. - An alternative is to provide already signed :file:`cert.pem` file with optional - :file:`intermediate.pem` and :file:`root.pem` certificates. + An alternative is to provide an already signed :file:`cert.pem` file and + optionally the :file:`intermediate.pem` and :file:`root.pem` files. :file:`internal/` This directory is used by the internal ``debops.pki`` Certificate Authority @@ -492,4 +493,3 @@ available for other applications and services: During this process, at various stages special "hook" scripts might be run, which can react to events like realm creation, activation of new certificates and so on. - From a6da3c495e40a05b366bb76ef3712d3d795a0f9c Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 12:47:37 +0200 Subject: [PATCH 04/65] Regen README.md --- README.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index daeee5c..8a9772c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -## [![DebOps project](http://debops.org/images/debops-small.png)](http://debops.org) pki +## [![DebOps](https://debops.org/images/debops-small.png)](https://debops.org) pki -[![Travis CI](http://img.shields.io/travis/debops/ansible-pki.svg?style=flat)](http://travis-ci.org/debops/ansible-pki) -[![test-suite](http://img.shields.io/badge/test--suite-ansible--pki-blue.svg?style=flat)](https://github.com/debops/test-suite/tree/master/ansible-pki/) -[![Ansible Galaxy](http://img.shields.io/badge/galaxy-debops.pki-660198.svg?style=flat)](https://galaxy.ansible.com/detail#/role/1588) +[![Travis CI](https://img.shields.io/travis/debops/ansible-pki.svg?style=flat)](https://travis-ci.org/debops/ansible-pki) +[![test-suite](https://img.shields.io/badge/test--suite-ansible--pki-blue.svg?style=flat)](https://github.com/debops/test-suite/tree/master/ansible-pki/) +[![Ansible Galaxy](https://img.shields.io/badge/galaxy-debops.pki-660198.svg?style=flat)](https://galaxy.ansible.com/debops/pki) The `debops.pki` role provides a standardized management of the X.509 @@ -32,7 +32,7 @@ ansible-galaxy install debops.pki ### Documentation More information about `debops.pki` can be found in the -[official debops.pki documentation](http://docs.debops.org/en/latest/ansible/roles/ansible-pki/docs/). +[official debops.pki documentation](https://docs.debops.org/en/latest/ansible/roles/ansible-pki/docs/). ### Role dependencies @@ -45,7 +45,7 @@ You may need to include missing roles from the [DebOps common playbook](https://github.com/debops/debops-playbooks/blob/master/playbooks/common.yml) into your playbook. -[Try DebOps now](https://github.com/debops/debops) for a complete solution to run your Debian-based infrastructure. +[Try DebOps now](https://debops.org/) for a complete solution to run your Debian-based infrastructure. @@ -53,13 +53,11 @@ into your playbook. ### Authors and license -`pki` role was written by: - -- Maciej Delmanowski | [e-mail](mailto:drybjed@gmail.com) | [Twitter](https://twitter.com/drybjed) | [GitHub](https://github.com/drybjed) +- Maciej Delmanowski (maintainer) | [e-mail](mailto:drybjed@gmail.com) | [Twitter](https://twitter.com/drybjed) | [GitHub](https://github.com/drybjed) - [Robin Schneider](http://ypid.de/) | [e-mail](mailto:ypid@riseup.net) | [Twitter](https://twitter.com/ypid) | [GitHub](https://github.com/ypid) -License: [GPLv3](https://tldrlegal.com/license/gnu-general-public-license-v3-%28gpl-3%29) +License: [GPL-3.0](https://tldrlegal.com/license/gnu-general-public-license-v3-%28gpl-3%29) *** -This role is part of the [DebOps](http://debops.org/) project. README generated by [ansigenome](https://github.com/nickjj/ansigenome/). +This role is part of the [DebOps](https://debops.org/) project. README generated by [ansigenome](https://github.com/nickjj/ansigenome/). From b56fafe196ff04ab248f33db19626d5e8ea6c10a Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 12:49:51 +0200 Subject: [PATCH 05/65] debops-optimize --- CHANGES.rst | 120 ++++++++++++++--------------- COPYRIGHT | 4 +- defaults/main.yml | 7 +- docs/acme-integration.rst | 2 +- docs/defaults-detailed.rst | 9 ++- docs/internal-ca.rst | 5 +- docs/pki-realms.rst | 10 +-- files/secret/pki/lib/pki-authority | 2 +- files/usr/local/lib/pki/pki-realm | 2 +- 9 files changed, 83 insertions(+), 78 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 61a46ee..60a0b0f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,7 +20,7 @@ Changed ~~~~~~~ - Change the method that Bash scripts use to compare the version numbers for - a more reliable one. [drybjed] + a more reliable one. [drybjed_] Fixed ~~~~~ @@ -28,13 +28,13 @@ Fixed - Fix an error where certain versions of GnuTLS ``certtool`` did not support the "URI" SubjectAltName which resulted in an abort and certificate requests not being generated correctly. The "URI" SANs will only be added when correct - version of the ``certtool`` is available. [drybjed] + version of the ``certtool`` is available. [drybjed_] - Fix an issue where ACME certificate requests were not performed correctly on Ubuntu hosts due to the default ``umask`` setting of the user accounts being ``0007``, which resulted in the web server not being able to serve ACME - challenge responses. Now, correct ``umask`` will be set for the ``acme-tiny`` - script, so that ACME responses are world-readable. [drybjed] + challenge responses. Now, correct ``umask`` will be set for the :program:`acme-tiny` + script, so that ACME responses are world-readable. [drybjed_] - Fix an error in ``pki-authority`` script which invoked a Python print call that was unsupported in modern Python versions, the call is now supported @@ -49,11 +49,11 @@ Fixed Changed ~~~~~~~ -- Update the Changelog with links to change diffs on GitHub. [drybjed] +- Update the Changelog with links to change diffs on GitHub. [drybjed_] -- Include the ``COPYRIGHT`` file in the RST documentation. [drybjed] +- Include the ``COPYRIGHT`` file in the RST documentation. [drybjed_] -- Update the ``.travis.yml`` configuration file. [drybjed] +- Update the :file:`.travis.yml` configuration file. [drybjed_] `debops.pki v0.2.12`_ - 2016-07-06 @@ -65,12 +65,12 @@ Changed ~~~~~~~ - The session token is now generated using ``sha256`` hashing algorithm instead - of ``MD5``. [drybjed] + of ``MD5``. [drybjed_] - Move the copyright information to a ``COPYRIGHT`` file in the main directory. - [drybjed] + [drybjed_] -- Move the example playbook to an external, separate file. [drybjed] +- Move the example playbook to an external, separate file. [drybjed_] `debops.pki v0.2.11`_ - 2016-07-05 @@ -85,12 +85,12 @@ Added for example :program:`etckeeper` is used for tracking changes in :file:`/etc`. Note that sensitive files which are already tracked by version control will need to be manually deleted from version control history! - Refer to :envvar:`pki_vcs_ignore_patterns_role` for more details. [ypid] + Refer to :envvar:`pki_vcs_ignore_patterns_role` for more details. [ypid_] Changed ~~~~~~~ -- Convert Changelog to the new format. [drybjed] +- Convert Changelog to the new format. [drybjed_] Fixed ~~~~~ @@ -98,7 +98,7 @@ Fixed - The PKI session token is now generated once for all hosts, by delegating the task to Ansible Controller. This fixes a bug with Ansible Playbook runs on multiple hosts at once, where only one host would receive the signed - certificates at a time. [drybjed] + certificates at a time. [drybjed_] `debops.pki v0.2.10`_ - 2016-06-14 @@ -111,16 +111,16 @@ Changed - Documentation fixes and improvements. Made variables hyperlinks using the `any` role in Sphinx which also ensures that variables which the - documentation refers to actually exist. [ypid] + documentation refers to actually exist. [ypid_] -- Assert that required dependencies are met. [ypid] +- Assert that required dependencies are met. [ypid_] - Use ``pki_ca_library`` variable to select correct crypto library for - assertion. [drybjed] + assertion. [drybjed_] - Don't assert crypto library version or ``bash`` version on Ansible Controller if no internal Certificate Authority is enabled. In this case they are not - relevant for ``debops.pki`` operation. [drybjed] + relevant for ``debops.pki`` operation. [drybjed_] `debops.pki v0.2.9`_ - 2016-06-01 @@ -132,12 +132,12 @@ Added ~~~~~ - Expose the list with order of authority preference used by a PKI realm to - select active valid certificate in role default variables. [drybjed] + select active valid certificate in role default variables. [drybjed_] - Add support for creation of self-signed certificates when internal CA is disabled. This enables proper operation of other services like :program:`nginx`, which can then be used to request and authenticate ACME certificates. - [drybjed] + [drybjed_] `debops.pki v0.2.8`_ - 2016-05-05 @@ -149,13 +149,13 @@ Added ~~~~~ - Add support for setting filesystem ACL entries for private directories and - files. [drybjed] + files. [drybjed_] Changed ~~~~~~~ - Include realms defined in :any:`pki_default_realms` in tasks that copy files - from Ansible Controller depending on an Ansible inventory group. [drybjed] + from Ansible Controller depending on an Ansible inventory group. [drybjed_] `debops.pki v0.2.7`_ - 2016-05-03 @@ -167,7 +167,7 @@ Changed ~~~~~~~ - Documentation improvements. Fixed examples, spelling, grammar and Sphinx inline - syntax. [ypid] + syntax. [ypid_] - Don’t rely on the value of the special variable ``omit`` for having a high enough entropy (or any entropy at all) to use it as PKI session token. @@ -175,13 +175,13 @@ Changed and has been suggested by one of the Ansible core developers, it is believed that this does not meet the quality and maintainability standards of the DebOps project. Now the ``random`` Jinja filter is used as random source - which is more explicit, has a proper entropy and is less hacky. [ypid] + which is more explicit, has a proper entropy and is less hacky. [ypid_] - Honor the value of ``ansible_local.root.lib``. Previously, using another - value than :file:`/usr/local/lib` would have broken the role. [ypid] + value than :file:`/usr/local/lib` would have broken the role. [ypid_] - Only use ``pki_fact_lib_path`` inside of quotes as this value could contain - whitespace characters. [ypid] + whitespace characters. [ypid_] `debops.pki v0.2.6`_ - 2016-04-12 @@ -193,10 +193,10 @@ Changed ~~~~~~~ - Convert ACME intermediate certificate from DER to PEM format automatically. - [drybjed] + [drybjed_] -- Make sure that role works with older ``debops.nginx`` deployments, which - didn't support ACME integration. [drybjed] +- Make sure that role works with older debops.nginx_ deployments, which + didn't support ACME integration. [drybjed_] `debops.pki v0.2.5`_ - 2016-03-02 @@ -208,7 +208,7 @@ Changed ~~~~~~~ - Don't run :program:`pki-authority` script on Ansible Controller if list of - :any:`pki_authorities` is not defined. [drybjed] + :any:`pki_authorities` is not defined. [drybjed_] `debops.pki v0.2.4`_ - 2016-02-21 @@ -219,30 +219,30 @@ Changed Changed ~~~~~~~ -- Use a more portable "shebang" string in Bash scripts. [drybjed] +- Use a more portable "shebang" string in Bash scripts. [drybjed_] - Provide a portable ``dnsdomainname`` alternative function which works on - operating systems without the former command present. [drybjed] + operating systems without the former command present. [drybjed_] -- Use short :command:`hostname -f` argument for portability. [drybjed] +- Use short :command:`hostname -f` argument for portability. [drybjed_] - Update support for ``subjectAltName`` extension in certificates. Currently - only IP addresses, DNS records, URI paths and emails are supported. [drybjed] + only IP addresses, DNS records, URI paths and emails are supported. [drybjed_] -- Document ``pki_realms`` lists. [drybjed] +- Document ``pki_realms`` lists. [drybjed_] - Redesign the :file:`secret/pki/ca-certificates/` directory. It's now based on Ansible inventory groups and allows distribution of CA certificates to all - hosts, specific host groups, or specific hosts. [drybjed] + hosts, specific host groups, or specific hosts. [drybjed_] -- Don't update symlinks if the target is correct. [drybjed] +- Don't update symlinks if the target is correct. [drybjed_] - Split file signature creation and verification. This allows checking if the file signature is correct without updating it, so that it can be performed at - different stages of the script. [drybjed] + different stages of the script. [drybjed_] - Make sure that request generation works without subdomains and SANs present. - [drybjed] + [drybjed_] - Automatically reset incomplete internal certificate requests. @@ -250,7 +250,7 @@ Changed are enabled, something must have gone wrong with the certificate signing. To make it easier, generated configuration file and CSR are removed so that they can be recreated further in the script with current session token and not - rejected by the internal CA. [drybjed] + rejected by the internal CA. [drybjed_] - Change the way ACME intermediate CA certificate is downloaded. @@ -259,11 +259,11 @@ Changed Issuers" URI and download the certificate using it. The URI is stored and used later to check if the new certificate has the same or different URI, to not download the intermediate certificate every time the :program:`pki-realm` script - is run. [drybjed] + is run. [drybjed_] - Slight changes in certificate chaining logic, to ensure that when certificates are changed, all generated chained certificate files are - correctly updated. [drybjed] + correctly updated. [drybjed_] `debops.pki v0.2.3`_ - 2016-02-08 @@ -274,9 +274,9 @@ Changed Changed ~~~~~~~ -- Replace the example hook script with something that actually works. [drybjed] +- Replace the example hook script with something that actually works. [drybjed_] -- Fix deprecation warnings in Ansible 2.1.0. [drybjed] +- Fix deprecation warnings in Ansible 2.1.0. [drybjed_] `debops.pki v0.2.2`_ - 2016-02-03 @@ -288,36 +288,36 @@ Added ~~~~~ - Add support for Diffie-Hellman parameters appended to certificate chains. DHE - parameters are managed by ``debops.dhparam`` Ansible role. [drybjed] + parameters are managed by debops.dhparam_ Ansible role. [drybjed_] Changed ~~~~~~~ - When an active authority directory is changed, correctly clean up files not present in the new authority directory and symlinks without existing targets. - [drybjed] + [drybjed_] - Do not enable PKI support on remote hosts without defined domain. Without this applications try to use non-existent X.509 certificates and fail. - [drybjed] + [drybjed_] - Make system PKI realm selection idempotent. Now, if another role changes the default system realm, running ``debops.pki`` role without that override will - keep the realm specified in Ansible local facts. [drybjed] + keep the realm specified in Ansible local facts. [drybjed_] - Make sure that CA organization is non-empty. If a host domain is not configured correctly, hostname will be used instead. This makes some of the URLs in created CA certificates incorrect, but the ``debops.pki`` role works fine otherwise, and internal Certificate Authorities are easy to recreate - with correct configuration. [drybjed] + with correct configuration. [drybjed_] - Change the file tracked by the PKI realm creation task to be the realm private key instead of the certificate. This allows for realms that only contain Root CA certificates and does not create idempotency issues. - [drybjed] + [drybjed_] - Do not create a :program:`cron` task when support for PKI is disabled on a host. - [drybjed] + [drybjed_] `debops.pki v0.2.1`_ - 2016-02-01 @@ -328,7 +328,7 @@ Changed Changed ~~~~~~~ -- Update old README with new documentation. [drybjed] +- Update old README with new documentation. [drybjed_] `debops.pki v0.2.0`_ - 2016-02-01 @@ -341,7 +341,7 @@ Changed - Replace old ``debops.pki`` role with a new, redesigned version. Some additional code, variable cleanup and documentation is still missing, but - role is usable at this point. [drybjed] + role is usable at this point. [drybjed_] debops.pki v0.1.0 - 2016-01-04 @@ -350,31 +350,31 @@ debops.pki v0.1.0 - 2016-01-04 Added ~~~~~ -- Add Changelog. [drybjed] +- Add Changelog. [drybjed_] - Blacklist CNNIC Root CA following the `Google decision to remove CNNIC`_ from - their Root CA store. [drybjed] + their Root CA store. [drybjed_] .. _Google decision to remove CNNIC: https://security.googleblog.com/2015/03/maintaining-digital-certificate-security.html - Add support for managing the list of active Root CA Certificates in :file:`/etc/ca-certificates.conf`. Current set of active Root CA Certificates is - preserved. [drybjed] + preserved. [drybjed_] - Add a way to copy arbitrary files from Ansible Controller to remote host PKI - directories. [drybjed] + directories. [drybjed_] - Expose ``ansible_fqdn`` variable as :any:`pki_fqdn` so that it can be overridden - if necessary. [drybjed] + if necessary. [drybjed_] Changed ~~~~~~~ -- Reorder Changelog entries. [drybjed] +- Reorder Changelog entries. [drybjed_] Removed ~~~~~~~ - Remove Diffie-Hellman parameter support from the role, it's now managed by - a separate ``debops.dhparam`` Ansible role. Existing hosts won't be affected. - [drybjed] + a separate debops.dhparam_ Ansible role. Existing hosts won't be affected. + [drybjed_] diff --git a/COPYRIGHT b/COPYRIGHT index d787092..e8523bd 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -2,7 +2,7 @@ debops.pki - PKI management using Ansible Copyright (C) 2013-2016 Maciej Delmanowski Copyright (C) 2015-2016 Robin Schneider -Copyright (C) 2014-2016 DebOps Project http://debops.org/ +Copyright (C) 2014-2016 DebOps Project https://debops.org/ This Ansible role is part of DebOps. @@ -16,4 +16,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with DebOps. If not, see http://www.gnu.org/licenses/. +along with DebOps. If not, see https://www.gnu.org/licenses/. diff --git a/defaults/main.yml b/defaults/main.yml index dd976f1..f01354a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -5,6 +5,9 @@ # .. contents:: Sections # :local: # +# .. include:: includes/all.rst + + # .. Global PKI configuration ((( # # ---------------------------- @@ -219,7 +222,7 @@ pki_acme_ca_api_map: # .. envvar:: pki_acme_challenge # # Directory where the ACME client should store responses to ACME CA challenges. -# By default it's defined by the ``debops.nginx`` Ansible role using Ansible +# By default it's defined by the debops.nginx_ Ansible role using Ansible # facts. pki_acme_challenge_dir: '{{ (ansible_local.nginx.acme_root if (ansible_local|d() and ansible_local.nginx|d() and @@ -324,7 +327,7 @@ pki_private_dir_acl_groups: [] # .. envvar:: pki_private_file_acl_groups # # List of system groups which should have read access to key files in -# ``private/`` directory of each realm, unless specified otherwise. The read +# :file:`private/` directory of each realm, unless specified otherwise. The read # access will be granted using the filesystem ACL table. pki_private_file_acl_groups: [] diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index a537b47..12b3e38 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -24,7 +24,7 @@ requirements enforced by this Ansible role: - A webserver configured to handle ACME challenges needs to be installed on the host (currently this role supports only "webroot" challenges). The - ``debops.nginx`` role configures ACME support for all servers by default when + debops.nginx_ role configures ACME support for all servers by default when other conditions are met. - A publicly routable IPv4 or IPv6 address is required, so that the Certificate diff --git a/docs/defaults-detailed.rst b/docs/defaults-detailed.rst index ae46a40..1827482 100644 --- a/docs/defaults-detailed.rst +++ b/docs/defaults-detailed.rst @@ -1,6 +1,8 @@ Default variable details ======================== +.. include:: includes/all.rst + Some of ``debops.pki`` default variables have more extensive configuration than simple strings or lists, here you can find documentation and examples for them. @@ -130,13 +132,13 @@ List of parameters related to the entire PKI realm: ``private_dir_acl_groups`` Optional. List of groups which should be allowed execute (``X``) permission to - the ``private/`` realm directory. The access will be granted using filesystem + the :file:`private/` realm directory. The access will be granted using filesystem ACL table. If not specified, the list defined in :any:`pki_private_dir_acl_groups` will be applied. ``private_file_acl_groups`` Optional. List of groups which should be allowed read (``r``) permission to - the files in the ``private/`` realm directory. The access will be granted + the files in the :file:`private/` realm directory. The access will be granted using filesystem ACL table. If not specified, the list defined in :any:`pki_private_file_acl_groups` will be applied. @@ -146,7 +148,7 @@ List of parameters related to the entire PKI realm: ``dhparam_file`` Optional. Path to the Diffie-Hellman parameters to include in the certificate - chain. If not specified, DHE parameters managed by the ``debops.dhparam`` + chain. If not specified, DHE parameters managed by the debops.dhparam_ role will be used automatically, if they're available. ``enabled``, ``when`` @@ -227,4 +229,3 @@ respectively: - 'uri:https://{{ ansible_domain }}/' - 'dns:*.{{ ansible_domain }}' - 'dns:{{ ansible_domain }}' - diff --git a/docs/internal-ca.rst b/docs/internal-ca.rst index fe6dddc..8476dd7 100644 --- a/docs/internal-ca.rst +++ b/docs/internal-ca.rst @@ -3,6 +3,8 @@ Internal Certificate Authorities ================================ +.. include:: includes/all.rst + One of the problems in deployment of a Public Key Infrastructure is the need for the certificates in use to be signed by a third party, called a Certificate Authority. By using a trusted CA, different entities that communicate with each @@ -27,7 +29,7 @@ cannot be used with internal hosts, which still need to be protected. The ``debops.pki`` role solves this problem by creating it's own set of internal Certificate Authorities, located on Ansible Controller in the :file:`secret/` -directory (see ``debops.secret`` role for more details). These Certificate +directory (see debops.secret_ role for more details). These Certificate Authorities can be used to bootstrap a new PKI environment, which can then be passed over to a stand-alone CA server located on the network. Alternatively, certificates signed by the internal CA can be used for internal communication @@ -166,4 +168,3 @@ intercepted (it's currently passed using environment variables). If for any reason CSR signing cannot be completed, you will need to remove the :file:`internal/gnutls.conf` and :file:`internal/request.pem` files to re-initialize the certificate signing. - diff --git a/docs/pki-realms.rst b/docs/pki-realms.rst index 76289db..6ef6a6f 100644 --- a/docs/pki-realms.rst +++ b/docs/pki-realms.rst @@ -103,7 +103,7 @@ This configuration explains where each certificate is used, but this is not sufficient to enable HTTPS for the webserver. Refer to the :program:`nginx` documentation for the rest of the required configuration options. -If you use the ``debops.nginx`` Ansible role provided with the project, it has +If you use the debops.nginx_ Ansible role provided with the project, it has extensive integration with the ``debops.pki`` role and can configure the webserver automatically. Usually all you need to do is to make sure the default realm is matches with the one you would like to use for each server configuration. @@ -161,7 +161,7 @@ is provided by the internal ``debops.pki`` Certificate Authority: └── trusted.crt -> public/trusted.pem On the Ansible Controller, there's a corresponding directory structure located -in the :file:`secret/` directory maintained by the ``debops.secret`` Ansible role: +in the :file:`secret/` directory maintained by the debops.secret_ Ansible role: .. code-block:: none @@ -252,7 +252,7 @@ detail in a separate document, here is a brief overview: This directory is for certificates issued using ACME support (for example `Let's Encrypt`_). It will be activated and used automatically when a host has a public IP address and the :program:`nginx` webserver is installed and configured to support ACME - Challenges (see the ``debops.nginx`` role for more details). + Challenges (see the debops.nginx_ role for more details). :file:`external/` This directory is used to manage certificates signed by an external @@ -441,10 +441,10 @@ root files to the :file:`public/` directory and generation of various chain file Some applications do not support separate :file:`dhparam` file, and instead expect that the DHE parameters are present after the X.509 certificate chain. If the -``debops.dhparam`` role has been configured on a host and Diffie-Hellman +debops.dhparam_ role has been configured on a host and Diffie-Hellman parameter support is enabled in a given PKI realm, DHE parameters will be appended to the final certificate chains (both public and private). When the -``debops.dhparam`` regenerates the parameters, :program:`pki-realm` script will +debops.dhparam_ regenerates the parameters, :program:`pki-realm` script will automatically detect the new ones and update the certificate chains. The end result is fully configured PKI realm with a set of valid certificates diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 2845b23..be718e2 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -2,7 +2,7 @@ # pki-authority: CA-side PKI management # Copyright (C) 2016 Maciej Delmanowski -# Homepage: http://debops.org/ +# Homepage: https://debops.org/ set -eu -o pipefail diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index daf0c83..5fd4c62 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -2,7 +2,7 @@ # pki-realm: client-side PKI management # Copyright (C) 2016 Maciej Delmanowski -# Homepage: http://debops.org/ +# Homepage: https://debops.org/ set -eu -o pipefail From e13a490948428a9ca7a194ff059af0ad872024d0 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 19:13:41 +0200 Subject: [PATCH 06/65] More useful order of pki_authorities in defaults/main.yml --- defaults/main.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index f01354a..edbb7cf 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -461,8 +461,8 @@ pki_dependent_realms: [] # .. envvar:: pki_scheduler # -# Enable periodic runs of :program:`pki-realm` script for all PKI realms. The script -# will check realm structure and renew certificates that are near their +# Enable periodic runs of :program:`pki-realm` script for all PKI realms. The +# script will check realm structure and renew certificates that are near their # expiration date. pki_scheduler: True @@ -477,8 +477,8 @@ pki_scheduler_interval: 'weekly' # .. envvar:: pki_dhparam # # Specify if Diffie-Hellman parameters should be appended to the certificate -# chain, required by specific applications like HAproxy, ZNC or others that don't -# support DHE parameters in a separate file. +# chain. This is required by applications that don't support DHE parameters in +# a separate file like HAproxy, ZNC. pki_dhparam: '{{ (True if (ansible_local|d() and ansible_local.dhparam|d() and ansible_local.dhparam.default|d()) @@ -524,16 +524,6 @@ pki_default_authority: 'domain' pki_ca_domain: '{{ ansible_domain if ansible_domain else ansible_hostname }}' -# .. envvar:: pki_authorities -# -# List of internal Certificate Authorities managed on an Ansible Controller. -# Each CA is defined as a dictionary variable. -pki_authorities: - - '{{ pki_authorities_ca_root }}' - - '{{ pki_authorities_ca_domain }}' - - '{{ pki_authorities_ca_service }}' - - # .. envvar:: pki_ca_organization # # The organizations name to be used in Distinguished Names (subject). @@ -597,6 +587,16 @@ pki_authorities_ca_service: enabled: '{{ pki_ca_service_enabled | bool }}' +# .. envvar:: pki_authorities +# +# List of internal Certificate Authorities managed on an Ansible Controller. +# Each CA is defined as a dictionary variable. +pki_authorities: + - '{{ pki_authorities_ca_root }}' + - '{{ pki_authorities_ca_domain }}' + - '{{ pki_authorities_ca_service }}' + + # .. envvar:: pki_dependent_authorities # # List of Certificate Authorities defined as a role dependency. @@ -627,7 +627,7 @@ pki_ca_certificates_path: 'by-group/all' # -------------------------- # You can use custom file lists to copy files to remote hosts or install -# contents of Jinja variables. See :ref:`custom_file_management` for more +# the content of Jinja variables. See :ref:`custom_file_management` for more # details. # .. envvar:: pki_private_files From 2cd8265df5575ce59c3569d3511265f68ae1abbb Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 19:14:26 +0200 Subject: [PATCH 07/65] Documentation fixes and updates --- docs/acme-integration.rst | 23 +++++++++--------- docs/internal-ca.rst | 46 +++++++++++++++++++---------------- docs/pki-realms.rst | 50 +++++++++++++++++++-------------------- 3 files changed, 63 insertions(+), 56 deletions(-) diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index 12b3e38..4a72ff8 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -5,16 +5,16 @@ ACME Integration .. include:: includes/all.rst -`Automated Certificate Management Environment (ACME) `_ -is a protocol that allows automated certificate requests, retrieval of signed -certificates and certificate renewal. It was designed to enable easy deployment -of TLS/SSL certificates by the `Let's Encrypt`_ project. +`Automated Certificate Management Environment` (ACME_) is a protocol that +allows automated certificate requests, retrieval of signed certificates and +certificate renewal. It was designed to enable easy deployment of TLS/SSL +certificates by the `Let's Encrypt`_ project. The ``debops.pki`` Ansible role provides support for the ACME protocol which is used by default with the Let's Encrypt service (there is a possibility to integrate other similar services in the future). Interaction with the ACME -Certificate Authority is performed using the `acme-tiny -`_ alternative client written in Python. +Certificate Authority is performed using the acme-tiny_ alternative client +written in Python. Prerequisites ------------- @@ -38,18 +38,19 @@ requirements enforced by this Ansible role: correctly configured in the DNS to point to the host that requests the certificate. This is currently not done automatically and requires intervention by the administrator. If any domain specified in the request is - not authorized by the correct ACME challenge, certificate request won't be - completed. + not authorized by the correct ACME challenge, the certificate request won't be + successful. Due to above requirements, the default ``domain`` PKI realm configured by the role does not request ACME certificates automatically. Other realms created by the ``debops.pki`` role might have ACME support enabled, depending on presence -of a public IP address and configured a :program:`nginx` server. +of a public IP address and a configured :program:`nginx` server. Let's Encrypt rate limits ------------------------- -The Let's Encrypt ACME Certificate Authority has `different rate limits `_ +The Let's Encrypt ACME Certificate Authority has +`different rate limits `_ related to the number of certificate requests and the number of domains permitted per certificate. @@ -93,7 +94,7 @@ this: When the :program:`pki-realm` detects the :file:`acme/request.pem` file, it automatically calls the :program:`acme-tiny` script using the ``pki-acme`` unprivileged account to request the certificate. When the request is completed successfully and an -:file:`external/cert.pem` certificate is not found, ACME certificate will be +:file:`external/cert.pem` certificate is found, the certificate will be activated in the :file:`public/` directory. The script automatically downloads Let's Encrypt intermediate certificate as well as links the Root CA certificate from the system certificate store provided by the ``ca-certificates`` package. diff --git a/docs/internal-ca.rst b/docs/internal-ca.rst index 8476dd7..7db7668 100644 --- a/docs/internal-ca.rst +++ b/docs/internal-ca.rst @@ -5,15 +5,16 @@ Internal Certificate Authorities .. include:: includes/all.rst -One of the problems in deployment of a Public Key Infrastructure is the need -for the certificates in use to be signed by a third party, called a Certificate +One of the problems in the deployment of a Public Key Infrastructure is the need +for the certificates to be signed by a third party, called a Certificate Authority. By using a trusted CA, different entities that communicate with each other can ensure that certificates in use are valid and genuine. A common -solution to that problem is creation of a "self-signed certificate" which can +solution to that problem is the creation of a "self-signed certificate" which can be used by various applications as any other certificate. Unfortunately, this is not a sufficient way to ensure validity of a given certificate in a distributed environment, where various services need to ensure trust without -a human intervention, like acceptance of an untrusted certificate. +a human intervention because other nodes in the cluster don’t trust the +self-signed certificate. There are various solutions that let you set up a Certificate Authority which then can use an automated API to receive Certificate Signing Requests and issue @@ -23,13 +24,13 @@ is confidential, you need to provide the service over HTTPS, which requires a set of certificates, which require a CA, and so on, and so forth. An alternative is to request a certificate in an already existing Certificate Authority and configure them manually on your own CA server, however this -requires human interaction. A proposed solution to this problem is an ACME -protocol, used for example by the Let's Encrypt project, however this solution -cannot be used with internal hosts, which still need to be protected. +requires human interaction. A proposed solution to this problem is ACME, used +for example by the `Let's Encrypt`, however this solution cannot be used +with internal hosts, which still need to be protected. The ``debops.pki`` role solves this problem by creating it's own set of internal -Certificate Authorities, located on Ansible Controller in the :file:`secret/` -directory (see debops.secret_ role for more details). These Certificate +Certificate Authorities, located on the Ansible Controller in the :file:`secret/` +directory (see debops.secret_ for more details). These Certificate Authorities can be used to bootstrap a new PKI environment, which can then be passed over to a stand-alone CA server located on the network. Alternatively, certificates signed by the internal CA can be used for internal communication @@ -43,7 +44,8 @@ By default, the ``debops.pki`` role creates two Certificate Authorities: - a Root Certificate Authority which is used as the "trust anchor" by intermediate Certificate Authorities; -- a Domain Certificate Authority which signs the incoming server certificates; +- a Domain Certificate Authority which issues certificates based on incoming + CSRs from remote hosts; The directory structure of the Certificate Authorities stored in the :file:`secret/` directory on the Ansible Controller:: @@ -96,7 +98,9 @@ The directory structure of the Certificate Authorities stored in the │   ├── cert.pem │   └── request.pem ├── ca-certificates/ - │   └── root-ca.example.com.crt -> ../authorities/root/subject/cert.pem + │   └── by-group/ + │   └── all + │   └── root-ca.example.com.crt -> ../../../authorities/root/subject/cert.pem ├── realms/ │   └── by-host/ │   └── hostname.example.com/ @@ -146,25 +150,27 @@ a secure location (preferably an encrypted, offline filesystem) and replacing it with an empty :file:`key.pem` file (otherwise the ``debops.pki`` role will replace the private key and regenerate all of the CA certificates). -Unfortunately, private keys of the Domain Certificate Authority, any other -Intermediate Certificate Authority or a "Service CA", which is a Root CA used +Unfortunately, private keys of the Domain Certificate Authority and any other +Intermediate Certificate Authority or "Service CA", which is a Root CA used to sign service certificates cannot be protected by taking them offline - the private keys are required to sign certificates. Therefore, it is strongly recommended to store the :file:`secret/` directory encrypted, and use it on an encrypted filesystem during use. In DebOps, you can use the EncFS filesystem -together with :command:`debops-padlock` script to keep the :file:`secret/` directory +together with the :command:`debops-padlock` script to keep the :file:`secret/` directory encrypted at rest. You should make sure that access to the plaintext files in -:file:`secret/` is only possible when it is really needed be unmounting the -encrypted filesystem as soon as possible after usage, to avoid leaks of private -keys. +:file:`secret/` is only possible when it is really needed by unmounting the +encrypted filesystem as soon as possible after usage and that only programs +which need access can read the files by setting up restrictions like `Mandatory +Access Control`_ and compartmentalization/sandboxing, to avoid leakage of +private keys. The Certificate Signing Requests created by ``debops.pki`` Ansible role contain a random challenge password (different on each run) which is then checked on -Ansible Controller, and only the CSR with correct passwords are signed by the +the Ansible Controller, and only the CSR with correct passwords are signed by the Certificate Authorities. This should prevent signing of Certificate Signing Requests modified by a third party, unless the challenge password can be intercepted (it's currently passed using environment variables). If for any reason CSR signing cannot be completed, you will need to remove the -:file:`internal/gnutls.conf` and :file:`internal/request.pem` files to re-initialize -the certificate signing. +:file:`internal/gnutls.conf` and :file:`internal/request.pem` files to +re-initialize the certificate signing. diff --git a/docs/pki-realms.rst b/docs/pki-realms.rst index 6ef6a6f..fbad732 100644 --- a/docs/pki-realms.rst +++ b/docs/pki-realms.rst @@ -280,8 +280,8 @@ and valid certificates in order (``external``, ``acme``, ``internal``, ``selfsigned``), and the first valid one is used as the "active" directory. Files from the active directory are symlinked to the :file:`public/` directory. -The :file:`public/` directory holds currently active certificates which are -symlinks to the real certificate files in one of the active directories above. +The :file:`public/` directory holds the currently active certificates which are +symlinks to the real certificate files in one of the active directories mentioned above. Some additional files are also created here by the :program:`pki-realm` script, namely the certificate chain (server certificate + intermediate certificates) and the trusted chain (intermediate certificates + root certificate). @@ -293,9 +293,9 @@ allowed to access the files inside. The next step is the creation of all necessary files, like private/public keys, certificate requests, etc. At this point, if Ansible was provided with a -private RSA key to use, it will copy it to the :file:`private/` directory. After -that, all necessary files are created by the :program:`pki-realm` script on remote -host. The directory structure changes a bit: +private RSA key to use, it will copy it to the :file:`private/` directory. +After that, all necessary files are created by the :program:`pki-realm` script +on the remote host. The directory structure changes a bit: .. code-block:: none @@ -321,8 +321,8 @@ using the ``private/key.pem`` RSA key. By default, if no :file:`root.pem` certificate is provided, the system CA certificate store is symlinked as :file:`CA.crt`. -Afterwards, Ansible uploads the generated Certificate Signing Request (CSR) to -the Ansible Controller for the internal CA to sign (if it's enabled). CSR is +Afterwards, Ansible uploads the generated `Certificate Signing Request`_ (CSR_) to +the Ansible Controller for the internal CA to sign (if it's enabled). The CSR is uploaded to the :file:`secret/` directory: .. code-block:: none @@ -348,7 +348,7 @@ uploaded to the :file:`secret/` directory: To avoid possible confusion, the :file:`secret/pki/requests/domain/` directory points to the "domain" internal CA which is an intermediate CA located under -"root" CA. The :file:`hostname.example.com/domain/` directory inside the +the "root" CA. The :file:`hostname.example.com/domain/` directory inside the :file:`domain/` directory points to the "domain" realm on the ``hostname.example.com`` host. @@ -391,10 +391,10 @@ there: └── domain/ └── request.pem -When all of the requests have been processed, Ansible copies contents of the -directories to remote hosts. The :file:`by-host/` directory contents are copied -first and overwrite any files that are present on remote hosts, the -:file:`by-group/` directory contents are copied only when the corresponding files +When all of the requests have been processed, Ansible copies the content of the +directories to remote hosts. The content of the :file:`by-host/` directory is copied +first and overwrite all files that are present on remote hosts, the +:file:`by-group/` directory content is copied only when the corresponding files are not present. This allows the administrator to provide the shared scripts or private keys/certificates as needed, per host, per group or for all managed hosts. @@ -425,29 +425,29 @@ directory structure might look similar to: ├── CA.crt -> /etc/ssl/certs/ca-certificates.crt └── default.key -> private/key.pem -Other authority directories (:file:`acme/` and :file:`external/`) might also contain -various files. +Other authority directories (:file:`acme/` and :file:`external/`) might also +contain various files. -After certificates are copied from Ansible Controller, :program:`pki-realm` script is -executed again for each PKI realm configured on a given host. It checks which -authority directories have signed and valid certificates, picks the first -viable one according to the preference (``external``, ``acme``, ``internal``), -and activates them. +After certificates are copied from the Ansible Controller, the +:program:`pki-realm` script is executed again for each PKI realm configured on +a given host. It checks which authority directories have signed and valid +certificates, picks the first viable one according to +:envvar:`pki_authority_preference` and activates them. Certificate activation entails symlinking the certificate, intermediate and -root files to the :file:`public/` directory and generation of various chain files -- certificate + intermediate, intermediate + root and key + certificate +root files to the :file:`public/` directory and generation of various chain files: +certificate + intermediate, intermediate + root and key + certificate + intermediate (which is stored securely in the :file:`private/` directory). -Some applications do not support separate :file:`dhparam` file, and instead expect +Some applications do not support a separate :file:`dhparam` file, and instead expect that the DHE parameters are present after the X.509 certificate chain. If the debops.dhparam_ role has been configured on a host and Diffie-Hellman parameter support is enabled in a given PKI realm, DHE parameters will be -appended to the final certificate chains (both public and private). When the -debops.dhparam_ regenerates the parameters, :program:`pki-realm` script will +appended to the final certificate chains (both public and private). When +debops.dhparam_ regenerates the parameters, the :program:`pki-realm` script will automatically detect the new ones and update the certificate chains. -The end result is fully configured PKI realm with a set of valid certificates +The end result is a fully configured PKI realm with a set of valid certificates available for other applications and services: .. code-block:: none From 666a25bfd0bf236bae4b7a05e2bd44d571a83ebe Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 14 Aug 2016 19:16:17 +0200 Subject: [PATCH 08/65] Use :envvar: instead of :any: for Sphinx docs --- CHANGES.rst | 6 +++--- defaults/main.yml | 2 +- docs/acme-integration.rst | 18 +++++++++--------- docs/ansible-integration.rst | 4 ++-- docs/custom-files.rst | 14 +++++++------- docs/defaults-detailed.rst | 24 ++++++++++++------------ docs/external-certificates.rst | 2 +- docs/getting-started.rst | 6 +++--- docs/pki-realms.rst | 2 +- docs/system-ca-certificates.rst | 6 +++--- 10 files changed, 42 insertions(+), 42 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 60a0b0f..403d556 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -154,7 +154,7 @@ Added Changed ~~~~~~~ -- Include realms defined in :any:`pki_default_realms` in tasks that copy files +- Include realms defined in :envvar:`pki_default_realms` in tasks that copy files from Ansible Controller depending on an Ansible inventory group. [drybjed_] @@ -208,7 +208,7 @@ Changed ~~~~~~~ - Don't run :program:`pki-authority` script on Ansible Controller if list of - :any:`pki_authorities` is not defined. [drybjed_] + :envvar:`pki_authorities` is not defined. [drybjed_] `debops.pki v0.2.4`_ - 2016-02-21 @@ -364,7 +364,7 @@ Added - Add a way to copy arbitrary files from Ansible Controller to remote host PKI directories. [drybjed_] -- Expose ``ansible_fqdn`` variable as :any:`pki_fqdn` so that it can be overridden +- Expose ``ansible_fqdn`` variable as :envvar:`pki_fqdn` so that it can be overridden if necessary. [drybjed_] Changed diff --git a/defaults/main.yml b/defaults/main.yml index edbb7cf..00575d6 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -206,7 +206,7 @@ pki_acme_tiny_bin: '/usr/local/lib/pki/acme-tiny' # .. envvar:: pki_acme_ca # # Name of the ACME API endpoint used by the ACME client. The name-URL mapping -# is done in :any:`pki_acme_ca_api_map` dictionary variable. +# is done in :envvar:`pki_acme_ca_api_map` dictionary variable. pki_acme_ca: 'le-live' diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index 4a72ff8..97cb55c 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -187,27 +187,27 @@ ACME configuration variables The ``debops.pki`` role has several default variables which can be used to control ACME support. The most important are: -:any:`pki_acme` +:envvar:`pki_acme` Boolean. When ``True``, support for ACME Certificate Authority will be configured for all PKI realms unless disabled on the realm level. By default the role checks if a public IP address is available and a default domain is configured, otherwise the support is disabled automatically. -:any:`pki_acme_install` +:envvar:`pki_acme_install` Boolean. Enable or disable installation of :program:`acme-tiny` and configuration of ACME support without enabling it for all realms. When this variable is set to - ``True`` and :any:`pki_acme` is set to ``False``, ACME support can be enabled + ``True`` and :envvar:`pki_acme` is set to ``False``, ACME support can be enabled independently in each PKI realm. By default, it is set to the same value as - :any:`pki_acme`. + :envvar:`pki_acme`. -:any:`pki_acme_ca` +:envvar:`pki_acme_ca` Name of the ACME Certificate Authority API endpoint to use. Dictionary with - endpoints is defined in the :any:`pki_acme_ca_api_map` variable. By default, + endpoints is defined in the :envvar:`pki_acme_ca_api_map` variable. By default, ``le-live`` is used which points to the Let's Encrypt Live CA. For testing you can switch the default CA to ``le-staging`` which points to Let's Encrypt Staging CA. -:any:`pki_acme_default_subdomains` +:envvar:`pki_acme_default_subdomains` List of subdomains which will be added to the default ACME domain and all other domains configured for ACME certificate by default, can be overridden by ``item.acme_subdomains`` parameter. By default, the ``www.`` subdomain will be @@ -215,7 +215,7 @@ control ACME support. The most important are: need to be correctly configured in the DNS for the Certificate Authority to sign the request. -Each PKI realm configured in the :any:`pki_realms` or ``pki_*_realms`` variables +Each PKI realm configured in the :envvar:`pki_realms` or ``pki_*_realms`` variables can have several parameters related to the ACME certificates: ``item.name`` @@ -233,7 +233,7 @@ can have several parameters related to the ACME certificates: List of subdomains that should be added to all of the ACME apex/root domains. If you want to create an ACME certificate only with the apex domain, you need to use this parameter with ``[]`` value to override - :any:`pki_acme_default_subdomains`. + :envvar:`pki_acme_default_subdomains`. ``item.acme_subdomains`` List of subdomains added to each apex (root) domain configured in the ACME diff --git a/docs/ansible-integration.rst b/docs/ansible-integration.rst index 960a9a0..03e5175 100644 --- a/docs/ansible-integration.rst +++ b/docs/ansible-integration.rst @@ -47,7 +47,7 @@ available facts: The facts listed below are currently static, but are planned to be used in the future for better control over PKI realm directory structure: -``ansible_local.pki.crt`` +:file:`ansible_local.pki.crt` Name of the default certificate symlink located in the PKI realm main directory. @@ -55,7 +55,7 @@ future for better control over PKI realm directory structure: Name of the default private key symlink located in the PKI realm main directory. -``ansible_local.pki.pem`` +:file:`ansible_local.pki.pem` Name of the default private key and certificate bundle symlink located in the PKI realm main directory. diff --git a/docs/custom-files.rst b/docs/custom-files.rst index 1808431..5f1245e 100644 --- a/docs/custom-files.rst +++ b/docs/custom-files.rst @@ -26,7 +26,7 @@ Each element of the file list is a dict with specific parameters: ``group`` File group, depending on the file type it will be ``root`` (for public files) - or a group specified by the :any:`pki_private_group` variable, usually + or a group specified by the :envvar:`pki_private_group` variable, usually ``ssl-cert`` (for private files). ``mode`` @@ -41,14 +41,14 @@ There are multiple list variables which can be used on multiple inventory levels: - all hosts in the inventory: - - :any:`pki_private_files` - - :any:`pki_public_files` + - :envvar:`pki_private_files` + - :envvar:`pki_public_files` - hosts in specific inventory group: - - :any:`pki_group_private_files` - - :any:`pki_group_public_files` + - :envvar:`pki_group_private_files` + - :envvar:`pki_group_public_files` - specific hosts: - - :any:`pki_host_private_files` - - :any:`pki_host_public_files` + - :envvar:`pki_host_private_files` + - :envvar:`pki_host_public_files` The private files will be copied before PKI realms are created, so that you can provide private keys if you want to. Public files will be copied after PKI diff --git a/docs/defaults-detailed.rst b/docs/defaults-detailed.rst index 1827482..0abe079 100644 --- a/docs/defaults-detailed.rst +++ b/docs/defaults-detailed.rst @@ -56,7 +56,7 @@ Ensure two system groups exist, one with a condition: pki_realms ---------- -The set of :any:`pki_realms` lists can be used to define the configuration of PKI +The set of :envvar:`pki_realms` lists can be used to define the configuration of PKI realms located on remote hosts. Each realm keeps a set of private keys and certificates which are signed by the various Certificate Authorities. @@ -90,14 +90,14 @@ List of parameters related to the entire PKI realm: ``authority`` Specify name of the internal Certificate Authority to send the internal certificate requests to instead of the default one configured in - :any:`pki_default_authority` variable. This should be the "normal" name of the + :envvar:`pki_default_authority` variable. This should be the "normal" name of the authority, not it's subdomain name. ``acme`` Optional, boolean. Enable or disable support for ACME Certificate Authority. - Can be used to invert the global :any:`pki_acme` setting per PKI realm if + Can be used to invert the global :envvar:`pki_acme` setting per PKI realm if needed, but support for ACME needs to be present on the remote host for it to - work (see :any:`pki_acme_install` variable). + work (see :envvar:`pki_acme_install` variable). ``internal`` Optional, boolean. Enable or disable support for internal CA certificates in @@ -108,7 +108,7 @@ List of parameters related to the entire PKI realm: Optional. List of directory names (``external``, ``acme``, ``internal``, ``selfsigned``) which determines the order in which the PKI realm looks for valid certificates. The first found valid certificate is enabled. If not - specified, the order configured in :any:`pki_authority_preference` will be used. + specified, the order configured in :envvar:`pki_authority_preference` will be used. ``library`` Optional. Specify name of the crypto library used to generate private key and @@ -123,24 +123,24 @@ List of parameters related to the entire PKI realm: ``private_dir_group`` Optional. System group which will be set as the group of the :file:`private/` directory of a given PKI realm. By default, ``ssl-cert``. It needs to exist, - and can be created using :any:`pki_private_groups_present` list. + and can be created using :envvar:`pki_private_groups_present` list. ``private_file_group`` Optional. System group which will be set as the group of the private keys inside of the :file:`private/` directory. It needs to exist, and can be created - using :any:`pki_private_groups_present` list. + using :envvar:`pki_private_groups_present` list. ``private_dir_acl_groups`` Optional. List of groups which should be allowed execute (``X``) permission to the :file:`private/` realm directory. The access will be granted using filesystem ACL table. If not specified, the list defined in - :any:`pki_private_dir_acl_groups` will be applied. + :envvar:`pki_private_dir_acl_groups` will be applied. ``private_file_acl_groups`` Optional. List of groups which should be allowed read (``r``) permission to the files in the :file:`private/` realm directory. The access will be granted using filesystem ACL table. If not specified, the list defined in - :any:`pki_private_file_acl_groups` will be applied. + :envvar:`pki_private_file_acl_groups` will be applied. ``dhparam`` Optional, boolean. Enable or disable support for adding the Diffie-Hellman @@ -163,7 +163,7 @@ respectively: ``default_domain`` Optional. Change the default domain used by a given PKI realm. If not specified, default domain is based on the ``name`` parameter if it has at - least 1 dot, or it will be taken from :any:`pki_default_domain` variable which + least 1 dot, or it will be taken from :envvar:`pki_default_domain` variable which is populated by the ``ansible_domain`` variable. ``default_subdomains``, ``acme_default_subdomains`` @@ -171,8 +171,8 @@ respectively: realm. A special value ``_wildcard_`` can be used to indicate that a wildcard domain should be present in the certificate. - If not specified, :any:`pki_default_subdomains` (for internal CA) and - :any:`pki_acme_default_subdomains` (for ACME CA) will be used. The PKI + If not specified, :envvar:`pki_default_subdomains` (for internal CA) and + :envvar:`pki_acme_default_subdomains` (for ACME CA) will be used. The PKI parameters can be set to empty to override the default variables. ``subject``, ``acme_subject`` diff --git a/docs/external-certificates.rst b/docs/external-certificates.rst index 7189385..d4ffc71 100644 --- a/docs/external-certificates.rst +++ b/docs/external-certificates.rst @@ -105,7 +105,7 @@ Because files copied from :file:`by-group/all/` and :file:`by-group/inventory_gr directories are not overwritten automatically, you will need to remove the corresponding files on remote hosts yourself if you want to update them. -The :any:`pki_inventory_groups` default variable is a list of Ansible inventory +The :envvar:`pki_inventory_groups` default variable is a list of Ansible inventory groups that will have their corresponding directories. You need to specify your custom inventory groups in order to have them "active". diff --git a/docs/getting-started.rst b/docs/getting-started.rst index dac3933..124bb8d 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -47,7 +47,7 @@ remote hosts. Most of these variables are related to Certificate Authority operation, the ones you will likely want to change are: -:any:`pki_ca_domain` +:envvar:`pki_ca_domain` This is the DNS domain used as a base for the internal Certificate Authority Distinguished Names. If you use more than one domain in your environment, you should set this variable to your preferred domain on all hosts, through @@ -57,11 +57,11 @@ ones you will likely want to change are: configured with no default domain, or the provider domain might be set up by default. Make sure that you check what domain is used by your remote hosts. -:any:`pki_ca_organization` +:envvar:`pki_ca_organization` This is the organizations name used as a base for the internal Certificate Authority Distinguished Names. -:any:`pki_ca_root_dn`, :any:`pki_ca_domain_dn`, :any:`pki_ca_service_dn` +:envvar:`pki_ca_root_dn`, :envvar:`pki_ca_domain_dn`, :envvar:`pki_ca_service_dn` These variables define the Distinguished Name or Subject of the Root Certificate Authority and Domain Certificate Authority. The value is a list of DN entries which define the subject. diff --git a/docs/pki-realms.rst b/docs/pki-realms.rst index fbad732..f4027ff 100644 --- a/docs/pki-realms.rst +++ b/docs/pki-realms.rst @@ -317,7 +317,7 @@ on the remote host. The directory structure changes a bit: As you can see, the configuration of a Certificate Request for an internal CA has been created, and the :file:`internal/request.pem` file has been generated, -using the ``private/key.pem`` RSA key. By default, if no :file:`root.pem` +using the :file:`private/key.pem` RSA key. By default, if no :file:`root.pem` certificate is provided, the system CA certificate store is symlinked as :file:`CA.crt`. diff --git a/docs/system-ca-certificates.rst b/docs/system-ca-certificates.rst index 83d888e..e02db6a 100644 --- a/docs/system-ca-certificates.rst +++ b/docs/system-ca-certificates.rst @@ -25,12 +25,12 @@ from the system CA store. By default, Debian hosts automatically trust new Root Certificate Authorities added in the ``ca-certificates`` package. To control this, you can use -:any:`pki_system_ca_certificates_trust_new` boolean variable. Setting this +:envvar:`pki_system_ca_certificates_trust_new` boolean variable. Setting this variable to ``True`` will ensure that new Root CA certificates are trusted. Setting it to ``False`` will not enable new CA certificates automatically. -You can use :any:`pki_system_ca_certificates_blacklist` and -:any:`pki_system_ca_certificates_whitelist` list variables to define which +You can use :envvar:`pki_system_ca_certificates_blacklist` and +:envvar:`pki_system_ca_certificates_whitelist` list variables to define which certificates will be excluded/included in the CA store. Each list element is a regexp of the certificate file name. If a given file is found in both lists, it will be excluded from the certificate store. From dd407d482e7c9b501c14a91430181c9a3580bd73 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 19:30:03 +0200 Subject: [PATCH 09/65] Be more precise what `pki_acme_tiny_version` can be used for --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 00575d6..34a4ff2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -184,7 +184,7 @@ pki_acme_tiny_repo: 'https://github.com/diafygi/acme-tiny' # .. envvar:: pki_acme_tiny_version # -# Branch of the :program:`acme-tiny` source which should be checked. +# Branch or version of the :program:`acme-tiny` source which should be used. pki_acme_tiny_version: 'master' From 979958674bbb3ee1b74b2162534a2ec5446af5b2 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 19:30:44 +0200 Subject: [PATCH 10/65] Trim useless trailing stuff --- docs/custom-hooks.rst | 1 - handlers/main.yml | 1 - tasks/ca_certificates.yml | 1 - tasks/main.yml | 3 +-- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/custom-hooks.rst b/docs/custom-hooks.rst index 0d3905d..b4e742a 100644 --- a/docs/custom-hooks.rst +++ b/docs/custom-hooks.rst @@ -157,4 +157,3 @@ it reloads the :program:`nginx` daemon so that new certificate can be activated. done fi - diff --git a/handlers/main.yml b/handlers/main.yml index a01e3d9..b6b26ac 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -21,4 +21,3 @@ - name: Install ca-certificates.crt into Postfix chroot shell: test -d /var/spool/postfix && cp -f /etc/ssl/certs/ca-certificates.crt /var/spool/postfix/etc/ssl/certs/ca-certificates.crt || true - diff --git a/tasks/ca_certificates.yml b/tasks/ca_certificates.yml index 658f888..6615a35 100644 --- a/tasks/ca_certificates.yml +++ b/tasks/ca_certificates.yml @@ -42,4 +42,3 @@ group: 'root' mode: '0644' notify: [ 'Reconfigure ca-certificates' ] - diff --git a/tasks/main.yml b/tasks/main.yml index 6b4c17b..f3a823f 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -154,7 +154,7 @@ owner: 'root' group: 'root' mode: '0755' - + - name: Ensure that sensitive files are excluded from version control template: src: 'etc/pki/gitignore.j2' @@ -484,4 +484,3 @@ - name: Flush handlers for PKI if needed meta: flush_handlers when: pki_register_facts|changed - From 2f03591510381c32d849737d59f76a0773195faf Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 19:33:56 +0200 Subject: [PATCH 11/65] Move comments in function bodys for better Vim folds and optimize --- files/secret/pki/lib/pki-authority | 46 ++++++++++++++---------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index be718e2..5bc7abd 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -4,15 +4,15 @@ # Copyright (C) 2016 Maciej Delmanowski # Homepage: https://debops.org/ -set -eu -o pipefail +set -o nounset -o pipefail -o errexit umask 022 script="$(basename "${0}")" -# OpenSSL writes to stderr/stdout even when there are no errors. So just -# display the output if the exit code was != 0 to simplify debugging. _openssl () { + # OpenSSL writes to stderr/stdout even when there are no errors. So just + # display the output if the exit code was != 0 to simplify debugging. set +e _openssl_out="$(openssl ${@} 2>&1)" local rc=$? @@ -23,23 +23,23 @@ _openssl () { echo "Details:" >&2 echo "${_openssl_out}" >&2 exit ${rc} - fi - unset _openssl_out - return ${rc} + fi + unset _openssl_out + return ${rc} } -# Normalize version numbers for comparsion version () { + # Normalize version numbers for compassion. echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' } -# Check if an associative array has a specified key present key_exists () { + # Check if an associative array has a specified key present eval '[ ${'$1'[$2]+test_of_existence} ]' } -# Check if an element is in an array array_exists () { + # Check if an element is in an array local array="$1[@]" local seeking=${2} local in=1 @@ -52,23 +52,24 @@ array_exists () { return $in } -# Get an absolute path to a file get_absolute_path () { + # Get an absolute path to a file python -c 'import sys, os.path; print(os.path.abspath(sys.argv[1]))' "${1}" } -# Get a relative path to a file get_relative_path () { + # Get a relative path to a file python -c 'import sys, os.path; print(os.path.relpath(sys.argv[1], sys.argv[2]))' "${1}" "${2:-$PWD}" } -# Wrap dnsdomainname if it's not present (on MacOS X) get_dnsdomainname () { + # Wrap dnsdomainname if it's not present (on MacOS X) + if type dnsdomainname > /dev/null 2>&1 ; then dnsdomainname else - - local fqdn="$(hostname -f)" + local fqdn + fqdn="$(hostname -f)" if [[ ${fqdn} == *.* ]] ; then echo "${fqdn#*.}" else @@ -122,13 +123,6 @@ initialize_environment () { test -d ${config['pki_root']} || mkdir -p -m ${config['public_dir_mode']} ${config['pki_root']} } -print_usage () { - cat << EOF -Usage: ${script} [parameters] -EOF - -} - enter_authority () { local authority="${1}" @@ -987,8 +981,8 @@ generate_openssl_serial () { fi } -# GnuTLS doesn't use this, so do nothing generate_gnutls_serial () { + # GnuTLS doesn't use this, so do nothing return 0 } @@ -1492,7 +1486,12 @@ sub_init () { fi } -subcommand="" +print_usage () { + cat << EOF +Usage: ${script} [parameters] +EOF + +} initialize_environment @@ -1519,4 +1518,3 @@ else print_usage exit 1 fi - From afda3648f7f6e378390e59f9636596eb5e0db160 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 19:40:31 +0200 Subject: [PATCH 12/65] Fix SC2166 for pki-authority Ref: https://github.com/koalaman/shellcheck/wiki/SC2166 --- files/secret/pki/lib/pki-authority | 112 ++++++++++++++--------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 5bc7abd..8240680 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -152,7 +152,7 @@ update_symlink () { for target in ${@} ; do if [ -r "${target}" ] ; then - if [ -L "${symlink_target}" -a "$(readlink "${symlink_target}")" == "${target}" ] ; then + if [ -L "${symlink_target}" ] && [ "$(readlink "${symlink_target}")" == "${target}" ] ; then break else ln -sf "${target}" "${symlink_target}" @@ -169,7 +169,7 @@ create_openssl_request_config () { local config_file="${1:-config/openssl-request.conf}" local config_dn="${2}" - if [ -n "${config_file}" -a -n "${config_dn}" -a ! -r "${config_file}" ] ; then + if [ -n "${config_file}" ] && [ -n "${config_dn}" ] && [ ! -r "${config_file}" ] ; then cat << EOF > ${config_file} # Configuration file generated by pki-authority @@ -202,7 +202,7 @@ create_gnutls_request_config () { local config_file="${1:-config/gnutls-request.conf}" local config_dn="${2}" - if [ -n "${config_file}" -a -n "${config_dn}" -a ! -r "${config_file}" ] ; then + if [ -n "${config_file}" ] && [ -n "${config_dn}" ] && [ ! -r "${config_file}" ] ; then cat << EOF > ${config_file} # Configuration file generated by pki-authority @@ -227,7 +227,7 @@ create_openssl_selfsign_config () { local config_domain="${3}" local config_ca_type="${4}" - if [ -n "${config_file}" -a ! -r "${config_file}" ] ; then + if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then cat << EOF > ${config_file} # Configuration file generated by pki-authority @@ -283,7 +283,7 @@ emailAddress = optional [ extension_default ] EOF - if [ -z "${config_ca_type}" -o "${config_ca_type}" = "root" ] ; then + if [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then cat << EOF >> ${config_file} basicConstraints = critical, CA:TRUE keyUsage = critical, keyCertSign, cRLSign @@ -311,7 +311,7 @@ create_gnutls_selfsign_config () { local config_domain="${3}" local config_ca_type="${4}" - if [ -n "${config_file}" -a ! -r "${config_file}" ] ; then + if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then cat << EOF > ${config_file} # Configuration file generated by pki-authority @@ -320,7 +320,7 @@ expiration_days = ${config['root_sign_days']:-$(( ${config['pki_default_sign_bas EOF - if [ -z "${config_ca_type}" -o "${config_ca_type}" = "root" ] ; then + if [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then cat << EOF >> ${config_file} ca cert_signing_key @@ -352,7 +352,7 @@ create_openssl_sign_config () { local config_ca_type="${4}" local config_issuer="${5}" - if [ -n "${config_file}" -a ! -r "${config_file}" ] ; then + if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then cat << EOF > ${config_file} # Configuration file generated by pki-authority @@ -380,7 +380,7 @@ policy = policy_default x509_extensions = extension_default EOF - if [ -z "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "root" ] ; then + if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then cat << EOF >> ${config_file} copy_extensions = none default_days = ${config['ca_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_ca_sign_multiplier']} ))} @@ -388,7 +388,7 @@ default_crl_days = 365 default_md = sha256 EOF - elif [ -z "${config_issuer}" -a "${config_ca_type}" = "service" ] ; then + elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then cat << EOF >> ${config_file} copy_extensions = copy default_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} @@ -396,7 +396,7 @@ default_crl_days = 365 default_md = sha256 EOF - elif [ -n "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "server" ] ; then + elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then cat << EOF >> ${config_file} copy_extensions = copy default_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} @@ -423,7 +423,7 @@ subjectKeyIdentifier = hash EOF - if [ -z "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "root" ] ; then + if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then cat << EOF >> ${config_file} [ policy_default ] countryName = optional @@ -434,7 +434,7 @@ commonName = optional emailAddress = optional EOF - elif [ -z "${config_issuer}" -a "${config_ca_type}" = "service" ] ; then + elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then cat << EOF >> ${config_file} [ policy_default ] countryName = optional @@ -445,7 +445,7 @@ commonName = optional emailAddress = optional EOF - elif [ -n "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "server" ] ; then + elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then cat << EOF >> ${config_file} [ policy_default ] countryName = optional @@ -458,7 +458,7 @@ emailAddress = optional EOF fi - if [ -z "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "root" ] ; then + if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then cat << EOF >> ${config_file} [ extension_default ] authorityInfoAccess = @issuer_info @@ -469,7 +469,7 @@ keyUsage = critical, keyCertSign, cRLSign subjectKeyIdentifier = hash EOF - elif [ -z "${config_issuer}" -a "${config_ca_type}" = "service" ] ; then + elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then cat << EOF >> ${config_file} [ extension_default ] authorityInfoAccess = @issuer_info @@ -481,7 +481,7 @@ keyUsage = critical, digitalSignature, keyEncipherment subjectKeyIdentifier = hash EOF - elif [ -n "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "server" ] ; then + elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then cat << EOF >> ${config_file} [ extension_default ] authorityInfoAccess = @issuer_info @@ -506,14 +506,14 @@ create_gnutls_sign_config () { local config_ca_type="${4}" local config_issuer="${5}" - if [ -n "${config_file}" -a ! -r "${config_file}" ] ; then + if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then cat << EOF > ${config_file} # Configuration file generated by pki-authority EOF - if [ -z "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "root" ] ; then + if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then cat << EOF >> ${config_file} expiration_days = ${config['ca_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_ca_sign_multiplier']} ))} @@ -527,7 +527,7 @@ crl_dist_points = "http://${config_name}.${config_domain}/crl/" #ocsp_uri = "http://${config_name}.${config_domain}/ocsp/" EOF - elif [ -z "${config_issuer}" -a "${config_ca_type}" = "service" ] ; then + elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then cat << EOF >> ${config_file} expiration_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} #copy_extensions = copy @@ -542,7 +542,7 @@ crl_dist_points = "http://${config_name}.${config_domain}/crl/" #ocsp_uri = "http://${config_name}.${config_domain}/ocsp/" EOF - elif [ -n "${config_issuer}" -a -z "${config_ca_type}" -o "${config_ca_type}" = "server" ] ; then + elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then cat << EOF >> ${config_file} expiration_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} #copy_extensions = copy @@ -591,7 +591,7 @@ check_openssl_req_session_match () { local check_req="${1}" local check_session="${PKI_SESSION_TOKEN:-}" - if [ -n "${check_req}" -a -n "${check_session}" ] ; then + if [ -n "${check_req}" ] && [ -n "${check_session}" ] ; then if [ -r "${check_req}" ] ; then openssl asn1parse -in "${check_req}" | grep -q "${check_session}" rc=$? @@ -611,9 +611,9 @@ check_openssl_crt_ca_match () { local check_ca="${2}" local check_ca_issuer="${3:-}" - if [ -n "${check_crt}" -a -n "${check_ca}" ] ; then - if [ -r "${check_crt}" -a -r "${check_ca}" ] ; then - if [ -n "${check_ca_issuer}" -a -r "${check_ca_issuer}" ] ; then + if [ -n "${check_crt}" ] && [ -n "${check_ca}" ] ; then + if [ -r "${check_crt}" ] && [ -r "${check_ca}" ] ; then + if [ -n "${check_ca_issuer}" ] && [ -r "${check_ca_issuer}" ] ; then _openssl verify -CAfile "${check_ca_issuer}" -untrusted "${check_ca}" "${check_crt}" local rc=$? else @@ -657,16 +657,16 @@ sign_openssl_certificate () { local sign_sect="${4}" local sign_ext="${5}" - if [ -n "${sign_config}" -a -n "${sign_request}" -a -n "${sign_out}" ] ; then + if [ -n "${sign_config}" ] && [ -n "${sign_request}" ] && [ -n "${sign_out}" ] ; then - if [ -r "${sign_request}" -a ! -r "${sign_out}" ] ; then + if [ -r "${sign_request}" ] && [ ! -r "${sign_out}" ] ; then _openssl ca -batch -notext \ -in "${sign_request}" -out "${sign_out}.tmp" \ -name "${sign_sect}" -extensions "${sign_ext}" \ -config "${sign_config}" - if [ -r "${sign_out}.tmp" -a -s "${sign_out}.tmp" ] ; then + if [ -r "${sign_out}.tmp" ] && [ -s "${sign_out}.tmp" ] ; then mv "${sign_out}.tmp" "${sign_out}" fi @@ -704,15 +704,15 @@ sign_openssl_host_certificate () { local sign_out="${3}" local sign_alt="${4:-}" - if [ -n "${sign_config}" -a -n "${sign_request}" -a -n "${sign_out}" ] ; then + if [ -n "${sign_config}" ] && [ -n "${sign_request}" ] && [ -n "${sign_out}" ] ; then - if [ -r "${sign_request}" -a ! -r "${sign_out}" ] ; then + if [ -r "${sign_request}" ] && [ ! -r "${sign_out}" ] ; then _openssl ca -batch -notext \ -in "${sign_request}" -out "${sign_out}.tmp" \ -config "${sign_config}" - if [ -r "${sign_out}.tmp" -a -s "${sign_out}.tmp" ] ; then + if [ -r "${sign_out}.tmp" ] && [ -s "${sign_out}.tmp" ] ; then mv "${sign_out}.tmp" "${sign_out}" fi @@ -779,15 +779,15 @@ sign_gnutls_host_certificate () { local sign_out="${3}" local sign_alt="${4:-}" - if [ -n "${sign_config}" -a -n "${sign_request}" -a -n "${sign_out}" ] ; then + if [ -n "${sign_config}" ] && [ -n "${sign_request}" ] && [ -n "${sign_out}" ] ; then - if [ -r "${sign_request}" -a ! -r "${sign_out}" ] ; then + if [ -r "${sign_request}" ] && [ ! -r "${sign_out}" ] ; then certtool --generate-certificate --template "${sign_config}" \ --load-request "${sign_request}" --load-ca-privkey private/key.pem \ --load-ca-certificate subject/cert.pem --outfile "${sign_out}.tmp" - if [ -r "${sign_out}.tmp" -a -s "${sign_out}.tmp" ] ; then + if [ -r "${sign_out}.tmp" ] && [ -s "${sign_out}.tmp" ] ; then mv "${sign_out}.tmp" "${sign_out}" fi @@ -853,14 +853,14 @@ sign_openssl_ca_certificate () { local sign_request="${2}" local sign_out="${3}" - if [ -n "${sign_config}" -a -n "${sign_request}" -a -n "${sign_out}" ] ; then - if [ -r "${sign_request}" -a ! -r "${sign_out}" ] ; then + if [ -n "${sign_config}" ] && [ -n "${sign_request}" ] && [ -n "${sign_out}" ] ; then + if [ -r "${sign_request}" ] && [ ! -r "${sign_out}" ] ; then _openssl ca -batch -notext \ -in "${sign_request}" -out "${sign_out}.tmp" \ -config "${sign_config}" - if [ -r "${sign_out}.tmp" -a -s "${sign_out}.tmp" ] ; then + if [ -r "${sign_out}.tmp" ] && [ -s "${sign_out}.tmp" ] ; then mv "${sign_out}.tmp" "${sign_out}" fi @@ -874,14 +874,14 @@ sign_gnutls_ca_certificate () { local sign_request="${2}" local sign_out="${3}" - if [ -n "${sign_config}" -a -n "${sign_request}" -a -n "${sign_out}" ] ; then - if [ -r "${sign_request}" -a ! -r "${sign_out}" ] ; then + if [ -n "${sign_config}" ] && [ -n "${sign_request}" ] && [ -n "${sign_out}" ] ; then + if [ -r "${sign_request}" ] && [ ! -r "${sign_out}" ] ; then certtool --generate-certificate --template "${sign_config}" \ --load-request "${sign_request}" --load-ca-privkey private/key.pem \ --load-ca-certificate subject/cert.pem --outfile "${sign_out}.tmp" - if [ -r "${sign_out}.tmp" -a -s "${sign_out}.tmp" ] ; then + if [ -r "${sign_out}.tmp" ] && [ -s "${sign_out}.tmp" ] ; then mv "${sign_out}.tmp" "${sign_out}" fi @@ -895,14 +895,14 @@ sign_openssl_root_certificate () { local sign_request="${2}" local sign_out="${3}" - if [ -n "${sign_config}" -a -n "${sign_request}" -a -n "${sign_out}" ] ; then - if [ -r "${sign_request}" -a ! -r "${sign_out}" ] ; then + if [ -n "${sign_config}" ] && [ -n "${sign_request}" ] && [ -n "${sign_out}" ] ; then + if [ -r "${sign_request}" ] && [ ! -r "${sign_out}" ] ; then _openssl ca -selfsign -batch -notext \ -in "${sign_request}" -out "${sign_out}.tmp" \ -config "${sign_config}" - if [ -r "${sign_out}.tmp" -a -s "${sign_out}.tmp" ] ; then + if [ -r "${sign_out}.tmp" ] && [ -s "${sign_out}.tmp" ] ; then mv "${sign_out}.tmp" "${sign_out}" fi @@ -916,14 +916,14 @@ sign_gnutls_root_certificate () { local sign_request="${2}" local sign_out="${3}" - if [ -n "${sign_config}" -a -n "${sign_request}" -a -n "${sign_out}" ] ; then - if [ -r "${sign_request}" -a ! -r "${sign_out}" ] ; then + if [ -n "${sign_config}" ] && [ -n "${sign_request}" ] && [ -n "${sign_out}" ] ; then + if [ -r "${sign_request}" ] && [ ! -r "${sign_out}" ] ; then certtool --generate-self-signed --template "${sign_config}" \ --load-request "${sign_request}" --load-privkey private/key.pem \ --outfile "${sign_out}.tmp" - if [ -r "${sign_out}.tmp" -a -s "${sign_out}.tmp" ] ; then + if [ -r "${sign_out}.tmp" ] && [ -s "${sign_out}.tmp" ] ; then mv "${sign_out}.tmp" "${sign_out}" fi @@ -937,8 +937,8 @@ generate_openssl_request () { local req_config="${1}" local req_out="${2}" - if [ -n "${req_config}" -a -n "${req_out}" ] ; then - if [ -r "${req_config}" -a ! -r "${req_out}" ] ; then + if [ -n "${req_config}" ] && [ -n "${req_out}" ] ; then + if [ -r "${req_config}" ] && [ ! -r "${req_out}" ] ; then local req_keyfile=$(grep -E '^default_keyfile\s+=\s+' "${req_config}" | awk '{print $3}') if [ -n "${req_keyfile}" ] ; then @@ -958,8 +958,8 @@ generate_gnutls_request () { local req_config="${1}" local req_out="${2}" - if [ -n "${req_config}" -a -n "${req_out}" ] ; then - if [ -r "${req_config}" -a ! -r "${req_out}" ] ; then + if [ -n "${req_config}" ] && [ -n "${req_out}" ] ; then + if [ -r "${req_config}" ] && [ ! -r "${req_out}" ] ; then certtool --generate-request --template "${req_config}" \ --load-privkey private/key.pem --outfile "${req_out}.tmp" @@ -976,7 +976,7 @@ generate_openssl_serial () { local serial_file="${1}" local serial_length="${2:-16}" - if [ -n "${serial_file}" -a ! -r "${serial_file}" ] ; then + if [ -n "${serial_file}" ] && [ ! -r "${serial_file}" ] ; then openssl rand -hex "${serial_length}" > "${serial_file}" fi } @@ -1154,7 +1154,7 @@ sub_sign () { sub_sign-by-host () { if [ $# -gt 0 ] ; then - if [ -d requests -a -d realms ] ; then + if [ -d requests ] && [ -d realms ] ; then for authority in requests/* ; do if [ -r "authorities/$(basename "${authority}")/subject/cert.pem" ] ; then for host in ${authority}/* ; do @@ -1170,7 +1170,7 @@ sub_sign-by-host () { local alt_authority="" - if [ -n "${config['alt_authority']}" -a -d ../${config['alt_authority']} ] ; then + if [ -n "${config['alt_authority']}" ] && [ -d ../${config['alt_authority']} ] ; then alt_authority="$(get_absolute_path ../${config['alt_authority']})" fi @@ -1365,12 +1365,12 @@ sub_new-ca () { generate_${library}_request config/${library}-request.conf subject/request.pem - if [ -z "${config['issuer_name']}" -a ! -L issuer ] ; then + if [ -z "${config['issuer_name']}" ] && [ ! -L issuer ] ; then sign_${library}_root_certificate config/${library}-selfsign.conf \ subject/request.pem subject/cert.pem - elif [ -n "${config['issuer_name']}" -a -L issuer ] ; then + elif [ -n "${config['issuer_name']}" ] && [ -L issuer ] ; then local subject_dir="$(pwd)" cd issuer sign_${library}_ca_certificate config/${library}-sign.conf \ @@ -1378,7 +1378,7 @@ sub_new-ca () { cd - > /dev/null fi - if [ "${config['system_ca']}" = "true" -a -n "${config['pki_ca_certificates']}" -a -n "${config['subdomain']}" -a -z "${config['issuer_name']}" -a ! -L issuer ] ; then + if [ "${config['system_ca']}" = "true" ] && [ -n "${config['pki_ca_certificates']}" ] && [ -n "${config['subdomain']}" ] && [ -z "${config['issuer_name']}" ] && [ ! -L issuer ] ; then if [ -r "$(dirname "${config['pki_ca_certificates']}")/${config['subdomain']}.${config['domain']}.crt" ] ; then if ! diff -q -N "$(get_relative_path "subject/cert.pem" "${config['pki_ca_certificates']}")" "${config['pki_ca_certificates']}/${config['subdomain']}.${config['domain']}.crt" > /dev/null ; then ln -sf "$(get_relative_path "subject/cert.pem" "${config['pki_ca_certificates']}")" "${config['pki_ca_certificates']}/${config['subdomain']}.${config['domain']}.crt" From de51ad4b1d23dfd0f3d10c5318a0cc57b5279de5 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 19:47:06 +0200 Subject: [PATCH 13/65] Fix more Shellcheck warnings --- files/secret/pki/lib/pki-authority | 36 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 8240680..8bb9935 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -602,8 +602,7 @@ check_openssl_req_session_match () { } check_gnutls_req_session_match () { - local rc=$(check_openssl_req_session_match "${@}") - return "${rc}" + return "$(check_openssl_req_session_match "${@}")" } check_openssl_crt_ca_match () { @@ -627,16 +626,18 @@ check_openssl_crt_ca_match () { } check_gnutls_crt_ca_match () { - local rc=$(check_openssl_crt_ca_match "${@}") - return "${rc}" + return "$(check_openssl_crt_ca_match "${@}")" } check_openssl_req_crt_match () { local check_req="${1}" local check_crt="${2}" - local md5_req="$(openssl req -noout -modulus -in "${check_req}" | md5sum | awk '{print $1}')" - local md5_crt="$(openssl x509 -noout -modulus -in "${check_crt}" | md5sum | awk '{print $1}')" + local md5_req + local md5_crt + + md5_req="$(openssl req -noout -modulus -in "${check_req}" | md5sum | awk '{print $1}')" + md5_crt="$(openssl x509 -noout -modulus -in "${check_crt}" | md5sum | awk '{print $1}')" if [ "${md5_req}" = "${md5_crt}" ] ; then return 0 @@ -646,8 +647,7 @@ check_openssl_req_crt_match () { } check_gnutls_req_crt_match () { - local rc=$(check_openssl_req_crt_match "${@}") - return "${rc}" + return "$(check_openssl_req_crt_match "${@}")" } sign_openssl_certificate () { @@ -940,7 +940,8 @@ generate_openssl_request () { if [ -n "${req_config}" ] && [ -n "${req_out}" ] ; then if [ -r "${req_config}" ] && [ ! -r "${req_out}" ] ; then - local req_keyfile=$(grep -E '^default_keyfile\s+=\s+' "${req_config}" | awk '{print $3}') + local req_keyfile + req_keyfile=$(grep -E '^default_keyfile\s+=\s+' "${req_config}" | awk '{print $3}') if [ -n "${req_keyfile}" ] ; then openssl req -new -key "${req_keyfile}" -config "${req_config}" -out "${req_out}.tmp" else @@ -1016,7 +1017,7 @@ generate_gnutls_rsa_private_key () { local key_group="${3:-${config['private_file_group']}}" if ! [ -r "${key_file}" ] ; then - if [ $(version $(certtool --version | head -n 1 | awk '{print $NF}')) -lt $(version 3.3.0) ] ; then + if [ "$(version "$(certtool --version | head -n 1 | awk '{print $NF}')")" -lt "$(version 3.3.0)" ] ; then certtool --generate-privkey --outfile "${key_file}.tmp" --bits "${key_size}" else certtool --generate-privkey --rsa --outfile "${key_file}.tmp" --bits "${key_size}" @@ -1143,8 +1144,10 @@ sub_sign () { enter_authority ${args['name']} local library="${config['pki_library']}" - local input="$(get_absolute_path ${args['req']})" - local output="$(get_absolute_path ${args['out']})" + local input + local output + input="$(get_absolute_path ${args['req']})" + output="$(get_absolute_path ${args['out']})" sign_${library}_certificate "config/${library}-sign.conf" "${input}" "${output}" @@ -1163,8 +1166,10 @@ sub_sign-by-host () { for realm in ${host}/* ; do if [ -r "${realm}/request.pem" ] ; then - local input="$(get_absolute_path "${realm}"/request.pem)" - local output="$(get_absolute_path "realms/by-host/$(basename "${play_host}")/$(basename "${realm}")/internal/cert.pem")" + local input + local output + input="$(get_absolute_path "${realm}"/request.pem)" + output="$(get_absolute_path "realms/by-host/$(basename "${play_host}")/$(basename "${realm}")/internal/cert.pem")" enter_authority "$(basename "${authority}")" @@ -1371,7 +1376,8 @@ sub_new-ca () { subject/request.pem subject/cert.pem elif [ -n "${config['issuer_name']}" ] && [ -L issuer ] ; then - local subject_dir="$(pwd)" + local subject_dir + subject_dir="$(pwd)" cd issuer sign_${library}_ca_certificate config/${library}-sign.conf \ "${subject_dir}/subject/request.pem" "${subject_dir}/subject/cert.pem" From 46bd9905e4043442925008ee2d3bcbec28f82e1c Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 19:57:02 +0200 Subject: [PATCH 14/65] Mark redundant parts between the scripts So that if one gets updated, the other hopefully will also be updated. --- files/secret/pki/lib/pki-authority | 22 ++++++++++--------- files/usr/local/lib/pki/pki-realm | 34 ++++++++++++++++-------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 8bb9935..4fc9197 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -28,16 +28,6 @@ _openssl () { return ${rc} } -version () { - # Normalize version numbers for compassion. - echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' -} - -key_exists () { - # Check if an associative array has a specified key present - eval '[ ${'$1'[$2]+test_of_existence} ]' -} - array_exists () { # Check if an element is in an array local array="$1[@]" @@ -52,6 +42,17 @@ array_exists () { return $in } +# Inlined in the following scripts: pki-authority, pki-realm {{{ +version () { + # Normalize version numbers for compassion. + echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' +} + +key_exists () { + # Check if an associative array has a specified key present + eval '[ ${'$1'[$2]+test_of_existence} ]' +} + get_absolute_path () { # Get an absolute path to a file python -c 'import sys, os.path; print(os.path.abspath(sys.argv[1]))' "${1}" @@ -77,6 +78,7 @@ get_dnsdomainname () { fi fi } +# }}} initialize_environment () { diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 5fd4c62..0bd9af7 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -14,13 +14,8 @@ pid="$$" state=() -# Normalize version numbers for comparsion -version () { - echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' -} - -# Display a message if script is used interactively, otherwise send it to syslog log_message () { + # Display a message if script is used interactively, otherwise send it to syslog local msg="${1:-}" if [ -n "${msg}" ] ; then @@ -32,8 +27,8 @@ log_message () { fi } -# Clean up pidfile clean_up () { + # Clean up pidfile local pidfile="${1}" if [ -n "${pidfile}" -a -r "${pidfile}" ] ; then @@ -42,8 +37,8 @@ clean_up () { exit 0 } -# Wait for the specified process to exit wait_for_pid () { + # Wait for the specified process to exit local pidfile="${1}" if [ -n "${pidfile}" -a -r "${pidfile}" ] ; then @@ -73,28 +68,35 @@ create_lock () { trap "clean_up ${pidfile}" EXIT } -# Check if an associative array has a specified key present -key_exists() { +# Inlined in the following scripts: pki-authority, pki-realm {{{ +version () { + # Normalize version numbers for compassion. + echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' +} + +key_exists () { + # Check if an associative array has a specified key present eval '[ ${'$1'[$2]+test_of_existence} ]' } -# Get an absolute path to a file get_absolute_path () { + # Get an absolute path to a file python -c 'import sys, os.path; print os.path.abspath(sys.argv[1])' "${1}" } -# Get a relative path to a file get_relative_path () { + # Get a relative path to a file python -c 'import sys, os.path; print os.path.relpath(sys.argv[1], sys.argv[2])' "${1}" "${2:-$PWD}" } -# Wrap dnsdomainname if it's not present (on MacOS X) get_dnsdomainname () { + # Wrap dnsdomainname if it's not present (on MacOS X) + if type dnsdomainname > /dev/null 2>&1 ; then dnsdomainname else - - local fqdn="$(hostname -f)" + local fqdn + fqdn="$(hostname -f)" if [[ ${fqdn} == *.* ]] ; then echo "${fqdn#*.}" else @@ -102,6 +104,7 @@ get_dnsdomainname () { fi fi } +# }}} initialize_environment () { @@ -2405,4 +2408,3 @@ else print_usage exit 1 fi - From c194577e8ee17fc52f91ecf5896f432a1329ed72 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 20:01:11 +0200 Subject: [PATCH 15/65] Move comments in function bodys for better Vim folds and optimize --- files/usr/local/lib/pki/pki-realm | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 0bd9af7..86cd343 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -4,7 +4,7 @@ # Copyright (C) 2016 Maciej Delmanowski # Homepage: https://debops.org/ -set -eu -o pipefail +set -o nounset -o pipefail -o errexit umask 022 @@ -265,13 +265,6 @@ initialize_environment () { test -d "${config['pki_root']}" || mkdir -p -m "${config['public_dir_mode']}" "${config['pki_root']}" } -print_usage () { - cat << EOF -Usage: ${script_name} [parameters] -EOF - -} - check_openssl_key_req_match () { local check_key="${1}" local check_req="${2}" @@ -1341,9 +1334,9 @@ check_files () { } -# Select the preferred authority in a given PKI realm (external, acme, -# internal) and check all of the files, make sure that everything is in order process_public_files () { + # Select the preferred authority in a given PKI realm (external, acme, + # internal) and check all of the files, make sure that everything is in order local authority_preference=( $(echo "${config['pki_authority_preference']}" | tr "/" " ") ) @@ -2381,7 +2374,12 @@ sub_schedule () { fi } -subcommand="" +print_usage () { + cat << EOF +Usage: ${script_name} [parameters] +EOF + +} initialize_environment From 79a062e2992b9bd7b9f6c4d216ed8964d7ed76b2 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 21:11:17 +0200 Subject: [PATCH 16/65] Fix more Shellcheck warnings --- files/usr/local/lib/pki/pki-realm | 95 +++++++++++++++++-------------- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 86cd343..0196c37 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -196,7 +196,7 @@ initialize_environment () { config["realm_dir_group"]="root" config["realm_file_group"]="root" - if $(getent group "${config['private_group']}" > /dev/null) ; then + if getent group "${config['private_group']}" > /dev/null ; then config["private_dir_group"]="${config['private_group']}" config["private_file_group"]="${config['private_group']}" else @@ -204,7 +204,7 @@ initialize_environment () { config["private_file_group"]="root" fi - if $(getent group "${config['acme_group']}" > /dev/null) ; then + if getent group "${config['acme_group']}" > /dev/null ; then config["acme_dir_group"]="${config['acme_group']}" config["acme_file_group"]="${config['acme_group']}" else @@ -269,8 +269,11 @@ check_openssl_key_req_match () { local check_key="${1}" local check_req="${2}" - local md5_key="$(openssl rsa -noout -modulus -in "${check_key}" | md5sum | awk '{print $1}')" - local md5_req="$(openssl req -noout -modulus -in "${check_req}" | md5sum | awk '{print $1}')" + local md5_key + local md5_req + + md5_key="$(openssl rsa -noout -modulus -in "${check_key}" | md5sum | awk '{print $1}')" + md5_req="$(openssl req -noout -modulus -in "${check_req}" | md5sum | awk '{print $1}')" if [ "${md5_key}" = "${md5_req}" ] ; then return 0 @@ -284,8 +287,11 @@ check_openssl_key_crt_match () { local check_crt="${2}" if [ -r "${check_key}" -a -r "${check_crt}" ] ; then - local md5_key="$(openssl rsa -noout -modulus -in "${check_key}" | md5sum | awk '{print $1}')" - local md5_crt="$(openssl x509 -noout -modulus -in "${check_crt}" | md5sum | awk '{print $1}')" + local md5_key + local md5_crt + + md5_key="$(openssl rsa -noout -modulus -in "${check_key}" | md5sum | awk '{print $1}')" + md5_crt="$(openssl x509 -noout -modulus -in "${check_crt}" | md5sum | awk '{print $1}')" if [ "${md5_key}" = "${md5_crt}" ] ; then return 0 @@ -393,7 +399,7 @@ run_external_script () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group ${acl_group} > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi done @@ -634,7 +640,7 @@ EOF printf 'ip_address = "%s"\n' "${san_ip[${i}]}" >> "${config_file}" done - if [ $(version $(certtool --version | head -n 1 | awk '{print $NF}')) -ge $(version 3.0.20) ] ; then + if [ "$(version "$(certtool --version | head -n 1 | awk '{print $NF}')")" -ge "$(version 3.0.20)" ] ; then for i in "${!san_uri[@]}" ; do printf 'uri = "%s"\n' "${san_uri[${i}]}" >> "${config_file}" done @@ -652,7 +658,7 @@ save_realm_config () { local config_file="${1:-config/realm.conf}" if [ -r "${config_file}" ] ; then - if $(grep -q -E "^#\s+Configuration\s+file\s+generated\s+by\s+pki-realm$" "${config_file}") ; then + if grep -q -E "^#\s+Configuration\s+file\s+generated\s+by\s+pki-realm$" "${config_file}" ; then rm -f "${config_file}" fi fi @@ -676,7 +682,8 @@ generate_openssl_request () { if [ -n "${req_config}" -a -n "${req_out}" ] ; then if [ -r "${req_config}" -a ! -r "${req_out}" ] ; then - local req_keyfile=$(grep -E '^default_keyfile\s+=\s+' "${req_config}" | awk '{print $3}') + local req_keyfile + req_keyfile=$(grep -E '^default_keyfile\s+=\s+' "${req_config}" | awk '{print $3}') if [ -n "${req_keyfile}" ] ; then openssl req -new -key "${req_keyfile}" -config "${req_config}" -out "${req_out}.tmp" else @@ -721,7 +728,7 @@ selfsign_openssl_request () { -req -signkey private/key.pem -days "${config['selfsigned_sign_days']}" test -r "${sign_out}.tmp" && mv "${sign_out}.tmp" "${sign_out}" if [ -r "${sign_out}" -a ! -r "${root_out}" ] ; then - cd $(dirname "${root_out}") + cd "$(dirname "${root_out}")" ln -s "${sign_out}" "${root_out}" cd - > /dev/null fi @@ -745,8 +752,8 @@ selfsign_gnutls_request () { --template selfsigned/gnutls.conf test -r "${sign_out}.tmp" && mv "${sign_out}.tmp" "${sign_out}" if [ -r "${sign_out}" -a ! -r "${root_out}" ] ; then - cd $(dirname "${root_out}") - ln -s "$(basename ${sign_out})" $(basename "${root_out}") + cd "$(dirname "${root_out}")" + ln -s "$(basename ${sign_out})" "$(basename "${root_out}")" cd - > /dev/null fi @@ -785,7 +792,7 @@ generate_gnutls_rsa_realm_key () { local key_group="${3:-${config['realm_file_group']}}" if ! [ -r "${key_file}" ] ; then - if [ $(version $(certtool --version | head -n 1 | awk '{print $NF}')) -lt $(version 3.1.0) ] ; then + if [ "$(version "$(certtool --version | head -n 1 | awk '{print $NF}')")" -lt "$(version 3.1.0)" ] ; then certtool --generate-privkey --outfile "${key_file}.tmp" --bits "${key_size}" else certtool --generate-privkey --rsa --outfile "${key_file}.tmp" --bits "${key_size}" @@ -825,7 +832,7 @@ generate_openssl_rsa_private_key () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" "${key_file}.tmp" fi done @@ -852,7 +859,7 @@ generate_gnutls_rsa_private_key () { local key_acl="${4:-true}" if ! [ -r "${key_file}" ] ; then - if [ $(version $(certtool --version | head -n 1 | awk '{print $NF}')) -lt $(version 3.1.0) ] ; then + if [ "$(version "$(certtool --version | head -n 1 | awk '{print $NF}')")" -lt "$(version 3.1.0)" ] ; then certtool --generate-privkey --outfile "${key_file}.tmp" --bits "${key_size}" else certtool --generate-privkey --rsa --outfile "${key_file}.tmp" --bits "${key_size}" @@ -868,7 +875,7 @@ generate_gnutls_rsa_private_key () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" "${key_file}.tmp" fi done @@ -933,7 +940,7 @@ create_private_directories () { local private_dir_acl_groups_x=( $(echo "${config['private_dir_acl_groups_x']}" | tr "/" " ") ) if [ ${#private_dir_acl_groups_x[@]} -ne 0 ] ; then for acl_group in ${private_dir_acl_groups_x[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:x" "${directory}" fi done @@ -955,11 +962,11 @@ create_private_noacl_directories () { local directories=( ${@} ) for directory in ${directories[@]} ; do - test -d ${directory} || mkdir -p -m ${config['private_dir_mode']} ${directory} - if [ "$(stat -c %a ${directory})" != "${config['private_dir_mode']}" ] ; then - chmod ${config['private_dir_mode']} ${directory} + test -d "${directory}" || mkdir -p -m ${config['private_dir_mode']} "${directory}" + if [ "$(stat -c %a "${directory}")" != "${config['private_dir_mode']}" ] ; then + chmod "${config['private_dir_mode']}" "${directory}" fi - if [ "$(stat -c %G ${directory})" != "${dir_group}" ] ; then + if [ "$(stat -c %G "${directory}")" != "${dir_group}" ] ; then chgrp "${dir_group}" "${directory}" fi done @@ -978,10 +985,10 @@ check_expiration_time () { cert_expires=$(date --date="${cert_enddate}" +%s) if [ -n "${seconds}" ] ; then - cert_expires="$(( ${cert_expires} - ${seconds} ))" + cert_expires="$(( cert_expires - seconds ))" fi - if (( (${cert_expires} - ${current_time}) >= 0 )) ; then + if (( (cert_expires - current_time) >= 0 )) ; then return 0 else return 1 @@ -1033,7 +1040,8 @@ request_acme_tiny_certificate () { test -r acme/cert.pem && mv acme/cert.pem acme/cert.pem.old || true mv acme/cert.pem.tmp acme/cert.pem - local acme_intermediate_uri="$(openssl x509 -in acme/cert.pem -text -noout -certopt ca_default,no_validity,no_serial | grep -E '^\s+CA\s+Issuers\s+-\s+URI:' | awk '{print $4}' | sed -e 's/^URI://')" + local acme_intermediate_uri + acme_intermediate_uri="$(openssl x509 -in acme/cert.pem -text -noout -certopt ca_default,no_validity,no_serial | grep -E '^\s+CA\s+Issuers\s+-\s+URI:' | awk '{print $4}' | sed -e 's/^URI://')" if [ ! -r acme/intermediate.pem ] ; then @@ -1094,7 +1102,7 @@ request_acme_tiny_certificate () { check_public_certificate () { if [ -r public/cert.pem ] ; then - if ! $(check_file_signature public/cert.pem) ; then + if ! check_file_signature public/cert.pem ; then state+=("changed-certificate") state+=("file-change") fi @@ -1118,7 +1126,7 @@ check_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi done @@ -1136,7 +1144,7 @@ check_files () { if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then if ! getfacl -sc private/key.pem | grep -Eq '^group' ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem fi done @@ -1193,7 +1201,7 @@ check_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi done @@ -1211,7 +1219,7 @@ check_files () { if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then if ! getfacl -sc private/key.pem | grep -Eq '^group' ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem fi done @@ -1272,7 +1280,7 @@ check_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi done @@ -1479,7 +1487,8 @@ process_public_files () { process_private_files () { - local current_umask="$(umask)" + local current_umask + current_umask="$(umask)" umask 027 local authority_preference=( $(echo "${config['pki_authority_preference']}" | tr "/" " ") ) @@ -1498,7 +1507,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi done @@ -1521,7 +1530,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi done @@ -1541,7 +1550,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi done @@ -1561,7 +1570,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi done @@ -1585,7 +1594,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi done @@ -1603,7 +1612,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi done @@ -1617,7 +1626,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi done @@ -1635,7 +1644,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain_dhparam.pem.tmp fi done @@ -1649,7 +1658,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain_dhparam.pem.tmp fi done @@ -1664,7 +1673,7 @@ process_private_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain_dhparam.pem.tmp fi done @@ -1928,7 +1937,7 @@ sub_new-realm () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then for acl_group in ${private_file_acl_groups_r[@]} ; do - if $(getent group "${acl_group}" > /dev/null) ; then + if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi done From 33b77ae357ae2a03fe29be3d0d3b77983ee7d88f Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 22:06:31 +0200 Subject: [PATCH 17/65] Refactor and comment idempotent use of `chmod` and `chgrp` --- files/secret/pki/lib/pki-authority | 62 +++++++++++--------- files/usr/local/lib/pki/pki-realm | 93 +++++++++++++++--------------- 2 files changed, 83 insertions(+), 72 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 4fc9197..364f40c 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -78,6 +78,32 @@ get_dnsdomainname () { fi fi } + +chmod_idempotent () { + # chmod does a `fchmodat` (after a `stat`) even if it does not need to + # change anything as of 8.23-4. + # This behavior is not ideal for this script as it would update the ctime. + + local new_mode_in_octal="${1##0}" + local file_path="${2}" + + if [ "$(stat -c %a "${file_path}")" != "${new_mode_in_octal}" ] ; then + chmod "${new_mode_in_octal}" "${file_path}" + fi +} + +chgrp_idempotent () { + # chgrp does a `fchownat` (after a `newfstatat`) even if it does not need + # to change anything as of 8.23-4. + # This behavior is not ideal for this script as it would update the ctime. + + local new_group_name="${1}" + local file_path="${2}" + + if [ "$(stat -c %G "${file_path}")" != "${new_group_name}" ] ; then + chgrp "${new_group_name}" "${file_path}" + fi +} # }}} initialize_environment () { @@ -1003,12 +1029,8 @@ generate_openssl_rsa_private_key () { mv "${key_file}.tmp" "${key_file}" fi - if [ "$(stat -c %a "${key_file}")" != "${config['private_file_mode']}" ] ; then - chmod ${config['private_file_mode']} "${key_file}" - fi - if [ "$(stat -c %G "${key_file}")" != "${key_group}" ] ; then - chgrp "${key_group}" "${key_file}" - fi + chmod_idempotent ${config['private_file_mode']} "${key_file}" + chgrp_idempotent "${key_group}" "${key_file}" } @@ -1033,12 +1055,8 @@ generate_gnutls_rsa_private_key () { mv "${key_file}.tmp" "${key_file}" fi - if [ "$(stat -c %a "${key_file}")" != "${config['private_file_mode']}" ] ; then - chmod "${config['private_file_mode']}" "${key_file}" - fi - if [ "$(stat -c %G "${key_file}")" != "${key_group}" ] ; then - chgrp "${key_group}" "${key_file}" - fi + chmod_idempotent "${config['private_file_mode']}" "${key_file}" + chgrp_idempotent "${key_group}" "${key_file}" } @@ -1054,13 +1072,9 @@ create_public_directories () { local directories=( ${@} ) for directory in ${directories[@]} ; do - test -d "${directory}" || mkdir -p -m "${config['public_dir_mode']}" "${directory}" - if [ "$(stat -c %a "${directory}")" != "${config['public_dir_mode']}" ] ; then - chmod "${config['public_dir_mode']}" "${directory}" - fi - if [ "$(stat -c %G "${directory}")" != "${dir_group}" ] ; then - chgrp "${dir_group}" "${directory}" - fi + mkdir -p "${directory}" + chmod_idempotent "${config['public_dir_mode']}" "${directory}" + chgrp_idempotent "${dir_group}" "${directory}" done } @@ -1077,13 +1091,9 @@ create_private_directories () { local directories=( ${@} ) for directory in ${directories[@]} ; do - test -d "${directory}" || mkdir -p -m "${config['private_dir_mode']}" "${directory}" - if [ "$(stat -c %a "${directory}")" != "${config['private_dir_mode']}" ] ; then - chmod "${config['private_dir_mode']}" "${directory}" - fi - if [ "$(stat -c %G "${directory}")" != "${dir_group}" ] ; then - chgrp "${dir_group}" "${directory}" - fi + mkdir -p "${directory}" + chmod_idempotent "${config['private_dir_mode']}" "${directory}" + chgrp_idempotent "${dir_group}" "${directory}" done } diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 0196c37..1a32283 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -104,6 +104,32 @@ get_dnsdomainname () { fi fi } + +chmod_idempotent () { + # chmod does a `fchmodat` (after a `stat`) even if it does not need to + # change anything as of 8.23-4. + # This behavior is not ideal for this script as it would update the ctime. + + local new_mode_in_octal="${1##0}" + local file_path="${2}" + + if [ "$(stat -c %a "${file_path}")" != "${new_mode_in_octal}" ] ; then + chmod "${new_mode_in_octal}" "${file_path}" + fi +} + +chgrp_idempotent () { + # chgrp does a `fchownat` (after a `newfstatat`) even if it does not need + # to change anything as of 8.23-4. + # This behavior is not ideal for this script as it would update the ctime. + + local new_group_name="${1}" + local file_path="${2}" + + if [ "$(stat -c %G "${file_path}")" != "${new_group_name}" ] ; then + chgrp "${new_group_name}" "${file_path}" + fi +} # }}} initialize_environment () { @@ -262,7 +288,10 @@ initialize_environment () { config["private_dir_acl_groups_x"]="" config["private_file_acl_groups_r"]="" - test -d "${config['pki_root']}" || mkdir -p -m "${config['public_dir_mode']}" "${config['pki_root']}" + if [ ! -d "${config['pki_root']}" ] ; then + mkdir -p -m "${config['public_dir_mode']}" "${config['pki_root']}" + chmod "${config['public_dir_mode']}" "${config['pki_root']}" + fi } check_openssl_key_req_match () { @@ -776,12 +805,8 @@ generate_openssl_rsa_realm_key () { mv "${key_file}.tmp" "${key_file}" fi - if [ "$(stat -c %a "${key_file}")" != "${config['realm_file_mode']}" ] ; then - chmod "${config['realm_file_mode']}" "${key_file}" - fi - if [ "$(stat -c %G "${key_file}")" != "${key_group}" ] ; then - chgrp "${key_group}" "${key_file}" - fi + chmod_idempotent "${config['realm_file_mode']}" "${key_file}" + chgrp_idempotent "${key_group}" "${key_file}" } @@ -806,12 +831,8 @@ generate_gnutls_rsa_realm_key () { mv "${key_file}.tmp" "${key_file}" fi - if [ "$(stat -c %a "${key_file}")" != "${config['realm_file_mode']}" ] ; then - chmod "${config['realm_file_mode']}" "${key_file}" - fi - if [ "$(stat -c %G "${key_file}")" != "${key_group}" ] ; then - chgrp "${key_group}" "${key_file}" - fi + chmod_idempotent "${config['realm_file_mode']}" "${key_file}" + chgrp_idempotent "${key_group}" "${key_file}" } @@ -842,12 +863,8 @@ generate_openssl_rsa_private_key () { mv "${key_file}.tmp" "${key_file}" fi - if [ "$(stat -c %a "${key_file}")" != "${config['private_file_mode']}" ] ; then - chmod "${config['private_file_mode']}" "${key_file}" - fi - if [ "$(stat -c %G "${key_file}")" != "${key_group}" ] ; then - chgrp "${key_group}" "${key_file}" - fi + chmod_idempotent "${config['private_file_mode']}" "${key_file}" + chgrp_idempotent "${key_group}" "${key_file}" } @@ -885,12 +902,8 @@ generate_gnutls_rsa_private_key () { mv "${key_file}.tmp" "${key_file}" fi - if [ "$(stat -c %a "${key_file}")" != "${config['private_file_mode']}" ] ; then - chmod "${config['private_file_mode']}" "${key_file}" - fi - if [ "$(stat -c %G "${key_file}")" != "${key_group}" ] ; then - chgrp "${key_group}" "${key_file}" - fi + chmod_idempotent "${config['private_file_mode']}" "${key_file}" + chgrp_idempotent "${key_group}" "${key_file}" } @@ -906,13 +919,9 @@ create_public_directories () { local directories=( ${@} ) for directory in ${directories[@]} ; do - test -d "${directory}" || mkdir -p -m "${config['public_dir_mode']}" "${directory}" - if [ "$(stat -c %a "${directory}")" != "${config['public_dir_mode']}" ] ; then - chmod "${config['public_dir_mode']}" "${directory}" - fi - if [ "$(stat -c %G "${directory}")" != "${dir_group}" ] ; then - chgrp "${dir_group}" "${directory}" - fi + mkdir -p "${directory}" + chmod_idempotent "${config['public_dir_mode']}" "${directory}" + chgrp_idempotent "${dir_group}" "${directory}" done } @@ -929,13 +938,9 @@ create_private_directories () { local directories=( ${@} ) for directory in ${directories[@]} ; do - test -d "${directory}" || mkdir -p -m "${config['private_dir_mode']}" "${directory}" - if [ "$(stat -c %a "${directory}")" != "${config['private_dir_mode']}" ] ; then - chmod "${config['private_dir_mode']}" "${directory}" - fi - if [ "$(stat -c %G "${directory}")" != "${dir_group}" ] ; then - chgrp "${dir_group}" "${directory}" - fi + mkdir -p "${directory}" + chmod_idempotent "${config['private_dir_mode']}" "${directory}" + chgrp_idempotent "${dir_group}" "${directory}" if type setfacl > /dev/null 2>&1 ; then local private_dir_acl_groups_x=( $(echo "${config['private_dir_acl_groups_x']}" | tr "/" " ") ) if [ ${#private_dir_acl_groups_x[@]} -ne 0 ] ; then @@ -962,13 +967,9 @@ create_private_noacl_directories () { local directories=( ${@} ) for directory in ${directories[@]} ; do - test -d "${directory}" || mkdir -p -m ${config['private_dir_mode']} "${directory}" - if [ "$(stat -c %a "${directory}")" != "${config['private_dir_mode']}" ] ; then - chmod "${config['private_dir_mode']}" "${directory}" - fi - if [ "$(stat -c %G "${directory}")" != "${dir_group}" ] ; then - chgrp "${dir_group}" "${directory}" - fi + mkdir -p "${directory}" + chmod_idempotent "${config['private_dir_mode']}" "${directory}" + chgrp_idempotent "${dir_group}" "${directory}" done } From dc62b4cb808d4ee36cc7aa1797df793b97ce740d Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 22:25:48 +0200 Subject: [PATCH 18/65] Fix SC2166 for pki-realm Ref: https://github.com/koalaman/shellcheck/wiki/SC2166 --- files/usr/local/lib/pki/pki-realm | 152 +++++++++++++++--------------- 1 file changed, 75 insertions(+), 77 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 1a32283..016afd5 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -31,7 +31,7 @@ clean_up () { # Clean up pidfile local pidfile="${1}" - if [ -n "${pidfile}" -a -r "${pidfile}" ] ; then + if [ -n "${pidfile}" ] && [ -r "${pidfile}" ] ; then rm -f "${pidfile}" fi exit 0 @@ -41,7 +41,7 @@ wait_for_pid () { # Wait for the specified process to exit local pidfile="${1}" - if [ -n "${pidfile}" -a -r "${pidfile}" ] ; then + if [ -n "${pidfile}" ] && [ -r "${pidfile}" ] ; then local wait_pid="$(< "${pidfile}")" while kill -0 "${wait_pid}" > /dev/null 2>&1 ; do log_message "Waiting for PID ${wait_pid} to finish" @@ -288,10 +288,8 @@ initialize_environment () { config["private_dir_acl_groups_x"]="" config["private_file_acl_groups_r"]="" - if [ ! -d "${config['pki_root']}" ] ; then - mkdir -p -m "${config['public_dir_mode']}" "${config['pki_root']}" - chmod "${config['public_dir_mode']}" "${config['pki_root']}" - fi + mkdir -p "${config['pki_root']}" + chmod_idempotent "${config['public_dir_mode']}" "${config['pki_root']}" } check_openssl_key_req_match () { @@ -315,7 +313,7 @@ check_openssl_key_crt_match () { local check_key="${1}" local check_crt="${2}" - if [ -r "${check_key}" -a -r "${check_crt}" ] ; then + if [ -r "${check_key}" ] && [ -r "${check_crt}" ] ; then local md5_key local md5_crt @@ -335,7 +333,7 @@ check_openssl_key_crt_match () { update_file_signature () { local check_file="${1}" - if [ -n "${check_file}" -a -r "${check_file}" ] ; then + if [ -n "${check_file}" ] && [ -r "${check_file}" ] ; then if [ -r "${check_file}.sig" ] ; then set +e md5sum --quiet --status -c "${check_file}.sig" @@ -354,7 +352,7 @@ update_file_signature () { check_file_signature () { local check_file="${1}" - if [ -n "${check_file}" -a -r "${check_file}" ] ; then + if [ -n "${check_file}" ] && [ -r "${check_file}" ] ; then if [ -r "${check_file}.sig" ] ; then set +e md5sum --quiet --status -c "${check_file}.sig" @@ -392,7 +390,7 @@ enter_realm () { run_pki_hooks () { - if [ -n "${state:-}" -a -d "${config['pki_hooks']}" ] ; then + if [ -n "${state:-}" ] && [ -d "${config['pki_hooks']}" ] ; then export PKI_SCRIPT_REALM="${config['name']}" export PKI_SCRIPT_FQDN="${config['pki_default_fqdn']}" @@ -472,7 +470,7 @@ update_symlink () { for target in ${@} ; do if [ -r "${target}" ] ; then - if [ -L "${symlink_target}" -a "$(readlink "${symlink_target}")" == "${target}" ] ; then + if [ -L "${symlink_target}" ] && [ "$(readlink "${symlink_target}")" == "${target}" ] ; then break else ln -sf "${target}" "${symlink_target}" @@ -497,7 +495,7 @@ create_openssl_config () { local req_subdomains="${5:-}" local req_san="${6:-}" - if [ -n "${config_file}" -a -n "${req_dn}" ] ; then + if [ -n "${config_file}" ] && [ -n "${req_dn}" ] ; then cat << EOF > "${config_file}" # Configuration file generated by pki-realm @@ -514,7 +512,7 @@ utf8 = yes string_mask = utf8only EOF - if [ -n "${PKI_SESSION_TOKEN:-}" -a "${config_type}" = "internal" ] ; then + if [ -n "${PKI_SESSION_TOKEN:-}" ] && [ "${config_type}" = "internal" ] ; then cat << EOF >> "${config_file}" attributes = req_attributes @@ -543,7 +541,7 @@ basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth EOF - if [ -n "${req_domains}" -o -n "${req_subdomains}" -o -n "${req_san}" ] ; then + if [ -n "${req_domains}" ] || [ -n "${req_subdomains}" ] || [ -n "${req_san}" ] ; then cat << EOF >> "${config_file}" subjectAltName = @ext_req_san @@ -604,7 +602,7 @@ create_gnutls_config () { local req_subdomains="${5:-}" local req_san="${6:-}" - if [ -n "${config_file}" -a -n "${req_dn}" ] ; then + if [ -n "${config_file}" ] && [ -n "${req_dn}" ] ; then cat << EOF > "${config_file}" # Configuration file generated by pki-realm @@ -616,13 +614,13 @@ tls_www_server EOF - if [ -n "${PKI_SESSION_TOKEN:-}" -a "${config_type}" = "internal" ] ; then + if [ -n "${PKI_SESSION_TOKEN:-}" ] && [ "${config_type}" = "internal" ] ; then cat << EOF >> "${config_file}" # This password is meaningless outside of current session challenge_password = ${PKI_SESSION_TOKEN:-} EOF - elif [ -n "${PKI_SESSION_TOKEN:-}" -a "${config_type}" = "selfsigned" ] ; then + elif [ -n "${PKI_SESSION_TOKEN:-}" ] && [ "${config_type}" = "selfsigned" ] ; then cat << EOF >> "${config_file}" expiration_days = ${config['selfsigned_sign_days']} EOF @@ -708,8 +706,8 @@ generate_openssl_request () { local req_config="${1}" local req_out="${2}" - if [ -n "${req_config}" -a -n "${req_out}" ] ; then - if [ -r "${req_config}" -a ! -r "${req_out}" ] ; then + if [ -n "${req_config}" ] && [ -n "${req_out}" ] ; then + if [ -r "${req_config}" ] && [ ! -r "${req_out}" ] ; then local req_keyfile req_keyfile=$(grep -E '^default_keyfile\s+=\s+' "${req_config}" | awk '{print $3}') @@ -730,8 +728,8 @@ generate_gnutls_request () { local req_config="${1}" local req_out="${2}" - if [ -n "${req_config}" -a -n "${req_out}" ] ; then - if [ -r "${req_config}" -a ! -r "${req_out}" ] ; then + if [ -n "${req_config}" ] && [ -n "${req_out}" ] ; then + if [ -r "${req_config}" ] && [ ! -r "${req_out}" ] ; then certtool --generate-request --template "${req_config}" \ --load-privkey private/key.pem --outfile "${req_out}.tmp" @@ -750,13 +748,13 @@ selfsign_openssl_request () { local sign_out="selfsigned/cert.pem" local root_out="selfsigned/root.pem" - if [ -n "${sign_req}" -a -n "${sign_out}" ] ; then - if [ -r "${sign_req}" -a ! -r "${sign_out}" ] ; then + if [ -n "${sign_req}" ] && [ -n "${sign_out}" ] ; then + if [ -r "${sign_req}" ] && [ ! -r "${sign_out}" ] ; then openssl x509 -in "${sign_req}" -out "${sign_out}.tmp" \ -req -signkey private/key.pem -days "${config['selfsigned_sign_days']}" test -r "${sign_out}.tmp" && mv "${sign_out}.tmp" "${sign_out}" - if [ -r "${sign_out}" -a ! -r "${root_out}" ] ; then + if [ -r "${sign_out}" ] && [ ! -r "${root_out}" ] ; then cd "$(dirname "${root_out}")" ln -s "${sign_out}" "${root_out}" cd - > /dev/null @@ -773,14 +771,14 @@ selfsign_gnutls_request () { local sign_out="selfsigned/cert.pem" local root_out="selfsigned/root.pem" - if [ -n "${sign_req}" -a -n "${sign_out}" ] ; then - if [ -r "${sign_req}" -a ! -r "${sign_out}" ] ; then + if [ -n "${sign_req}" ] && [ -n "${sign_out}" ] ; then + if [ -r "${sign_req}" ] && [ ! -r "${sign_out}" ] ; then certtool --generate-self-signed --load-privkey private/key.pem \ --load-request "${sign_req}" --outfile "${sign_out}.tmp" \ --template selfsigned/gnutls.conf test -r "${sign_out}.tmp" && mv "${sign_out}.tmp" "${sign_out}" - if [ -r "${sign_out}" -a ! -r "${root_out}" ] ; then + if [ -r "${sign_out}" ] && [ ! -r "${root_out}" ] ; then cd "$(dirname "${root_out}")" ln -s "$(basename ${sign_out})" "$(basename "${root_out}")" cd - > /dev/null @@ -979,7 +977,7 @@ check_expiration_time () { local cert_file="${1}" local seconds="${2}" - if [ -n "${cert_file}" -a -r "${cert_file}" ] ; then + if [ -n "${cert_file}" ] && [ -r "${cert_file}" ] ; then current_time="$(date +%s)" cert_enddate="$(openssl x509 -in "${cert_file}" -noout -enddate | cut -d= -f2)" @@ -1004,7 +1002,7 @@ convert_der_to_pem () { local input_file="${1}" - if [ -n "${input_file}" -a -r "${input_file}" ] ; then + if [ -n "${input_file}" ] && [ -r "${input_file}" ] ; then if ! openssl x509 -in "${input_file}" -noout 2>/dev/null ; then openssl x509 -inform DER -in "${input_file}" -out "${input_file}.tmp" mv "${input_file}.tmp" "${input_file}" @@ -1014,7 +1012,7 @@ convert_der_to_pem () { request_acme_tiny_certificate () { - if [ "${config['pki_acme']}" = "true" -a -x "${config['acme_client_script']}" -a -d "${config['acme_challenge_dir']}" -a ! -r acme/error.log -a -r acme/request.pem ] ; then + if [ "${config['pki_acme']}" = "true" ] && [ -x "${config['acme_client_script']}" ] && [ -d "${config['acme_challenge_dir']}" ] && [ ! -r acme/error.log ] && [ -r acme/request.pem ] ; then if ! ( check_expiration_time acme/cert.pem "${config['acme_expiration_seconds']}" && check_openssl_key_crt_match private/key.pem acme/cert.pem ) ; then @@ -1036,7 +1034,7 @@ request_acme_tiny_certificate () { fi - if [ -r acme/cert.pem.tmp -a -s acme/cert.pem.tmp ] ; then + if [ -r acme/cert.pem.tmp ] && [ -s acme/cert.pem.tmp ] ; then test -r acme/cert.pem && mv acme/cert.pem acme/cert.pem.old || true mv acme/cert.pem.tmp acme/cert.pem @@ -1057,7 +1055,7 @@ request_acme_tiny_certificate () { elif [ -r acme/intermediate.pem ] ; then - if [ -n "${acme_intermediate_uri}" -a -r acme/intermediate_uri.txt ] ; then + if [ -n "${acme_intermediate_uri}" ] && [ -r acme/intermediate_uri.txt ] ; then if [ "${acme_intermediate_uri}" != "$( /dev/null ; then @@ -1079,7 +1077,7 @@ request_acme_tiny_certificate () { fi if [ ! -r acme/root.pem ] ; then - if [ -n "${config['acme_root_ca_path']}" -a -n "${config['acme_root_ca_file']}" ] ; then + if [ -n "${config['acme_root_ca_path']}" ] && [ -n "${config['acme_root_ca_file']}" ] ; then if [ -r "${config['acme_root_ca_path']}/${config['acme_root_ca_file']}" ] && grep -q "${config['acme_root_ca_file']}" /etc/ca-certificates.conf ; then ln -s "${config['acme_root_ca_path']}/${config['acme_root_ca_file']}" acme/root.pem fi @@ -1090,7 +1088,7 @@ request_acme_tiny_certificate () { rm -f acme/error.log fi - elif [ -r acme/cert.pem.tmp -a ! -s acme/cert.pem.tmp ] ; then + elif [ -r acme/cert.pem.tmp ] && [ ! -s acme/cert.pem.tmp ] ; then rm -f acme/cert.pem.tmp fi @@ -1154,19 +1152,19 @@ check_files () { fi fi - if [ -n "${PKI_SESSION_TOKEN:-}" -a -r internal/cert.pem ] ; then + if [ -n "${PKI_SESSION_TOKEN:-}" ] && [ -r internal/cert.pem ] ; then if ! ( check_expiration_time internal/cert.pem "${config['internal_expiration_seconds']}" && check_openssl_key_crt_match private/key.pem internal/cert.pem ) ; then rm -f "internal/${library}.conf" internal/request.pem fi fi - if [ -n "${PKI_SESSION_TOKEN:-}" -a ! -r public/cert.pem ] ; then + if [ -n "${PKI_SESSION_TOKEN:-}" ] && [ ! -r public/cert.pem ] ; then if ! ( check_expiration_time internal/cert.pem "${config['internal_expiration_seconds']}" && check_openssl_key_crt_match private/key.pem internal/cert.pem ) ; then rm -f "internal/${library}.conf" internal/request.pem fi fi - if [ ! -r "internal/${library}.conf" -a ! -r internal/request.pem ] ; then + if [ ! -r "internal/${library}.conf" ] && [ ! -r internal/request.pem ] ; then if [[ ${name} != *.* && ${name} != *@* ]] ; then @@ -1182,7 +1180,7 @@ check_files () { state+=('new-internal-request') fi - if [ -r "internal/${library}.conf" -a -r internal/request.pem ] ; then + if [ -r "internal/${library}.conf" ] && [ -r internal/request.pem ] ; then if ! check_openssl_key_req_match private/key.pem internal/request.pem ; then rm -f internal/request.pem @@ -1229,19 +1227,19 @@ check_files () { fi fi - if [ -n "${PKI_SESSION_TOKEN:-}" -a -r selfsigned/cert.pem ] ; then + if [ -n "${PKI_SESSION_TOKEN:-}" ] && [ -r selfsigned/cert.pem ] ; then if ! ( check_expiration_time selfsigned/cert.pem "${config['selfsigned_expiration_seconds']}" && check_openssl_key_crt_match private/key.pem selfsigned/cert.pem ) ; then rm -f "selfsigned/${library}.conf" selfsigned/request.pem fi fi - if [ -n "${PKI_SESSION_TOKEN:-}" -a ! -r public/cert.pem ] ; then + if [ -n "${PKI_SESSION_TOKEN:-}" ] && [ ! -r public/cert.pem ] ; then if ! ( check_expiration_time selfsigned/cert.pem "${config['selfsigned_expiration_seconds']}" && check_openssl_key_crt_match private/key.pem selfsigned/cert.pem ) ; then rm -f "selfsigned/${library}.conf" selfsigned/request.pem fi fi - if [ ! -r "selfsigned/${library}.conf" -a ! -r selfsigned/request.pem ] ; then + if [ ! -r "selfsigned/${library}.conf" ] && [ ! -r selfsigned/request.pem ] ; then if [[ ${name} != *.* && ${name} != *@* ]] ; then @@ -1258,7 +1256,7 @@ check_files () { state+=('new-selfsigned-certificate') fi - if [ -r "selfsigned/${library}.conf" -a -r selfsigned/request.pem ] ; then + if [ -r "selfsigned/${library}.conf" ] && [ -r selfsigned/request.pem ] ; then if ! check_openssl_key_req_match private/key.pem selfsigned/request.pem ; then rm -f selfsigned/request.pem @@ -1293,13 +1291,13 @@ check_files () { fi fi - if [ -r acme/cert.pem -a -r "acme/${acme_library}.conf" -a -r acme/request.pem ] ; then + if [ -r acme/cert.pem ] && [ -r "acme/${acme_library}.conf" ] && [ -r acme/request.pem ] ; then if ! check_expiration_time acme/cert.pem "${config['acme_expiration_seconds']}" ; then rm -f "acme/${acme_library}.conf" acme/request.pem fi fi - if [ ! -r "acme/${acme_library}.conf" -a ! -r acme/request.pem ] ; then + if [ ! -r "acme/${acme_library}.conf" ] && [ ! -r acme/request.pem ] ; then if [[ ${name} != *.* && ${name} != *@* ]] ; then @@ -1319,7 +1317,7 @@ check_files () { state+=('new-acme-request') fi - if [ -r "acme/${acme_library}.conf" -a -r acme/request.pem ] ; then + if [ -r "acme/${acme_library}.conf" ] && [ -r acme/request.pem ] ; then if ! check_openssl_key_req_match private/key.pem acme/request.pem ; then rm -f acme/request.pem @@ -1330,7 +1328,7 @@ check_files () { fi - elif [ -r "acme/${acme_library}.conf" -a ! -r acme/request.pem ] ; then + elif [ -r "acme/${acme_library}.conf" ] && [ ! -r acme/request.pem ] ; then generate_${acme_library}_request "acme/${acme_library}.conf" acme/request.pem chgrp "${config['acme_file_group']}" acme/request.pem @@ -1361,7 +1359,7 @@ process_public_files () { if ! diff -q -N "${source_file}" "${source_file/${authority}/public}" > /dev/null ; then ln -sf "$(get_relative_path "${source_file}" "public")" "${source_file/${authority}/public}.tmp" fi - elif [ ! -r "${source_file}" -a -r "${source_file/${authority}/public}" ] ; then + elif [ ! -r "${source_file}" ] && [ -r "${source_file/${authority}/public}" ] ; then rm -f "${source_file/${authority}/public}" fi @@ -1376,33 +1374,33 @@ process_public_files () { fi fi - if [ -r public/cert.pem.tmp -a -r public/intermediate.pem.tmp ] ; then + if [ -r public/cert.pem.tmp ] && [ -r public/intermediate.pem.tmp ] ; then cat public/cert.pem.tmp public/intermediate.pem.tmp > public/cert_intermediate.pem.tmp - elif [ -r public/cert.pem.tmp -a -r public/intermediate.pem ] ; then + elif [ -r public/cert.pem.tmp ] && [ -r public/intermediate.pem ] ; then cat public/cert.pem.tmp public/intermediate.pem > public/cert_intermediate.pem.tmp fi - if [ -r public/intermediate.pem.tmp -a -r public/root.pem.tmp ] ; then + if [ -r public/intermediate.pem.tmp ] && [ -r public/root.pem.tmp ] ; then cat public/intermediate.pem.tmp public/root.pem.tmp > public/intermediate_root.pem.tmp - elif [ -r public/intermediate.pem -a -r public/root.pem.tmp ] ; then + elif [ -r public/intermediate.pem ] && [ -r public/root.pem.tmp ] ; then cat public/intermediate.pem public/root.pem.tmp > public/intermediate_root.pem.tmp fi - if [ -r public/alt_intermediate.pem.tmp -a -r public/alt_root.pem.tmp ] ; then + if [ -r public/alt_intermediate.pem.tmp ] && [ -r public/alt_root.pem.tmp ] ; then cat public/alt_intermediate.pem.tmp public/alt_root.pem.tmp > public/alt_intermediate_root.pem.tmp - elif [ -r public/alt_intermediate.pem -a -r public/alt_root.pem.tmp ] ; then + elif [ -r public/alt_intermediate.pem ] && [ -r public/alt_root.pem.tmp ] ; then cat public/alt_intermediate.pem public/alt_root.pem.tmp > public/alt_intermediate_root.pem.tmp fi for public_file in public/*.pem ; do - if [ ! -r "${public_file/public/${authority}}" -a ! -r "${public_file}.tmp" ] ; then + if [ ! -r "${public_file/public/${authority}}" ] && [ ! -r "${public_file}.tmp" ] ; then touch "${public_file}.rm" fi done fi - if [ -r private/key.pem -a -r public/cert.pem -a -r public/intermediate.pem -a -r public/cert_intermediate.pem ] ; then + if [ -r private/key.pem ] && [ -r public/cert.pem ] && [ -r public/intermediate.pem ] && [ -r public/cert_intermediate.pem ] ; then if ! check_openssl_key_crt_match private/key.pem public/cert_intermediate.pem ; then test -r public/cert_intermediate.pem.tmp && rm -f public/cert_intermediate.pem.tmp || true @@ -1411,7 +1409,7 @@ process_public_files () { fi - if [ "${config['pki_dhparam']}" = "true" -a -n "${config['dhparam_file']}" -a -r "${config['dhparam_file']}" ] ; then + if [ "${config['pki_dhparam']}" = "true" ] && [ -n "${config['dhparam_file']}" ] && [ -r "${config['dhparam_file']}" ] ; then if [ -r public/cert_intermediate.pem.tmp ] ; then cat public/cert_intermediate.pem.tmp "${config['dhparam_file']}" > public/cert_intermediate_dhparam.pem.tmp @@ -1419,10 +1417,10 @@ process_public_files () { elif [ -r public/cert.pem.tmp ] ; then cat public/cert.pem.tmp "${config['dhparam_file']}" > public/cert_dhparam.pem.tmp state+=("changed-dhparam") - elif [ ! -r public/cert_intermediate_dhparam.pem -a -r public/cert_intermediate.pem ] ; then + elif [ ! -r public/cert_intermediate_dhparam.pem ] && [ -r public/cert_intermediate.pem ] ; then cat public/cert_intermediate.pem "${config['dhparam_file']}" > public/cert_intermediate_dhparam.pem.tmp state+=("changed-dhparam") - elif [ ! -r public/cert_dhparam.pem -a ! -r public/cert_intermediate.pem -a -r public/cert.pem ] ; then + elif [ ! -r public/cert_dhparam.pem ] && [ ! -r public/cert_intermediate.pem ] && [ -r public/cert.pem ] ; then cat public/cert.pem "${config['dhparam_file']}" > public/cert_dhparam.pem.tmp state+=("changed-dhparam") elif [ -r public/cert_intermediate_dhparam.pem ] ; then @@ -1444,7 +1442,7 @@ process_public_files () { break - elif [ ! -r "${authority}/cert.pem" -a -r "${authority}/root.pem" ] ; then + elif [ ! -r "${authority}/cert.pem" ] && [ -r "${authority}/root.pem" ] ; then if ! diff -q -N "${authority}/root.pem" public/root.pem > /dev/null ; then @@ -1458,20 +1456,20 @@ process_public_files () { done - if [ -r public/intermediate.pem.tmp -a -r public/root.pem.tmp ] ; then + if [ -r public/intermediate.pem.tmp ] && [ -r public/root.pem.tmp ] ; then cat public/intermediate.pem.tmp public/root.pem.tmp > public/intermediate_root.pem.tmp - elif [ -r "${authority}/intermediate.pem" -a -r public/intermediate.pem -a -r public/root.pem.tmp ] ; then + elif [ -r "${authority}/intermediate.pem" ] && [ -r public/intermediate.pem ] && [ -r public/root.pem.tmp ] ; then cat public/intermediate.pem public/root.pem.tmp > public/intermediate_root.pem.tmp fi - if [ -r public/alt_intermediate.pem.tmp -a -r public/alt_root.pem.tmp ] ; then + if [ -r public/alt_intermediate.pem.tmp ] && [ -r public/alt_root.pem.tmp ] ; then cat public/alt_intermediate.pem.tmp public/alt_root.pem.tmp > public/alt_intermediate_root.pem.tmp - elif [ -r "${authority}/alt_intermediate.pem" -a -r public/alt_intermediate.pem -a -r public/alt_root.pem.tmp ] ; then + elif [ -r "${authority}/alt_intermediate.pem" ] && [ -r public/alt_intermediate.pem ] && [ -r public/alt_root.pem.tmp ] ; then cat public/alt_intermediate.pem public/alt_root.pem.tmp > public/alt_intermediate_root.pem.tmp fi for public_file in public/*.pem ; do - if [ ! -r "${public_file/public/${authority}}" -a ! -r "${public_file}.tmp" ] ; then + if [ ! -r "${public_file/public/${authority}}" ] && [ ! -r "${public_file}.tmp" ] ; then touch "${public_file}.rm" fi done @@ -1519,9 +1517,9 @@ process_private_files () { fi fi - if [ -r public/cert.pem.tmp -o -r public/cert_intermediate.pem.tmp ] ; then + if [ -r public/cert.pem.tmp ] || [ -r public/cert_intermediate.pem.tmp ] ; then - if [ -r public/cert.pem.tmp -a -r private/realm_key.pem ] ; then + if [ -r public/cert.pem.tmp ] && [ -r private/realm_key.pem ] ; then if ! check_openssl_key_crt_match private/key.pem public/cert.pem.tmp ; then @@ -1586,7 +1584,7 @@ process_private_files () { fi fi - if [ -r private/key.pem -a -r public/cert_intermediate.pem ] ; then + if [ -r private/key.pem ] && [ -r public/cert_intermediate.pem ] ; then if ! check_openssl_key_crt_match private/key.pem public/cert_intermediate.pem ; then test -r private/key_chain.pem.tmp && rm -f private/key_chain.pem.tmp || true @@ -1604,7 +1602,7 @@ process_private_files () { cat private/key.pem public/cert_intermediate.pem >> private/key_chain.pem.tmp fi - elif [ -r private/key.pem -a -r public/cert.pem ] ; then + elif [ -r private/key.pem ] && [ -r public/cert.pem ] ; then if ! check_openssl_key_crt_match private/key.pem public/cert.pem ; then test -r private/key_chain.pem.tmp && rm -f private/key_chain.pem.tmp || true @@ -1638,7 +1636,7 @@ process_private_files () { fi - if [ "${config['pki_dhparam']}" = "true" -a -n "${config['dhparam_file']}" -a -r "${config['dhparam_file']}" ] ; then + if [ "${config['pki_dhparam']}" = "true" ] && [ -n "${config['dhparam_file']}" ] && [ -r "${config['dhparam_file']}" ] ; then if [ -r private/key_chain.pem.tmp ] ; then install -g ${config['private_file_group']} -m ${config['private_file_mode']} /dev/null private/key_chain_dhparam.pem.tmp if type setfacl > /dev/null 2>&1 ; then @@ -1653,7 +1651,7 @@ process_private_files () { fi cat private/key_chain.pem.tmp ${config['dhparam_file']} >> private/key_chain_dhparam.pem.tmp state+=("changed-dhparam") - elif [ ! -r private/key_chain_dhparam.pem -a -r private/key_chain.pem ] ; then + elif [ ! -r private/key_chain_dhparam.pem ] && [ -r private/key_chain.pem ] ; then install -g ${config['private_file_group']} -m ${config['private_file_mode']} /dev/null private/key_chain_dhparam.pem.tmp if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) @@ -1688,7 +1686,7 @@ process_private_files () { break - elif [ ! -r "${authority}/cert.pem" -a -r "${authority}/root.pem" ] ; then + elif [ ! -r "${authority}/cert.pem" ] && [ -r "${authority}/root.pem" ] ; then if ! diff -q -N "${authority}/root.pem" public/root.pem > /dev/null ; then @@ -1711,14 +1709,14 @@ process_private_files () { activate_new_files () { - if [ -r public/cert.pem.tmp -o -r public/root.pem.tmp ] ; then + if [ -r public/cert.pem.tmp ] || [ -r public/root.pem.tmp ] ; then - if [ ! -r public/intermediate.pem.tmp -a -r public/intermediate.pem ] ; then + if [ ! -r public/intermediate.pem.tmp ] && [ -r public/intermediate.pem ] ; then rm -f public/intermediate.pem public/cert_intermediate.pem public/cert_intermediate_dhparam.pem public/chain.pem public/intermediate_root.pem state+=("file-change") fi - if [ ! -r public/alt_intermediate.pem.tmp -a -r public/alt_intermediate.pem ] ; then + if [ ! -r public/alt_intermediate.pem.tmp ] && [ -r public/alt_intermediate.pem ] ; then rm -f public/alt_intermediate.pem public/alt_intermediate_root.pem public/alt_trusted.pem state+=("file-change") fi @@ -1731,7 +1729,7 @@ activate_new_files () { state+=("file-deletion") done - if [ ! -r public/cert.pem -a public/cert.pem.sig ] ; then + if [ ! -r public/cert.pem ] && [ public/cert.pem.sig ] ; then rm -f public/cert.pem.sig fi @@ -2293,11 +2291,11 @@ schedule_job () { local min_delay="${3:-30}" local max_delay="${4:-300}" - if [ -n "${scheduler_type}" -a "${scheduler_type}" = "batch" ] ; then + if [ -n "${scheduler_type}" ] && [ "${scheduler_type}" = "batch" ] ; then if type batch > /dev/null 2>&1 ; then echo "${script} run -n '${name}'" | batch > /dev/null 2>&1 fi - elif [ -n "${scheduler_type}" -a "${scheduler_type}" = "sleep" ] ; then + elif [ -n "${scheduler_type}" ] && [ "${scheduler_type}" = "sleep" ] ; then ( sleep $(( ( $RANDOM % ${max_delay} ) + ${min_delay} )) ; ${script} run -n "${name}" ) & else if type batch > /dev/null 2>&1 ; then From 69d15261b68a16d4eba2eb771cabbc3c7b51d99d Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 22:53:30 +0200 Subject: [PATCH 19/65] Rework quoting and mkdir tasks in pki-realm --- files/usr/local/lib/pki/pki-realm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 016afd5..580d873 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -369,10 +369,12 @@ enter_realm () { local realm="${1}" local config_file="${2:-config/realm.conf}" - test -d "${config['pki_hooks']}" || mkdir -p -m "${config['public_dir_mode']}" "${config['pki_hooks']}" + mkdir -p "${config['pki_hooks']}" + chmod_idempotent "${config['public_dir_mode']}" "${config['pki_hooks']}" if [ ! -d "${config['pki_realms']}/${realm}" ] ; then - mkdir -p -m "${config['public_dir_mode']}" "${config['pki_realms']}/${realm}" + mkdir -p "${config['pki_realms']}/${realm}" + chmod "${config['public_dir_mode']}" "${config['pki_realms']}/${realm}" state+=('new-realm') fi @@ -2399,7 +2401,7 @@ if [ $# -gt 0 ] ; then case "${subcommand}" in init|new-realm|run|schedule) shift - sub_${subcommand} "${@}" + "sub_${subcommand}" "${@}" ;; *) From 898e501710319eaff0ee577157914ce990d84961 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 22:57:36 +0200 Subject: [PATCH 20/65] Fix more Shellcheck warnings --- files/usr/local/lib/pki/pki-realm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 580d873..2640794 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -42,12 +42,15 @@ wait_for_pid () { local pidfile="${1}" if [ -n "${pidfile}" ] && [ -r "${pidfile}" ] ; then - local wait_pid="$(< "${pidfile}")" + local wait_pid + wait_pid="$(< "${pidfile}")" while kill -0 "${wait_pid}" > /dev/null 2>&1 ; do log_message "Waiting for PID ${wait_pid} to finish" sleep $(( ( RANDOM % 30 ) + 5 )) done - test -f "${pidfile}" && rm -f "${pidfile}" || true + if [ -f "${pidfile}" ] ; then + rm -f "${pidfile}" + fi fi } From 616cbbbaf706e2e9cdde40fbd210aa7df53ee1bb Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 16 Aug 2016 22:58:30 +0200 Subject: [PATCH 21/65] Fix SC2064 in pki-realm Fix https://github.com/koalaman/shellcheck/wiki/SC2064 --- files/usr/local/lib/pki/pki-realm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 2640794..7e242fd 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -68,7 +68,7 @@ create_lock () { fi # Exclusive lock succeeded - trap "clean_up ${pidfile}" EXIT + trap 'clean_up ${pidfile}' EXIT } # Inlined in the following scripts: pki-authority, pki-realm {{{ From c55e5b2da89962faed94a0f3d97f8186293c6fc0 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Wed, 17 Aug 2016 09:27:53 +0200 Subject: [PATCH 22/65] Partly revert e73bf1775 --- defaults/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 34a4ff2..316bf5b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -25,8 +25,8 @@ pki_enabled: '{{ (True # .. envvar:: pki_internal # # Enable or disable support for internal certificates. If the support is -# enabled, the PKI realm will generate its own set of self-signed -# certificates. +# disabled, the PKI realm will generate its own set of self-signed +# certificates on remote hosts. pki_internal: '{{ (True if pki_default_domain else False) | bool }}' From ca1bc536f4664393d3492d9fe6e37a34a31af417 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Thu, 18 Aug 2016 22:10:25 +0200 Subject: [PATCH 23/65] =?UTF-8?q?Don=E2=80=99t=20use=20`MD5`=20to=20saniti?= =?UTF-8?q?ze=20STDOUT=20and=20instead=20use=20`base64`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit base64 is much simpler then MD5 or other hash functions. Using a hash function to sanitize input just introduces an additional risk (e. g. collisions). --- CHANGES.rst | 5 ++++- files/secret/pki/lib/pki-authority | 10 +++++----- files/usr/local/lib/pki/pki-realm | 20 ++++++++++---------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 403d556..9c20c2b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -40,6 +40,9 @@ Fixed that was unsupported in modern Python versions, the call is now supported on both 2.x and 3.x. [yuvadm] +- Don’t use ``MD5`` or other hash functions to sanitize STDOUT of programs for later + comparison when a simple ``base64`` encoding is enough. [ypid_] + `debops.pki v0.2.13`_ - 2016-07-07 ---------------------------------- @@ -64,7 +67,7 @@ Changed Changed ~~~~~~~ -- The session token is now generated using ``sha256`` hashing algorithm instead +- The session token is now generated using ``SHA-256`` hashing algorithm instead of ``MD5``. [drybjed_] - Move the copyright information to a ``COPYRIGHT`` file in the main directory. diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 364f40c..1158f51 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -661,13 +661,13 @@ check_openssl_req_crt_match () { local check_req="${1}" local check_crt="${2}" - local md5_req - local md5_crt + local req_modulus + local crt_modulus - md5_req="$(openssl req -noout -modulus -in "${check_req}" | md5sum | awk '{print $1}')" - md5_crt="$(openssl x509 -noout -modulus -in "${check_crt}" | md5sum | awk '{print $1}')" + req_modulus="$(openssl req -noout -modulus -in "${check_req}" | base64)" + crt_modulus="$(openssl x509 -noout -modulus -in "${check_crt}" | base64)" - if [ "${md5_req}" = "${md5_crt}" ] ; then + if [ "${req_modulus}" = "${crt_modulus}" ] ; then return 0 else return 1 diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 7e242fd..999f858 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -299,13 +299,13 @@ check_openssl_key_req_match () { local check_key="${1}" local check_req="${2}" - local md5_key - local md5_req + local key_modulus + local req_modulus - md5_key="$(openssl rsa -noout -modulus -in "${check_key}" | md5sum | awk '{print $1}')" - md5_req="$(openssl req -noout -modulus -in "${check_req}" | md5sum | awk '{print $1}')" + key_modulus="$(openssl rsa -noout -modulus -in "${check_key}" | base64)" + req_modulus="$(openssl req -noout -modulus -in "${check_req}" | base64)" - if [ "${md5_key}" = "${md5_req}" ] ; then + if [ "${key_modulus}" = "${req_modulus}" ] ; then return 0 else return 1 @@ -317,13 +317,13 @@ check_openssl_key_crt_match () { local check_crt="${2}" if [ -r "${check_key}" ] && [ -r "${check_crt}" ] ; then - local md5_key - local md5_crt + local key_modulus + local crt_modulus - md5_key="$(openssl rsa -noout -modulus -in "${check_key}" | md5sum | awk '{print $1}')" - md5_crt="$(openssl x509 -noout -modulus -in "${check_crt}" | md5sum | awk '{print $1}')" + key_modulus="$(openssl rsa -noout -modulus -in "${check_key}" | base64)" + crt_modulus="$(openssl x509 -noout -modulus -in "${check_crt}" | base64)" - if [ "${md5_key}" = "${md5_crt}" ] ; then + if [ "${key_modulus}" = "${crt_modulus}" ] ; then return 0 else return 1 From 5dc961f870d2943b60b60f38a984e37c8aef947b Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Thu, 18 Aug 2016 22:36:49 +0200 Subject: [PATCH 24/65] No need for `awk` when `sed` is all you need and improve readability --- files/usr/local/lib/pki/pki-realm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 999f858..5d9b7eb 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -556,10 +556,10 @@ EOF local domains=( $(echo "${req_domains}" | tr "/" " ") ) local subdomains=( $(echo "${req_subdomains}" | tr "/" " ") ) - local san_ip=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Ii][Pp]:/ {print;}' | sed -e 's/^[Ii][Pp]://' | xargs ) ) - local san_dns=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Dd][Nn][Ss]:/ {print;}' | sed -e 's/^[Dd][Nn][Ss]://' | xargs ) ) - local san_uri=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Uu][Rr][Ii]:/ {print;}' | sed -e 's/^[Uu][Rr][Ii]://' | xargs ) ) - local san_email=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Ee][Mm][Aa][Ii][Ll]:/ {print;}' | sed -e 's/^[Ee][Mm][Aa][Ii][Ll]://' | xargs ) ) + local san_ip=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^ip://pi' | xargs ) ) + local san_dns=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^dns://pi' | xargs ) ) + local san_uri=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^uri://pi' | xargs ) ) + local san_email=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^email://pi' | xargs ) ) local all_dns=( ${domains[@]:-} ) @@ -643,10 +643,10 @@ EOF local domains=( $(echo "${req_domains}" | tr "/" " ") ) local subdomains=( $(echo "${req_subdomains}" | tr "/" " ") ) - local san_ip=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Ii][Pp]:/ {print;}' | sed -e 's/^[Ii][Pp]://' | xargs ) ) - local san_dns=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Dd][Nn][Ss]:/ {print;}' | sed -e 's/^[Dd][Nn][Ss]://' | xargs ) ) - local san_uri=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Uu][Rr][Ii]:/ {print;}' | sed -e 's/^[Uu][Rr][Ii]://' | xargs ) ) - local san_email=( $( echo "${req_san}" | tr "|" "\n" | awk '/^[Ee][Mm][Aa][Ii][Ll]:/ {print;}' | sed -e 's/^[Ee][Mm][Aa][Ii][Ll]://' | xargs ) ) + local san_ip=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^ip://pi' | xargs ) ) + local san_dns=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^dns://pi' | xargs ) ) + local san_uri=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^uri://pi' | xargs ) ) + local san_email=( $( echo "${req_san}" | tr "|" "\n" | sed --quiet -e 's/^email://pi' | xargs ) ) local all_dns=( ${domains[@]:-} ) From e8e76f1f6d48343c18e941540ae99f9a36b6ba4f Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 00:00:46 +0200 Subject: [PATCH 25/65] ${pidfile} needs to be expanded in the function context Reverts a9161b5d14c --- files/usr/local/lib/pki/pki-realm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 5d9b7eb..7149db6 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -68,7 +68,8 @@ create_lock () { fi # Exclusive lock succeeded - trap 'clean_up ${pidfile}' EXIT + # shellcheck disable=SC2064 + trap "clean_up ${pidfile}" EXIT } # Inlined in the following scripts: pki-authority, pki-realm {{{ From 73a902a5441a908f1377c408789538c15a6e4b18 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 21:58:14 +0200 Subject: [PATCH 26/65] Improve readability --- files/usr/local/lib/pki/pki-realm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 7149db6..5fa4f10 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -1249,11 +1249,19 @@ check_files () { if [[ ${name} != *.* && ${name} != *@* ]] ; then - "create_${library}_config" "selfsigned/${library}.conf" selfsigned "${config['subject']:-${config['pki_default_subject']}}" "${config['domains']:-${config['pki_default_domain']}}" "${config['subdomains']:-${config['pki_default_subdomains']}}" "${config['subject_alt_names']:-}" + "create_${library}_config" "selfsigned/${library}.conf" selfsigned \ + "${config['subject']:-${config['pki_default_subject']}}" \ + "${config['domains']:-${config['pki_default_domain']}}" \ + "${config['subdomains']:-${config['pki_default_subdomains']}}" \ + "${config['subject_alt_names']:-}" elif [[ ${name} == *.* && ${name} != *@* ]] ; then - "create_${library}_config" "selfsigned/${library}.conf" selfsigned "${config['subject']:-cn=${name}}" "${config['domains']:-${name:-${config['pki_default_domain']}}}" "${config['subdomains']:-${config['pki_default_subdomains']}}" "${config['subject_alt_names']:-}" + "create_${library}_config" "selfsigned/${library}.conf" selfsigned \ + "${config['subject']:-cn=${name}}" \ + "${config['domains']:-${name:-${config['pki_default_domain']}}}" \ + "${config['subdomains']:-${config['pki_default_subdomains']}}" \ + "${config['subject_alt_names']:-}" fi From 6c56e627ad00e821192c9ed5fb3f47be215fe1ec Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 21:59:15 +0200 Subject: [PATCH 27/65] acme/error.log does not need to be readable in order to abort --- files/usr/local/lib/pki/pki-realm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 5fa4f10..59ad744 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -1018,7 +1018,7 @@ convert_der_to_pem () { request_acme_tiny_certificate () { - if [ "${config['pki_acme']}" = "true" ] && [ -x "${config['acme_client_script']}" ] && [ -d "${config['acme_challenge_dir']}" ] && [ ! -r acme/error.log ] && [ -r acme/request.pem ] ; then + if [ "${config['pki_acme']}" = "true" ] && [ -x "${config['acme_client_script']}" ] && [ -d "${config['acme_challenge_dir']}" ] && [ ! -e acme/error.log ] && [ -r acme/request.pem ] ; then if ! ( check_expiration_time acme/cert.pem "${config['acme_expiration_seconds']}" && check_openssl_key_crt_match private/key.pem acme/cert.pem ) ; then From 74232b24e35d980f256f6ec10100e3c1e9a7f510 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 22:07:47 +0200 Subject: [PATCH 28/65] Fix SC2027 in pki-realm https://github.com/koalaman/shellcheck/wiki/SC2027 --- files/usr/local/lib/pki/pki-realm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 59ad744..d16279c 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -1026,8 +1026,8 @@ request_acme_tiny_certificate () { set +e su --shell /bin/sh -c "umask 0022 ; ${config['acme_client_script']} --account-key acme/account_key.pem \ - --ca "${config['acme_ca_api']}" --csr acme/request.pem \ - --acme-dir "${config['acme_challenge_dir']}" > acme/cert.pem.tmp 2>acme/error.log" "${config['acme_user']}" + --ca \"${config['acme_ca_api']}\" --csr acme/request.pem \ + --acme-dir \"${config['acme_challenge_dir']}\" > acme/cert.pem.tmp 2>acme/error.log" "${config['acme_user']}" set -e else From 1ac77123d610e3774a3bb8448f153a1b1f027581 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 23:00:24 +0200 Subject: [PATCH 29/65] Fix SC2068 and SC1090 https://github.com/koalaman/shellcheck/wiki/SC2068 https://github.com/koalaman/shellcheck/wiki/SC1090 --- files/secret/pki/lib/pki-authority | 14 ++++---- files/usr/local/lib/pki/pki-realm | 52 ++++++++++++++++-------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 1158f51..def90d3 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -14,7 +14,7 @@ _openssl () { # OpenSSL writes to stderr/stdout even when there are no errors. So just # display the output if the exit code was != 0 to simplify debugging. set +e - _openssl_out="$(openssl ${@} 2>&1)" + _openssl_out="$(openssl "${@}" 2>&1)" local rc=$? set -e if [ ${rc} -ne 0 ]; then @@ -156,7 +156,8 @@ enter_authority () { local authority="${1}" local config_file="${2:-config/authority.conf}" - test -d "${config['pki_authorities']}/${authority}" || mkdir -p -m ${config['public_dir_mode']} "${config['pki_authorities']}/${authority}" + mkdir -p "${config['pki_authorities']}/${authority}" + chmod_idempotent ${config['public_dir_mode']} "${config['pki_authorities']}/${authority}" cd "${config['pki_authorities']}/${authority}" local rc=$? @@ -164,6 +165,7 @@ enter_authority () { if [ -r "${config_file}" ] ; then # FIXME: Add a code that checks if the config file has no dangerous code inside + # shellcheck disable=SC1090 . "${config_file}" fi @@ -178,7 +180,7 @@ update_symlink () { shift 1 - for target in ${@} ; do + for target in "${@}" ; do if [ -r "${target}" ] ; then if [ -L "${symlink_target}" ] && [ "$(readlink "${symlink_target}")" == "${target}" ] ; then break @@ -1071,7 +1073,7 @@ create_public_directories () { local directories=( ${@} ) - for directory in ${directories[@]} ; do + for directory in "${directories[@]}" ; do mkdir -p "${directory}" chmod_idempotent "${config['public_dir_mode']}" "${directory}" chgrp_idempotent "${dir_group}" "${directory}" @@ -1090,7 +1092,7 @@ create_private_directories () { local directories=( ${@} ) - for directory in ${directories[@]} ; do + for directory in "${directories[@]}" ; do mkdir -p "${directory}" chmod_idempotent "${config['private_dir_mode']}" "${directory}" chgrp_idempotent "${dir_group}" "${directory}" @@ -1173,7 +1175,7 @@ sub_sign-by-host () { for authority in requests/* ; do if [ -r "authorities/$(basename "${authority}")/subject/cert.pem" ] ; then for host in ${authority}/* ; do - for play_host in ${@} ; do + for play_host in "${@}" ; do if [ "$(basename "${host}")" = "${play_host}" ] ; then for realm in ${host}/* ; do if [ -r "${realm}/request.pem" ] ; then diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index d16279c..11fa1f2 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -388,6 +388,7 @@ enter_realm () { if [ -r "${config_file}" ] ; then # FIXME: Add a code that checks if the config file has no dangerous code inside + # shellcheck disable=SC1090 . "${config_file}" fi @@ -431,7 +432,7 @@ run_external_script () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi @@ -856,7 +857,7 @@ generate_openssl_rsa_private_key () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" "${key_file}.tmp" fi @@ -895,7 +896,7 @@ generate_gnutls_rsa_private_key () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" "${key_file}.tmp" fi @@ -922,7 +923,7 @@ create_public_directories () { local directories=( ${@} ) - for directory in ${directories[@]} ; do + for directory in "${directories[@]}" ; do mkdir -p "${directory}" chmod_idempotent "${config['public_dir_mode']}" "${directory}" chgrp_idempotent "${dir_group}" "${directory}" @@ -941,14 +942,14 @@ create_private_directories () { local directories=( ${@} ) - for directory in ${directories[@]} ; do + for directory in "${directories[@]}" ; do mkdir -p "${directory}" chmod_idempotent "${config['private_dir_mode']}" "${directory}" chgrp_idempotent "${dir_group}" "${directory}" if type setfacl > /dev/null 2>&1 ; then local private_dir_acl_groups_x=( $(echo "${config['private_dir_acl_groups_x']}" | tr "/" " ") ) if [ ${#private_dir_acl_groups_x[@]} -ne 0 ] ; then - for acl_group in ${private_dir_acl_groups_x[@]} ; do + for acl_group in "${private_dir_acl_groups_x[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:x" "${directory}" fi @@ -970,7 +971,7 @@ create_private_noacl_directories () { local directories=( ${@} ) - for directory in ${directories[@]} ; do + for directory in "${directories[@]}" ; do mkdir -p "${directory}" chmod_idempotent "${config['private_dir_mode']}" "${directory}" chgrp_idempotent "${dir_group}" "${directory}" @@ -1130,7 +1131,7 @@ check_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi @@ -1148,7 +1149,7 @@ check_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then if ! getfacl -sc private/key.pem | grep -Eq '^group' ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem fi @@ -1205,7 +1206,7 @@ check_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi @@ -1223,7 +1224,7 @@ check_files () { local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then if ! getfacl -sc private/key.pem | grep -Eq '^group' ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem fi @@ -1292,7 +1293,7 @@ check_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi @@ -1361,7 +1362,7 @@ process_public_files () { local authority_preference=( $(echo "${config['pki_authority_preference']}" | tr "/" " ") ) - for authority in ${authority_preference[@]} ; do + for authority in "${authority_preference[@]}" ; do if [ -r "${authority}/cert.pem" ] && ( check_expiration_time "${authority}/cert.pem" $(( 60 * 60 * 24 * 10 )) || [ "${authority}" = "${authority_preference[-1]}" ] ) ; then @@ -1506,7 +1507,7 @@ process_private_files () { local authority_preference=( $(echo "${config['pki_authority_preference']}" | tr "/" " ") ) - for authority in ${authority_preference[@]} ; do + for authority in "${authority_preference[@]}" ; do if [ -r "${authority}/cert.pem" ] && ( check_expiration_time "${authority}/cert.pem" $(( 60 * 60 * 24 * 10 )) || [ "${authority}" = "${authority_preference[-1]}" ] ) ; then @@ -1519,7 +1520,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi @@ -1542,7 +1543,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi @@ -1562,7 +1563,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi @@ -1582,7 +1583,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi @@ -1606,7 +1607,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi @@ -1624,7 +1625,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi @@ -1638,7 +1639,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain.pem.tmp fi @@ -1656,7 +1657,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain_dhparam.pem.tmp fi @@ -1670,7 +1671,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain_dhparam.pem.tmp fi @@ -1685,7 +1686,7 @@ process_private_files () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key_chain_dhparam.pem.tmp fi @@ -1743,6 +1744,7 @@ activate_new_files () { state+=("file-deletion") done + ## FIXME if [ ! -r public/cert.pem ] && [ public/cert.pem.sig ] ; then rm -f public/cert.pem.sig fi @@ -1949,7 +1951,7 @@ sub_new-realm () { if type setfacl > /dev/null 2>&1 ; then local private_file_acl_groups_r=( $(echo "${config['private_file_acl_groups_r']}" | tr "/" " ") ) if [ ${#private_file_acl_groups_r[@]} -ne 0 ] ; then - for acl_group in ${private_file_acl_groups_r[@]} ; do + for acl_group in "${private_file_acl_groups_r[@]}" ; do if getent group "${acl_group}" > /dev/null ; then setfacl -m "g:${acl_group}:r" private/key.pem.tmp fi From db0b5cd174524fd88b8db47512979d914ca70ce8 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 23:01:54 +0200 Subject: [PATCH 30/65] Fix static condition --- files/usr/local/lib/pki/pki-realm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 11fa1f2..5fd6624 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -1744,8 +1744,7 @@ activate_new_files () { state+=("file-deletion") done - ## FIXME - if [ ! -r public/cert.pem ] && [ public/cert.pem.sig ] ; then + if [ ! -r public/cert.pem ] && [ -e public/cert.pem.sig ] ; then rm -f public/cert.pem.sig fi From fd2f0da333c5daadbf8b0f7fa1a231734794e1df Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 23:57:38 +0200 Subject: [PATCH 31/65] Quick and dirty update of Vim folds in defaults/main.yml --- defaults/main.yml | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 316bf5b..45a409a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,4 +1,6 @@ --- +# .. vim: foldmarker=[[[,]]]:foldmethod=marker + # Default variables # ================= @@ -8,7 +10,7 @@ # .. include:: includes/all.rst -# .. Global PKI configuration ((( +# .. Global PKI configuration [[[ # # ---------------------------- # Global PKI configuration @@ -110,9 +112,9 @@ pki_vcs_ignore_patterns_group: [] # this role. pki_vcs_ignore_patterns_host: [] -# .. ))) +# .. ]]] -# .. Automatic Certificate Management Environment ((( +# .. Automatic Certificate Management Environment [[[ # # ------------------------------------------------ # Automatic Certificate Management Environment @@ -230,9 +232,9 @@ pki_acme_challenge_dir: '{{ (ansible_local.nginx.acme_root else "/srv/www/sites/acme/public") + "/.well-known/acme-challenge" }}' -# .. ))) +# .. ]]] -# .. Required software packages ((( +# .. Required software packages [[[ # # ------------------------------ # Required software packages @@ -257,9 +259,9 @@ pki_acme_packages: [ 'curl', 'git' ] # List of additional APT packages to install. pki_packages: [] -# .. ))) +# .. ]]] -# .. Directory, file and user/group configuration ((( +# .. Directory, file and user/group configuration [[[ # # ------------------------------------------------ # Directory, file and user/group configuration @@ -331,9 +333,9 @@ pki_private_dir_acl_groups: [] # access will be granted using the filesystem ACL table. pki_private_file_acl_groups: [] -# .. ))) +# .. ]]] -# .. Certificate sign times ((( +# .. Certificate sign times [[[ # # -------------------------- # Certificate sign times @@ -366,9 +368,9 @@ pki_default_ca_sign_multiplier: '10' # the base time amount. pki_default_cert_sign_multiplier: '3' -# .. ))) +# .. ]]] -# .. Configuration of PKI Realms ((( +# .. Configuration of PKI Realms [[[ # # ------------------------------- # Configuration of PKI Realms @@ -494,9 +496,9 @@ pki_dhparam_file: '{{ ansible_local.dhparam.default ansible_local.dhparam.default) else "" }}' -# .. ))) +# .. ]]] -# .. Configuration of PKI Certificate Authorities ((( +# .. Configuration of PKI Certificate Authorities [[[ # # ------------------------------------------------ # Configuration of PKI Certificate Authorities @@ -618,9 +620,9 @@ pki_dependent_authorities: [] # pki_ca_certificates_path: 'by-group/all' -# .. ))) +# .. ]]] -# .. Custom file management ((( +# .. Custom file management [[[ # # -------------------------- # Custom file management @@ -665,9 +667,9 @@ pki_group_public_files: [] # Copy public files to specific hosts in inventory. pki_host_public_files: [] -# .. ))) +# .. ]]] -# .. System-wide Root CA Certificates ((( +# .. System-wide Root CA Certificates [[[ # # ------------------------------------ # System-wide Root CA Certificates @@ -702,4 +704,4 @@ pki_system_ca_certificates_blacklist: # certificate files or use regular expressions. pki_system_ca_certificates_whitelist: [] -# .. ))) +# .. ]]] From 6b50a90ed3d2e4bcc0fd8077b99a882bb4919123 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 19 Aug 2016 23:58:22 +0200 Subject: [PATCH 32/65] Fix redundancy and spelling in docs, add fixme --- docs/pki-realms.rst | 8 ++++---- files/usr/local/lib/pki/pki-realm | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/pki-realms.rst b/docs/pki-realms.rst index f4027ff..8d9e46e 100644 --- a/docs/pki-realms.rst +++ b/docs/pki-realms.rst @@ -276,9 +276,9 @@ existence of the private keys and certificates can function correctly at all times. The :program:`pki-realm` script checks which of these directories have signed -and valid certificates in order (``external``, ``acme``, ``internal``, -``selfsigned``), and the first valid one is used as the "active" directory. -Files from the active directory are symlinked to the :file:`public/` directory. +and valid certificates in order of :envvar:`pki_authority_preference`, and the +first valid one is used as the "active" directory. Files from the active +directory are symlinked to the :file:`public/` directory. The :file:`public/` directory holds the currently active certificates which are symlinks to the real certificate files in one of the active directories mentioned above. @@ -393,7 +393,7 @@ there: When all of the requests have been processed, Ansible copies the content of the directories to remote hosts. The content of the :file:`by-host/` directory is copied -first and overwrite all files that are present on remote hosts, the +first and overwrites all files that are present on remote hosts, the :file:`by-group/` directory content is copied only when the corresponding files are not present. This allows the administrator to provide the shared scripts or private keys/certificates as needed, per host, per group or for all managed diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 5fd6624..8e2366e 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -427,6 +427,7 @@ run_external_script () { if [ ! -r private/realm_key.pem ] ; then generate_${config['pki_library']}_rsa_realm_key private/realm_key.pem +# FIXME: Redundancy! Why? if [ ! -r private/key.pem ] ; then install -g "${config['private_file_group']}" -m "${config['private_file_mode']}" /dev/null private/key.pem.tmp if type setfacl > /dev/null 2>&1 ; then From 7f16f14dbc38272d06c4c1978e9c657f06ff390b Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sat, 20 Aug 2016 00:28:05 +0200 Subject: [PATCH 33/65] Make realm RSA key size configurable --- CHANGES.rst | 6 ++++++ defaults/main.yml | 6 ++++++ files/usr/local/lib/pki/pki-realm | 15 +++++++++++---- tasks/main.yml | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 9c20c2b..fe8b9ca 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -16,6 +16,12 @@ The current role maintainer_ is drybjed_. .. _debops.pki master: https://github.com/debops/ansible-pki/compare/v0.2.13...master +Added +~~~~~ + +- Reintroduce the possibility to configure RSA key sizes using + :envvar:`pki_realm_key_size` which was removed in v0.2.0. [ypid_] + Changed ~~~~~~~ diff --git a/defaults/main.yml b/defaults/main.yml index 45a409a..b24a449 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -383,6 +383,12 @@ pki_default_cert_sign_multiplier: '3' pki_library: 'gnutls' +# .. envvar:: pki_realm_key_size +# +# The key size in bits to use when generating realm RSA keys. +pki_realm_key_size: '2048' + + # .. envvar:: pki_system_realm # # System-wide PKI realm which is used by services by default for server diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 8e2366e..07e1479 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -183,6 +183,7 @@ initialize_environment () { config["pki_dhparam"]="false" config["dhparam_file"]="" + config["realm_key_size"]="2048" config["internal_expiration_days"]="14" config["internal_expiration_seconds"]="$(( 60 * 60 * 24 * ${config['internal_expiration_days']} ))" @@ -800,7 +801,7 @@ selfsign_gnutls_request () { generate_openssl_rsa_realm_key () { local key_file="${1:-private/realm_key.pem}" - local key_size="${2:-2048}" + local key_size="${2:-${config['realm_key_size']}}" local key_group="${3:-${config['realm_file_group']}}" test -r "${key_file}" || openssl genrsa -out "${key_file}.tmp" "${key_size}" @@ -819,7 +820,7 @@ generate_openssl_rsa_realm_key () { generate_gnutls_rsa_realm_key () { local key_file="${1:-private/realm_key.pem}" - local key_size="${2:-2048}" + local key_size="${2:-${config['realm_key_size']}}" local key_group="${3:-${config['realm_file_group']}}" if ! [ -r "${key_file}" ] ; then @@ -845,7 +846,7 @@ generate_gnutls_rsa_realm_key () { generate_openssl_rsa_private_key () { local key_file="${1:-private/key.pem}" - local key_size="${2:-2048}" + local key_size="${2:-${config['realm_key_size']}}" local key_group="${3:-${config['private_file_group']}}" local key_acl="${4:-true}" @@ -877,7 +878,7 @@ generate_openssl_rsa_private_key () { generate_gnutls_rsa_private_key () { local key_file="${1:-private/key.pem}" - local key_size="${2:-2048}" + local key_size="${2:-${config['realm_key_size']}}" local key_group="${3:-${config['private_file_group']}}" local key_acl="${4:-true}" @@ -2124,6 +2125,12 @@ sub_init () { dhparam-file=*) args["dhparam_file"]=${OPTARG#*=} ;; + realm-key-size) + args["realm_key_size"]="${!OPTIND}"; OPTIND=$(( OPTIND + 1 )) + ;; + realm-key-size=*) + args["realm_key_size"]=${OPTARG#*=} + ;; acme) args["pki_acme"]="${!OPTIND}"; OPTIND=$(( OPTIND + 1 )) ;; diff --git a/tasks/main.yml b/tasks/main.yml index f3a823f..0781906 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -122,6 +122,7 @@ "{{ pki_fact_lib_path }}/pki-realm" init -n "{{ item.name }}" --authority-preference "{{ (item.authority_preference | d(pki_authority_preference)) | join('/') }}" --library "{{ item.library | d(pki_library) }}" + --realm-key-size "{{ item.realm_key_size | d(pki_realm_key_size) }}" --internal "{{ (item.internal | d(pki_internal)) | bool | lower }}" --private-dir-group "{{ item.private_dir_group | d(pki_private_group) }}" --private-file-group "{{ item.private_file_group | d(pki_private_group) }}" From 3a7ab159eba2f1d433d7dca817bcaa2e3c0f937c Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sat, 20 Aug 2016 00:47:15 +0200 Subject: [PATCH 34/65] Make RSA key size of default CAs configurable --- CHANGES.rst | 3 ++- defaults/main.yml | 21 +++++++++++++++++++++ files/secret/pki/lib/pki-authority | 11 +++++++++-- tasks/main.yml | 1 + 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index fe8b9ca..0a91bd2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,7 +20,8 @@ Added ~~~~~ - Reintroduce the possibility to configure RSA key sizes using - :envvar:`pki_realm_key_size` which was removed in v0.2.0. [ypid_] + :envvar:`pki_realm_key_size` (realms) and ``pki_ca_*_key_size`` (CAs) which + was removed in v0.2.0. [ypid_] Changed ~~~~~~~ diff --git a/defaults/main.yml b/defaults/main.yml index b24a449..89aab2b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -544,12 +544,24 @@ pki_ca_organization: '{{ pki_ca_domain.split(".") | first | capitalize }}' pki_ca_root_dn: [ 'o={{ pki_ca_organization }} Certificate Authority' ] +# .. envvar:: pki_ca_root_key_size +# +# The key size in bits to use when generating the RSA Root CA key. +pki_ca_root_key_size: '4096' + + # .. envvar:: pki_ca_domain_dn # # The Distinguished Name (subject) of the Domain Certificate Authority. pki_ca_domain_dn: [ 'o={{ pki_ca_organization }}', 'ou=Domain CA' ] +# .. envvar:: pki_ca_domain_key_size +# +# The key size in bits to use when generating the RSA Domain CA key. +pki_ca_domain_key_size: '4096' + + # .. envvar:: pki_ca_service_enabled # # Enable or disable special Service Certificate Authority, which is a Root CA @@ -565,6 +577,12 @@ pki_ca_service_enabled: False pki_ca_service_dn: [ 'o={{ pki_ca_organization }}', 'ou=Internal Services CA' ] +# .. envvar:: pki_ca_service_key_size +# +# The key size in bits to use when generating the RSA Service CA key. +pki_ca_service_key_size: '4096' + + # .. envvar:: pki_authorities_ca_root # # Configuration of the Root Certificate Authority. @@ -572,6 +590,7 @@ pki_authorities_ca_root: name: 'root' subdomain: 'root-ca' subject: '{{ pki_ca_root_dn }}' + key_size: '{{ pki_ca_root_key_size }}' # .. envvar:: pki_authorities_ca_domain @@ -582,6 +601,7 @@ pki_authorities_ca_domain: subdomain: 'domain-ca' subject: '{{ pki_ca_domain_dn }}' issuer_name: 'root' + key_size: '{{ pki_ca_domain_key_size }}' # .. envvar:: pki_authorities_ca_service @@ -593,6 +613,7 @@ pki_authorities_ca_service: subject: '{{ pki_ca_service_dn }}' type: 'service' enabled: '{{ pki_ca_service_enabled | bool }}' + key_size: '{{ pki_ca_service_key_size }}' # .. envvar:: pki_authorities diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index def90d3..b255e24 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -135,6 +135,7 @@ initialize_environment () { config["root_sign_days"]="" config["ca_sign_days"]="" config["cert_sign_days"]="" + config["key_size"]="4096" config["public_dir_group"]="$(id -gn)" config["public_file_group"]="$(id -gn)" @@ -1020,7 +1021,7 @@ generate_gnutls_serial () { generate_openssl_rsa_private_key () { local key_file="${1:-private/key.pem}" - local key_size="${2:-4096}" + local key_size="${2:-${config['key_size']}}" local key_group="${3:-${config['private_file_group']}}" test -r "${key_file}" || openssl genrsa -out "${key_file}.tmp" "${key_size}" @@ -1039,7 +1040,7 @@ generate_openssl_rsa_private_key () { generate_gnutls_rsa_private_key () { local key_file="${1:-private/key.pem}" - local key_size="${2:-4096}" + local key_size="${2:-${config['key_size']}}" local key_group="${3:-${config['private_file_group']}}" if ! [ -r "${key_file}" ] ; then @@ -1314,6 +1315,12 @@ sub_new-ca () { cert-sign-days=*) args["cert_sign_days"]=${OPTARG#*=} ;; + key-size) + args["key_size"]="${!OPTIND}"; OPTIND=$(( OPTIND + 1 )) + ;; + key-size=*) + args["key_size"]=${OPTARG#*=} + ;; *) if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then echo "Unknown option --${OPTARG}" >&2 diff --git a/tasks/main.yml b/tasks/main.yml index 0781906..54bb6c3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -322,6 +322,7 @@ --cert-sign-days "{{ item.cert_sign_days | d('') }}" --system-ca "{{ (item.system_ca | d(True)) | bool | lower }}" --alt-authority "{{ item.alt_authority | d('') }}" + --key-size "{{ item.key_size | d('') }}" args: chdir: '{{ secret + "/pki" }}' creates: '{{ secret + "/pki/authorities/" + item.name + "/subject/cert.pem" }}' From fd6ff022924ebb2221d8dfd562e08ca38f9926ba Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sat, 20 Aug 2016 16:10:29 +0200 Subject: [PATCH 35/65] Set openssl req default_bits to the configured key size --- files/secret/pki/lib/pki-authority | 2 +- files/usr/local/lib/pki/pki-realm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index b255e24..27bb51d 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -207,7 +207,7 @@ create_openssl_request_config () { [ req ] default_md = sha256 -default_bits = 4096 +default_bits = ${config['key_size']} default_keyfile = private/key.pem prompt = no encrypt_key = no diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 07e1479..c8596c0 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -511,7 +511,7 @@ create_openssl_config () { [ req ] default_md = sha256 -default_bits = 2048 +default_bits = ${config['realm_key_size']} default_keyfile = private/key.pem prompt = no encrypt_key = no From 7f830cda82c073fd4c2cab6bf030646077b4b3b5 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Mon, 29 Aug 2016 23:34:56 +0200 Subject: [PATCH 36/65] Fix spelling --- defaults/main.yml | 4 ++-- tasks/acme_tiny.yml | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 89aab2b..6b37dbd 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -139,8 +139,8 @@ pki_acme_install: '{{ pki_acme | bool }}' # .. envvar:: pki_acme_library # # The crypto library used to generate Certificate Signing Requests for ACME -# certificates, either :command:`openssl` or :command:`gnutls`. Currently OpenSSL is -# recommended due to issues with GnuTLS generation. +# certificates, either :command:`openssl` or :command:`gnutls`. Currently +# OpenSSL is recommended due to issues with GnuTLS generation. pki_acme_library: 'openssl' diff --git a/tasks/acme_tiny.yml b/tasks/acme_tiny.yml index 264cdbf..5d4540d 100644 --- a/tasks/acme_tiny.yml +++ b/tasks/acme_tiny.yml @@ -43,7 +43,7 @@ group: 'root' mode: '0755' -- name: Create ACME Challenge path +- name: Create ACME challenge path file: path: '{{ pki_acme_challenge_dir | dirname }}' state: 'directory' @@ -54,7 +54,7 @@ ansible_local.nginx.acme|d() and ansible_local.nginx.acme|bool) -- name: Create ACME Challenge directory +- name: Create ACME challenge directory file: path: '{{ pki_acme_challenge_dir }}' state: 'directory' @@ -64,4 +64,3 @@ when: (ansible_local|d() and ansible_local.nginx|d() and ansible_local.nginx.acme|d() and ansible_local.nginx.acme|bool) - From 028c0279390f3484f63b7a8c01eaf5a3645d2fa0 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 4 Sep 2016 18:21:26 +0200 Subject: [PATCH 37/65] Be more precise in defaults documentation --- defaults/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 6b37dbd..e797ae3 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -55,12 +55,12 @@ pki_inventory_groups: [ 'debops_service_pki' ] # .. envvar:: pki_vcs_ignore_patterns_role # -# This list allows you to define ignore patterns for files below -# :file:`/etc/pki` that version control systems should ignore. -# :file:`/etc` is not tracked by default by a version control system so this -# definition exists preliminary in case you decide to use :program:`etckeeper` for -# example to track changes in :file:`/etc`. In case you want to track -# sensitive files by a version control system specify: +# This list of ignore patterns for files below :file:`/etc/pki` that version +# control systems should ignore. +# :file:`/etc` is not tracked by default by a version control system. +# This definition exists preliminary in case you decide to use +# :program:`etckeeper` for example to track changes in :file:`/etc`. In case +# you want to track sensitive files by a version control system specify: # # .. code-block:: yaml # :linenos: From 89ac98d8cca1d4991c35f6184cf37b163a35f09e Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 6 Sep 2016 21:00:21 +0200 Subject: [PATCH 38/65] Improve "Certificate for subdomains excluding apex domain" section * Remove "I want a" from title :) * The ACME severs is unspecific. * `pki_acme` is unrelated to this section. * Comments after YAML variables might case problems in certain YAML modes and should thus be avoided. * Use the more specific term "apex domain" as already suggested by @drybjed in: https://github.com/debops/ansible-pki/pull/82#discussion_r77451126 Related to: #82 Wanted confirmation from: @ser, @drybjed --- docs/acme-integration.rst | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index 97cb55c..5218715 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -155,31 +155,32 @@ configuration active, it will check for validity of the signed certificate, and about a month before the expiration date it will try to renew the certificate automatically. -I want a certificate for subdomains but domain ----------------------------------------------- +Certificate for subdomains excluding apex domain +------------------------------------------------ Yes, it's possible :-) Please consult the example and create your own similar -configuration. In the example we create a certificate for ``logs.example.com`` -and ``mon.example.com`` subdoimains, without creating cert for ``example.com`` -domain itself. Please notice that PKI realm does not contain your full domain -name, it's crucial. +configuration. In the example we create a certificate for the ``logs.example.com`` +and ``mon.example.com`` subdomains, which does not include the ``example.com`` +apex domain. Please notice that the PKI realm does not contain your full domain +name. This is crucial. .. code-block:: yaml - pki_acme: True pki_realms: - - name: 'example' # do not include full domain name here! + # Do not include the full domain name here! + - name: 'example' acme: True acme_default_subdomains: [] acme_subject: [ 'cn=logs.example.com' ] acme_domains: [ 'logs.example.com', 'mon.example.com' ] domains: [ 'logs.example.com', 'mon.example.com' ] - #acme_ca: 'le-staging' + # acme_ca: 'le-staging' -For testing it's strongly advised to uncomment ``acme_ca`` with ``le-staging`` to -use testing ACME servers. It does not create a real cert, but allows you to avoid -problems with usual ACME servers rate limits. When you are sure that everything works -correctly, comment the staging environment back. +For testing it's strongly advised to uncomment ``acme_ca`` with ``le-staging`` +to use the staging environment of Let's Encrypt. It does not create a trusted +certificate and allows you to avoid problems with the rate limits in the +production environment. When you are sure that everything works correctly, +comment the staging environment back. ACME configuration variables ---------------------------- From 600f9c510b600cc6308459f0623c996b52c0caca Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 6 Sep 2016 21:12:35 +0200 Subject: [PATCH 39/65] Add reference to the Let's Encrypt Staging Environment documentation --- defaults/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/defaults/main.yml b/defaults/main.yml index e797ae3..9dbca39 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -216,6 +216,8 @@ pki_acme_ca: 'le-live' # # Dictionary map of the ACME API endpoints, mapped to custom names, used by the # ACME client. +# Refer to the `Let's Encrypt Staging Environment documentation `__ +# for details about ``le-staging``. pki_acme_ca_api_map: 'le-live': 'https://acme-v01.api.letsencrypt.org' 'le-staging': 'https://acme-staging.api.letsencrypt.org' From bc04da395671797e96bb9abc96be6ebb877b2ce8 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 6 Sep 2016 21:52:37 +0200 Subject: [PATCH 40/65] "signed" in "signed certificate" is redundant Certificates are signed by definition. --- CHANGES.rst | 8 ++++---- README.md | 2 +- docs/acme-integration.rst | 4 ++-- docs/external-certificates.rst | 5 ++--- docs/internal-ca.rst | 10 +++++----- docs/introduction.rst | 2 +- docs/pki-realms.rst | 14 +++++++------- meta/ansigenome.yml | 2 +- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 0a91bd2..d19aea6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -107,8 +107,8 @@ Fixed - The PKI session token is now generated once for all hosts, by delegating the task to Ansible Controller. This fixes a bug with Ansible Playbook runs on - multiple hosts at once, where only one host would receive the signed - certificates at a time. [drybjed_] + multiple hosts at once, where only one host would receive the certificates at + a time. [drybjed_] `debops.pki v0.2.10`_ - 2016-06-14 @@ -256,7 +256,7 @@ Changed - Automatically reset incomplete internal certificate requests. - If a signed certificate does not exist in the realm and internal certificates + If a certificate does not exist in the realm and internal certificates are enabled, something must have gone wrong with the certificate signing. To make it easier, generated configuration file and CSR are removed so that they can be recreated further in the script with current session token and not @@ -265,7 +265,7 @@ Changed - Change the way ACME intermediate CA certificate is downloaded. Instead of using a static URL to download an intermediate certificate, - :program:`pki-realm` script will now check the signed certificate for the "CA + :program:`pki-realm` script will now check the certificate for the "CA Issuers" URI and download the certificate using it. The URI is stored and used later to check if the new certificate has the same or different URI, to not download the intermediate certificate every time the :program:`pki-realm` script diff --git a/README.md b/README.md index 8a9772c..012c14d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ encrypted connections. Using this role, you can bootstrap a Public Key Infrastructure in your environment using an internal Certificate Authority, easily switch the active set of certificates between internal and external Certificate Authorities, or -use the ACME protocol to automatically obtain signed certificates from CA that +use the ACME protocol to automatically obtain certificates from CA that support it (currently, [Let's Encrypt][lets-encrypt]). [lets-encrypt]: https://letsencrypt.org/ diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index 5218715..3ccb042 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -6,7 +6,7 @@ ACME Integration .. include:: includes/all.rst `Automated Certificate Management Environment` (ACME_) is a protocol that -allows automated certificate requests, retrieval of signed certificates and +allows automated certificate requests, retrieval of certificates and certificate renewal. It was designed to enable easy deployment of TLS/SSL certificates by the `Let's Encrypt`_ project. @@ -151,7 +151,7 @@ Certificate renewal The ``debops.pki`` role creates a :program:`cron` entry for the :program:`pki-realm` script to be executed periodically for all realms. When a realm has the ACME -configuration active, it will check for validity of the signed certificate, and +configuration active, it will check for validity of the certificate, and about a month before the expiration date it will try to renew the certificate automatically. diff --git a/docs/external-certificates.rst b/docs/external-certificates.rst index d4ffc71..b168fb7 100644 --- a/docs/external-certificates.rst +++ b/docs/external-certificates.rst @@ -5,7 +5,7 @@ External certificates The PKI realms managed by the ``debops.pki`` role support management of private keys and certificates from external Certificate Authorities. You can either -provide a set of already signed certificates with corresponding private keys, +provide a set of valid certificates with corresponding private keys, or use a script with a custom environment to request a certificate remotely in an external Certificate Authority. @@ -87,7 +87,7 @@ hosts, in a specific order: copied to all currently managed remote hosts, but won't overwrite already present files; -You can use this to distribute already signed certificates with their private +You can use this to distribute already issued certificates with their private keys. Putting them in :file:`realms/by-group/all/` directory will ensure that all hosts will have the same set of keys and certificates. If you put them in a specific group directory, only hosts in that group will receive the files. @@ -169,4 +169,3 @@ executed multiple times during ``debops.pki`` run. The state in which the realm is in will be present in the ``$PKI_SCRIPT_STATE`` variable and using that you can perform various operations, like issuing a new certificate request when the realm is created. - diff --git a/docs/internal-ca.rst b/docs/internal-ca.rst index 7db7668..791cc37 100644 --- a/docs/internal-ca.rst +++ b/docs/internal-ca.rst @@ -123,11 +123,11 @@ a Certificate Authority, on above directory tree you can see that a request has been uploaded from ``hostname.example.com`` host for the ``domain`` Certificate Authority. -The signed certificates are placed in subdirectories of the -:file:`secret/pki/realms/` directory. The intermediate CA certificate and root CA -certificate files are symlinked in the same subdirectory as the signed -certificate, so that Ansible can copy their contents as regular files to remote -host and correct certificate chains can be created in the PKI realm. +The certificates are placed in subdirectories of the :file:`secret/pki/realms/` +directory. The intermediate CA certificate and root CA certificate files are +symlinked in the same subdirectory as the leaf certificate, so that Ansible can copy +their contents as regular files to remote host and correct certificate chains +can be created in the PKI realm. Security of an internal CA -------------------------- diff --git a/docs/introduction.rst b/docs/introduction.rst index 1b67c29..e70d641 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -11,7 +11,7 @@ encrypted connections. Using this role, you can bootstrap a Public Key Infrastructure in your environment using an internal Certificate Authority, easily switch the active set of certificates between internal and external Certificate Authorities, or -use the ACME protocol to automatically obtain signed certificates from CA that +use the ACME protocol to automatically obtain certificates from CA that support it (for example `Let's Encrypt`_). Installation diff --git a/docs/pki-realms.rst b/docs/pki-realms.rst index 8d9e46e..eba5292 100644 --- a/docs/pki-realms.rst +++ b/docs/pki-realms.rst @@ -259,14 +259,14 @@ detail in a separate document, here is a brief overview: Certificate Authority. To do this, you need to provide a special :file:`script` file, which will be executed with a set of environment variables. This can be used to request a certificate from an external CA, like Active Directory or - FreeIPA, or download a signed certificate from an external location. + FreeIPA, or download a certificate from an external location. An alternative is to provide an already signed :file:`cert.pem` file and optionally the :file:`intermediate.pem` and :file:`root.pem` files. :file:`internal/` This directory is used by the internal ``debops.pki`` Certificate Authority - to transfer certificate requests as well as signed certificates. + to transfer certificate requests as well as certificates. If the internal CA is disabled either globally for a host, or for a particular PKI realm, an alternative directory, :file:`selfsigned/` will be created. It @@ -275,10 +275,10 @@ host that has created it). This is done, so that services depending on the existence of the private keys and certificates can function correctly at all times. -The :program:`pki-realm` script checks which of these directories have signed -and valid certificates in order of :envvar:`pki_authority_preference`, and the -first valid one is used as the "active" directory. Files from the active -directory are symlinked to the :file:`public/` directory. +The :program:`pki-realm` script checks which of these directories have valid +certificates in order of :envvar:`pki_authority_preference`, and the first +valid one is used as the "active" directory. Files from the active directory +are symlinked to the :file:`public/` directory. The :file:`public/` directory holds the currently active certificates which are symlinks to the real certificate files in one of the active directories mentioned above. @@ -355,7 +355,7 @@ the "root" CA. The :file:`hostname.example.com/domain/` directory inside the When all of the requests from the remote hosts are uploaded to the Ansible Controller, the :program:`pki-authority` script inside the :file:`secret/` directory takes over and performs certificate signing for all of the currently managed hosts. -The signed certificate named :file:`cert.pem` is placed in the :file:`internal/` +The certificate named :file:`cert.pem` is placed in the :file:`internal/` directory of each host according to the realm the request came from. In addition to the certificates, the CA intermediate and root certificates are diff --git a/meta/ansigenome.yml b/meta/ansigenome.yml index 88d6aaf..705e140 100644 --- a/meta/ansigenome.yml +++ b/meta/ansigenome.yml @@ -31,7 +31,7 @@ ansigenome_info: Using this role, you can bootstrap a Public Key Infrastructure in your environment using an internal Certificate Authority, easily switch the active set of certificates between internal and external Certificate Authorities, or - use the ACME protocol to automatically obtain signed certificates from CA that + use the ACME protocol to automatically obtain certificates from CA that support it (currently, [Let's Encrypt][lets-encrypt]). [lets-encrypt]: https://letsencrypt.org/ From 9ac2cfffe3cede4a19d5e65c034eafc89ef9f5ae Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 6 Sep 2016 21:58:39 +0200 Subject: [PATCH 41/65] debops-optimize and regen README --- CHANGES.rst | 2 +- COPYRIGHT | 2 +- README.md | 2 +- docs/custom-hooks.rst | 2 +- meta/main.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index d19aea6..e876849 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,7 +6,7 @@ Changelog **debops.pki** This project adheres to `Semantic Versioning `__ -and `human-readable changelog `__. +and `human-readable changelog `__. The current role maintainer_ is drybjed_. diff --git a/COPYRIGHT b/COPYRIGHT index e8523bd..e7efba6 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -2,7 +2,7 @@ debops.pki - PKI management using Ansible Copyright (C) 2013-2016 Maciej Delmanowski Copyright (C) 2015-2016 Robin Schneider -Copyright (C) 2014-2016 DebOps Project https://debops.org/ +Copyright (C) 2014-2016 DebOps https://debops.org/ This Ansible role is part of DebOps. diff --git a/README.md b/README.md index 012c14d..2134bdb 100644 --- a/README.md +++ b/README.md @@ -60,4 +60,4 @@ License: [GPL-3.0](https://tldrlegal.com/license/gnu-general-public-license-v3-% *** -This role is part of the [DebOps](https://debops.org/) project. README generated by [ansigenome](https://github.com/nickjj/ansigenome/). +This role is part of [DebOps](https://debops.org/). README generated by [ansigenome](https://github.com/nickjj/ansigenome/). diff --git a/docs/custom-hooks.rst b/docs/custom-hooks.rst index b4e742a..dfc2e14 100644 --- a/docs/custom-hooks.rst +++ b/docs/custom-hooks.rst @@ -112,7 +112,7 @@ it reloads the :program:`nginx` daemon so that new certificate can be activated. # Reload or restart nginx on a certificate state change - set -eu -o pipefail + set -o nounset -o pipefail -o errexit nginx_config="/etc/nginx/nginx.conf" nginx_sites="/etc/nginx/sites-enabled" diff --git a/meta/main.yml b/meta/main.yml index 265a072..d6e9edc 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -9,7 +9,7 @@ galaxy_info: company: 'DebOps' author: 'Maciej Delmanowski' description: 'Bootstrap and manage internal PKI, Certificate Authorities and OpenSSL/GnuTLS certificates' - license: 'GNU General Public License v3' + license: 'GPL-3.0' min_ansible_version: '2.0.0' platforms: From 3205e9f2e8cdc34bbca25f6f9332eb2fad8f65ad Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 6 Sep 2016 22:09:56 +0200 Subject: [PATCH 42/65] Test Shell scripts with shellcheck in CI build --- .travis.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5fb7508..7346fea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,15 @@ install: True script: - 'git clone --depth 1 https://github.com/nickjj/rolespec' - - 'cd rolespec ; bin/rolespec -r https://github.com/debops/test-suite' + - 'cd rolespec ; bin/rolespec -r https://github.com/debops/test-suite ; cd -' + + # We know the scripts are not perfect. Please don’t add more things that shellcheck v0.4.4 will complain about! + # The shellcheck and jq command does not return a non-zero exit code when the tested file does not exist. + - 'test -r ./files/secret/pki/lib/pki-authority' + - 'shellcheck --format=json ./files/secret/pki/lib/pki-authority | jq --exit-status "(. | length) <= 74"' + - 'test -r ./files/usr/local/lib/pki/pki-realm' + - 'shellcheck --format=json ./files/usr/local/lib/pki/pki-realm | jq --exit-status "(. | length) <= 105"' notifications: webhooks: - 'https://galaxy.ansible.com/api/v1/notifications/' - From 6a67345cd74ac219eccfa33711006e29a81c4f60 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 6 Sep 2016 23:32:52 +0200 Subject: [PATCH 43/65] More spelling fixes in ACME Integration docs --- docs/acme-integration.rst | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index 3ccb042..b89cd1c 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -1,4 +1,4 @@ -.. _acme_integration: +.. _pki__ref_acme_integration: ACME Integration ================ @@ -91,13 +91,14 @@ this: ├── CA.crt -> /etc/ssl/certs/ca-certificates.crt └── default.key -> private/key.pem -When the :program:`pki-realm` detects the :file:`acme/request.pem` file, it automatically -calls the :program:`acme-tiny` script using the ``pki-acme`` unprivileged account to request -the certificate. When the request is completed successfully and an -:file:`external/cert.pem` certificate is found, the certificate will be -activated in the :file:`public/` directory. The script automatically downloads Let's -Encrypt intermediate certificate as well as links the Root CA certificate from -the system certificate store provided by the ``ca-certificates`` package. +When the :program:`pki-realm` detects the :file:`acme/request.pem` file, it +automatically calls the :program:`acme-tiny` script using the ``pki-acme`` +unprivileged account to request the certificate. When the request has completed +successfully and an :file:`external/cert.pem` certificate is found, the +certificate will be activated in the :file:`public/` directory. The script +automatically downloads Let's Encrypt intermediate certificate as well as links +the Root CA certificate from the system certificate store provided by the +``ca-certificates`` package. The realm directory after the process is complete: @@ -155,8 +156,8 @@ configuration active, it will check for validity of the certificate, and about a month before the expiration date it will try to renew the certificate automatically. -Certificate for subdomains excluding apex domain ------------------------------------------------- +Certificate for subdomains excluding the apex domain +---------------------------------------------------- Yes, it's possible :-) Please consult the example and create your own similar configuration. In the example we create a certificate for the ``logs.example.com`` From 07ac7fae95d255ccb2c4db4f17a93d20188aa1c4 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Thu, 8 Sep 2016 20:14:55 +0200 Subject: [PATCH 44/65] Better section names for defaults/main.yml and avoid redundancy --- defaults/main.yml | 74 ++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 55 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 9dbca39..ad857c7 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -10,11 +10,7 @@ # .. include:: includes/all.rst -# .. Global PKI configuration [[[ -# -# ---------------------------- -# Global PKI configuration -# ---------------------------- +# Global PKI configuration [[[ # .. envvar:: pki_enabled # @@ -112,13 +108,9 @@ pki_vcs_ignore_patterns_group: [] # this role. pki_vcs_ignore_patterns_host: [] -# .. ]]] +# ]]] -# .. Automatic Certificate Management Environment [[[ -# -# ------------------------------------------------ -# Automatic Certificate Management Environment -# ------------------------------------------------ +# Automatic Certificate Management Environment [[[ # .. envvar:: pki_acme # @@ -234,13 +226,9 @@ pki_acme_challenge_dir: '{{ (ansible_local.nginx.acme_root else "/srv/www/sites/acme/public") + "/.well-known/acme-challenge" }}' -# .. ]]] +# ]]] -# .. Required software packages [[[ -# -# ------------------------------ -# Required software packages -# ------------------------------ +# Required software packages [[[ # .. envvar:: pki_base_packages # @@ -261,13 +249,9 @@ pki_acme_packages: [ 'curl', 'git' ] # List of additional APT packages to install. pki_packages: [] -# .. ]]] +# ]]] -# .. Directory, file and user/group configuration [[[ -# -# ------------------------------------------------ -# Directory, file and user/group configuration -# ------------------------------------------------ +# Directory, file and user/group configuration [[[ # .. envvar:: pki_root # @@ -335,13 +319,9 @@ pki_private_dir_acl_groups: [] # access will be granted using the filesystem ACL table. pki_private_file_acl_groups: [] -# .. ]]] +# ]]] -# .. Certificate sign times [[[ -# -# -------------------------- -# Certificate sign times -# -------------------------- +# Certificate sign times [[[ # .. envvar:: pki_default_sign_base # @@ -370,13 +350,9 @@ pki_default_ca_sign_multiplier: '10' # the base time amount. pki_default_cert_sign_multiplier: '3' -# .. ]]] +# ]]] -# .. Configuration of PKI Realms [[[ -# -# ------------------------------- -# Configuration of PKI Realms -# ------------------------------- +# Configuration of PKI Realms [[[ # .. envvar:: pki_library # @@ -504,13 +480,9 @@ pki_dhparam_file: '{{ ansible_local.dhparam.default ansible_local.dhparam.default) else "" }}' -# .. ]]] +# ]]] -# .. Configuration of PKI Certificate Authorities [[[ -# -# ------------------------------------------------ -# Configuration of PKI Certificate Authorities -# ------------------------------------------------ +# Internal Certificate Authorities [[[ # .. envvar:: pki_ca_library # @@ -649,13 +621,9 @@ pki_dependent_authorities: [] # pki_ca_certificates_path: 'by-group/all' -# .. ]]] +# ]]] -# .. Custom file management [[[ -# -# -------------------------- -# Custom file management -# -------------------------- +# Custom file management [[[ # You can use custom file lists to copy files to remote hosts or install # the content of Jinja variables. See :ref:`custom_file_management` for more @@ -696,14 +664,10 @@ pki_group_public_files: [] # Copy public files to specific hosts in inventory. pki_host_public_files: [] -# .. ]]] +# ]]] + +# System-wide CA Certificates [[[ -# .. System-wide Root CA Certificates [[[ -# -# ------------------------------------ -# System-wide Root CA Certificates -# ------------------------------------ -# # See :ref:`system_ca_certificates` for more details about management of # system-wide CA certificates. @@ -733,4 +697,4 @@ pki_system_ca_certificates_blacklist: # certificate files or use regular expressions. pki_system_ca_certificates_whitelist: [] -# .. ]]] +# ]]] From b1ab374055752a1eba5e8c6e728f0c18056c7d9e Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Thu, 8 Sep 2016 23:13:50 +0200 Subject: [PATCH 45/65] Use Vim folds in tasks and restructured tasks --- tasks/main.yml | 57 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 54bb6c3..98dd354 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -111,6 +111,24 @@ when: (pki_enabled|bool and (pki_acme|bool or pki_acme_install|bool)) +# Initialize PKI realms [[[ + +- name: Ensure that /etc/pki directory exists + file: + path: '/etc/pki' + state: 'directory' + owner: 'root' + group: 'root' + mode: '0755' + +- name: Ensure that sensitive files are excluded from version control + template: + src: 'etc/pki/gitignore.j2' + dest: '/etc/pki/.gitignore' + owner: 'root' + group: 'root' + mode: '0644' + - name: Initialize PKI realms environment: PKI_ROOT: '{{ pki_root }}' @@ -147,23 +165,9 @@ when: (pki_enabled|bool and item.name is defined and (item.enabled|d(True) | bool) and (item.when|d(True) | bool)) +# ]]] -- name: Ensure that /etc/pki directory exists - file: - path: '/etc/pki' - state: 'directory' - owner: 'root' - group: 'root' - mode: '0755' - -- name: Ensure that sensitive files are excluded from version control - template: - src: 'etc/pki/gitignore.j2' - dest: '/etc/pki/.gitignore' - owner: 'root' - group: 'root' - mode: '0644' - +# Download files [[[ - name: Download custom private files copy: src: '{{ item.src | d(omit) }}' @@ -224,8 +228,10 @@ when: (pki_enabled|bool and item.name is defined and (item.enabled|d(True) | bool) and (item.when|d(True) | bool)) +# ]]] -- name: Create PKI realms +# Create new PKI realms [[[ +- name: Create new PKI realms environment: PKI_SESSION_TOKEN: '{{ pki_fact_session_token }}' command: | @@ -251,7 +257,9 @@ ((item.internal|d(True) | bool) and pki_internal|bool) and (item.enabled|d(True) | bool) and (item.when|d(True) | bool)) +# ]]] +# Execute PKI realm commands [[[ - name: Execute PKI realm commands environment: PKI_SESSION_TOKEN: '{{ pki_fact_session_token }}' @@ -266,7 +274,9 @@ when: (pki_enabled|bool and item.name is defined and (item.enabled|d(True) | bool) and (item.when|d(True) | bool)) +# ]]] +# Upload internal certificate requests [[[ - name: Upload internal certificate requests fetch: src: '/etc/pki/realms/{{ item.name }}/internal/request.pem' @@ -283,7 +293,9 @@ ((item.internal|d(True) | bool) and pki_internal|bool) and (item.enabled|d(True) | bool) and (item.when|d(True) | bool)) +# ]]] +# PKI authorities [[[ - name: Initialize PKI authorities environment: PKI_ROOT: '{{ secret + "/pki" }}' @@ -332,7 +344,9 @@ with_flattened: - '{{ pki_authorities + pki_dependent_authorities }}' when: (item.name is defined and (item.enabled|d(True) | bool)) +# ]]] +# Sign certificate requests [[[ - name: Sign certificate requests for current hosts environment: PKI_SESSION_TOKEN: '{{ pki_fact_session_token }}' @@ -346,7 +360,9 @@ run_once: True when: (pki_authorities or pki_dependent_authorities) changed_when: pki_register_sign_by_host.stdout != "" +# ]]] +# Download files [[[ - name: Download public realm contents by host copy: src: '{{ secret + "/pki/realms/by-host/" + pki_fqdn + "/" + item.0.name + "/" + item.1 + "/" }}' @@ -436,7 +452,9 @@ force: False notify: [ 'Regenerate ca-certificates.crt' ] when: pki_enabled | bool +# ]]] +# Execute PKI realm commands [[[ - name: Execute PKI realm commands environment: PKI_SESSION_TOKEN: '{{ pki_fact_session_token }}' @@ -451,7 +469,9 @@ when: (pki_enabled|bool and item.name is defined and (item.enabled|d(True) | bool) and (item.when|d(True) | bool)) +# ]]] +# Manage PKI scheduler [[[ - name: Manage PKI scheduler cron: name: 'Process PKI system realms' @@ -460,11 +480,13 @@ job: 'test -x "{{ pki_fact_lib_path }}/pki-realm" && "{{ pki_fact_lib_path }}/pki-realm" schedule' special_time: '{{ pki_scheduler_interval }}' state: '{{ "present" if (pki_enabled|bool and pki_scheduler | bool) else "absent" }}' +# ]]] - name: Manage system CA certificates include: ca_certificates.yml when: pki_enabled | bool +# Ansible local facts [[[ - name: Make sure that Ansible local facts directory exists file: path: '/etc/ansible/facts.d' @@ -486,3 +508,4 @@ - name: Flush handlers for PKI if needed meta: flush_handlers when: pki_register_facts|changed +# ]]] From 864081c3c03db6bcaa4ee677e30abcedbbad8e19 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Thu, 8 Sep 2016 23:30:03 +0200 Subject: [PATCH 46/65] Fix spelling and other docs enhancements --- defaults/main.yml | 2 ++ docs/acme-integration.rst | 10 +++++----- docs/defaults-detailed.rst | 8 ++++---- docs/introduction.rst | 6 ++++-- docs/pki-realms.rst | 12 ++++++------ 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index ad857c7..cf682e5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -241,6 +241,8 @@ pki_base_packages: [ 'ssl-cert', 'make', 'ca-certificates', # .. envvar:: pki_acme_packages # # List of APT packages required by ACME support. +# ``acme-tiny`` itself is not yet available in Debian Stable. +# Ref: https://packages.debian.org/source/stretch/acme-tiny pki_acme_packages: [ 'curl', 'git' ] diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index b89cd1c..d8e6f4d 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -7,11 +7,11 @@ ACME Integration `Automated Certificate Management Environment` (ACME_) is a protocol that allows automated certificate requests, retrieval of certificates and -certificate renewal. It was designed to enable easy deployment of TLS/SSL -certificates by the `Let's Encrypt`_ project. +certificate renewal. It was designed to enable easy deployment of X.509 +certificates from `Let's Encrypt`_. The ``debops.pki`` Ansible role provides support for the ACME protocol which is -used by default with the Let's Encrypt service (there is a possibility to +used by default with the Let's Encrypt (there is a possibility to integrate other similar services in the future). Interaction with the ACME Certificate Authority is performed using the acme-tiny_ alternative client written in Python. @@ -233,8 +233,8 @@ can have several parameters related to the ACME certificates: ``item.acme_default_subdomains`` List of subdomains that should be added to all of the ACME apex/root domains. - If you want to create an ACME certificate only with the apex domain, you need - to use this parameter with ``[]`` value to override + If you want to create an ACME certificate only with the apex domain, you + might need to set this parameter to an empty list using ``[]`` to override :envvar:`pki_acme_default_subdomains`. ``item.acme_subdomains`` diff --git a/docs/defaults-detailed.rst b/docs/defaults-detailed.rst index 0abe079..704c064 100644 --- a/docs/defaults-detailed.rst +++ b/docs/defaults-detailed.rst @@ -162,9 +162,9 @@ respectively: ``default_domain`` Optional. Change the default domain used by a given PKI realm. If not - specified, default domain is based on the ``name`` parameter if it has at - least 1 dot, or it will be taken from :envvar:`pki_default_domain` variable which - is populated by the ``ansible_domain`` variable. + specified, the default domain is based on the ``name`` parameter if it has at + least 1 dot, or it will be taken from :envvar:`pki_default_domain` variable + which is populated by the ``ansible_domain`` variable. ``default_subdomains``, ``acme_default_subdomains`` Optional. List of subdomains added to each domain configured in a given PKI @@ -178,7 +178,7 @@ respectively: ``subject``, ``acme_subject`` Optional. The Distinguished Name of the certificate, specified as a list of DN elements. If not specified, a CommonName based on the default domain of - the given PKI realm. + the given PKI realm will be used. Example: diff --git a/docs/introduction.rst b/docs/introduction.rst index e70d641..d3f22cf 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -17,9 +17,11 @@ support it (for example `Let's Encrypt`_). Installation ~~~~~~~~~~~~ -This role requires at least Ansible ``v2.0.0``. To install it, run:: +This role requires at least Ansible ``v2.0.0``. To install it, run: - ansible-galaxy install debops.pki +.. code-block:: console + + ansible-galaxy install debops.pki Ansible Controller requirements ------------------------------- diff --git a/docs/pki-realms.rst b/docs/pki-realms.rst index eba5292..11971ec 100644 --- a/docs/pki-realms.rst +++ b/docs/pki-realms.rst @@ -106,7 +106,7 @@ documentation for the rest of the required configuration options. If you use the debops.nginx_ Ansible role provided with the project, it has extensive integration with the ``debops.pki`` role and can configure the webserver automatically. Usually all you need to do is to make sure the default -realm is matches with the one you would like to use for each server configuration. +realm matches the one you would like to use for each server configuration. The PKI realm directory structure --------------------------------- @@ -249,7 +249,7 @@ data files for different Certificate Authorities. Each CA is described in more detail in a separate document, here is a brief overview: :file:`acme/` - This directory is for certificates issued using ACME support (for example `Let's Encrypt`_). + This directory is for certificates issued using ACME_ (for example `Let's Encrypt`_). It will be activated and used automatically when a host has a public IP address and the :program:`nginx` webserver is installed and configured to support ACME Challenges (see the debops.nginx_ role for more details). @@ -270,7 +270,7 @@ detail in a separate document, here is a brief overview: If the internal CA is disabled either globally for a host, or for a particular PKI realm, an alternative directory, :file:`selfsigned/` will be created. It -will hold a self-signed certificate, not trusted by anything else (even the +will hold a self-signed certificate, not trusted by anything else (not even the host that has created it). This is done, so that services depending on the existence of the private keys and certificates can function correctly at all times. @@ -399,8 +399,8 @@ are not present. This allows the administrator to provide the shared scripts or private keys/certificates as needed, per host, per group or for all managed hosts. -After certificates signed by internal CA are downloaded to remote host, the -directory structure might look similar to: +After certificates signed by the internal CA are downloaded to remote hosts, +the directory structure might look similar to: .. code-block:: none @@ -430,7 +430,7 @@ contain various files. After certificates are copied from the Ansible Controller, the :program:`pki-realm` script is executed again for each PKI realm configured on -a given host. It checks which authority directories have signed and valid +a given host. It checks which authority directories have valid certificates, picks the first viable one according to :envvar:`pki_authority_preference` and activates them. From f32393d4298a09a68d9d283219010dbbb9e8ec31 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Thu, 8 Sep 2016 23:55:08 +0200 Subject: [PATCH 47/65] Also run `pki-realm new-realm` against realms with disabled internal CA For example setting a custom subject for such a realm would result in the custom subject being ignored. --- CHANGES.rst | 3 +++ tasks/main.yml | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index e876849..59cff0f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -50,6 +50,9 @@ Fixed - Don’t use ``MD5`` or other hash functions to sanitize STDOUT of programs for later comparison when a simple ``base64`` encoding is enough. [ypid_] +- Also run :program:`pki-realm new-realm` against realms with disabled internal + CA. [ypid_] + `debops.pki v0.2.13`_ - 2016-07-07 ---------------------------------- diff --git a/tasks/main.yml b/tasks/main.yml index 98dd354..9555fc2 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -254,7 +254,6 @@ - '{{ pki_default_realms }}' - '{{ pki_dependent_realms }}' when: (pki_enabled|bool and item.name is defined and - ((item.internal|d(True) | bool) and pki_internal|bool) and (item.enabled|d(True) | bool) and (item.when|d(True) | bool)) # ]]] From a018fef9b4d04dec6a61426336319a07f4f703ef Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 11 Sep 2016 14:47:25 +0200 Subject: [PATCH 48/65] Silently ignore empty elements in `subject` and `acme_subject` lists --- CHANGES.rst | 3 +++ docs/defaults-detailed.rst | 1 + files/usr/local/lib/pki/pki-realm | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 59cff0f..dead4f6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -23,6 +23,9 @@ Added :envvar:`pki_realm_key_size` (realms) and ``pki_ca_*_key_size`` (CAs) which was removed in v0.2.0. [ypid_] +- Silently ignore empty elements in ``subject`` and ``acme_subject`` lists. + This can come in handy for generated certificate subjects. [ypid_] + Changed ~~~~~~~ diff --git a/docs/defaults-detailed.rst b/docs/defaults-detailed.rst index 704c064..c905af4 100644 --- a/docs/defaults-detailed.rst +++ b/docs/defaults-detailed.rst @@ -179,6 +179,7 @@ respectively: Optional. The Distinguished Name of the certificate, specified as a list of DN elements. If not specified, a CommonName based on the default domain of the given PKI realm will be used. + Empty string elements of the list will be ignored. Example: diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index c8596c0..2591edc 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -535,7 +535,7 @@ EOF [ req_dn ] EOF - echo "${req_dn}" | tr "/" "\n" | sed \ + echo "${req_dn}" | tr "/" "\n" | grep --invert-match '^\s*$' | sed \ -e 's/^[Cc]=/countryName=/' \ -e 's/^[Ss][Tt]=/stateOrProvinceName=/' \ -e 's/^[Ll]=/localityName=/' \ @@ -635,7 +635,7 @@ expiration_days = ${config['selfsigned_sign_days']} EOF fi - echo "${req_dn}" | tr "/" "\n" | sed \ + echo "${req_dn}" | tr "/" "\n" | grep --invert-match '^\s*$' | sed \ -e 's/^[Cc]=/country = "/' \ -e 's/^[Ss][Tt]=/state = "/' \ -e 's/^[Ll]=/locality = "/' \ From 09bcca0da9a54d23ac3a8d8d9d42830db68cf8d3 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 11 Sep 2016 14:55:37 +0200 Subject: [PATCH 49/65] debops-optimize --- CHANGES.rst | 4 ++-- defaults/main.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index dead4f6..8c0a0e3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -46,9 +46,9 @@ Fixed challenge responses. Now, correct ``umask`` will be set for the :program:`acme-tiny` script, so that ACME responses are world-readable. [drybjed_] -- Fix an error in ``pki-authority`` script which invoked a Python print call +- Fix an error in :program:`pki-authority` script which invoked a Python print call that was unsupported in modern Python versions, the call is now supported - on both 2.x and 3.x. [yuvadm] + on both 2.x and 3.x. [yuvadm_] - Don’t use ``MD5`` or other hash functions to sanitize STDOUT of programs for later comparison when a simple ``base64`` encoding is enough. [ypid_] diff --git a/defaults/main.yml b/defaults/main.yml index cf682e5..27d4491 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -241,7 +241,7 @@ pki_base_packages: [ 'ssl-cert', 'make', 'ca-certificates', # .. envvar:: pki_acme_packages # # List of APT packages required by ACME support. -# ``acme-tiny`` itself is not yet available in Debian Stable. +# :program:`acme-tiny` itself is not yet available in Debian Stable. # Ref: https://packages.debian.org/source/stretch/acme-tiny pki_acme_packages: [ 'curl', 'git' ] From a01d6e83fc56a6e69c3860e020855fcec4f662fa Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 11 Sep 2016 15:00:05 +0200 Subject: [PATCH 50/65] Change python print statements to functions in `pki-realm` as well This makes the scripts work well both under Python 2.x and 3.x Fixes #85 in redundant places. Follow up for: #85 --- files/usr/local/lib/pki/pki-realm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 2591edc..aee31b5 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -85,12 +85,12 @@ key_exists () { get_absolute_path () { # Get an absolute path to a file - python -c 'import sys, os.path; print os.path.abspath(sys.argv[1])' "${1}" + python -c 'import sys, os.path; print(os.path.abspath(sys.argv[1]))' "${1}" } get_relative_path () { # Get a relative path to a file - python -c 'import sys, os.path; print os.path.relpath(sys.argv[1], sys.argv[2])' "${1}" "${2:-$PWD}" + python -c 'import sys, os.path; print(os.path.relpath(sys.argv[1], sys.argv[2]))' "${1}" "${2:-$PWD}" } get_dnsdomainname () { From 45d14dffed420262dd23885796d89bd461f430b7 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 11 Sep 2016 15:13:54 +0200 Subject: [PATCH 51/65] Fix more quoting issues in `pki-authority` --- files/secret/pki/lib/pki-authority | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 27bb51d..a06e094 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -202,7 +202,7 @@ create_openssl_request_config () { if [ -n "${config_file}" ] && [ -n "${config_dn}" ] && [ ! -r "${config_file}" ] ; then - cat << EOF > ${config_file} + cat << EOF > "${config_file}" # Configuration file generated by pki-authority [ req ] @@ -235,7 +235,7 @@ create_gnutls_request_config () { if [ -n "${config_file}" ] && [ -n "${config_dn}" ] && [ ! -r "${config_file}" ] ; then - cat << EOF > ${config_file} + cat << EOF > "${config_file}" # Configuration file generated by pki-authority EOF @@ -260,7 +260,7 @@ create_openssl_selfsign_config () { if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then - cat << EOF > ${config_file} + cat << EOF > "${config_file}" # Configuration file generated by pki-authority [ default ] @@ -315,14 +315,14 @@ emailAddress = optional EOF if [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" basicConstraints = critical, CA:TRUE keyUsage = critical, keyCertSign, cRLSign subjectKeyIdentifier = hash EOF elif [ "${config_ca_type}" = "service" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" authorityInfoAccess = @issuer_info basicConstraints = critical, CA:TRUE, pathlen:0 crlDistributionPoints = @crl_info @@ -344,7 +344,7 @@ create_gnutls_selfsign_config () { if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then - cat << EOF > ${config_file} + cat << EOF > "${config_file}" # Configuration file generated by pki-authority expiration_days = ${config['root_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_root_sign_multiplier']} ))} @@ -352,14 +352,14 @@ expiration_days = ${config['root_sign_days']:-$(( ${config['pki_default_sign_bas EOF if [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" ca cert_signing_key crl_signing_key EOF elif [ "${config_ca_type}" = "service" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" ca cert_signing_key crl_signing_key @@ -385,7 +385,7 @@ create_openssl_sign_config () { if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then - cat << EOF > ${config_file} + cat << EOF > "${config_file}" # Configuration file generated by pki-authority [ default ] @@ -412,7 +412,7 @@ x509_extensions = extension_default EOF if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" copy_extensions = none default_days = ${config['ca_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_ca_sign_multiplier']} ))} default_crl_days = 365 @@ -420,7 +420,7 @@ default_md = sha256 EOF elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" copy_extensions = copy default_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} default_crl_days = 365 @@ -428,7 +428,7 @@ default_md = sha256 EOF elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" copy_extensions = copy default_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} default_crl_days = 30 @@ -437,7 +437,7 @@ default_md = sha256 EOF fi - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" [ crl_info ] URI.0 = \$crl_url @@ -455,7 +455,7 @@ subjectKeyIdentifier = hash EOF if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" [ policy_default ] countryName = optional stateOrProvinceName = optional @@ -466,7 +466,7 @@ emailAddress = optional EOF elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" [ policy_default ] countryName = optional stateOrProvinceName = optional @@ -477,7 +477,7 @@ emailAddress = optional EOF elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" [ policy_default ] countryName = optional stateOrProvinceName = optional @@ -490,7 +490,7 @@ EOF fi if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" [ extension_default ] authorityInfoAccess = @issuer_info authorityKeyIdentifier = keyid:always @@ -501,7 +501,7 @@ subjectKeyIdentifier = hash EOF elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" [ extension_default ] authorityInfoAccess = @issuer_info authorityKeyIdentifier = keyid:always, issuer:always @@ -513,7 +513,7 @@ subjectKeyIdentifier = hash EOF elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" [ extension_default ] authorityInfoAccess = @issuer_info authorityKeyIdentifier = keyid:always, issuer:always @@ -539,13 +539,13 @@ create_gnutls_sign_config () { if [ -n "${config_file}" ] && [ ! -r "${config_file}" ] ; then - cat << EOF > ${config_file} + cat << EOF > "${config_file}" # Configuration file generated by pki-authority EOF if [ -z "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "root" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" expiration_days = ${config['ca_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_ca_sign_multiplier']} ))} ca @@ -559,7 +559,7 @@ crl_dist_points = "http://${config_name}.${config_domain}/crl/" EOF elif [ -z "${config_issuer}" ] && [ "${config_ca_type}" = "service" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" expiration_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} #copy_extensions = copy @@ -574,7 +574,7 @@ crl_dist_points = "http://${config_name}.${config_domain}/crl/" EOF elif [ -n "${config_issuer}" ] && [ -z "${config_ca_type}" ] || [ "${config_ca_type}" = "server" ] ; then - cat << EOF >> ${config_file} + cat << EOF >> "${config_file}" expiration_days = ${config['cert_sign_days']:-$(( ${config['pki_default_sign_base']} * ${config['pki_default_cert_sign_multiplier']} ))} #copy_extensions = copy @@ -606,7 +606,7 @@ save_authority_config () { fi if [ ! -r "${config_file}" ] ; then - cat << EOF > ${config_file} + cat << EOF > "${config_file}" # Configuration file generated by pki-authority EOF From 2caae9b6860c8b279e56f1437e0e4ebd53364a39 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 11 Sep 2016 15:15:33 +0200 Subject: [PATCH 52/65] Remove surrounding $() to avoid executing output [SC2091] --- files/secret/pki/lib/pki-authority | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index a06e094..1311882 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -600,7 +600,7 @@ save_authority_config () { local ignored_config_vars=( pki_root pki_requests pki_authorities pki_ca_certificates public_file_group public_dir_group private_file_group private_dir_group ) if [ -r "${config_file}" ] ; then - if $(grep -q -E "^#\s+Configuration\s+file\s+generated\s+by\s+pki-authority$" "${config_file}") ; then + if grep -q -E "^#\s+Configuration\s+file\s+generated\s+by\s+pki-authority$" "${config_file}" ; then rm -f "${config_file}" fi fi From db220a43a772b99c9fee9bbf4a62d0b6cb213de4 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 11 Sep 2016 15:21:01 +0200 Subject: [PATCH 53/65] `ignored_config_vars` is used but shellcheck can not detect it --- .travis.yml | 4 ++-- files/secret/pki/lib/pki-authority | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7346fea..d5eb8a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,9 +15,9 @@ script: - 'cd rolespec ; bin/rolespec -r https://github.com/debops/test-suite ; cd -' # We know the scripts are not perfect. Please don’t add more things that shellcheck v0.4.4 will complain about! - # The shellcheck and jq command does not return a non-zero exit code when the tested file does not exist. + # The shellcheck and jq command one-liner does not return with a non-zero exit code when the tested file does not exist. - 'test -r ./files/secret/pki/lib/pki-authority' - - 'shellcheck --format=json ./files/secret/pki/lib/pki-authority | jq --exit-status "(. | length) <= 74"' + - 'shellcheck --format=json ./files/secret/pki/lib/pki-authority | jq --exit-status "(. | length) <= 48"' - 'test -r ./files/usr/local/lib/pki/pki-realm' - 'shellcheck --format=json ./files/usr/local/lib/pki/pki-realm | jq --exit-status "(. | length) <= 105"' diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 1311882..995042b 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -597,6 +597,7 @@ save_authority_config () { local config_file="${1:-config/authority.conf}" + # shellcheck disable=SC2034 local ignored_config_vars=( pki_root pki_requests pki_authorities pki_ca_certificates public_file_group public_dir_group private_file_group private_dir_group ) if [ -r "${config_file}" ] ; then From cefeeed5a854d75f1db2f3ac9d894d4eb8b24bd8 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sun, 11 Sep 2016 15:36:38 +0200 Subject: [PATCH 54/65] More fixes in `pki-realm` suggested by shellcheck --- .travis.yml | 2 +- files/usr/local/lib/pki/pki-realm | 65 ++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index d5eb8a9..1bd3a33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ script: - 'test -r ./files/secret/pki/lib/pki-authority' - 'shellcheck --format=json ./files/secret/pki/lib/pki-authority | jq --exit-status "(. | length) <= 48"' - 'test -r ./files/usr/local/lib/pki/pki-realm' - - 'shellcheck --format=json ./files/usr/local/lib/pki/pki-realm | jq --exit-status "(. | length) <= 105"' + - 'shellcheck --format=json ./files/usr/local/lib/pki/pki-realm | jq --exit-status "(. | length) <= 83"' notifications: webhooks: diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index aee31b5..107787a 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -405,14 +405,20 @@ run_pki_hooks () { export PKI_SCRIPT_SUBJECT="${config['subject']:-${config['pki_default_subject']}}" export PKI_SCRIPT_DOMAINS="${config['domains']:-${config['pki_default_domain']}}" export PKI_SCRIPT_SUBDOMAINS="${config['subdomains']:-${config['pki_default_subdomains']}}" - export PKI_SCRIPT_PRIVATE_KEY="$(get_absolute_path private/key.pem)" + export PKI_SCRIPT_PRIVATE_KEY + PKI_SCRIPT_PRIVATE_KEY="$(get_absolute_path private/key.pem)" - export PKI_SCRIPT_DEFAULT_CRT="$(get_absolute_path default.crt)" - export PKI_SCRIPT_DEFAULT_KEY="$(get_absolute_path default.key)" - export PKI_SCRIPT_DEFAULT_PEM="$(get_absolute_path default.pem)" + export PKI_SCRIPT_DEFAULT_CRT + export PKI_SCRIPT_DEFAULT_KEY + export PKI_SCRIPT_DEFAULT_PEM - local current_state=$(printf ",%s" "${state[@]:-}") - local current_state="${current_state:1}" + PKI_SCRIPT_DEFAULT_CRT="$(get_absolute_path default.crt)" + PKI_SCRIPT_DEFAULT_KEY="$(get_absolute_path default.key)" + PKI_SCRIPT_DEFAULT_PEM="$(get_absolute_path default.pem)" + + local current_state + current_state=$(printf ",%s" "${state[@]:-}") + current_state="${current_state:1}" export PKI_SCRIPT_STATE="${current_state}" cd "${config['pki_hooks']}" @@ -451,14 +457,22 @@ run_external_script () { export PKI_SCRIPT_SUBJECT="${config['subject']:-${config['pki_default_subject']}}" export PKI_SCRIPT_DOMAINS="${config['domains']:-${config['pki_default_domain']}}" export PKI_SCRIPT_SUBDOMAINS="${config['subdomains']:-${config['pki_default_subdomains']}}" - export PKI_SCRIPT_PRIVATE_KEY="$(get_absolute_path private/key.pem)" - export PKI_SCRIPT_DEFAULT_CRT="$(get_absolute_path default.crt)" - export PKI_SCRIPT_DEFAULT_KEY="$(get_absolute_path default.key)" - export PKI_SCRIPT_DEFAULT_PEM="$(get_absolute_path default.pem)" +# FIXME: Redundancy! Why? + export PKI_SCRIPT_PRIVATE_KEY + PKI_SCRIPT_PRIVATE_KEY="$(get_absolute_path private/key.pem)" + + export PKI_SCRIPT_DEFAULT_CRT + export PKI_SCRIPT_DEFAULT_KEY + export PKI_SCRIPT_DEFAULT_PEM + + PKI_SCRIPT_DEFAULT_CRT="$(get_absolute_path default.crt)" + PKI_SCRIPT_DEFAULT_KEY="$(get_absolute_path default.key)" + PKI_SCRIPT_DEFAULT_PEM="$(get_absolute_path default.pem)" - local current_state=$(printf ",%s" "${state[@]:-}") - local current_state="${current_state:1}" + local current_state + current_state=$(printf ",%s" "${state[@]:-}") + current_state="${current_state:1}" export PKI_SCRIPT_STATE="${current_state}" test -x external/script || chmod ug+x external/script @@ -477,7 +491,7 @@ update_symlink () { shift 1 - for target in ${@} ; do + for target in "${@}" ; do if [ -r "${target}" ] ; then if [ -L "${symlink_target}" ] && [ "$(readlink "${symlink_target}")" == "${target}" ] ; then break @@ -530,6 +544,7 @@ challengePassword = \${ENV::PKI_SESSION_TOKEN} EOF fi + # shellcheck disable=SC2129 cat << EOF >> "${config_file}" [ req_dn ] @@ -1741,31 +1756,35 @@ activate_new_files () { state+=("changed-certificate") fi - for rm_file in $(find public/ -maxdepth 1 -name '*.rm') ; do + while IFS= read -r -d '' rm_file + do rm -f "${rm_file/.rm/}" "${rm_file}" state+=("file-deletion") - done + done < <(find public/ -maxdepth 1 -name '*.rm' -print0) if [ ! -r public/cert.pem ] && [ -e public/cert.pem.sig ] ; then rm -f public/cert.pem.sig fi - for new_file in $(find public/ -maxdepth 1 -name '*.tmp') ; do + while IFS= read -r -d '' new_file + do mv --force "${new_file}" "${new_file/.tmp/}" state+=("changed-public-file") state+=("file-change") - done + done < <(find public/ -maxdepth 1 -name '*.tmp' -print0) - for rm_file in $(find private/ -maxdepth 1 -name '*.rm') ; do + while IFS= read -r -d '' rm_file + do rm -f "${rm_file/.rm/}" "${rm_file}" state+=("file-deletion") - done + done < <(find private/ -maxdepth 1 -name '*.rm' -print0) - for new_file in $(find private/ -maxdepth 1 -name '*.tmp') ; do + while IFS= read -r -d '' new_file + do mv --force "${new_file}" "${new_file/.tmp/}" state+=("changed-private-file") state+=("file-change") - done + done < <(find private/ -maxdepth 1 -name '*.tmp' -print0) update_file_signature public/cert.pem update_realm_symlinks @@ -2319,12 +2338,12 @@ schedule_job () { echo "${script} run -n '${name}'" | batch > /dev/null 2>&1 fi elif [ -n "${scheduler_type}" ] && [ "${scheduler_type}" = "sleep" ] ; then - ( sleep $(( ( $RANDOM % ${max_delay} ) + ${min_delay} )) ; ${script} run -n "${name}" ) & + ( sleep $(( ( RANDOM % max_delay ) + min_delay )) ; ${script} run -n "${name}" ) & else if type batch > /dev/null 2>&1 ; then echo "${script} run -n '${name}'" | batch > /dev/null 2>&1 else - ( sleep $(( ( $RANDOM % ${max_delay} ) + ${min_delay} )) ; ${script} run -n "${name}" ) & + ( sleep $(( ( RANDOM % max_delay ) + min_delay )) ; ${script} run -n "${name}" ) & fi fi } From bc982a28a7a7c70d865bdcde197a9d70dc5d6258 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Mon, 12 Sep 2016 19:20:57 +0200 Subject: [PATCH 55/65] Simplify certificate for subdomains excluding the apex domain Tested with: - name: 'www.ypid.de' acme_default_subdomains: [] acme_domains: [ 'www.ypid.de', 'me.ypid.de' ] Resulted in: Certificate: Data: Version: 3 (0x2) Serial Number: fa:fb:15:22:6b:4c:9c:40:46:d4:13:ad:42:c0:8f:a4:2f:f3 Signature Algorithm: sha256WithRSAEncryption Issuer: CN=Fake LE Intermediate X1 Validity Not Before: Sep 12 16:18:00 2016 GMT Not After : Dec 11 16:18:00 2016 GMT Subject: CN=www.ypid.de Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus: 00:a3:0c:03:c2:24:7c:8d:f0:86:6f:f6:0b:a4:e8: c2:ce:4a:57:3a:97:59:75:00:01:8a:2c:e9:89:af: 65:d0:0c:dc:df:2f:2b:21:57:e6:b0:3e:11:7f:ad: d8:6a:9a:33:2e:ef:62:fb:4b:0f:80:f0:f3:c8:e9: d6:e4:75:6f:18:88:25:3f:e7:ce:23:43:c8:4d:05: 99:66:9a:be:a1:7a:e7:8a:80:ab:94:55:68:de:26: e9:c1:95:44:5b:b7:d9:b8:30:45:2b:ce:57:6c:7b: f3:a2:af:cc:b0:41:e3:0c:c1:cd:6b:c7:a1:6b:2d: 8d:09:c2:b5:fa:c1:7e:f4:b1:d2:2a:f3:8b:f1:7b: 5b:1f:7c:bf:9c:ab:ad:24:04:48:b7:03:22:fa:fc: e5:67:99:50:8f:48:5d:ab:1a:92:f1:27:2f:10:9a: 0b:67:75:6f:e5:9a:bd:f4:56:f3:9a:fc:6f:a7:6f: d8:86:ff:59:bc:ec:1e:8f:5a:e9:05:63:0b:ed:63: 6c:77:fa:09:e1:20:7e:7c:cb:91:8b:8f:3e:cb:b3: 65:dd:5f:2d:68:7c:46:7d:2c:bf:e7:6a:57:23:55: 1a:17:45:bc:8f:1d:dd:d6:d9:6e:e9:ef:d6:96:97: 5c:e5:9b:de:93:23:70:74:e1:47:ae:56:bb:b4:35: 9a:53:81:49:10:61:07:24:d2:53:6c:35:41:09:ef: 00:1a:3c:7b:de:0f:97:86:87:67:7a:a8:d0:a9:d4: 90:88:2f:0b:5c:a8:74:74:04:af:6f:f7:b1:ba:23: 83:00:27:a0:f6:8a:d4:7d:61:3a:75:03:4a:a8:d3: 42:2d:fb:2c:3b:ab:bc:b7:8a:18:42:5b:66:b9:d7: 8b:76:8d:da:62:1b:6b:64:cd:65:1e:53:6c:f8:54: 69:39:5d:ca:e7:23:c4:ef:cc:44:45:23:f3:1c:9c: 5d:73:33:59:a7:47:26:ef:43:47:a7:ed:02:ab:fc: 15:75:9a:64:fa:46:c1:20:3d:99:22:b0:91:67:c9: ce:99:5c:03:46:fd:81:ae:67:11:d0:be:d6:2b:ff: ac:32:51:bb:05:70:c1:6e:d0:6c:58:17:9c:c6:4f: fb:4a:79:c6:c5:ce:7a:55:ec:d3:6b:66:cf:2c:5b: d2:a1:35:a3:55:0a:b9:b6:a5:83:f5:12:21:7f:46: dc:d3:10:d5:5b:db:19:03:46:b2:fb:56:fe:8a:85: 26:d9:3d:33:e7:d5:eb:6b:a4:20:dc:df:e1:fe:d5: e3:92:6b:f5:81:aa:2a:05:3b:4c:32:56:74:67:ac: 8c:2b:66:c1:c5:27:12:10:01:90:3e:63:b0:23:63: 9f:19:a7 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: E5:11:34:94:ED:18:1A:7A:22:A8:6B:CC:32:D5:38:0E:F0:F0:06:C3 X509v3 Authority Key Identifier: keyid:C0:CC:03:46:B9:58:20:CC:5C:72:70:F3:E1:2E:CB:20:A6:F5:68:3A Authority Information Access: OCSP - URI:http://ocsp.stg-int-x1.letsencrypt.org/ CA Issuers - URI:http://cert.stg-int-x1.letsencrypt.org/ X509v3 Subject Alternative Name: DNS:me.ypid.de, DNS:www.ypid.de X509v3 Certificate Policies: Policy: 2.23.140.1.2.1 Policy: 1.3.6.1.4.1.44947.1.1.1 CPS: http://cps.letsencrypt.org User Notice: Explicit Text: This Certificate may only be relied upon by Relying Parties and only in accordance with the Certificate Policy found at https://letsencrypt.org/repository/ Signature Algorithm: sha256WithRSAEncryption 69:1f:9a:83:ae:10:17:ff:34:eb:d7:01:23:2f:05:39:cb:b0: ad:d1:d7:d2:47:69:31:f7:bc:f9:e2:73:62:c1:a6:df:16:0e: 65:65:9d:76:09:97:0f:d8:f6:73:30:0e:ba:d7:9e:61:96:12: 15:f9:19:d0:e6:2e:ec:aa:07:b1:03:b8:bb:af:5d:ea:69:ef: af:8a:a8:29:94:10:8b:04:5a:f1:de:14:6e:6a:a0:39:5c:d2: 7b:f3:65:06:6b:67:03:c6:1f:18:89:84:28:2a:0e:3e:1d:e2: a0:bc:4f:ce:3e:7c:f8:81:6e:f7:34:a0:cd:01:7e:66:ae:d6: 82:0e:e8:73:11:e6:c0:b0:c7:b0:0c:fa:de:d8:fa:61:89:c7: c7:dd:6f:cc:b2:32:1a:b8:74:93:82:5b:f9:55:25:15:f1:51: bc:32:98:f8:70:3a:c3:c2:e2:ec:3a:6f:a7:e6:8e:15:9a:43: 09:9f:b1:28:c7:d5:13:82:9e:20:86:40:45:4f:6d:cc:c6:7c: 9a:26:1a:e2:8b:40:eb:ed:24:67:b9:0e:a4:b7:4a:5f:3a:d0: 4f:a9:d3:bf:a5:59:67:40:0c:50:39:96:8e:a3:fb:de:a2:74: 72:78:b5:fc:2b:01:b8:1b:af:a5:78:6c:da:66:b6:2d:3c:ce: c8:c1:c8:1b --- docs/acme-integration.rst | 16 ++++++---------- docs/getting-started.rst | 1 - 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index d8e6f4d..9a56119 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -23,7 +23,7 @@ To request and renew ACME certificates, a host needs to meet several requirements enforced by this Ansible role: - A webserver configured to handle ACME challenges needs to be installed on the - host (currently this role supports only "webroot" challenges). The + host (currently this role supports only ``http-01`` challenges). The debops.nginx_ role configures ACME support for all servers by default when other conditions are met. @@ -159,22 +159,18 @@ automatically. Certificate for subdomains excluding the apex domain ---------------------------------------------------- -Yes, it's possible :-) Please consult the example and create your own similar -configuration. In the example we create a certificate for the ``logs.example.com`` -and ``mon.example.com`` subdomains, which does not include the ``example.com`` -apex domain. Please notice that the PKI realm does not contain your full domain -name. This is crucial. +Please consult the example and create your own similar configuration. In the +example we create a certificate for the ``logs.example.com`` and +``mon.example.com`` subdomains, which does not include the ``example.com`` apex +domain. .. code-block:: yaml pki_realms: - # Do not include the full domain name here! - - name: 'example' + - name: 'logs.example.com' acme: True acme_default_subdomains: [] - acme_subject: [ 'cn=logs.example.com' ] acme_domains: [ 'logs.example.com', 'mon.example.com' ] - domains: [ 'logs.example.com', 'mon.example.com' ] # acme_ca: 'le-staging' For testing it's strongly advised to uncomment ``acme_ca`` with ``le-staging`` diff --git a/docs/getting-started.rst b/docs/getting-started.rst index 124bb8d..c512a5a 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -83,4 +83,3 @@ special ``debops.pki/env`` role provided within the main role. .. literalinclude:: playbooks/pki.yml :language: yaml - From 47ba82266b762e3c608115d9d5fb0127204c4d4a Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Mon, 12 Sep 2016 20:09:27 +0200 Subject: [PATCH 56/65] Add example for ACME standard cases Closes: #83 --- docs/acme-integration.rst | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index 9a56119..07de5f7 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -156,28 +156,44 @@ configuration active, it will check for validity of the certificate, and about a month before the expiration date it will try to renew the certificate automatically. -Certificate for subdomains excluding the apex domain ----------------------------------------------------- +Example: Certificate for apex domain and subdomains +--------------------------------------------------- -Please consult the example and create your own similar configuration. In the -example we create a certificate for the ``logs.example.com`` and -``mon.example.com`` subdomains, which does not include the ``example.com`` apex -domain. +In this example a X.509 certificate for the apex domain ``example.com`` is +going to be issued. The certificate will also be valid for the subdomains +``www.example.com``, ``blog.example.com`` and ``mail.example.com`` which are +included into the certificate as `Subject Alternative Names`_. .. code-block:: yaml pki_realms: - - name: 'logs.example.com' + - name: 'example.com' acme: True - acme_default_subdomains: [] - acme_domains: [ 'logs.example.com', 'mon.example.com' ] + acme_subdomains: [ 'www', 'blog', 'mail' ] # acme_ca: 'le-staging' For testing it's strongly advised to uncomment ``acme_ca`` with ``le-staging`` to use the staging environment of Let's Encrypt. It does not create a trusted certificate and allows you to avoid problems with the rate limits in the production environment. When you are sure that everything works correctly, -comment the staging environment back. +comment the staging environment out again to get yourself a valid and trusted +X.509 certificate. + +Example: Certificate for subdomains excluding the apex domain +------------------------------------------------------------- + +In the example we create a certificate for the ``logs.example.com`` and +``mon.example.com`` subdomains, which does not include the ``example.com`` apex +domain. + +.. code-block:: yaml + + pki_realms: + - name: 'logs.example.com' + acme: True + acme_default_subdomains: [] + acme_domains: [ 'logs.example.com', 'mon.example.com' ] + # acme_ca: 'le-staging' ACME configuration variables ---------------------------- From 3fc1483c0cba1aac38f7a88a4b8790ae7577b094 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sat, 17 Sep 2016 18:36:06 +0200 Subject: [PATCH 57/65] Update changelog --- CHANGES.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 8c0a0e3..58fa919 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -24,7 +24,8 @@ Added was removed in v0.2.0. [ypid_] - Silently ignore empty elements in ``subject`` and ``acme_subject`` lists. - This can come in handy for generated certificate subjects. [ypid_] + This can come in handy to create the certificate subjects using Jinja in the + Ansible inventory. [ypid_] Changed ~~~~~~~ @@ -32,6 +33,8 @@ Changed - Change the method that Bash scripts use to compare the version numbers for a more reliable one. [drybjed_] +- Documentation improvements. [ypid_] + Fixed ~~~~~ @@ -56,6 +59,9 @@ Fixed - Also run :program:`pki-realm new-realm` against realms with disabled internal CA. [ypid_] +- Reviewed the role. Fixed potential shell script issues reported by + :command:`shellcheck` and added CI tests using :command:`shellcheck`. [ypid_] + `debops.pki v0.2.13`_ - 2016-07-07 ---------------------------------- From 89d16499081931dc9d10961c9e0e006cc3725a7b Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sat, 17 Sep 2016 19:28:44 +0200 Subject: [PATCH 58/65] Add note that remote CA certificates are not updated unless by host --- docs/system-ca-certificates.rst | 5 ++++- env/tasks/main.yml | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/system-ca-certificates.rst b/docs/system-ca-certificates.rst index e02db6a..66d6066 100644 --- a/docs/system-ca-certificates.rst +++ b/docs/system-ca-certificates.rst @@ -71,8 +71,11 @@ Ansible Controller will be copied to all of the remote hosts by the directory. After that, they will be automatically added to the system Root CA store using the :command:`update-ca-certificates` script. +Note that already present CA certificates on remote hosts with the same name +are not updated after the first download unless the CA certificates are by +host. + The internal Root Certificate Authorities created by the ``debops.pki`` role will have their certificates automatically symlinked in the :file:`secret/pki/ca-certificates/` directory. You can prevent that by adding an ``item.system_ca: False`` parameter in the CA configuration variable. - diff --git a/env/tasks/main.yml b/env/tasks/main.yml index d058eda..51e8848 100644 --- a/env/tasks/main.yml +++ b/env/tasks/main.yml @@ -3,4 +3,3 @@ - name: Prepare debops.pki environment set_fact: pki_env_secret_directories: '{{ lookup("template", "lookup/pki_env_secret_directories.j2") | from_yaml }}' - From 86c0492b1ba0ef32682a815dc524c563f230cccc Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sat, 17 Sep 2016 19:51:29 +0200 Subject: [PATCH 59/65] Allow to disable CA certificates download for the different levels --- CHANGES.rst | 2 ++ defaults/main.yml | 19 +++++++++++++++++++ tasks/main.yml | 6 +++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 58fa919..fb1f207 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -27,6 +27,8 @@ Added This can come in handy to create the certificate subjects using Jinja in the Ansible inventory. [ypid_] +- Allow to disable CA certificates download for the different levels. [ypid_] + Changed ~~~~~~~ diff --git a/defaults/main.yml b/defaults/main.yml index 27d4491..ca65431 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -699,4 +699,23 @@ pki_system_ca_certificates_blacklist: # certificate files or use regular expressions. pki_system_ca_certificates_whitelist: [] + +# .. envvar:: pki_system_ca_certificates_download_by_host +# +# If ``True``, by hosts CA certificates are downloaded on remote hosts. +pki_system_ca_certificates_download_by_host: '{{ pki_enabled|bool }}' + + +# .. envvar:: pki_system_ca_certificates_download_by_group +# +# If ``True``, by group CA certificates are downloaded on remote hosts. +pki_system_ca_certificates_download_by_group: '{{ pki_enabled|bool }}' + + +# .. envvar:: pki_system_ca_certificates_download_all_hosts +# +# If ``True``, CA certificates intended for all hosts are downloaded on remote +# hosts. +pki_system_ca_certificates_download_all_hosts: '{{ pki_enabled|bool }}' + # ]]] diff --git a/tasks/main.yml b/tasks/main.yml index 9555fc2..67c432f 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -429,7 +429,7 @@ group: 'root' mode: '0644' notify: [ 'Regenerate ca-certificates.crt' ] - when: pki_enabled | bool + when: pki_system_ca_certificates_download_by_host|d(pki_enabled) | bool - name: Download custom CA certificates by group copy: @@ -440,7 +440,7 @@ force: False with_items: '{{ pki_inventory_groups }}' notify: [ 'Regenerate ca-certificates.crt' ] - when: (pki_enabled|bool and item in group_names) + when: ((pki_system_ca_certificates_download_by_group|d(pki_enabled) | bool) and item in group_names) - name: Download custom CA certificates for all hosts copy: @@ -450,7 +450,7 @@ group: 'root' force: False notify: [ 'Regenerate ca-certificates.crt' ] - when: pki_enabled | bool + when: pki_system_ca_certificates_download_all_hosts|d(pki_enabled) | bool # ]]] # Execute PKI realm commands [[[ From 23b4c42b14430ee7dca647d8921b2a3363b2b771 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Sat, 17 Sep 2016 19:59:23 +0200 Subject: [PATCH 60/65] Add `pki_system_ca_certificates_download_all_hosts_force` --- CHANGES.rst | 2 ++ defaults/main.yml | 9 +++++++++ tasks/main.yml | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index fb1f207..e642ad6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -29,6 +29,8 @@ Added - Allow to disable CA certificates download for the different levels. [ypid_] +- Added :envvar:`pki_system_ca_certificates_download_all_hosts_force`. [ypid_] + Changed ~~~~~~~ diff --git a/defaults/main.yml b/defaults/main.yml index ca65431..8612dd8 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -718,4 +718,13 @@ pki_system_ca_certificates_download_by_group: '{{ pki_enabled|bool }}' # hosts. pki_system_ca_certificates_download_all_hosts: '{{ pki_enabled|bool }}' + +# .. envvar:: pki_system_ca_certificates_download_all_hosts_force +# +# If ``True``, force the download of CA certificates intended for all hosts. +# Note that this will overwrite by-host and by-group CA certificates. +# This option can be used to push new root certificates from a internal CA to +# hosts. +pki_system_ca_certificates_download_all_hosts_force: False + # ]]] diff --git a/tasks/main.yml b/tasks/main.yml index 67c432f..7a37ea6 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -448,7 +448,7 @@ dest: '/usr/local/share/ca-certificates/pki/' owner: 'root' group: 'root' - force: False + force: '{{ pki_system_ca_certificates_download_all_hosts_force|bool }}' notify: [ 'Regenerate ca-certificates.crt' ] when: pki_system_ca_certificates_download_all_hosts|d(pki_enabled) | bool # ]]] From c84aa2c224b1e44842f06500a577b8e77dad2db0 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Mon, 19 Sep 2016 15:42:33 +0200 Subject: [PATCH 61/65] Incorporate feedback from htgoebel into ACME docs --- docs/acme-integration.rst | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/acme-integration.rst b/docs/acme-integration.rst index 07de5f7..4e112f5 100644 --- a/docs/acme-integration.rst +++ b/docs/acme-integration.rst @@ -160,9 +160,11 @@ Example: Certificate for apex domain and subdomains --------------------------------------------------- In this example a X.509 certificate for the apex domain ``example.com`` is -going to be issued. The certificate will also be valid for the subdomains -``www.example.com``, ``blog.example.com`` and ``mail.example.com`` which are -included into the certificate as `Subject Alternative Names`_. +going to be issued. ``example.com`` will be listed in the certificate +``Subject`` DN. +The certificate will also be valid for the subdomains ``www.example.com``, +``blog.example.com`` and ``mail.example.com`` which are included in the +certificate as `Subject Alternative Names`_. .. code-block:: yaml @@ -182,9 +184,9 @@ X.509 certificate. Example: Certificate for subdomains excluding the apex domain ------------------------------------------------------------- -In the example we create a certificate for the ``logs.example.com`` and -``mon.example.com`` subdomains, which does not include the ``example.com`` apex -domain. +In the example we create a certificate for ``logs.example.com`` (certificate +``Subject``) and for ``mon.example.com`` (certificate `Subject Alternative +Names`_), which does not include the ``example.com`` apex domain. .. code-block:: yaml @@ -192,6 +194,8 @@ domain. - name: 'logs.example.com' acme: True acme_default_subdomains: [] + # Can also include different domains like 'mail.example.org' + # in the same realm. acme_domains: [ 'logs.example.com', 'mon.example.com' ] # acme_ca: 'le-staging' From 03409afd14c9f8f681e2cb4ac284b75ee6aac156 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 20 Sep 2016 19:41:07 +0200 Subject: [PATCH 62/65] Regen README --- README.md | 4 ++-- meta/ansigenome.yml | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2134bdb..01ae6a0 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ into your playbook. ### Authors and license -- Maciej Delmanowski (maintainer) | [e-mail](mailto:drybjed@gmail.com) | [Twitter](https://twitter.com/drybjed) | [GitHub](https://github.com/drybjed) -- [Robin Schneider](http://ypid.de/) | [e-mail](mailto:ypid@riseup.net) | [Twitter](https://twitter.com/ypid) | [GitHub](https://github.com/ypid) +- [Maciej Delmanowski](https://docs.debops.org/en/latest/debops-keyring/docs/entities.html#debops-keyring-entity-drybjed) (maintainer) | [e-mail](mailto:drybjed@gmail.com) | [Twitter](https://twitter.com/drybjed) | [GitHub](https://github.com/drybjed) +- [Robin Schneider](https://docs.debops.org/en/latest/debops-keyring/docs/entities.html#debops-keyring-entity-ypid) | [e-mail](mailto:ypid@riseup.net) | [Twitter](https://twitter.com/ypid) | [GitHub](https://github.com/ypid) License: [GPL-3.0](https://tldrlegal.com/license/gnu-general-public-license-v3-%28gpl-3%29) diff --git a/meta/ansigenome.yml b/meta/ansigenome.yml index 705e140..91a7374 100644 --- a/meta/ansigenome.yml +++ b/meta/ansigenome.yml @@ -11,13 +11,11 @@ ansigenome_info: authors: - name: 'Maciej Delmanowski' - url: '' email: 'drybjed@gmail.com' twitter: 'drybjed' github: 'drybjed' - name: 'Robin Schneider' - url: 'http://ypid.de/' email: 'ypid@riseup.net' twitter: 'ypid' github: 'ypid' @@ -35,4 +33,3 @@ ansigenome_info: support it (currently, [Let's Encrypt][lets-encrypt]). [lets-encrypt]: https://letsencrypt.org/ - From 9c537c202684b963f7782fa525f67ed817db6e66 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Fri, 23 Sep 2016 13:00:53 +0200 Subject: [PATCH 63/65] Fix spelling in docs --- docs/external-certificates.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/external-certificates.rst b/docs/external-certificates.rst index b168fb7..7ee0ae0 100644 --- a/docs/external-certificates.rst +++ b/docs/external-certificates.rst @@ -6,7 +6,7 @@ External certificates The PKI realms managed by the ``debops.pki`` role support management of private keys and certificates from external Certificate Authorities. You can either provide a set of valid certificates with corresponding private keys, -or use a script with a custom environment to request a certificate remotely in +or use a script with a custom environment to request a certificate remotely from an external Certificate Authority. Required files @@ -75,8 +75,8 @@ As you can see, the directory structure reflects the Ansible inventory model: Each of those directories has a set of subdirectories for configured PKI realms, with the :file:`external/`, :file:`internal/` and :file:`private/` directories corresponding to the same ones on the remote hosts. Ansible at different stages -of the ``debops.pki`` role will copy contents of these directories to remote -hosts, in a specific order: +of the ``debops.pki`` role run will copy contents of these directories to +remote hosts, in a specific order: - contents of the :file:`realms/by-host/` directories for each host will be copied and overwrite already present files; From 3ebe9d3270b800f00b8caba83e24397c957a87d2 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Mon, 26 Sep 2016 21:09:58 +0200 Subject: [PATCH 64/65] Reintroduce rst sections in defaults/main.yml --- defaults/main.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/defaults/main.yml b/defaults/main.yml index 8612dd8..89d59d3 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -11,6 +11,7 @@ # Global PKI configuration [[[ +# ---------------------------- # .. envvar:: pki_enabled # @@ -111,6 +112,7 @@ pki_vcs_ignore_patterns_host: [] # ]]] # Automatic Certificate Management Environment [[[ +# ------------------------------------------------ # .. envvar:: pki_acme # @@ -229,6 +231,7 @@ pki_acme_challenge_dir: '{{ (ansible_local.nginx.acme_root # ]]] # Required software packages [[[ +# ------------------------------ # .. envvar:: pki_base_packages # @@ -254,6 +257,7 @@ pki_packages: [] # ]]] # Directory, file and user/group configuration [[[ +# ------------------------------------------------ # .. envvar:: pki_root # @@ -324,6 +328,7 @@ pki_private_file_acl_groups: [] # ]]] # Certificate sign times [[[ +# -------------------------- # .. envvar:: pki_default_sign_base # @@ -355,6 +360,7 @@ pki_default_cert_sign_multiplier: '3' # ]]] # Configuration of PKI Realms [[[ +# ------------------------------- # .. envvar:: pki_library # @@ -485,6 +491,7 @@ pki_dhparam_file: '{{ ansible_local.dhparam.default # ]]] # Internal Certificate Authorities [[[ +# ------------------------------------ # .. envvar:: pki_ca_library # @@ -626,6 +633,7 @@ pki_ca_certificates_path: 'by-group/all' # ]]] # Custom file management [[[ +# -------------------------- # You can use custom file lists to copy files to remote hosts or install # the content of Jinja variables. See :ref:`custom_file_management` for more @@ -669,6 +677,7 @@ pki_host_public_files: [] # ]]] # System-wide CA Certificates [[[ +# ------------------------------- # See :ref:`system_ca_certificates` for more details about management of # system-wide CA certificates. From 4d16312ac6d9f5036dbb56d52a36ac32de39d092 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Mon, 26 Sep 2016 21:14:04 +0200 Subject: [PATCH 65/65] Fix spelling --- files/secret/pki/lib/pki-authority | 2 +- files/usr/local/lib/pki/pki-realm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/files/secret/pki/lib/pki-authority b/files/secret/pki/lib/pki-authority index 995042b..ab954bf 100755 --- a/files/secret/pki/lib/pki-authority +++ b/files/secret/pki/lib/pki-authority @@ -44,7 +44,7 @@ array_exists () { # Inlined in the following scripts: pki-authority, pki-realm {{{ version () { - # Normalize version numbers for compassion. + # Normalize version numbers for comparison. echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' } diff --git a/files/usr/local/lib/pki/pki-realm b/files/usr/local/lib/pki/pki-realm index 107787a..8439d00 100755 --- a/files/usr/local/lib/pki/pki-realm +++ b/files/usr/local/lib/pki/pki-realm @@ -74,7 +74,7 @@ create_lock () { # Inlined in the following scripts: pki-authority, pki-realm {{{ version () { - # Normalize version numbers for compassion. + # Normalize version numbers for comparison. echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' }