# 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