From 4b6efbf043d334667ae82b609ab3c1462bc1f8f9 Mon Sep 17 00:00:00 2001 From: John Garbutt Date: Tue, 15 Jul 2025 16:11:01 +0100 Subject: [PATCH 1/5] WIP: attempt to validate community image using sigstore --- roles/community_images/defaults/main.yml | 5 +++++ roles/community_images/tasks/upload_image.yml | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/roles/community_images/defaults/main.yml b/roles/community_images/defaults/main.yml index cbd5b750e..27d6c09ef 100644 --- a/roles/community_images/defaults/main.yml +++ b/roles/community_images/defaults/main.yml @@ -64,6 +64,7 @@ community_images_azimuth_images: |- "{{ dest_key }}": { "name": "{{ image.name }}", "source_url": "{{ image.url }}", + "cosign_bundle_url": "{{ image["cosign-bundle-url"] }}", "checksum": "{{ image.checksum }}", "source_disk_format": "qcow2", "container_format": "bare", @@ -75,6 +76,9 @@ community_images_azimuth_images: |- {% endfor %} } +community_images_certificate_oidc_issuer: "https://token.actions.githubusercontent.com" +community_images_certificate_identity_regexp: "https://github.com/azimuth-cloud/azimuth-images/.github/.*" + # Slurm images are published by the ansible-slurm-appliance repo - https://github.com/stackhpc/ansible-slurm-appliance/ community_images_slurm_base_url: >- https://object.arcus.openstack.hpc.cam.ac.uk/swift/v1/AUTH_3a06571936a0424bb40bc5c672c4ccb1/openhpc-images @@ -85,6 +89,7 @@ community_images_slurm: source_url: "{{ community_images_slurm_base_url }}/openhpc-RL9-250506-1259-abb6394b" source_disk_format: qcow2 container_format: bare + cosign_bundle_url: "todo" # The default community images to upload community_images_default: >- diff --git a/roles/community_images/tasks/upload_image.yml b/roles/community_images/tasks/upload_image.yml index 0dcdb1040..cceeaaf75 100644 --- a/roles/community_images/tasks/upload_image.yml +++ b/roles/community_images/tasks/upload_image.yml @@ -48,12 +48,14 @@ community_images_image_current_visibility: "{{ community_images_image_info.stdout | from_json | json_query('visibility') }}" - name: Download, convert and upload images to Glance - when: "community_images_image_list | length == 0" + # TODO when: "community_images_image_list | length == 0" block: - name: "Set image facts - {{ community_images_image_spec.name }}" ansible.builtin.set_fact: community_images_image_download_path: >- {{ (community_images_workdir, community_images_image_spec.name + '.download') | path_join }} + community_images_image_cosign_download_path: >- + {{ (community_images_workdir, community_images_image_spec.name + '.bundle') | path_join }} community_images_image_decompress_path: >- {{ (community_images_workdir, community_images_image_spec.name + '.decompress') | path_join }} community_images_image_convert_path: >- @@ -87,6 +89,20 @@ timeout: 600 mode: "0644" + - name: "Download cosign bundle - {{ community_images_image_spec.name }}" + ansible.builtin.get_url: + url: "{{ community_images_image_spec.cosign_bundle_url }}" + dest: "{{ community_images_image_cosign_download_path }}" + timeout: 120 + mode: "0644" + + - name: "Validate downloaded image with sigstore - {{ community_images_image_spec.name }}" + ansible.builtin.shell: >- + cosign verify-blob "{{ community_images_image_download_path }}" \ + --bundle "{{ community_images_image_cosign_download_path }}" \ + --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ + --certificate-identity-regexp="https://github.com/azimuth-cloud/azimuth-images/.github/.*" + - name: "Uncompress image (bzip2) - {{ community_images_image_spec.name }}" ansible.builtin.shell: "bunzip2 -dc {{ community_images_image_download_path }} > {{ community_images_image_decompress_path }}" args: @@ -124,6 +140,7 @@ state: absent loop: - "{{ community_images_image_download_path }}" + - "{{ community_images_image_cosign_download_path }}" - "{{ community_images_image_decompress_path }}" - "{{ community_images_image_convert_path }}" loop_control: From b6cf7ab2a2aff1e159b781d007ef6537ed4b058b Mon Sep 17 00:00:00 2001 From: John Garbutt Date: Tue, 15 Jul 2025 16:45:58 +0100 Subject: [PATCH 2/5] Fix no-changed-when lint error --- roles/community_images/tasks/upload_image.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/community_images/tasks/upload_image.yml b/roles/community_images/tasks/upload_image.yml index cceeaaf75..04dac24da 100644 --- a/roles/community_images/tasks/upload_image.yml +++ b/roles/community_images/tasks/upload_image.yml @@ -102,6 +102,9 @@ --bundle "{{ community_images_image_cosign_download_path }}" \ --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ --certificate-identity-regexp="https://github.com/azimuth-cloud/azimuth-images/.github/.*" + register: community_images_verify_blob_cmd + changed_when: false + failed_when: community_images_verify_blob_cmd.rc != 0 - name: "Uncompress image (bzip2) - {{ community_images_image_spec.name }}" ansible.builtin.shell: "bunzip2 -dc {{ community_images_image_download_path }} > {{ community_images_image_decompress_path }}" From 559ba1a0c42b89b629f5e7aff526d76922e312dd Mon Sep 17 00:00:00 2001 From: John Garbutt Date: Mon, 21 Jul 2025 15:56:10 +0100 Subject: [PATCH 3/5] Try to fix missing cosign_bundle_url --- roles/community_images/defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/community_images/defaults/main.yml b/roles/community_images/defaults/main.yml index 27d6c09ef..5667c8b98 100644 --- a/roles/community_images/defaults/main.yml +++ b/roles/community_images/defaults/main.yml @@ -64,7 +64,7 @@ community_images_azimuth_images: |- "{{ dest_key }}": { "name": "{{ image.name }}", "source_url": "{{ image.url }}", - "cosign_bundle_url": "{{ image["cosign-bundle-url"] }}", + "cosign_bundle_url": "{{ image.get("cosign-bundle-url", "todo-missing") }}", "checksum": "{{ image.checksum }}", "source_disk_format": "qcow2", "container_format": "bare", From 2753f55a9117470c3784cd63f1dbdf27dac165c8 Mon Sep 17 00:00:00 2001 From: John Garbutt Date: Mon, 21 Jul 2025 18:23:44 +0100 Subject: [PATCH 4/5] Always set cosign_bundle_url --- roles/community_images/defaults/main.yml | 2 +- roles/community_images/tasks/upload_image.yml | 4 +++- roles/infra/tasks/main.yml | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/roles/community_images/defaults/main.yml b/roles/community_images/defaults/main.yml index 5667c8b98..4f255abf6 100644 --- a/roles/community_images/defaults/main.yml +++ b/roles/community_images/defaults/main.yml @@ -89,7 +89,7 @@ community_images_slurm: source_url: "{{ community_images_slurm_base_url }}/openhpc-RL9-250506-1259-abb6394b" source_disk_format: qcow2 container_format: bare - cosign_bundle_url: "todo" + cosign_bundle_url: "" # The default community images to upload community_images_default: >- diff --git a/roles/community_images/tasks/upload_image.yml b/roles/community_images/tasks/upload_image.yml index 04dac24da..754509bb5 100644 --- a/roles/community_images/tasks/upload_image.yml +++ b/roles/community_images/tasks/upload_image.yml @@ -48,7 +48,7 @@ community_images_image_current_visibility: "{{ community_images_image_info.stdout | from_json | json_query('visibility') }}" - name: Download, convert and upload images to Glance - # TODO when: "community_images_image_list | length == 0" + # todo when: "community_images_image_list | length == 0" block: - name: "Set image facts - {{ community_images_image_spec.name }}" ansible.builtin.set_fact: @@ -95,6 +95,7 @@ dest: "{{ community_images_image_cosign_download_path }}" timeout: 120 mode: "0644" + when: community_images_image_spec.cosign_bundle_url - name: "Validate downloaded image with sigstore - {{ community_images_image_spec.name }}" ansible.builtin.shell: >- @@ -105,6 +106,7 @@ register: community_images_verify_blob_cmd changed_when: false failed_when: community_images_verify_blob_cmd.rc != 0 + when: community_images_image_spec.cosign_bundle_url - name: "Uncompress image (bzip2) - {{ community_images_image_spec.name }}" ansible.builtin.shell: "bunzip2 -dc {{ community_images_image_download_path }} > {{ community_images_image_decompress_path }}" diff --git a/roles/infra/tasks/main.yml b/roles/infra/tasks/main.yml index a316f7fb8..25141122d 100644 --- a/roles/infra/tasks/main.yml +++ b/roles/infra/tasks/main.yml @@ -19,6 +19,7 @@ source_disk_format: "{{ infra_image_source_disk_format }}" container_format: "{{ infra_image_container_format }}" visibility: private + cosign_bundle_url: "" - name: Set infra image ID fact ansible.builtin.set_fact: From 1f90a05b312aef4a4d36f2269c63d0788ca2791e Mon Sep 17 00:00:00 2001 From: John Garbutt Date: Wed, 23 Jul 2025 10:09:40 +0100 Subject: [PATCH 5/5] Install cosign (needs to move to ansible!) --- .github/workflows/test-pr.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test-pr.yml b/.github/workflows/test-pr.yml index 97ca44717..10cb28338 100644 --- a/.github/workflows/test-pr.yml +++ b/.github/workflows/test-pr.yml @@ -53,6 +53,10 @@ jobs: - name: Checkout uses: actions/checkout@v4 + # TODO: move this into the ansible! + - name: Install cosign + uses: sigstore/cosign-installer@v3 + - name: Paths Filter # For safety using commit of dorny/paths-filter@v3 uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36