Skip to content

Metadata Signing#

It is possible to sign Pulp's metadata so that users can verify the authenticity of an object. This is done by enabling the Signing Services feature. The steps to enable it are:

  • create a gpg key
  • create a Secret with a gpg key
  • create a Secret with the signing script(s)
  • configure Pulp CR

See pulpcore documentation for details on Content Signing: https://docs.pulpproject.org/pulpcore/workflows/signed-metadata.html#metadata-signing
See pulp_container documentation for details on Container Image Signing: https://docs.pulpproject.org/pulp_container/workflows/sign-images.html

Creating a gpg key#

  • create the key

    $ GPG_EMAIL=pulp@example.com
    $ cat >/tmp/gpg.txt <<EOF
    %echo Generating a basic OpenPGP key
    Key-Type: DSA
    Key-Length: 1024
    Subkey-Type: ECDSA
    Subkey-Curve: nistp256
    Name-Real: Collection Signing Service
    Name-Comment: with no passphrase
    Name-Email: $GPG_EMAIL
    Expire-Date: 0
    %no-ask-passphrase
    %no-protection
    # Do a commit here, so that we can later print "done" :-)
    %commit
    %echo done
    EOF
    
    $ gpg --batch --gen-key /tmp/gpg.txt
    

  • verify the list of available keyrings

    $ gpg --list-keys
    /var/lib/pulp/.gnupg/pubring.kbx
    --------------------------------
    pub   rsa4096 2022-12-14 [SC]
          66BBFE010CF70CC92826D9AB71684D7912B09BC1
    uid           [ultimate] Collection Signing Service (with no passphrase) <pulp@example.com>
    sub   rsa2048 2022-12-14 [E]
    

See the GnuPG official documentation for more information on how to generate a new keypair: https://www.gnupg.org/gph/en/manual/c14.html

Creating a Secret with the gpg key#

$ gpg --export-secret-keys -a pulp@example.com  > /tmp/gpg_private_key.gpg
$ kubectl create secret generic signing-secret --from-file=signing_service.gpg=/tmp/gpg_private_key.gpg

Creating a Secret with the signing scripts#

  • example of a collection signing script

    $ SIGNING_SCRIPT_PATH=/tmp
    $ COLLECTION_SIGNING_SCRIPT=collection_script.sh
    $ cat<<EOF> "$SIGNING_SCRIPT_PATH/$COLLECTION_SIGNING_SCRIPT"
    #!/usr/bin/env bash
    set -u
    FILE_PATH=\$1
    SIGNATURE_PATH="\$1.asc"
    
    ADMIN_ID="\$PULP_SIGNING_KEY_FINGERPRINT"
    PASSWORD="password"
    
    # Create a detached signature
    gpg --quiet --batch --pinentry-mode loopback --yes --passphrase \
       \$PASSWORD --homedir ~/.gnupg/ --detach-sign --default-key \$ADMIN_ID \
       --armor --output \$SIGNATURE_PATH \$FILE_PATH
    
    # Check the exit status
    STATUS=\$?
    if [ \$STATUS -eq 0 ]; then
       echo {\"file\": \"\$FILE_PATH\", \"signature\": \"\$SIGNATURE_PATH\"}
    else
       exit \$STATUS
    fi
    EOF
    

  • example of a container signing script

    $ SIGNING_SCRIPT_PATH=/tmp
    $ CONTAINER_SIGNING_SCRIPT=container_script.sh
    $ cat<<EOF> "$SIGNING_SCRIPT_PATH/$CONTAINER_SIGNING_SCRIPT"
    #!/usr/bin/env bash
    set -u
    
    MANIFEST_PATH=\$1
    IMAGE_REFERENCE="\$REFERENCE"
    SIGNATURE_PATH="\$SIG_PATH"
    
    skopeo standalone-sign \
          \$MANIFEST_PATH \
          \$IMAGE_REFERENCE \
          \$PULP_SIGNING_KEY_FINGERPRINT \
          --output \$SIGNATURE_PATH
    
    # Check the exit status
    STATUS=\$?
    if [ \$STATUS -eq 0 ]; then
      echo {\"signature_path\": \"\$SIGNATURE_PATH\"}
    else
      exit \$STATUS
    fi
    EOF
    

Warning

Make sure to set collection_script.sh and/or container_script.sh as key names (using different names would fail operator's execution)

$ kubectl create secret generic signing-scripts --from-file=collection_script.sh=/tmp/collection_script.sh --from-file=container_script.sh=/tmp/container_script.sh

Configuring Pulp CR#

  • configure Pulp CR with the Secrets created in the previous steps
    $ kubectl edit pulp
    ...
    spec:
      signing_secret: "signing-secret"
      signing_scripts: "signing-scripts"
    ...
    

After configuring Pulp CR the operator should create a new job to store the new signing services into the database:

$ kubectl get jobs
NAME                          COMPLETIONS   DURATION   AGE
pulp-signing-metadata-54mtp   1/1           15s        30s

$ kubectl logs job/pulp-signing-metadata-54mtp
...
Signing service 'collection-signing-service' has been successfully removed.
Successfully added signing service collection-signing-service for key 66BBFE010CF70CC92826D9AB71684D7912B09BC1.
Signing service 'container-signing-service' has been successfully removed.
Successfully added signing service container-signing-service for key 66BBFE010CF70CC92826D9AB71684D7912B09BC1.

double-checking if the signing services are stored in the database:

$ PULP_PWD=$(kubectl get secrets pulp-admin-password -ojsonpath='{.data.password}'|base64 -d)
$ kubectl exec deployment/pulp-api -- curl -suadmin:$PULP_PWD localhost:24817/pulp/api/v3/signing-services/|jq
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "pulp_href": "/pulp/api/v3/signing-services/018c0126-1f0c-7803-868d-1a1ee7210db1/",
      "pulp_created": "2023-11-22T11:45:25.042451Z",
      "name": "container-signing-service",
      "public_key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGJFjREBEACS1aBb6sqz1kfO/Ii...",
      "pubkey_fingerprint": "66BBFE010CF70CC92826D9AB71684D7912B09BC1",
      "script": "/var/lib/pulp/scripts/container_script.sh"
    },
    {
      "pulp_href": "/pulp/api/v3/signing-services/018c0126-1226-7d7d-abae-aebdc040743c/",
      "pulp_created": "2023-11-22T11:45:21.522412Z",
      "name": "collection-signing-service",
      "public_key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGJFjREBE...",
      "pubkey_fingerprint": "66BBFE010CF70CC92826D9AB71684D7912B09BC1",
      "script": "/var/lib/pulp/scripts/collection_script.sh"
    }
  ]
}

and it should also redeploy pulpcore pods and mount the gpg key:

$ kubectl exec deployment/pulp-api -- gpg -k
------------------------------
pub   rsa4096 2022-12-14 [SC]
      66BBFE010CF70CC92826D9AB71684D7912B09BC1
uid           [ultimate] Collection Signing Service (with no passphrase) <pulp@example.com>
sub   rsa2048 2022-12-14 [E]


$ kubectl exec deployment/pulp-worker -- gpg -k
------------------------------
pub   rsa4096 2022-12-14 [SC]
      66BBFE010CF70CC92826D9AB71684D7912B09BC1
uid           [ultimate] Collection Signing Service (with no passphrase) <pulp@example.com>
sub   rsa2048 2022-12-14 [E]