Skip to content

Commit

Permalink
cosign support
Browse files Browse the repository at this point in the history
  • Loading branch information
rohanmars committed Sep 15, 2024
1 parent a4746be commit 6448a08
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 33 deletions.
65 changes: 63 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ jobs:
- name: Run Test - Attestation Tagged
uses: ./
with:
tags: test
delete-tags: test
token: ${{ secrets.GITHUB_TOKEN }}
- name: Validate Test Results - Attestation Tagged
run:
Expand Down Expand Up @@ -414,10 +414,71 @@ jobs:
node citester/index.js --token ${{ secrets.GITHUB_TOKEN }} --directory
tests/attestation-untagged --mode validate

cosign-test:
name: Cosign Test
needs: github-attestation-tests
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: lower-repo
run: |
echo "repository=${GITHUB_REPOSITORY@L}" >> $GITHUB_OUTPUT
- name: Prime Test - Cosign Test
run:
node citester/index.js --token ${{ secrets.GITHUB_TOKEN }} --directory
tests/cosign --mode prime

- name: Build and push image
uses: docker/[email protected]
with:
context: tests/cosign
file: tests/cosign/Dockerfile.image
push: true
tags:
${{ env.REGISTRY }}/${{ steps.lower-repo.outputs.repository
}}:cosign

- name: Install Cosign
uses: sigstore/[email protected]

- name: Sign container image
run: |
cosign sign -y ${{ env.REGISTRY }}/${{ steps.lower-repo.outputs.repository }}:cosign
env:
TAGS: cosign
COSIGN_EXPERIMENTAL: false

- name: Run Test - Cosign
uses: ./
with:
delete-tags: cosign
token: ${{ secrets.GITHUB_TOKEN }}

- name: Validate Test Results - Cosign
run:
node citester/index.js --token ${{ secrets.GITHUB_TOKEN }} --directory
tests/cosign --mode validate

multi-package-cleanup:
name: Cleanup Multiple Packages
runs-on: ubuntu-latest
needs: github-attestation-tests
needs: cosign-test

steps:
- name: Checkout
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ It includes the following features:
- Untagging of multi-tagged images
- Multiple package execution
- Referrers/GitHub attestation support (OCIv1 tag approach)
- Sigstore cosign support
- Retry and throttle support for the GitHub API calls
- Validation mode to verify multi-architecture & referrers images

Expand Down Expand Up @@ -325,7 +326,7 @@ jobs:
with:
packages: myimage*,someotherimage
expand-packages: true
token: ${{ env.GHCR_PAT }}
token: ${{ secrets.GHCR_PAT }}
```

A regular expression can be used alternatively. This requires the `use-regex`
Expand All @@ -338,10 +339,10 @@ jobs:
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
packages: ^myimage[12]$
packages: '^myimage[12]$'
expand-packages: true
use-regex: true
token: ${{ env.GHCR_PAT }}
token: ${{ secrets.GHCR_PAT }}
```

