summaryrefslogtreecommitdiff
path: root/roles/acmetool/base/tasks/selfsigned.yml
blob: 449fbdb9a96fb7767efb5f941344215ea277bb15 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
---
- name: get id of existing selfsigned interim certificate
  ansible.builtin.shell: cat /var/lib/acme/.selfsigned-interim-cert || true
  changed_when: false
  check_mode: false
  register: existing_selfsigned_interim_cert_id

- name: set existing_selfsigned_interim_cert_id variable
  ansible.builtin.set_fact:
    existing_selfsigned_interim_cert_id: "{{ existing_selfsigned_interim_cert_id.stdout }}"

- name: check if selfsigned interim certificate does exist
  ansible.builtin.stat:
    path: "/var/lib/acme/certs/{{ existing_selfsigned_interim_cert_id }}"
  register: existing_selfsigned_interim_cert_stat

- name: create selfsigned interim certificate
  when: not existing_selfsigned_interim_cert_id or not existing_selfsigned_interim_cert_stat.stat.exists
  block:
  - name: create temporary directory
    ansible.builtin.tempfile:
      path: /var/lib/acme/tmp
      prefix: selfsigned-interim-cert-
      state: directory
    register: tmpdir

  - name: set tmpdir variable
    ansible.builtin.set_fact:
      tmpdir: "{{ tmpdir.path }}"

  - name: generate private key for selfsigned interim certificate
    ansible.builtin.openssl_privatekey:
      path: "{{ tmpdir }}/privkey"
      mode: 0600

  - name: generate csr for selfsigned interim certificate
    community.crypto.openssl_csr_pipe:
      privatekey_path: "{{ tmpdir }}/privkey"
      common_name: "{{ ansible_fqdn }}"
    register: selfsigned_interim_cert_req


  ### this is needed because strftime filter in ansible is exceptionally stupid
  ### see: https://github.com/ansible/ansible/issues/39835
  - name: get remote date-time 10s ago
    ansible.builtin.command: date -d '10 seconds ago' -u '+%Y%m%d%H%M%SZ'
    register: remote_datetime_10sago

  - name: get remote date-time now
    ansible.builtin.command: date -u '+%Y%m%d%H%M%SZ'
    register: remote_datetime_now

  - name: generate selfsigned interim certificate
    community.crypto.x509_certificate_pipe:
      privatekey_path: "{{ tmpdir }}/privkey"
      csr_content: "{{ selfsigned_interim_cert_req.csr }}"
      provider: selfsigned
      ## make sure the certificate is not valid anymore to force acmetool to create a new cert
      selfsigned_not_before: "{{ remote_datetime_10sago.stdout }}"
      selfsigned_not_after: "{{ remote_datetime_now.stdout }}"
    register: selfsigned_interim_cert

  - name: install selfsigned interim certificate and fullchain
    loop:
    - cert
    - fullchain
    ansible.builtin.copy:
      content: "{{ selfsigned_interim_cert.certificate }}"
      dest: "{{ tmpdir }}/{{ item }}"

  - name: create additional empty files
    loop:
    - chain
    - selfsigned
    ansible.builtin.copy:
      content: ""
      dest: "{{ tmpdir }}/{{ item }}"

  ### TODO: remove this once acmetool respects it's own storage layout
  ###       see: https://github.com/hlandau/acme/blob/master/_doc/SCHEMA.md#temporary-use-of-self-signed-certificates
  - name: generate fake url file
    ansible.builtin.copy:
      content: "https://acme.example.com/acme/cert/self-signed\n"
      dest: "{{ tmpdir }}/url"

  - name: get key id
    ansible.builtin.shell: "openssl x509 -in '{{ tmpdir }}/cert' -noout -pubkey | openssl enc -base64 -d | openssl sha256 -binary | base32 | tr -d '=' | tr '[:upper:]' '[:lower:]'"
    register: selfsigned_interim_key_id

  - name: set selfsigned_interim_key_id variable
    ansible.builtin.set_fact:
      selfsigned_interim_key_id: "{{ selfsigned_interim_key_id.stdout }}"

  - name: create directory for private key of selfsigned interim certificate
    ansible.builtin.file:
      path: "/var/lib/acme/keys/{{ selfsigned_interim_key_id }}"
      state: directory
      mode: 0700

  - name: move private key to its directory
    ansible.builtin.command: "mv '{{ tmpdir }}/privkey' '/var/lib/acme/keys/{{ selfsigned_interim_key_id }}/privkey'"

  - name: create symlink to privkey
    ansible.builtin.file:
      src: "../../keys/{{ selfsigned_interim_key_id }}/privkey"
      dest: "{{ tmpdir }}/privkey"
      state: link

  # - name: get certificate id
  #   ansible.builtin.shell: "openssl x509 -in '{{ tmpdir }}/cert' -outform der | openssl sha256 -binary | base32 | tr -d '=' | tr '[:upper:]' '[:lower:]'"
  #   register: selfsigned_interim_cert_id

  # - name: set selfsigned_interim_cert_id variable
  #   ansible.builtin.set_fact:
  #     selfsigned_interim_cert_id: "selfsigned-{{ selfsigned_interim_cert_id.stdout }}"

  ### TODO: replace with the above once acmetool respects it's own storage layout
  ###       see: https://github.com/hlandau/acme/blob/master/_doc/SCHEMA.md#temporary-use-of-self-signed-certificates
  - name: get certificate id
    ansible.builtin.shell: "cat '{{ tmpdir }}/url' | tr -d '\n' | openssl sha256 -binary | base32 | tr -d '=' | tr '[:upper:]' '[:lower:]'"
    register: selfsigned_interim_cert_id

  - name: set selfsigned_interim_cert_id variable
    ansible.builtin.set_fact:
      selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"

  - name: set permissions for selfsigned interim certificate directory
    ansible.builtin.file:
      path: "{{ tmpdir }}"
      mode: 0755
      state: directory

  - name: move selfsigned interim certificate directory into place
    ansible.builtin.command: "mv '{{ tmpdir }}' '/var/lib/acme/certs/{{ selfsigned_interim_cert_id }}'"

  - name: write cert-id of selfsigned interim certificate to state directory
    ansible.builtin.copy:
      content: "{{ selfsigned_interim_cert_id }}"
      dest: /var/lib/acme/.selfsigned-interim-cert

  rescue:
  - name: remove temporary directory for selfsigned interim certificate
    ansible.builtin.file:
      path: "{{ tmpdir }}"
      state: absent