--- # Copyright 2025, Advanced Hosters B.V. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - name: Try to read secrets file as yaml or fallback to decrypt secrets block: - name: Fetch the file ansible.builtin.slurp: src: "{{ file['stat']['path'] }}" register: _secrets_file - name: Read file as unencrypted ansible.builtin.set_fact: _secrets: "{{ _secrets_file['content'] | b64decode | from_yaml }}" rescue: - name: Skipping file as it is likely already encrypted ansible.builtin.debug: msg: "We failed to read file as YAML, which means that it's likely already encrypted. Skipping..." when: - ansible_vault_action == "encrypt" - name: Loading encrypted variables to re-encrypt ansible.builtin.include_vars: file: "{{ file['stat']['path'] }}" when: - ansible_vault_action == "rotate" - name: Read current secrets file for rotation vars: _secret_vars: "{{ _secrets_file['content'] | b64decode | regex_findall('(.*):\\s!vault\\s\\|\\n') }}" ansible.builtin.set_fact: _secrets: |- {% set secrets_mapping = {} %} {% for var in _secret_vars %} {% set _ = secrets_mapping.update({var: hostvars['localhost'][var]}) %} {% endfor %} {{ secrets_mapping }} when: - ansible_vault_action == "rotate" always: - name: Encrypt individual secrets from unencrypted file ansible.builtin.command: argv: - "{{ ansible_vault_binary }}" - encrypt_string - --vault-id - "{{ ansible_vault_region | upper }}@{{ _ansible_vault_encrypt_file }}" - --encrypt-vault-id - "{{ ansible_vault_region | upper }}" - '{{ item.value }}' - --name - "{{ item.key }}" with_dict: "{{ _secrets | default({}) }}" no_log: true register: new_secrets changed_when: false - name: Place encrypted secrets in-place ansible.builtin.copy: content: "---\n{{ new_secrets.results | map(attribute='stdout') | join('\n') }}\n" dest: "{{ file['stat']['path'] }}" mode: "0600" when: - _secrets is defined - _secrets | length > 0 - ansible_vault_in_place_copy - name: Place encrypted secrets in independent blocks ansible.builtin.blockinfile: block: "{{ item['stdout'] }}" dest: "{{ file['stat']['path'] }}" marker: "# {mark} ANSIBLE MANAGED {{ item.item['key'] }}" mode: "0600" loop: "{{ new_secrets.results }}" when: - _secrets is defined - _secrets | length > 0 - not ansible_vault_in_place_copy - name: Undefine the secrets variable ansible.builtin.set_fact: _secrets: {}