33-clair-deploy.yml 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. ---
  2. # Tasks required by 15-clair-deploy.adoc.
  3. # TODO: import vuln updates somehow
  4. - name: Prepare registry VM to run Clair services.
  5. hosts: registry.ocp4.example.com
  6. gather_subset: min
  7. remote_user: quay
  8. tasks:
  9. - name: Ensure the podman network is there.
  10. containers.podman.podman_network_info:
  11. name: quay
  12. register: quay_net
  13. ignore_errors: yes
  14. - ansible.builtin.assert:
  15. that:
  16. - not quay_net.failed
  17. - quay_net.networks is defined
  18. - quay_net.networks is iterable
  19. - quay_net.networks | length == 1
  20. fail_msg: "FATAL: Podman network 'quay' does not exist for 'quay' user. Ensure you deployed Quay before running this playbook."
  21. success_msg: "OK, network 'quay' found."
  22. - name: Ensure the quay service is defined.
  23. ansible.builtin.stat:
  24. path: "{{ ansible_facts['user_dir'] }}/.config/systemd/user/quay.service"
  25. get_attributes: no
  26. get_checksum: no
  27. get_mime: no
  28. register: quay_svc_unit
  29. - ansible.builtin.assert:
  30. that:
  31. - not quay_svc_unit.failed
  32. - quay_svc_unit.stat.exists
  33. fail_msg: "FATAL: User service 'quay.service' not found for 'quay' user. Ensure you deployed Quay before running this playbook."
  34. success_msg: "OK, service 'quay.service' found."
  35. - name: Ensure the quay-pg service is defined.
  36. ansible.builtin.stat:
  37. path: "{{ ansible_facts['user_dir'] }}/.config/systemd/user/quay-pg.service"
  38. get_attributes: no
  39. get_checksum: no
  40. get_mime: no
  41. register: quay_pg_svc_unit
  42. - ansible.builtin.assert:
  43. that:
  44. - not quay_pg_svc_unit.failed
  45. - quay_pg_svc_unit.stat.exists
  46. fail_msg: "FATAL: User service 'quay-pg.service' not found for 'quay' user. Ensure you deployed Quay before running this playbook."
  47. success_msg: "OK, service 'quay-pg.service' found."
  48. - name: Ensure Quay PostgreSQL is running.
  49. ansible.builtin.systemd_service:
  50. name: quay-pg
  51. scope: user
  52. state: started
  53. - name: Check whether the clair database exists.
  54. containers.podman.podman_container_exec:
  55. name: postgresql
  56. command: psql -d postgres -U postgres -t -A -c "SELECT datname FROM pg_database WHERE datname = 'clair'"
  57. register: pg_clair
  58. changed_when: no
  59. - name: Create the clair database if necessary.
  60. containers.podman.podman_container_exec:
  61. name: postgresql
  62. command: 'psql -d postgres -U postgres -c "CREATE DATABASE clair OWNER quay"'
  63. when:
  64. - pg_clair is defined
  65. - pg_clair.stdout_lines | length == 0
  66. - name: Create the uuid-ossp extension if necessary.
  67. containers.podman.podman_container_exec:
  68. name: postgresql
  69. command: psql -d clair -U postgres -c 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'
  70. register: pg_ext
  71. changed_when:
  72. - not "already exists" in pg_ext.stderr
  73. - name: Pull all the images if necessary.
  74. containers.podman.podman_image:
  75. name: "{{ registry_host }}/quay/clair-rhel8:v{{ quay_version }}"
  76. pull: yes
  77. state: present
  78. # TODO: Make loop labels nicer.
  79. - name: Patch Quay config if necessary.
  80. ansible.builtin.lineinfile:
  81. path: "{{ ansible_facts['user_dir'] }}/config/config.yaml"
  82. insertafter: "{{ item.after }}"
  83. regexp: "{{ item.fixre }}"
  84. line: "{{ item.value }}"
  85. loop:
  86. - after: "^FEATURE_MAILING: false$"
  87. fixre: "^FEATURE_SECURITY_SCANNER: .*$"
  88. value: "FEATURE_SECURITY_SCANNER: true"
  89. - after: "^SECRET_KEY: .*$"
  90. fixre: "^SECURITY_SCANNER_INDEXING_INTERVAL: .*$"
  91. value: "SECURITY_SCANNER_INDEXING_INTERVAL: 30"
  92. - after: "^SECURITY_SCANNER_INDEXING_INTERVAL: .*$"
  93. fixre: "^SECURITY_SCANNER_V4_PSK: .*$"
  94. value: "SECURITY_SCANNER_V4_PSK: NjA1aWhnNWk4MWhqNw=="
  95. - after: "^SECURITY_SCANNER_V4_PSK: .*$"
  96. fixre: "^SECURITY_SCANNER_V4_ENDPOINT: .*$"
  97. value: "SECURITY_SCANNER_V4_ENDPOINT: http://clair:8081"
  98. notify:
  99. - restart quay and wait for ready
  100. - name: Create Clair config directory if necessary.
  101. ansible.builtin.file:
  102. path: "{{ ansible_facts['user_dir'] }}/clair"
  103. state: directory
  104. mode: 0775
  105. - name: Publish Clair config if necessary.
  106. ansible.builtin.copy:
  107. dest: "{{ ansible_facts['user_dir'] }}/clair/config.yaml"
  108. content: |
  109. http_listen_addr: :8081
  110. introspection_addr: :8088
  111. #log_level: debug # too noisy
  112. log_level: info
  113. indexer:
  114. connstring: host=postgresql port=5432 dbname=clair user=quay password=secret sslmode=disable
  115. scanlock_retry: 10
  116. layer_scan_concurrency: 5
  117. migrations: true
  118. scanner:
  119. repo:
  120. rhel-repository-scanner:
  121. repo2cpe_mapping_file: /data/repository-to-cpe.json
  122. package:
  123. rhel_containerscanner:
  124. name2repos_mapping_file: /data/container-name-repos-map.json
  125. airgap: true
  126. matcher:
  127. connstring: host=postgresql port=5432 dbname=clair user=quay password=secret sslmode=disable
  128. max_conn_pool: 100
  129. migrations: true
  130. indexer_addr: clair-indexer
  131. disable_updaters: true
  132. notifier:
  133. connstring: host=postgresql port=5432 dbname=clair user=quay password=secret sslmode=disable
  134. delivery_interval: 1m
  135. poll_interval: 5m
  136. migrations: true
  137. updaters:
  138. config:
  139. rhel:
  140. ignore_unpatched: false
  141. auth:
  142. psk:
  143. key: "NjA1aWhnNWk4MWhqNw=="
  144. iss: ["quay"]
  145. metrics:
  146. name: "prometheus"
  147. mode: 0664
  148. notify:
  149. - restart quay and wait for ready
  150. - restart clair
  151. - name: Ensure same TLS trust will be used for Clair as for workstation.
  152. ansible.builtin.copy:
  153. src: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
  154. dest: "{{ ansible_facts['user_dir'] }}/tls-ca-bundle.pem"
  155. mode: 0664
  156. notify:
  157. - restart clair
  158. - name: Ensure Clair service unit is there.
  159. ansible.builtin.template:
  160. dest: "{{ ansible_facts['user_dir'] }}/.config/systemd/user/clair.service"
  161. src: "templates/clair.service.j2"
  162. - name: Reload systemd.
  163. ansible.builtin.systemd_service:
  164. daemon_reload: yes
  165. scope: user
  166. - name: Enable services and start them.
  167. ansible.builtin.systemd_service:
  168. name: clair
  169. scope: user
  170. state: started
  171. enabled: yes
  172. handlers:
  173. - name: restart quay
  174. listen: restart quay and wait for ready
  175. ansible.builtin.systemd_service:
  176. name: quay
  177. scope: user
  178. state: restarted
  179. - name: wait for quay to become ready again
  180. listen: restart quay and wait for ready
  181. ansible.builtin.uri:
  182. method: GET
  183. url: https://registry.ocp4.example.com/
  184. headers:
  185. Accept: application/json
  186. Content-Type: application/json
  187. validate_certs: no
  188. status_code:
  189. - 200
  190. - 404
  191. - 502
  192. register: startup_wait
  193. until: startup_wait.status == 200
  194. retries: 30
  195. delay: 5
  196. - name: restart clair
  197. ansible.builtin.systemd_service:
  198. name: clair
  199. scope: user
  200. state: restarted
  201. ...