Add some guides (#237)
* Add first guides for creating certificates.
* Add extra docs check.
* Introduce error to see whether extra checks work.
* Revert "Introduce error to see whether extra checks work."
This reverts commit 8656a158b8
.
* Linting.
* Fix copy'n'paste error.
pull/239/head
parent
c6483751b5
commit
117438cff0
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
sections:
|
||||||
|
- title: Scenario Guides
|
||||||
|
toctree:
|
||||||
|
- guide_selfsigned
|
||||||
|
- guide_ownca
|
|
@ -0,0 +1,148 @@
|
||||||
|
.. _ansible_collections.community.crypto.docsite.guide_ownca:
|
||||||
|
|
||||||
|
How to create a small CA
|
||||||
|
========================
|
||||||
|
|
||||||
|
The `community.crypto collection <https://galaxy.ansible.com/community/crypto>`_ offers multiple modules that create private keys, certificate signing requests, and certificates. This guide shows how to create your own small CA and how to use it to sign certificates.
|
||||||
|
|
||||||
|
In all examples, we assume that the CA's private key is password protected, where the password is provided in the ``secret_ca_passphrase`` variable.
|
||||||
|
|
||||||
|
Set up the CA
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Any certificate can be used as a CA certificate. You can create a self-signed certificate (see :ref:`ansible_collections.community.crypto.docsite.guide_selfsigned`), use another CA certificate to sign a new certificate (using the instructions below for signing a certificate), ask (and pay) a commercial CA to sign your CA certificate, etc.
|
||||||
|
|
||||||
|
The following instructions show how to set up a simple self-signed CA certificate.
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
- name: Create private key with password protection
|
||||||
|
community.crypto.openssl_privatekey:
|
||||||
|
path: /path/to/ca-certificate.key
|
||||||
|
passphrase: "{{ secret_ca_passphrase }}"
|
||||||
|
|
||||||
|
- name: Create certificate signing request (CSR) for CA certificate
|
||||||
|
community.crypto.openssl_csr_pipe:
|
||||||
|
privatekey_path: /path/to/ca-certificate.key
|
||||||
|
privatekey_passphrase: "{{ secret_ca_passphrase }}"
|
||||||
|
common_name: Ansible CA
|
||||||
|
use_common_name_for_san: false # since we do not specify SANs, don't use CN as a SAN
|
||||||
|
basic_constraints:
|
||||||
|
- 'CA:TRUE'
|
||||||
|
basic_constraints_critical: yes
|
||||||
|
key_usage:
|
||||||
|
- keyCertSign
|
||||||
|
key_usage_critical: true
|
||||||
|
register: ca_csr
|
||||||
|
|
||||||
|
- name: Create self-signed CA certificate from CSR
|
||||||
|
community.crypto.x509_certificate:
|
||||||
|
path: /path/to/ca-certificate.pem
|
||||||
|
csr_content: "{{ ca_csr.csr }}"
|
||||||
|
privatekey_path: /path/to/ca-certificate.key
|
||||||
|
privatekey_passphrase: "{{ secret_ca_passphrase }}"
|
||||||
|
provider: selfsigned
|
||||||
|
|
||||||
|
Use the CA to sign a certificate
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
To sign a certificate, you must pass a CSR to the :ref:`community.crypto.x509_certificate module <ansible_collections.community.crypto.x509_certificate_module>` or :ref:`community.crypto.x509_certificate_pipe module <ansible_collections.community.crypto.x509_certificate_pipe_module>`.
|
||||||
|
|
||||||
|
In the following example, we assume that the certificate to sign (including its private key) are on ``server_1``, while our CA certificate is on ``server_2``. We do not want any key material to leave each respective server.
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
- name: Create private key for new certificate on server_1
|
||||||
|
community.crypto.openssl_privatekey:
|
||||||
|
path: /path/to/certificate.key
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
- name: Create certificate signing request (CSR) for new certificate
|
||||||
|
community.crypto.openssl_csr_pipe:
|
||||||
|
privatekey_path: /path/to/certificate.key
|
||||||
|
subject_alt_name:
|
||||||
|
- "DNS:ansible.com"
|
||||||
|
- "DNS:www.ansible.com"
|
||||||
|
- "DNS:docs.ansible.com"
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
register: csr
|
||||||
|
|
||||||
|
- name: Sign certificate with our CA
|
||||||
|
community.crypto.x509_certificate_pipe:
|
||||||
|
csr_content: "{{ ca_csr.csr }}"
|
||||||
|
provider: ownca
|
||||||
|
ownca_path: /path/to/ca-certificate.pem
|
||||||
|
ownca_privatekey_path: /path/to/ca-certificate.key
|
||||||
|
ownca_privatekey_passphrase: "{{ secret_ca_passphrase }}"
|
||||||
|
ownca_not_after: +365d # valid for one year
|
||||||
|
ownca_not_before: "-1d" # valid since yesterday
|
||||||
|
delegate_to: server_2
|
||||||
|
run_once: true
|
||||||
|
register: certificate
|
||||||
|
|
||||||
|
- name: Write certificate file on server_1
|
||||||
|
copy:
|
||||||
|
dest: /path/to/certificate.pem
|
||||||
|
content: "{{ certificate.certificate }}"
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
Please note that the above procedure is **not idempotent**. The following extended example reads the existing certificate from ``server_1`` (if exists) and provides it to the :ref:`community.crypto.x509_certificate_pipe module <ansible_collections.community.crypto.x509_certificate_pipe_module>`, and only writes the result back if it was changed:
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
- name: Create private key for new certificate on server_1
|
||||||
|
community.crypto.openssl_privatekey:
|
||||||
|
path: /path/to/certificate.key
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
- name: Create certificate signing request (CSR) for new certificate
|
||||||
|
community.crypto.openssl_csr_pipe:
|
||||||
|
privatekey_path: /path/to/certificate.key
|
||||||
|
subject_alt_name:
|
||||||
|
- "DNS:ansible.com"
|
||||||
|
- "DNS:www.ansible.com"
|
||||||
|
- "DNS:docs.ansible.com"
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
register: csr
|
||||||
|
|
||||||
|
- name: Check whether certificate exists
|
||||||
|
stat:
|
||||||
|
path: /path/to/certificate.pem
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
register: certificate_exists
|
||||||
|
|
||||||
|
- name: Read existing certificate if exists
|
||||||
|
slurp:
|
||||||
|
src: /path/to/certificate.pem
|
||||||
|
when: certificate_exists.stat.exists
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
register: certificate
|
||||||
|
|
||||||
|
- name: Sign certificate with our CA
|
||||||
|
community.crypto.x509_certificate_pipe:
|
||||||
|
content: "{{ (certificate.content | b64decode) if certificate_exists.stat.exists else omit }}"
|
||||||
|
csr_content: "{{ ca_csr.csr }}"
|
||||||
|
provider: ownca
|
||||||
|
ownca_path: /path/to/ca-certificate.pem
|
||||||
|
ownca_privatekey_path: /path/to/ca-certificate.key
|
||||||
|
ownca_privatekey_passphrase: "{{ secret_ca_passphrase }}"
|
||||||
|
ownca_not_after: +365d # valid for one year
|
||||||
|
ownca_not_before: "-1d" # valid since yesterday
|
||||||
|
delegate_to: server_2
|
||||||
|
run_once: true
|
||||||
|
register: certificate
|
||||||
|
|
||||||
|
- name: Write certificate file on server_1
|
||||||
|
copy:
|
||||||
|
dest: /path/to/certificate.pem
|
||||||
|
content: "{{ certificate.certificate }}"
|
||||||
|
delegate_to: server_1
|
||||||
|
run_once: true
|
||||||
|
when: certificate is changed
|
|
@ -0,0 +1,60 @@
|
||||||
|
.. _ansible_collections.community.crypto.docsite.guide_selfsigned:
|
||||||
|
|
||||||
|
How to create self-signed certificates
|
||||||
|
======================================
|
||||||
|
|
||||||
|
The `community.crypto collection <https://galaxy.ansible.com/community/crypto>`_ offers multiple modules that create private keys, certificate signing requests, and certificates. This guide shows how to create self-signed certificates.
|
||||||
|
|
||||||
|
For creating any kind of certificate, you always have to start with a private key. You can use the :ref:`community.crypto.openssl_privatekey module <ansible_collections.community.crypto.openssl_privatekey_module>` to create a private key. If you only specify ``path``, the default parameters will be used. This will result in a 4096 bit RSA private key:
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
- name: Create private key (RSA, 4096 bits)
|
||||||
|
community.crypto.openssl_privatekey:
|
||||||
|
path: /path/to/certificate.key
|
||||||
|
|
||||||
|
You can specify ``type`` to select another key type, ``size`` to select a different key size (only available for RSA and DSA keys), or ``passphrase`` if you want to store the key password-protected:
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
- name: Create private key (X25519) with password protection
|
||||||
|
community.crypto.openssl_privatekey:
|
||||||
|
path: /path/to/certificate.key
|
||||||
|
type: X25519
|
||||||
|
passphrase: changeme
|
||||||
|
|
||||||
|
To create a very simple self-signed certificate with no specific information, you can proceed directly with the :ref:`community.crypto.x509_certificate module <ansible_collections.community.crypto.x509_certificate_module>`:
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
- name: Create simple self-signed certificate
|
||||||
|
community.crypto.x509_certificate:
|
||||||
|
path: /path/to/certificate.pem
|
||||||
|
privatekey_path: /path/to/certificate.key
|
||||||
|
provider: selfsigned
|
||||||
|
|
||||||
|
(If you used ``passphrase`` for the private key, you have to provide ``privatekey_passphrase``.)
|
||||||
|
|
||||||
|
You can use ``selfsigned_not_after`` to define when the certificate expires (default: in roughly 10 years), and ``selfsigned_not_before`` to define from when the certificate is valid (default: now).
|
||||||
|
|
||||||
|
To define further properties of the certificate, like the subject, Subject Alternative Names (SANs), key usages, name constraints, etc., you need to first create a Certificate Signing Request (CSR) and provide it to the :ref:`community.crypto.x509_certificate module <ansible_collections.community.crypto.x509_certificate_module>`. If you do not need the CSR file, you can use the :ref:`community.crypto.openssl_csr_pipe module <ansible_collections.community.crypto.openssl_csr_pipe_module>` as in the example below. (To store it to disk, use the :ref:`community.crypto.openssl_csr module <ansible_collections.community.crypto.openssl_csr_module>` instead.)
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
- name: Create certificate signing request (CSR) for self-signed certificate
|
||||||
|
community.crypto.openssl_csr_pipe:
|
||||||
|
privatekey_path: /path/to/certificate.key
|
||||||
|
common_name: ansible.com
|
||||||
|
organization_name: Ansible, Inc.
|
||||||
|
subject_alt_name:
|
||||||
|
- "DNS:ansible.com"
|
||||||
|
- "DNS:www.ansible.com"
|
||||||
|
- "DNS:docs.ansible.com"
|
||||||
|
register: csr
|
||||||
|
|
||||||
|
- name: Create self-signed certificate from CSR
|
||||||
|
community.crypto.x509_certificate:
|
||||||
|
path: /path/to/certificate.pem
|
||||||
|
csr_content: "{{ csr.csr }}"
|
||||||
|
privatekey_path: /path/to/certificate.key
|
||||||
|
provider: selfsigned
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"include_symlinks": false,
|
||||||
|
"prefixes": [
|
||||||
|
"docs/docsite/"
|
||||||
|
],
|
||||||
|
"output": "path-line-column-message",
|
||||||
|
"requirements": [
|
||||||
|
"antsibull"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright (c) Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
"""Check extra collection docs with antsibull-lint."""
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main entry point."""
|
||||||
|
if not os.path.isdir(os.path.join('docs', 'docsite')):
|
||||||
|
return
|
||||||
|
p = subprocess.run(['antsibull-lint', 'collection-docs', '.'], check=False)
|
||||||
|
if p.returncode not in (0, 3):
|
||||||
|
print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue