14

I want to create a self signed certificate to use it with stunnel, in order to securely tunnel my redis traffic between the redis server and client. I'm using this command to generate the certificate and it works fine.

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/stunnel/redis-server.key -out /etc/stunnel/redis-server.crt

Since I'm using Ansible for provisioning, I would like to know how I can convert this into a more Ansible way of doing, using a module. There actually is a module called the openssl_certificate Ansible module and it states "This module allows one to (re)generate OpenSSL certificates.". I tried to use the module to generate the certificate, but I couldn't get it to work.

- name: Generate a Self Signed OpenSSL certificate
  openssl_certificate:
    path: /etc/stunnel/redis-server.crt
    privatekey_path: /etc/stunnel/redis-server.key
    csr_path: /etc/stunnel/redis-server.csr
    provider: selfsigned

From a look at the documentation, I can't specify the following arguments -x509 -nodes -days 3650 -newkey rsa:2048. Of course, I could also split the key and cert generation, but that still wouldn't allow me to use the Ansible module, correct?

Example given:

openssl genrsa -out /etc/stunnel/key.pem 4096

openssl req -new -x509 -key /etc/stunnel/key.pem -out /etc/stunnel/cert.pem -days 1826

I would like to know the following things:

  • a) How can I get the same result from the original command, but using an Ansible module?
  • b) Is there a better way to manage self signed certificates using Ansible?
Tom
  • 4,070
  • 4
  • 22
  • 50
  • 3
    It's necessary to 1) [Generate private key](https://docs.ansible.com/ansible/latest/modules/openssl_privatekey_module.html#openssl-privatekey-generate-openssl-private-keys) 2) use the private key to [Generate Certificate Signing Request (CSR)](https://docs.ansible.com/ansible/latest/modules/openssl_csr_module.html#openssl-csr-generate-openssl-certificate-signing-request-csr) and 3) use the private key and CSR to [Generate a Self Signed certificate](https://docs.ansible.com/ansible/latest/modules/openssl_certificate_module.html#openssl-certificate-generate-and-or-check-openssl-certificates). – Vladimir Botka May 28 '19 at 22:48
  • 4
    For example see [cert-self-signed.yml](https://github.com/vbotka/ansible-certificate/blob/master/tasks/cert-self-signed.yml). – Vladimir Botka May 28 '19 at 22:56
  • Thanks! - This is exactly what I was looking for! – Tom May 29 '19 at 15:44

3 Answers3

24
- openssl_privatekey:
    path: /etc/stunnel/redis-server.key
    size: 2048 

- openssl_csr:
    path: /etc/stunnel/redis-server.csr
    privatekey_path: /etc/stunnel/redis-server.key

- openssl_certificate:
    provider: selfsigned
    path: /etc/stunnel/redis-server.crt
    privatekey_path: /etc/stunnel/redis-server.key
    csr_path:/etc/stunnel/redis-server.csr
  • "-newkey rsa:2048" is dealt with "size" on privatekey
  • "-x509" is defaulted
  • "-nodes" and "-days 3650" I couldn't find
Tyhal
  • 759
  • 9
  • 12
  • oof I guess you are right, but I've never actually used the solution in production... If the answer gets like 5 upvotes or someone posts a comment I will accept the answer. – Tom Oct 12 '19 at 01:43
  • 7
    `openssl_certificate` needs a `provider: selfsigned`. Otherwise this worked for me. `-days` could then be achieved using `selfsigned_not_after`, I guess. – nondeterministic Dec 06 '19 at 16:04
5

You can achieve this in 2 steps (tested with Ansible 5.7.1):

- name: Ensure private key is present
  community.crypto.openssl_privatekey:
    path: /etc/stunnel/redis-server.key
    size: 2048
    mode: 0600
    type: RSA
    
- name: Ensure self-signed cert is present
  community.crypto.x509_certificate:
    path: /etc/stunnel/redis-server.crt
    privatekey_path: /etc/stunnel/redis-server.key
    provider: selfsigned
    selfsigned_not_after: "+3650d" # this is the default
    mode: 0644

If you don't set a passphrase in the private key generation task, it will be password-less by default.

As @nondeterministic mentioned before, you can set the expiration date via selfsigned_not_after.

The mode parameter sets the file permissions of the key and cert files. It's a common best practice to set the permissions whenever possible and it is also checked per default by ansible-lint.

Sources:

itg-dave
  • 174
  • 3
  • 10
1

For others and my future self, this is an extended example with a CRT to set the subject and organization name of the self-signed certificate.

    - name: Generate a self-signed private key
      community.crypto.openssl_privatekey:
        path: "{{ nginx_ssl_certificate_key }}"
        size: 4096
        mode: 0600
        type: RSA
        state: present

    - name: Create certificate signing request (CSR) for self-signed certificate
      community.crypto.openssl_csr_pipe:
        privatekey_path: "{{ nginx_ssl_certificate_key }}"
        common_name: "{{ cert_common_name }}"
        organization_name: "{{ cert_organization_name }}"
      register: csr

    - name: Generate a self-signed SSL/TLS certificate (valid for 10 years)
      community.crypto.x509_certificate:
        path: "{{ nginx_ssl_certificate }}"
        privatekey_path: "{{ nginx_ssl_certificate_key }}"
        csr_content: "{{ csr.csr }}"
        provider: selfsigned
        selfsigned_not_after: "+3650d"
        mode: 0644

Hopefully this is of help to someone else.

nidkil
  • 11
  • 1