Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "delete obsolete signatures" feature #49

Closed
wants to merge 5 commits into from

Conversation

unennhexium
Copy link
Contributor

@unennhexium unennhexium commented Dec 30, 2024

I've added the ability to delete signatures corresponding to images that will be deleted due to lack of tags when using untagged_only: true.

The common process of signing an image results in the creation of an additional signature. When reusing the tag of the main image, the old image ends up tagless, but for the new signature a new tag will be generated (it depends not only on the content of the image, but also on some pseudo-random state). That is old signature persist its tag.

This way you end up with an orphan copy of the old signature. I've provided an option to remove it. with_sigs is false by default, so default action behavior remains unchanged. I've also added the test for this feature.

Look at the drawing to visualize it, this was captured during signed.yml test execution.

Drawing

I noticed you use the terms "container" and "image" interchangeably, so I followed suit.

@unennhexium unennhexium force-pushed the main branch 6 times, most recently from 2949c3b to bcb29ea Compare December 30, 2024 05:13
@unennhexium unennhexium changed the title Add "delete obsolete signed images" feature Add "delete obsolete signatures" feature Dec 30, 2024
@unennhexium unennhexium force-pushed the main branch 2 times, most recently from ecc6ae7 to e6d3fd1 Compare December 30, 2024 05:33
@Chizkiyahu
Copy link
Owner

@unennhexium

thanks for the PR
all the signatures stuff is new for me I never looks on that
so is will take me few days to understand this deeply

@unennhexium
Copy link
Contributor Author

unennhexium commented Dec 30, 2024

For me too. My workflow uses signing only because a long time ago I started using ready-made workflow from GitHub, which you can find in Actions -> New workflow -> Type "Publish Docker Container" in search box -> Chose first workflow.

Signing an image with Cosign seems functionally similar to signing commits using GPG. Cosign can sign an image on your behalf using a GITHUB_TOKEN (this requires id-token permission). It will ask GitHub for a one-time OIDC/JWT token for verification. The pulled image can then be verified using GitHub as the provider again using command:

ID='https://github.com/<user|org>/<repo>/.github/workflows/<signing-workflow>.yml@<git-ref>'

cosign verify ghcr.io/<user|org>/<image>:<tag>@<digest> \
    --certificate-identity=$ID \
    --certificate-oidc-issuer=https://token.actions.githubusercontent.com
Output
Verification for ghcr.io/<user|org>/<image>:<tag>@<digest> --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The code-signing certificate was verified using trusted certificate authority certificates
[ // Prettified
   {
      "critical":{
         "identity":{
            "docker-reference":"ghcr.io/<user|org>/<image>"
         },
         "image":{
            "docker-manifest-digest":"sha256:<digest>"
         },
         "type":"cosign container image signature"
      },
      "optional":{
         "1.3.6.1.4.1.57264.1.1":"https://token.actions.githubusercontent.com",
         "1.3.6.1.4.1.57264.1.2":"<workflow-trigger>",
         "1.3.6.1.4.1.57264.1.3":"<hash>",
         "1.3.6.1.4.1.57264.1.4":"<workflow-name>",
         "1.3.6.1.4.1.57264.1.5":"<user|org>/<image>",
         "1.3.6.1.4.1.57264.1.6":"<git-ref>",
         "Bundle":{
            "SignedEntryTimestamp":"<signed-timestamp>",
            "Payload":{
               "body":"<signature>",
               "integratedTime":1735510995,
               "logIndex":158147845,
               "logID":"<log-id>"
            }
         },
         "Issuer":"https://token.actions.githubusercontent.com",
         "Subject":"https://github.com/<user|org>/<repo>/.github/workflows/<signing-workflow>.yml@<git-ref>",
         "githubWorkflowName":"<workflow-name>",
         "githubWorkflowRef":"<git-ref>",
         "githubWorkflowRepository":"<user|org>/<repo>",
         "githubWorkflowSha":"<hash>",
         "githubWorkflowTrigger":"<workflow-trigger>"
      }
   }
]

It looks a little useless because each Docker image created on GitHub using docker meta and docker publish actions already has a "org.opencontainers.image.{source,revision}" labels indicating the repo and commit from which the image was built, which in turn can be extracted and checked using standard GPG tools:

IMG='ghcr.io/<user|org>/<image>:<tag>@<digest>'

docker pull $IMG

git clone `docker inspect \
    --format '{{ index .Config.Labels "org.opencontainers.image.source"}}' \
    $IMG`

curl https://github.com/<user|org>.gpg | gpg --import
# https://github.com/web-flow.gpg - for web-based commits

git verify-commit `docker inspect \
    --format '{{ index .Config.Labels "org.opencontainers.image.revision"}}' \
    $IMG`
Output
git verify-commit <hash>
gpg: Signature made Sat 28 Dec 2024 05:15:50 AM
gpg:                using <key-algo> key <key-id>
gpg: Good signature from "<name> <comment> <email>" [<trust-level>]

Perhaps in scenarios using private repos, PKI or private Sigstore instances Cosign brings convenience. In any case, this is a superficial view from me as user who does not understand the math and tech behind signing and cryptography. I'm also not experienced in security things. I just poked around a little through documentation and tried to extract information here in order to clear my understanding of how it works as command line tool.

@unennhexium
Copy link
Contributor Author

unennhexium commented Dec 30, 2024

In any case, if this is ever accepted, a notice must be added that the with-sigs option has been tested with a specific version of the cosign-installer action and cosign-release itself, because how you can see that I'm relying on the fact that the tag of the signature has specific relationship to the name of the image it links to. In particular:

sha256-<digest>.sig refer to image with sha256:<digest> name

@Chizkiyahu
Copy link
Owner

@unennhexium

this code merge in #51
the login problem solved in #50

@Chizkiyahu Chizkiyahu closed this Dec 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants