From f2cfa6c356485021267c969b77b0cffca0d447a5 Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Fri, 18 Feb 2022 17:27:11 +1100 Subject: [PATCH] encrypt-file: always import expiring keys If a key is in our existing keyring has an expiry date (or, has expired), always import the provided value again as it may be refreshing the value. Add an expiring key to test the matching; although on an ephemeral node we're importing always anyway. Also update the file test to a stat -- this is better than a weird error from gpg later. Change-Id: I8e7bc38c68c224795630b90a1b989098a7661491 --- roles/encrypt-file/tasks/import-key.yaml | 14 ++++++- roles/encrypt-file/tasks/main.yaml | 9 +++- test-playbooks/encrypt-file.yaml | 53 ++++++++++++++++++++---- 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/roles/encrypt-file/tasks/import-key.yaml b/roles/encrypt-file/tasks/import-key.yaml index b90120aa6..fa7efd705 100644 --- a/roles/encrypt-file/tasks/import-key.yaml +++ b/roles/encrypt-file/tasks/import-key.yaml @@ -1,3 +1,5 @@ +# On a static node, this saves us having to re-import the key +# constantly - name: Check for existing key command: | gpg --list-keys {{ zj_encrypt_file.key_id }} @@ -5,8 +7,18 @@ # A found key returns 0, a missing key returns 2 failed_when: _key_exists.rc != 0 and _key_exists.rc != 2 +# If the key may expire, we need to always import it because we can't +# be sure if the key hasn't changed to have a new expiration date. +# GPG outputs this in a string: +# [expires: YYYY-DD-MM] or [expired: YYYY-DD-MM] +- name: Check for expiry string + set_fact: + _key_has_expiry: "{{ _key_exists.stdout | regex_search(regexp) }}" + vars: + regexp: '\[expire[sd]: ' + - name: Install key - when: _key_exists.rc != 0 + when: _key_exists.rc != 0 or _key_has_expiry != '' block: - name: Create temporary keyfile tempfile: diff --git a/roles/encrypt-file/tasks/main.yaml b/roles/encrypt-file/tasks/main.yaml index 277a35565..6d5c37044 100644 --- a/roles/encrypt-file/tasks/main.yaml +++ b/roles/encrypt-file/tasks/main.yaml @@ -1,7 +1,12 @@ +- name: Stat input file + stat: + path: '{{ encrypt_file }}' + register: _stat_result + - name: Validate input file fail: - msg: 'Must define "encrypt_file"' - when: encrypt_file is undefined + msg: '{{ encrypt_file }} : file does not exist' + when: not _stat_result.stat.exists - name: Ensure gpg2 installed package: diff --git a/test-playbooks/encrypt-file.yaml b/test-playbooks/encrypt-file.yaml index 1f4c799b0..89b801065 100644 --- a/test-playbooks/encrypt-file.yaml +++ b/test-playbooks/encrypt-file.yaml @@ -65,6 +65,27 @@ =CRYD -----END PGP PUBLIC KEY BLOCK----- + # NOTE(ianw): This key expires 2106-01-01 which is the + # maximum I seem to be able to convince gpg to do ATM. + # Someone else will have to regenerate it then because I am + # not likely to be available to do it. + - name: 'zuul-jobs-test-4' + key_id: '4A8C7A2A7E55816E' + gpg_asc: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + + mDMEYg9K5BYJKwYBBAHaRw8BAQdAIIezhOWTs9ggMpfePn/6B5sNY5/Bn9CguDcy + gKrjoIC0EHp1dWwtam9icy10ZXN0LTSImgQTFgoAQhYhBJZPfDNqTyma/Ekg0kqM + eip+VYFuBQJiD0rkAhsDBQmdv6CsBQsJCAcCAyICAQYVCgkICwIEFgIDAQIeBwIX + gAAKCRBKjHoqflWBbnOPAP9kJgpMbHh83haH7o+O1jJTbsW9XVX7Aq196ZbEiUhx + 5QD9FFfKnDQ7q8XX6rOK6joLG9Cq8pX5q6tSouqygKKicQm4OARiD0rkEgorBgEE + AZdVAQUBAQdAJ2oXpzmh5vUKhWr7PCT6y4nhIcs9bdnKFiIWfEinGVMDAQgHiHgE + GBYKACAWIQSWT3wzak8pmvxJINJKjHoqflWBbgUCYg9K5AIbDAAKCRBKjHoqflWB + btm1AQC+lvLW8iLbsKde5cqHlGAKgY7KPi5BKxSCzwdRuX3qGAEAvFKGNoEjmUzF + 7SUjadUXXizJoeJ9feocDzfBiaH53w8= + =XCeq + -----END PGP PUBLIC KEY BLOCK----- + - name: Encrypt file include_role: name: encrypt-file @@ -73,12 +94,7 @@ encrypt_file_recipients: - zuul-jobs-test-2 - zuul-jobs-test-3 - - - name: Remove temporary file - file: - path: '{{ _tempfile.path }}' - state: absent - when: _tempfile.path is defined + - zuul-jobs-test-4 - name: Check output file stat: @@ -107,8 +123,31 @@ - "'zuul-jobs-test-1' not in _gpg_output.stdout" - "'zuul-jobs-test-2' in _gpg_output.stdout" - "'zuul-jobs-test-3' in _gpg_output.stdout" + - "'zuul-jobs-test-4' in _gpg_output.stdout" - - name: Remove output file + - name: Remove encrypted output file + file: + path: '{{ _tempfile.path }}.gpg' + state: absent + + # Do it again to exercise already imported keys path + - name: Encrypt file + include_role: + name: encrypt-file + vars: + encrypt_file: '{{ _tempfile.path }}' + encrypt_file_recipients: + - zuul-jobs-test-2 + - zuul-jobs-test-3 + - zuul-jobs-test-4 + + - name: Remove temporary file + file: + path: '{{ _tempfile.path }}' + state: absent + when: _tempfile.path is defined + + - name: Remove encrypted output file file: path: '{{ _tempfile.path }}.gpg' state: absent