## Sample Action Setups
Expand Down
56 changes: 43 additions & 13 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43390,13 +43390,25 @@ class CleanupTask {
*/
async loadDigestUsedByMap() {
this.digestUsedBy.clear();
// used if debug logging
const manfiests = new Map();
let stopWatch = new Date();
const digests = this.packageRepo.getDigests();
const disgestCount = digests.size;
let processed = 0;
core.startGroup(`[${this.targetPackage}] Loading Manifests`);
for (const digest of digests) {
const manifest = await this.registry.getManifestByDigest(digest);
if (this.config.logLevel >= LogLevel.INFO) {
manfiests.set(digest, manifest);
processed++;
if (this.config.logLevel === LogLevel.DEBUG) {
const encoded = JSON.stringify(manifest, null, 4);
core.info(`${digest}:${encoded}`);
}
else {
// if 15 seconds has passed output a status message
const now = new Date();
if (now.getMilliseconds() - stopWatch.getMilliseconds() >= 15000) {
stopWatch = new Date(); // reset the clock
core.info(`loaded ${processed} of ${disgestCount} manifests`);
}
}
// we only map multi-arch images
if (manifest.manifests) {
Expand All @@ -43413,14 +43425,8 @@ class CleanupTask {
}
}
}
if (this.config.logLevel === LogLevel.DEBUG) {
core.startGroup(`[${this.targetPackage}] Image manfiests`);
for (const [digest, manifest] of manfiests) {
const encoded = JSON.stringify(manifest, null, 4);
core.info(`${digest}:${encoded}`);
}
core.endGroup();
}
core.info('loaded all manifests');
core.endGroup();
}
/*
* Remove all multi architecture platform images from the filterSet including its
Expand Down Expand Up @@ -43451,6 +43457,16 @@ class CleanupTask {
}
}
}
// process any cosign
const cosignTag = digest.replace('sha256:', 'sha256-').concat('.sig');
if (this.tagsInUse.has(cosignTag) &&
!this.excludeTags.includes(cosignTag)) {
// remove the sig from the filter set
const cosignDigest = this.packageRepo.getDigestByTag(cosignTag);
if (cosignDigest) {
this.filterSet.delete(cosignDigest);
}
}
}
}
// validate manifests list packages
Expand Down Expand Up @@ -43586,6 +43602,20 @@ class CleanupTask {
await this.deleteImage(attestationPackage);
}
}
// process any cosign
const cosignTag = ghPackage.name
.replace('sha256:', 'sha256-')
.concat('.sig');
if (this.tagsInUse.has(cosignTag) &&
!this.excludeTags.includes(cosignTag)) {
// find the package
const cosignDigest = this.packageRepo.getDigestByTag(cosignTag);
if (cosignDigest) {
const cosignPackage = this.packageRepo.getPackageByDigest(cosignDigest);
// recursively delete it
await this.deleteImage(cosignPackage);
}
}
}
}
async deleteGhostImages() {
Expand Down Expand Up @@ -43990,7 +44020,7 @@ var createTokenAuth = function createTokenAuth2(token) {


/*
* Main program run function
* Main program entrypoint
*/
async function run() {
try {
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

61 changes: 48 additions & 13 deletions src/cleanup-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,25 @@ export class CleanupTask {
*/
async loadDigestUsedByMap(): Promise<void> {
this.digestUsedBy.clear()

// used if debug logging
const manfiests = new Map<string, any>()
let stopWatch = new Date()
const digests = this.packageRepo.getDigests()
const disgestCount = digests.size
let processed = 0

core.startGroup(`[${this.targetPackage}] Loading Manifests`)
for (const digest of digests) {
const manifest = await this.registry.getManifestByDigest(digest)
if (this.config.logLevel >= LogLevel.INFO) {
manfiests.set(digest, manifest)
processed++
if (this.config.logLevel === LogLevel.DEBUG) {
const encoded = JSON.stringify(manifest, null, 4)
core.info(`${digest}:${encoded}`)
} else {
// if 15 seconds has passed output a status message
const now = new Date()
if (now.getMilliseconds() - stopWatch.getMilliseconds() >= 15000) {
stopWatch = new Date() // reset the clock
core.info(`loaded ${processed} of ${disgestCount} manifests`)
}
}

// we only map multi-arch images
Expand All @@ -164,14 +175,8 @@ export class CleanupTask {
}
}
}
if (this.config.logLevel === LogLevel.DEBUG) {
core.startGroup(`[${this.targetPackage}] Image manfiests`)
for (const [digest, manifest] of manfiests) {
const encoded = JSON.stringify(manifest, null, 4)
core.info(`${digest}:${encoded}`)
}
core.endGroup()
}
core.info('loaded all manifests')
core.endGroup()
}

/*
Expand Down Expand Up @@ -206,6 +211,18 @@ export class CleanupTask {
}
}
}
// process any cosign
const cosignTag = digest.replace('sha256:', 'sha256-').concat('.sig')
if (
this.tagsInUse.has(cosignTag) &&
!this.excludeTags.includes(cosignTag)
) {
// remove the sig from the filter set
const cosignDigest = this.packageRepo.getDigestByTag(cosignTag)
if (cosignDigest) {
this.filterSet.delete(cosignDigest)
}
}
}
}

Expand Down Expand Up @@ -375,6 +392,24 @@ export class CleanupTask {
await this.deleteImage(attestationPackage)
}
}

// process any cosign
const cosignTag = ghPackage.name
.replace('sha256:', 'sha256-')
.concat('.sig')
if (
this.tagsInUse.has(cosignTag) &&
!this.excludeTags.includes(cosignTag)
) {
// find the package
const cosignDigest = this.packageRepo.getDigestByTag(cosignTag)
if (cosignDigest) {
const cosignPackage =
this.packageRepo.getPackageByDigest(cosignDigest)
// recursively delete it
await this.deleteImage(cosignPackage)
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CleanupTask } from './cleanup-task.js'
import { createTokenAuth } from '@octokit/auth-token'

/*
* Main program run function
* Main program entrypoint
*/
export async function run(): Promise<void> {
try {
Expand Down
5 changes: 5 additions & 0 deletions tests/cosign/Dockerfile.image
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM busybox:1.36.1-uclibc

ENV DUMMY=VALUE
USER user
HEALTHCHECK CMD ls
1 change: 1 addition & 0 deletions tests/cosign/expected-digests
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sha256:1a41828fc1a347d7061f7089d6f0c94e5a056a3c674714712a1481a4a33eb56f
1 change: 1 addition & 0 deletions tests/cosign/expected-tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dummy
Empty file added tests/cosign/prime
Empty file.

0 comments on commit 6448a08

Please sign in to comment.