# Signing Execution Environments This is based on https://docs.pulpproject.org/pulp_container/workflows/sign-images.html#sign-images-that-were-pushed-to-the-pulp-registry > **NOTE** The instructions to enable container signing on your hub system is described on https://galaxyng.netlify.app/config/container_signing/ (WIP) > **IMPORTANT**: To perform signing actions the user must be a superuser (admin) or need `modify_content_containerpushrepository` permissions provided also by the Roles `execution environment admin`, `execution environment publisher`, `execution environment namespace owner`, `execution environment collaborator` > **IMPORTANT 2** The feature flags endpoint `/api/automation-hub/_ui/v1/feature-flags/` has a flag to tell if `container_signing` feature is enabled on the system, based on that UI decides if badges and button are shown on EE pages > **IMPORTANT 3** The workflow here requires the [PR](https://github.com/ansible/galaxy_ng/pull/1414) to be merged to galaxy_ng UI Issues: - https://issues.redhat.com/browse/AAH-1265 - https://issues.redhat.com/browse/AAH-1266 QE Issues: - https://issues.redhat.com/browse/AAH-1799 - https://issues.redhat.com/browse/AAH-962 Docs Issues: - https://issues.redhat.com/browse/AAP-4667 ## 1. Push a container image Get a container image locally and tag it ```bash docker pull alpine docker image tag alpine localhost:5001/alpine:latest ``` Login and push to the hub registry ```bash docker login -u admin -p admin localhost:5001 docker push localhost:5001/alpine:latest ``` > IF running on galaxy_ng dev environment you can run `make api/push-test-images` and this will feed your running system with 15 sample images ## 2. Check for Repository pulp_href for that image Do a GET request on http://0.0.0.0:5001/pulp/api/v3/repositories/container/container-push/?name=alpine ```json { "count": 1, "next": null, "previous": null, "results": [ { "name": "alpine", "pulp_href": "/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/", } ] } ``` Get what is in `pulp_href` attribute ```bash export CONTAINER_URL="/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/" ``` ## 3. Check for a configured SigningService for container Fetch the name of the signing service set on the system GET http://0.0.0.0:8002/api/automation-hub/_ui/v1/settings/ ```json { "GALAXY_CONTAINER_SIGNING_SERVICE": "container-default" } ``` ## 4. Fetch the SigningService pulp_href GET http://0.0.0.0:5001/pulp/api/v3/signing-services/?name=container-default ```json { "pulp_href": "/api/automation-hub/pulp/api/v3/signing-services/fe1969f2-0dbb-4661-a6d6-8e1ed6d814ce/" } ``` ```bash export SS_URL="/api/automation-hub/pulp/api/v3/signing-services/fe1969f2-0dbb-4661-a6d6-8e1ed6d814ce/" ``` ## 5. Call /sign/ on that Repository passing the SigningService parameter Now do a POST request to `CONTAINER_URL` + `/sign/` passing a `manifest_signing_service` containing `SS_URL` > **NOTE** curl below is just an example, you need to pass auth headers ```bash curl -X POST \ 'http://localhost:5001/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/sign/' \ --header 'Accept: */*' \ --header 'Content-Type: application/json' \ --data-raw '{ "manifest_signing_service": "/api/automation-hub/pulp/api/v3/signing-services/fe1969f2-0dbb-4661-a6d6-8e1ed6d814ce/" }' ``` ## 6. Check if the image has a signature do a GET request to http://localhost:5001/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/ > **NOTE** `/versions/4/` stands for the latest version of that repo > **NOTE** check lines 24-27 on the example below `content.signature` the `count` shows the number of signatures on that image repository ```json= { "pulp_href": "/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/", "pulp_created": "2022-08-10T18:58:03.603802Z", "number": 4, "repository": "/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/", "base_version": null, "content_summary": { "added": { "container.signature": { "count": 1, "href": "/api/automation-hub/pulp/api/v3/content/container/signatures/?repository_version_added=/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/" } }, "removed": {}, "present": { "container.blob": { "count": 2, "href": "/api/automation-hub/pulp/api/v3/content/container/blobs/?repository_version=/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/" }, "container.manifest": { "count": 1, "href": "/api/automation-hub/pulp/api/v3/content/container/manifests/?repository_version=/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/" }, "container.signature": { "count": 1, "href": "/api/automation-hub/pulp/api/v3/content/container/signatures/?repository_version=/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/" }, "container.tag": { "count": 1, "href": "/api/automation-hub/pulp/api/v3/content/container/tags/?repository_version=/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/" } } } } ``` ## 7. Read a specific signature Take the URL fron `container.signature` on previous request and do a GET on it GET http://localhost:5001/api/automation-hub/pulp/api/v3/content/container/signatures/?repository_version=/api/automation-hub/pulp/api/v3/repositories/container/container-push/fa5d7f9a-7e81-43bd-a471-e4038aea2abc/versions/4/ ```json { "count": 1, "next": null, "previous": null, "results": [ { "pulp_href": "/api/automation-hub/pulp/api/v3/content/container/signatures/cce0fbaf-e76f-4771-a331-a37f8122a6ec/", "pulp_created": "2022-08-10T18:58:03.597681Z", "name": "sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870@25cab602de2e8c302a06910aaabac717", "digest": "sha256:25cab602de2e8c302a06910aaabac71769f2c1626ed9275bc15f47c3efe90b13", "type": "atomic", "key_id": "15250E9EC0A62577", "timestamp": 1660157882, "creator": "atomic 5.21.1", "signed_manifest": "/api/automation-hub/pulp/api/v3/content/container/manifests/db6dbde4-2dd2-4712-8da9-d24dbed95b86/" } ] } ``` ## Extra information ### 1. Images synced from remotes For containers that are mirrored from a remote registry the process is almost the same, just the URL is different and there are extra parameters needed, more info on https://docs.pulpproject.org/pulp_container/workflows/sign-images.html#sign-images-that-were-mirrored-into-the-pulp-registry-from-a-remote-registry ### 2. Client side verification (podman/docker) Policies configuration for client side is described on https://docs.pulpproject.org/pulp_container/workflows/verify-images.html