commit 1296c4595b6c3bf3b724cb5217e8202f7d784fba Author: ababra Date: Fri Apr 20 04:40:41 2018 -0400 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..4401e5d --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +Generate TLS certificates +========================= +Generates self-signed CA, client and server certificates. Runs locally on control machine. **Note:** Ansible crypto modules do not support self-signed certs, using `shell` command instead as required. + + +Requirements +------------ +- For server certificates, must specify Ansible inventory file; FQDN must also be set as hostname in inventory file + + +Role Variables +-------------- +See `defaults/main.yml` + + +Dependencies +------------ +- Refer to [Ansible Crypto modules](http://docs.ansible.com/ansible/latest/modules/list_of_crypto_modules.html) + + +Example Playbook +---------------- +**generate-certs.yaml:** +``` +--- + +# ansible-playbook generate-certs.yaml -i localhost, +# ansible-playbook generate-certs.yaml -i inventory.yaml + +- hosts: all + + gather_facts: false + + tasks: + - include_vars: vars.yaml + + - name: Generate certs + import_role: + name: generate-tls-certs + +``` + +**vars.yaml:** +``` +--- +cert_dir: ./certs +generate_ca_cert: true +generate_client_cert: true +generate_server_cert: true + +# ------- +# CA CERT +# ------- +tls_ca_cert: my-ca.pem +tls_ca_csr: my-ca.csr +tls_ca_key: my-ca.key +tls_ca_country: CA +tls_ca_state: Ontario +tls_ca_locality: Toronto +tls_ca_organization: My Company Inc. +tls_ca_organizationalunit: IT +tls_ca_commonname: My Certificate Authority + +# ----------- +# CLIENT CERT +# ----------- +tls_client_cert: my-client.pem +tls_client_key: my-client.key +tls_client_csr: my-client.csr +tls_client_commonname: My Client + +``` + + +License +------- +BSD + + +Author Information +------------------ +[EasyPath IT Solutions Inc.](https://www.easypath.ca) diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..cbf1f9c --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,44 @@ +--- +# defaults file for generate-tls-certs + +# Do not put trailing slash "/" +cert_dir: ./certs +generate_ca_cert: false +generate_client_cert: false +generate_server_cert: false + +# ------- +# CA CERT +# ------- +tls_ca_cert: ca.pem +tls_ca_csr: ca.csr +tls_ca_key: ca.key +tls_ca_key_size: 4096 +# 10 years +tls_ca_valid_days: 3650 +# tls_ca_country: +# tls_ca_state: +# tls_ca_locality: +# tls_ca_organization: +# tls_ca_organizationalunit: +tls_ca_commonname: Certificate Authority +#tls_ca_email: + +# ----------- +# CLIENT CERT +# ----------- +tls_client_cert: client.pem +tls_client_key: client.key +tls_client_csr: client.csr +tls_client_key_size: 4096 +tls_client_commonname: Client +tls_client_extfile: extfile-client.cnf +# 2 years +tls_client_valid_days: 730 + +# ----------- +# SERVER CERT +# ----------- +# 2 years +tls_server_valid_days: 730 +tls_server_key_size: 4096 diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..174ff7d --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,61 @@ +galaxy_info: + author: Aman Babra + description: Generates self-signed CA, client and server certificates + company: EasyPath IT Solutions Inc. + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Some suggested licenses: + # - BSD (default) + # - MIT + # - GPLv2 + # - GPLv3 + # - Apache + # - CC-BY + license: BSD + + min_ansible_version: 2.4 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # Optionally specify the branch Galaxy will use when accessing the GitHub + # repo for this role. During role install, if no tags are available, + # Galaxy will use this branch. During import Galaxy will access files on + # this branch. If Travis integration is configured, only notifications for this + # branch will be accepted. Otherwise, in all cases, the repo's default branch + # (usually master) will be used. + #github_branch: + + # + # platforms is a list of platforms, and each platform has a name and a list of versions. + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: + - tls + - openssl + - certificates + - security + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..bfb2d69 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,80 @@ +--- +# tasks file for generate-tls-certs + + - name: Generate CA private key + local_action: + module: openssl_privatekey + path: "{{cert_dir}}/{{tls_ca_key}}" + size: "{{tls_ca_key_size}}" + run_once: true + when: generate_ca_cert + + - name: Generate self-signed cert for CA + local_action: + module: > + shell openssl req -x509 -new -days {{tls_ca_valid_days}} -sha256 -nodes -key {{cert_dir}}/{{tls_ca_key}} -out {{cert_dir}}/{{tls_ca_cert}} + -subj "{% if tls_ca_country is defined%}/C={{tls_ca_country}}{% endif %}{% if tls_ca_state is defined%}/ST={{tls_ca_state}}{% endif %}{% if tls_ca_locality is defined %}/L={{tls_ca_locality}}{% endif %}{% if tls_ca_organization is defined %}/O={{tls_ca_organization}}{% endif %}{% if tls_ca_organizationalunit is defined %}/OU={{tls_ca_organizationalunit}}{% endif %}/CN={{tls_ca_commonname}}{% if tls_ca_email is defined %}/emailAddress={{tls_ca_email}}{% endif %}" + ignore_errors: true + run_once: true + when: generate_ca_cert + + - name: Generate client private key + local_action: + module: openssl_privatekey + path: "{{cert_dir}}/{{tls_client_key}}" + size: "{{tls_client_key_size}}" + run_once: true + when: generate_client_cert + + - name: Generate CSR and key for client cert + local_action: + module: > + shell openssl req -newkey rsa:{{tls_client_key_size}} -nodes -subj "/CN={{tls_client_commonname}}" + -keyout "{{cert_dir}}/{{tls_client_key}}" -out "{{cert_dir}}/{{tls_client_csr}}" + ignore_errors: true + run_once: true + when: generate_client_cert + + - name: Add required extension for client authentication + local_action: + module: > + shell echo extendedKeyUsage = clientAuth >> {{cert_dir}}/{{tls_client_extfile}} + ignore_errors: true + run_once: true + when: generate_client_cert + + # @AB TODO: using OpenSSL CA serial file does not always generate unique serial when running playbook against multiple hosts + - name: Sign client cert request with CA + local_action: + module: > + shell openssl x509 -req -sha256 -days {{tls_client_valid_days}} -CA {{cert_dir}}/{{tls_ca_cert}} -CAkey {{cert_dir}}/{{tls_ca_key}} + -set_serial {{ 999999999 | random }} -in {{cert_dir}}/{{tls_client_csr}} -out {{cert_dir}}/{{tls_client_cert}} -extfile {{cert_dir}}/{{tls_client_extfile}} + ignore_errors: true + run_once: true + when: generate_client_cert + + # Generate server cert + - name: Create CSR for server cert + local_action: + module: > + shell openssl req -newkey rsa:{{tls_server_key_size}} -nodes -subj "/CN={{inventory_hostname}}" + -keyout "{{cert_dir}}/{{inventory_hostname_short}}.key" -out "{{cert_dir}}/{{inventory_hostname_short}}.csr" + ignore_errors: true + when: generate_server_cert + + - name: Generate certificate extensions file + local_action: + module: template + src: templates/server-cert-extfile.cnf.j2 + dest: "{{cert_dir}}/{{inventory_hostname_short}}-extfile.cnf" + when: generate_server_cert + + - name: Sign server cert request by CA + local_action: + module: > + shell openssl x509 -req -sha256 -days {{tls_server_valid_days}} + -CA "{{cert_dir}}/{{tls_ca_cert}}" -CAkey "{{cert_dir}}/{{tls_ca_key}}" -set_serial {{ 999999999 | random }} + -in "{{cert_dir}}/{{inventory_hostname_short}}.csr" -out "{{cert_dir}}/{{inventory_hostname_short}}.pem" + -extfile "{{cert_dir}}/{{inventory_hostname_short}}-extfile.cnf" + ignore_errors: true + when: generate_server_cert diff --git a/templates/server-cert-extfile.cnf.j2 b/templates/server-cert-extfile.cnf.j2 new file mode 100644 index 0000000..ed77463 --- /dev/null +++ b/templates/server-cert-extfile.cnf.j2 @@ -0,0 +1,3 @@ +subjectAltName = DNS:{{inventory_hostname}},DNS:{{inventory_hostname_short}},IP:{{(alt_interface_ip is defined) | ternary(alt_interface_ip, ansible_host)}},IP:0.0.0.0,IP:127.0.0.1 + +extendedKeyUsage = serverAuth