remote file concatenation

hi,

I've 3 files on a remote server after acme let's encrypt dns-01 process, that need to be concatenated in a specific order (private.key intermediate.cert public.cert ) for my TLS proxy, on the same system.

- the assemble module seems ideal but it doesn't enforce order, and it bundles a given directory, not specific files
- using fetch module and jinja ends up with a local copy of a private key which I'd rather avoid
- the easiest option (shell script) is not a way to learn new tricks in ansible :smiley:

Does anybody have suggestions on using some of the new features in loops to achieve this somehow?

https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

BTW this is what I currently tried; the copy/content block doesn't work yet as I've not figured out the correct way inside a jinja template to use {{ item }} inside the lookup:

- name: acme | fetch certificates for concatenation
  fetch:
    src: "/usr/local/etc/ssl/acme/{{ item }}"
    dest: "{{ config.domain }}/certs/{{ item }}"
  with_items:
    - "{{ config.domain }}.crt"
    - "intermediate.crt"
    - "{{ config.domain }}.key"
  tags:
    - acme
    - concatenate

- name: acme | concatenate certs for haproxy
  copy:
    content: >
      {{ lookup('file', "{{ config.domain }}/certs/{{ item }}") }}
      {{ lookup('file', "{{ config.domain }}/certs/{{ item }}") }}
      {{ lookup('file', "{{ config.domain }}/certs/{{ item }}") }}
    dest: "/usr/local/etc/ssl/acme/{{ config.domain }}.all"
    mode: 0600
    owner: root..
    group: wheel
  with_items:
    - "{{ config.domain }}.crt"
    - "intermediate.crt"
    - "{{ config.domain }}.key"
  tags:
    - acme
    - concatenate

thanks!

hi,

I've 3 files on a remote server after acme let's encrypt dns-01 process, that need to be concatenated in a specific order (private.key intermediate.cert public.cert ) for my TLS proxy, on the same system.

- the assemble module seems ideal but it doesn't enforce order,

It sort of does it's string sorting order.

and it bundles a given directory, not specific files

You have regexp to filter out only the files you want, but yes they need to be in the same directory.

- using fetch module and jinja ends up with a local copy of a private key which I'd rather avoid

You have slurp module, then the information is only in memory, but when you use copy module afterwards it might touch the disk, I'm not sure how Ansible is does it.

- the easiest option (shell script) is not a way to learn new tricks in ansible :smiley:

Sometimes that is you best and/or only option :wink:

Does anybody have suggestions on using some of the new features in loops to achieve this somehow?

I would probably just do

- shell: cat {{ config.domain }}.crt intermediate.crt {{ config.domain }}.key >/usr/local/etc/ssl/acme/{{ config.domain }}.all
  args:
    chdir: /usr/local/etc/ssl/acme

BTW this is what I currently tried; the copy/content block doesn't work yet as I've not figured out the correct way inside a jinja template to use {{ item }} inside the lookup:

- name: acme | fetch certificates for concatenation
  fetch:
    src: "/usr/local/etc/ssl/acme/{{ item }}"
    dest: "{{ config.domain }}/certs/{{ item }}"
  with_items:
    - "{{ config.domain }}.crt"
    - "intermediate.crt"
    - "{{ config.domain }}.key"
  tags:
    - acme
    - concatenate

- name: acme | concatenate certs for haproxy
  copy:
    content: >
      {{ lookup('file', "{{ config.domain }}/certs/{{ item }}") }}
      {{ lookup('file', "{{ config.domain }}/certs/{{ item }}") }}
      {{ lookup('file', "{{ config.domain }}/certs/{{ item }}") }}

You can't use {{}} inside {{}} since you already are in template mode, so you need to use concatenation.

  {{ lookup('file', config.domain ~ '/certs/' ~ item) }}

You can also create dir with symlinks to each file, have the symlink
name keep the order you want 01, 02, 03, then run assemble module.