summaryrefslogtreecommitdiff
path: root/roles/x509/acmetool/base/tasks/selfsigned.yml
blob: 9b1af9039a1de179aa76f5d62bb9cde4c65ce407 (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
  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
  set_fact:
    existing_selfsigned_interim_cert_id: "{{ existing_selfsigned_interim_cert_id.stdout }}"

- name: check if selfsigned interim certificate does exist
  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
    tempfile:
      path: /var/lib/acme/tmp
      prefix: selfsigned-interim-cert-
      state: directory
    register: tmpdir

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

  - name: generate private key for selfsigned interim certificate
    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
    command: date -d '10 seconds ago' -u '+%Y%m%d%H%M%SZ'
    register: remote_datetime_10sago

  - name: get remote date-time now
    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
    copy:
      content: "{{ selfsigned_interim_cert.certificate }}"
      dest: "{{ tmpdir }}/{{ item }}"

  - name: create additional empty files
    loop:
    - chain
    - selfsigned
    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
    copy:
      content: "https://acme.example.com/acme/cert/self-signed\n"
      dest: "{{ tmpdir }}/url"

  - name: get key id
    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
    set_fact:
      selfsigned_interim_key_id: "{{ selfsigned_interim_key_id.stdout }}"

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

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

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

  # - name: get certificate id
  #   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
  #   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
    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
    set_fact:
      selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"

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

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

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

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