diff --git a/.travis.yml b/.travis.yml index ee0e314..9a9a2bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,48 +1,36 @@ --- language: python -python: "2.7" - -# Use the new container infrastructure -sudo: false - -# Install ansible -addons: - apt: - packages: - - python-pip +services: docker + +env: + global: + - ROLE_NAME: ca-certificates + matrix: + - MOLECULE_DISTRO: centos7 + - MOLECULE_DISTRO: centos6 + - MOLECULE_DISTRO: ubuntu1804 + - MOLECULE_DISTRO: debian9 + - MOLECULE_DISTRO: debian10 + - MOLECULE_DISTRO: fedora29 install: - # Install ansible - - pip install ansible - - # Install ansible-lint - - pip install ansible-lint - - # Install yamllint - - pip install yamllint + - pip install molecule docker - # Install tests rules - - git submodule add https://github.com/arillso/tests tests + - git clone https://github.com/arillso/tests molecule/default/lint before_script: - # Check ansible version - - ansible --version - - # Check ansible-lint version - - ansible-lint --version - - # Check ansible-lint version - - yamllint --version + - cd ../ + - mv ansible.$ROLE_NAME arillso.$ROLE_NAME + - cd arillso.$ROLE_NAME script: - # Ansible Lint check - - ansible-lint -R -r tests/ansible-lint/ . - - # YAML Lint check - - yamllint -c tests/yaml-lint/yamllint.yml . + - molecule test notifications: - webhooks: https://galaxy.ansible.com/api/v1/notifications/ + webhooks: + urls: + - https://galaxy.ansible.com/api/v1/notifications/ + on_success: always email: on_success: never on_failure: always diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5920362 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) +and [human-readable changelog](https://keepachangelog.com/en/1.0.0/). + +## 1.0.0 + +### Added + +- Initial release diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7d07096 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019 Arillso + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index e2ac40e..4c772dc 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,74 @@ # Ansible Role: ca-certificates -[![Build Status](https://img.shields.io/travis/arillso/ansible.ca-certificates.svg?branch=master&style=popout-square)](https://travis-ci.org/arillso/ansible.ca-certificates) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=popout-square)](https://sbaerlo.ch/licence) [![Ansible Galaxy](http://img.shields.io/badge/ansible--galaxy-ca-certificates-blue.svg?style=popout-square)](https://galaxy.ansible.com/arillso/ca-certificates) [![Ansible Role](https://img.shields.io/ansible/role/d/id.svg?style=popout-square)](https://galaxy.ansible.com/arillso/ca-certificates) +[![Build Status](https://img.shields.io/travis/arillso/ansible.ca-certificates.svg?branch=master&style=popout-square)](https://travis-ci.org/arillso/ansible.ca-certificates) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=popout-square)](https://sbaerlo.ch/licence) [![Ansible Galaxy](https://img.shields.io/badge/ansible--galaxy-ca_certificates-blue.svg?style=popout-square)](https://galaxy.ansible.com/arillso/ca_certificates) [![Ansible Role](https://img.shields.io/ansible/role/d/id.svg?style=popout-square)](https://galaxy.ansible.com/arillso/ca_certificates) ## Description +Ansible role to manage CA certificates in the Linux and Windows system trust store. It's possible to add PEM formatted certificates from the local file system, a already trusted HTTP(s) URL, from raw content. + ## Installation ```bash -ansible-galaxy install arillso.ca-certificates +ansible-galaxy install arillso.ca_certificates ``` ## Requirements +none + ## Role Variables -| Variable | Default | Comments (type) | -| :--- | :--- | :--- | -| | | | -| | | | +### ca_certificates_root_directory + +Location where the certificates are stored under windows before +they are imported into the certificate store of Windows. + +```yml +ca_certificates_root_directory: '{{ ansible_env.TMP }}' +``` + +### ca_certificates_packages + +Packages to be installed. + +```yml +ca_certificates_packages: + - ca-certificates +``` + +### ca_certificates_files + +List of CA certificates that are to be added to the certificate store of the system. Each list element is a configuration directory that defines the source (URL, Files or Inline as variable) of the certificate. It must contain a key'name' and one of the following keys in order to use the certificate: + +| Option | Comments | +| :------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| file | Path to a file on the host running the Ansible playbook. Relative file paths are related to the role's `files/` directory. | +| url | URL to a PEM-formatted certificate file | +| content | Certificate inline as PEM-formatted | +| store_name | Optional in Windows. The store name to use when importing. See: [Ansible doc](https://docs.ansible.com/ansible/latest/modules/win_certificate_store_module.html#win-certificate-store-module) | +| store_location | Optional in Windows. See: [Ansible doc](https://docs.ansible.com/ansible/latest/modules/win_certificate_store_module.html#win-certificate-store-module) | + +```yml +ca_certificates_files: [] +``` ## Dependencies +None + ## Example Playbook ```yml - hosts: all roles: - - arillso.ca-certificates + - arillso.ca_certificates ``` ## Changelog ## Author -* [Simon Bärlocher](https://sbaerlocher.ch) +- [Simon Bärlocher](https://sbaerlocher.ch) ## License @@ -41,4 +76,4 @@ This project is under the MIT License. See the [LICENSE](https://sbaerlo.ch/lice ## Copyright -(c) 2019, Simon Bärlocher +(c) 2019, Arillso diff --git a/defaults/main.yml b/defaults/main.yml index 8d77ec4..8fe31a1 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,2 +1,41 @@ --- # defaults file for arillso.ca-certificates + +# Location where the certificates are stored under windows before +# they are imported into the certificate memory of Windows. +ca_certificates_path: '{{ ansible_env.TMP }}' + +# Packages to be installed. +ca_certificates_packages: + - ca-certificates + +# List of CA certificates that are to be added to the certificate +# memory of the system. Each list element is a configuration +# directory that defines the source (URL, Files or Inline as variable) +# of the certificate. It must contain a key'name' and one of the +# following keys in order to use the certificate: +# +# file Path to a file on the host running the Ansible playbook. +# Relative file paths are related to the +# role's `files/` directory. +# url URL to a PEM-formatted certificate file +# content Certificate inline as PEM-formatted +# store_name Optional in Windows. The store name to use when importing +# a certificate or searching for a certificate. +# AddressBook: The X.509 certificate store for other users +# AuthRoot: The X.509 certificate store for third-party +# certificate authorities (CAs) +# CertificateAuthority: The X.509 certificate store for +# intermediate certificate authorities (CAs) +# Disallowed: The X.509 certificate store +# for revoked certificates +# My: The X.509 certificate store for personal certificates +# Root: The X.509 certificate store for trusted root +# certificate authorities (CAs) +# TrustedPeople: The X.509 certificate store for directly +# trusted people and resources +# TrustedPublisher: The X.509 certificate store for directly +# trusted publishers +# store_location Optional in Windows. The store location to use when +# importing a certificate or searching for a certificate. +ca_certificates_files: [] diff --git a/handlers/main.yml b/handlers/main.yml index fc693d4..0f0921c 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,2 +1,5 @@ --- # handlers file for arillso.ca-certificates + +- name: Update CA trust + command: '{{ ca_certificates_handler }}' diff --git a/meta/main.yml b/meta/main.yml index 6b0db57..d35187a 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,35 +1,34 @@ --- - galaxy_info: role_name: ca-certificates - author: - description: - company: + author: arillso + description: Install certificates from a file or url under Windows and Linux. license: MIT - min_ansible_version: 2 + min_ansible_version: 2.8 platforms: - - name: Archlinux - versions: - - all - name: EL versions: - - 5 - 6 + - 7 - name: Fedora versions: - - 16 - - 17 - - 18 + - 29 - name: Ubuntu versions: - - precise - - quantal - - raring - - saucy + - bionic + - cosmic + - disco - name: Debian versions: - - wheezy + - jessie + - stretch + - buster + - name: Windows + versions: + - all - galaxy_tags: [] + galaxy_tags: + - ca + - certificates dependencies: [] diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 0000000..c80c5c6 --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,27 @@ +--- +dependency: + name: galaxy +driver: + name: docker +lint: + name: yamllint +platforms: + - name: instance + image: 'geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest' + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + privileged: true + pre_build_image: true +provisioner: + name: ansible + lint: + name: ansible-lint + playbooks: + converge: ${MOLECULE_PLAYBOOK:-playbook.yml} +scenario: + name: default +verifier: + name: testinfra + lint: + name: flake8 diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml new file mode 100644 index 0000000..a1bd535 --- /dev/null +++ b/molecule/default/playbook.yml @@ -0,0 +1,33 @@ +--- +- name: Converge + hosts: all + vars: + ca_certificates_files: + - name: CA-Test + content: | + -----BEGIN CERTIFICATE----- + MIID2jCCA0MCAg39MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG + A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE + MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl + YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw + ODIyMDUyODAwWhcNMTcwODIxMDUyODAwWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE + CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs + ZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwvWITOLeyTbS1 + Q/UacqeILIK16UHLvSymIlbbiT7mpD4SMwB343xpIlXN64fC0Y1ylT6LLeX4St7A + cJrGIV3AMmJcsDsNzgo577LqtNvnOkLH0GojisFEKQiREX6gOgq9tWSqwaENccTE + sAXuV6AQ1ST+G16s00iN92hjX9V/V66snRwTsJ/p4WRpLSdAj4272hiM19qIg9zr + h92e2rQy7E/UShW4gpOrhg2f6fcCBm+aXIga+qxaSLchcDUvPXrpIxTd/OWQ23Qh + vIEzkGbPlBA8J7Nw9KCyaxbYMBFb1i0lBjwKLjmcoihiI7PVthAOu/B71D2hKcFj + Kpfv4D1Uam/0VumKwhwuhZVNjLq1BR1FKRJ1CioLG4wCTr0LVgtvvUyhFrS+3PdU + R0T5HlAQWPMyQDHgCpbOHW0wc0hbuNeO/lS82LjieGNFxKmMBFF9lsN2zsA6Qw32 + Xkb2/EFltXCtpuOwVztdk4MDrnaDXy9zMZuqFHpv5lWTbDVwDdyEQNclYlbAEbDe + vEQo/rAOZFl94Mu63rAgLiPeZN4IdS/48or5KaQaCOe0DuAb4GWNIQ42cYQ5TsEH + Wt+FIOAMSpf9hNPjDeu1uff40DOtsiyGeX9NViqKtttaHpvd7rb2zsasbcAGUl+f + NQJj4qImPSB9ThqZqPTukEcM/NtbeQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAIAi + gU3My8kYYniDuKEXSJmbVB+K1upHxWDA8R6KMZGXfbe5BRd8s40cY6JBYL52Tgqd + l8z5Ek8dC4NNpfpcZc/teT1WqiO2wnpGHjgMDuDL1mxCZNL422jHpiPWkWp3AuDI + c7tL1QjbfAUHAQYwmHkWgPP+T2wAv0pOt36GgMCM + -----END CERTIFICATE----- + + roles: + - role: arillso.ca-certificates diff --git a/tasks/distribution/Linux.yml b/tasks/distribution/Linux.yml index 519c3e3..58cd6b5 100644 --- a/tasks/distribution/Linux.yml +++ b/tasks/distribution/Linux.yml @@ -1,2 +1,18 @@ --- # tasks file for arillso.ca-certificates + +- name: 'linux : Install CA certificates packages' + package: + name: '{{ item }}' + state: present + with_items: '{{ ca_certificates_packages }}' + +- name: 'linux : include tasks to install custom CA certificates' + include_tasks: Linux/certificate.yml + with_items: + - '{{ ca_certificates_files }}' + loop_control: + loop_var: ca_certificates_loop_install_item + +- name: Trigger handler + meta: flush_handlers diff --git a/tasks/distribution/Linux/certificate.yml b/tasks/distribution/Linux/certificate.yml new file mode 100644 index 0000000..4d9d00f --- /dev/null +++ b/tasks/distribution/Linux/certificate.yml @@ -0,0 +1,50 @@ +--- +# tasks file for arillso.ca-certificates + +- name: 'linux : Fail on invalid certificate definition' + fail: + msg: "Certificate definition must contain key 'name'." + when: ("name" not in install_item.keys()) + vars: + install_item: '{{ ca_certificates_loop_install_item }}' + +- name: 'linux : {{ install_item.name }} - Copy certificate file' + copy: + src: '{{ install_item.file }}' + dest: '{{ ca_certificates_path }}/{{ install_item.name }}.crt' + owner: root + group: root + mode: 0644 + validate: openssl x509 -inform PEM -in %s -noout + when: ("file" in install_item.keys()) + notify: Update CA trust + vars: + install_item: '{{ ca_certificates_loop_install_item }}' + +- name: 'linux : {{ install_item.name }} - Copy certificate content' + copy: + content: '{{ install_item.content }}' + dest: '{{ ca_certificates_path }}/{{ install_item.name }}.pem' + owner: root + group: root + mode: 0644 + when: ("content" in install_item.keys()) + notify: Update CA trust + vars: + install_item: '{{ ca_certificates_loop_install_item }}' + +- name: 'linux : {{ install_item.name }} - Download certificate file' + get_url: + url: '{{ install_item.url }}' + dest: '{{ ca_certificates_path }}/{{ install_item.name }}.crt' + owner: root + group: root + mode: 0644 + when: ("url" in install_item.keys()) + notify: Update CA trust + register: ca_certificates_register_download + retries: 3 + delay: 2 + until: ca_certificates_register_download is succeeded + vars: + install_item: '{{ ca_certificates_loop_install_item }}' diff --git a/tasks/distribution/Windows.yml b/tasks/distribution/Windows.yml index 519c3e3..da62d49 100644 --- a/tasks/distribution/Windows.yml +++ b/tasks/distribution/Windows.yml @@ -1,2 +1,9 @@ --- # tasks file for arillso.ca-certificates + +- name: 'windows : include tasks to install custom CA certificates' + include_tasks: Windows/certificate.yml + with_items: + - '{{ ca_certificates_files }}' + loop_control: + loop_var: ca_certificates_loop_install_item diff --git a/tasks/distribution/Windows/certificate.yml b/tasks/distribution/Windows/certificate.yml new file mode 100644 index 0000000..398e64a --- /dev/null +++ b/tasks/distribution/Windows/certificate.yml @@ -0,0 +1,46 @@ +--- +# tasks file for arillso.ca-certificates + +- name: 'windows : Fail on invalid certificate definition' + fail: + msg: "Certificate definition must contain key 'name'." + when: ("name" not in install_item.keys()) + vars: + install_item: '{{ ca_certificates_loop_install_item }}' + +- name: 'windows : {{ install_item.name }} - Download certificate file' + win_get_url: + url: '{{ install_item.url }}' + dest: '{{ ca_certificates_root_directory }}\\{{ install_item.name }}' + when: ("url" in install_item.keys()) + register: ca_certificates_register_download + retries: 3 + delay: 2 + until: ca_certificates_register_download is succeeded + vars: + install_item: '{{ ca_certificates_loop_install_item }}' + +- name: 'windows : {{ install_item.name }} - Copy certificate content' + win_copy: + content: '{{ install_item.content }}' + dest: '{{ ca_certificates_path }}/{{ install_item.name }}.pem' + when: ("content" in install_item.keys()) + vars: + install_item: '{{ ca_certificates_loop_install_item }}' + +- name: 'windows : {{ install_item.name }} - Copy certificate file' + win_copy: + src: '{{ install_item.file }}' + dest: '{{ ca_certificates_path }}/{{ install_item.name }}.pem' + when: ("file" in install_item.keys()) + vars: + install_item: '{{ ca_certificates_loop_install_item }}' + +- name: 'windows : {{ install_item.name }} - Import certificate' + win_certificate_store: + path: '{{ ca_certificates_path }}/{{ install_item.name }}.pem' + state: present + store_name: '{{ install_item.store_name | default(omit) }}' + store_location: '{{ install_item.store_location | default(omit) }}' + vars: + install_item: '{{ ca_certificates_loop_install_item }}' diff --git a/tasks/main.yml b/tasks/main.yml index 41a057e..6d3fe77 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,37 +2,45 @@ # tasks file for arillso.ca-certificates - name: add OS specific variables - include_vars: "{{ loop_vars }}" + include_vars: '{{ loop_vars }}' with_first_found: - files: - - "{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" - - "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" - - "{{ ansible_distribution }}.yml" - - "{{ ansible_os_family }}.yml" - - "{{ ansible_system }}.yml" - - "defaults.yml" + - '{{ distribution }}-{{ distribution_version }}.yml' + - '{{ distribution }}-{{ distribution_major_version }}.yml' + - '{{ distribution }}.yml' + - '{{ ansible_os_family }}.yml' + - '{{ ansible_system }}.yml' + - 'defaults.yml' paths: - - "vars" + - 'vars' loop_control: loop_var: loop_vars + vars: + distribution: '{{ ansible_distribution }}' + distribution_version: '{{ ansible_distribution_version }}' + distribution_major_version: '{{ ansible_distribution_major_version }}' tags: - configuration - packages - name: include distribution tasks - include_tasks: "{{ loop_distribution }}" + include_tasks: '{{ loop_distribution }}' with_first_found: - files: - - "{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" - - "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" - - "{{ ansible_distribution }}.yml" - - "{{ ansible_os_family }}.yml" - - "{{ ansible_system }}.yml" - - "defaults.yml" + - '{{ distribution }}-{{ distribution_version }}.yml' + - '{{ distribution }}-{{ distribution_major_version }}.yml' + - '{{ distribution }}.yml' + - '{{ ansible_os_family }}.yml' + - '{{ ansible_system }}.yml' + - 'defaults.yml' paths: - - "distribution" + - 'distribution' loop_control: loop_var: loop_distribution + vars: + distribution: '{{ ansible_distribution }}' + distribution_version: '{{ ansible_distribution_version }}' + distribution_major_version: '{{ ansible_distribution_major_version }}' tags: - configuration - packages diff --git a/vars/CentOS.yml b/vars/CentOS.yml deleted file mode 100644 index 0d5e0f3..0000000 --- a/vars/CentOS.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for arillso.ca-certificates diff --git a/vars/Debian.yml b/vars/Debian.yml index 0d5e0f3..548976b 100644 --- a/vars/Debian.yml +++ b/vars/Debian.yml @@ -1,2 +1,12 @@ --- # vars file for arillso.ca-certificates + +# +# Defaults for Debian-based Linux systems +# + +# Directory where certificates should be placed +ca_certificates_path: /usr/local/share/ca-certificates + +# Command to run after adding new certificates +ca_certificates_handler: /usr/sbin/update-ca-certificates diff --git a/vars/RedHat.yml b/vars/RedHat.yml new file mode 100644 index 0000000..448a119 --- /dev/null +++ b/vars/RedHat.yml @@ -0,0 +1,12 @@ +--- +# vars file for arillso.ca-certificates + +# +# Defaults for RedHat-based Linux systems +# + +# Directory where certificates should be placed +ca_certificates_path: /etc/pki/ca-trust/source/anchors + +# Command to run after adding new certificates +ca_certificates_handler: /usr/bin/update-ca-trust extract diff --git a/vars/Ubuntu.yml b/vars/Ubuntu.yml deleted file mode 100644 index 0d5e0f3..0000000 --- a/vars/Ubuntu.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for arillso.ca-certificates