Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* Merge pull request from GHSA-vfp6-jrw2-99g9

* Add limit to number of sigs and attestations

Signed-off-by: AdamKorcz <[email protected]>

* Update pkg/cosign/fetch.go

Co-authored-by: Cody Soyland <[email protected]>
Signed-off-by: AdamKorcz <[email protected]>

* Update error message

Signed-off-by: Hayden B <[email protected]>

* fix compilation error

Signed-off-by: Hayden Blauzvern <[email protected]>

* Add e2e tests

Signed-off-by: Hayden Blauzvern <[email protected]>

---------

Signed-off-by: AdamKorcz <[email protected]>
Signed-off-by: Hayden B <[email protected]>
Signed-off-by: Hayden Blauzvern <[email protected]>
Co-authored-by: Cody Soyland <[email protected]>
Co-authored-by: Hayden B <[email protected]>

* fix missing import

Signed-off-by: cpanato <[email protected]>

* bump golang to 1.19.13

Signed-off-by: cpanato <[email protected]>

* update tests

Signed-off-by: cpanato <[email protected]>

* refactor validate release

Signed-off-by: cpanato <[email protected]>

* pin sigstore/scaffolding/actions/setup to v0.4.13

Signed-off-by: cpanato <[email protected]>

* update ko-local

Signed-off-by: cpanato <[email protected]>

---------

Signed-off-by: AdamKorcz <[email protected]>
Signed-off-by: Hayden B <[email protected]>
Signed-off-by: Hayden Blauzvern <[email protected]>
Signed-off-by: cpanato <[email protected]>
Co-authored-by: AdamKorcz <[email protected]>
Co-authored-by: Cody Soyland <[email protected]>
Co-authored-by: Hayden B <[email protected]>
  • Loading branch information
4 people authored Nov 15, 2023
1 parent d862088 commit ea92927
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/kind-verify-attestation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
make cosign
- name: Install cluster + sigstore
uses: sigstore/scaffolding/actions/setup@main
uses: sigstore/scaffolding/actions/setup@v0.4.13
with:
legacy-variables: "false"
k8s-version: ${{ matrix.k8s-version }}
Expand Down
119 changes: 84 additions & 35 deletions .github/workflows/validate-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,55 +20,104 @@ on:
branches:
- main
- release-*
- 1.0-fork
pull_request:

jobs:
check-signature:
runs-on: ubuntu-latest
container:
image: gcr.io/projectsigstore/cosign:v1.13.1@sha256:fd5b09be23ef1027e1bdd490ce78dcc65d2b15902e1f4ba8e04f3b4019cc1057

steps:
- name: Check Signature
run: |
cosign verify ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06
env:
TUF_ROOT: /tmp
COSIGN_EXPERIMENTAL: true

validate-release-job:
runs-on: ubuntu-latest
needs:
- check-signature

permissions:
actions: none
checks: none
contents: none
deployments: none
issues: none
packages: none
pull-requests: none
repository-projects: none
security-events: none
statuses: none
container:
image: ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06

env:
CROSS_BUILDER_IMAGE: ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec
COSIGN_IMAGE: gcr.io/projectsigstore/cosign:v1.13.1@sha256:fd5b09be23ef1027e1bdd490ce78dcc65d2b15902e1f4ba8e04f3b4019cc1057
permissions: {}

steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.0.2
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Check Signature
# Error: fatal: detected dubious ownership in repository at '/__w/cosign/cosign'
# To add an exception for this directory, call:
# git config --system --add safe.directory /__w/cosign/cosign
# Reason: Recent versions of git require the .git folder to be owned
# by the same user (see https://github.blog/2022-04-12-git-security-vulnerability-announced/).
# Related
# - https://github.com/actions/runner/issues/2033
# - https://github.com/actions/checkout/issues/1048
# - https://github.com/actions/runner-images/issues/6775
- run: git config --system --add safe.directory /__w/cosign/cosign

# Related to https://github.com/sigstore/cosign/issues/3149
- name: free up disk space for the release
run: |
docker run --rm \
-e COSIGN_EXPERIMENTAL=true \
-e TUF_ROOT=/tmp \
$COSIGN_IMAGE \
verify \
$CROSS_BUILDER_IMAGE
rm -rf /usr/share/dotnet/
rm -rf "$AGENT_TOOLSDIRECTORY"
rm -rf "/usr/local/share/boost"
rm -rf /opt/ghc
docker rmi $(docker image ls -aq) || true
swapoff /swapfile || true
rm -rf /swapfile /usr/share/dotnet /usr/local/lib/android /opt/ghc || true
apt purge aria2 ansible hhvm mono-devel azure-cli shellcheck rpm xorriso zsync \
clang-6.0 lldb-6.0 lld-6.0 clang-format-6.0 clang-8 lldb-8 lld-8 clang-format-8 \
clang-9 lldb-9 lld-9 clangd-9 clang-format-9 dotnet-sdk-3.0 dotnet-sdk-3.1=3.1.101-1 \
esl-erlang firefox g++-8 g++-9 gfortran-8 gfortran-9 google-chrome-stable \
google-cloud-sdk ghc-8.0.2 ghc-8.2.2 ghc-8.4.4 ghc-8.6.2 ghc-8.6.3 ghc-8.6.4 \
ghc-8.6.5 ghc-8.8.1 ghc-8.8.2 ghc-8.8.3 ghc-8.10.1 cabal-install-2.0 cabal-install-2.2 \
cabal-install-2.4 cabal-install-3.0 cabal-install-3.2 heroku imagemagick \
libmagickcore-dev libmagickwand-dev libmagic-dev ant ant-optional kubectl \
mercurial apt-transport-https mono-complete mysql-client libmysqlclient-dev \
mysql-server mssql-tools unixodbc-dev yarn bazel chrpath libssl-dev libxft-dev \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev php7.1 php7.1-bcmath \
php7.1-bz2 php7.1-cgi php7.1-cli php7.1-common php7.1-curl php7.1-dba php7.1-dev \
php7.1-enchant php7.1-fpm php7.1-gd php7.1-gmp php7.1-imap php7.1-interbase php7.1-intl \
php7.1-json php7.1-ldap php7.1-mbstring php7.1-mcrypt php7.1-mysql php7.1-odbc \
php7.1-opcache php7.1-pgsql php7.1-phpdbg php7.1-pspell php7.1-readline php7.1-recode \
php7.1-snmp php7.1-soap php7.1-sqlite3 php7.1-sybase php7.1-tidy php7.1-xml \
php7.1-xmlrpc php7.1-xsl php7.1-zip php7.2 php7.2-bcmath php7.2-bz2 php7.2-cgi \
php7.2-cli php7.2-common php7.2-curl php7.2-dba php7.2-dev php7.2-enchant php7.2-fpm \
php7.2-gd php7.2-gmp php7.2-imap php7.2-interbase php7.2-intl php7.2-json php7.2-ldap \
php7.2-mbstring php7.2-mysql php7.2-odbc php7.2-opcache php7.2-pgsql php7.2-phpdbg \
php7.2-pspell php7.2-readline php7.2-recode php7.2-snmp php7.2-soap php7.2-sqlite3 \
php7.2-sybase php7.2-tidy php7.2-xml php7.2-xmlrpc php7.2-xsl php7.2-zip php7.3 \
php7.3-bcmath php7.3-bz2 php7.3-cgi php7.3-cli php7.3-common php7.3-curl php7.3-dba \
php7.3-dev php7.3-enchant php7.3-fpm php7.3-gd php7.3-gmp php7.3-imap php7.3-interbase \
php7.3-intl php7.3-json php7.3-ldap php7.3-mbstring php7.3-mysql php7.3-odbc \
php7.3-opcache php7.3-pgsql php7.3-phpdbg php7.3-pspell php7.3-readline php7.3-recode \
php7.3-snmp php7.3-soap php7.3-sqlite3 php7.3-sybase php7.3-tidy php7.3-xml \
php7.3-xmlrpc php7.3-xsl php7.3-zip php7.4 php7.4-bcmath php7.4-bz2 php7.4-cgi \
php7.4-cli php7.4-common php7.4-curl php7.4-dba php7.4-dev php7.4-enchant php7.4-fpm \
php7.4-gd php7.4-gmp php7.4-imap php7.4-interbase php7.4-intl php7.4-json php7.4-ldap \
php7.4-mbstring php7.4-mysql php7.4-odbc php7.4-opcache php7.4-pgsql php7.4-phpdbg \
php7.4-pspell php7.4-readline php7.4-snmp php7.4-soap php7.4-sqlite3 php7.4-sybase \
php7.4-tidy php7.4-xml php7.4-xmlrpc php7.4-xsl php7.4-zip php-amqp php-apcu \
php-igbinary php-memcache php-memcached php-mongodb php-redis php-xdebug \
php-zmq snmp pollinate libpq-dev postgresql-client powershell ruby-full \
sphinxsearch subversion mongodb-org -yq >/dev/null 2>&1 || true
apt-get remove -y 'php.*' || true
apt-get autoremove -y >/dev/null 2>&1 || true
apt-get autoclean -y >/dev/null 2>&1 || true
- name: check disk space
run: df -h

- name: goreleaser snapshot
run: |
docker run --rm --privileged \
-e PROJECT_ID=honk-fake-project \
-e CI=$CI \
-e RUNTIME_IMAGE=gcr.io/distroless/static:debug-nonroot \
-v ${PWD}:/go/src/sigstore/cosign \
-v /var/run/docker.sock:/var/run/docker.sock \
-w /go/src/sigstore/cosign \
--entrypoint="" \
$CROSS_BUILDER_IMAGE \
make snapshot
run: make snapshot
env:
PROJECT_ID: honk-fake-project
RUNTIME_IMAGE: gcr.io/distroless/static:debug-nonroot

- name: check binaries
run: |
./dist/cosign-linux-amd64 version
./dist/sget-linux-amd64 version
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ ko-sget:
.PHONY: ko-local
ko-local:
$(create_kocache_path)
LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \
KO_DOCKER_REPO=ko.local LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \
KOCACHE=$(KOCACHE_PATH) ko build --base-import-paths \
--tags $(GIT_VERSION) --tags $(GIT_HASH) --local \
--tags $(GIT_VERSION) --tags $(GIT_HASH) \
$(ARTIFACT_HUB_LABELS) \
github.com/sigstore/cosign/cmd/cosign

Expand Down
10 changes: 10 additions & 0 deletions pkg/cosign/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"context"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"os"
"runtime"
Expand All @@ -29,6 +30,8 @@ import (
"golang.org/x/sync/errgroup"
)

const maxAllowedSigsOrAtts = 100

type SignedPayload struct {
Base64Signature string
Payload []byte
Expand Down Expand Up @@ -77,6 +80,9 @@ func FetchSignaturesForReference(ctx context.Context, ref name.Reference, opts .
if len(l) == 0 {
return nil, fmt.Errorf("no signatures associated with %s", ref)
}
if len(l) > maxAllowedSigsOrAtts {
return nil, fmt.Errorf("maximum number of signatures on an image is %d, found %d", maxAllowedSigsOrAtts, len(l))
}

signatures := make([]SignedPayload, len(l))
var g errgroup.Group
Expand Down Expand Up @@ -129,6 +135,10 @@ func FetchAttestationsForReference(ctx context.Context, ref name.Reference, opts
if len(l) == 0 {
return nil, fmt.Errorf("no attestations associated with %s", ref)
}
if len(l) > maxAllowedSigsOrAtts {
errMsg := fmt.Sprintf("maximum number of attestations on an image is %d, found %d", maxAllowedSigsOrAtts, len(l))
return nil, errors.New(errMsg)
}

attestations := make([]AttestationPayload, len(l))
var g errgroup.Group
Expand Down
6 changes: 3 additions & 3 deletions release/cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ steps:
- TUF_ROOT=/tmp
args:
- 'verify'
- 'ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec'
- 'ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06'

# maybe we can build our own image and use that to be more in a safe side
- name: ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec
- name: ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06
entrypoint: /bin/sh
dir: "go/src/sigstore/cosign"
env:
Expand All @@ -65,7 +65,7 @@ steps:
gcloud auth configure-docker \
&& make release
- name: ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec
- name: ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06
entrypoint: 'bash'
dir: "go/src/sigstore/cosign"
env:
Expand Down
109 changes: 109 additions & 0 deletions test/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,83 @@ func TestAttestationReplaceCreate(t *testing.T) {
}
}

func TestExcessiveAttestations(t *testing.T) {
// skipping tst it is falky and taking too long
t.Skip()
repo, stop := reg(t)
defer stop()
td := t.TempDir()

imgName := path.Join(repo, "cosign-attest-download-e2e")

_, _, cleanup := mkimage(t, imgName)
defer cleanup()

_, privKeyPath, _ := keypair(t, td)
ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}

ctx := context.Background()

slsaAttestation := `{ "buildType": "x", "builder": { "id": "2" }, "recipe": {} }`
slsaAttestationPath := filepath.Join(td, "attestation.slsa.json")
if err := os.WriteFile(slsaAttestationPath, []byte(slsaAttestation), 0600); err != nil {
t.Fatal(err)
}

vulnAttestation := `
{
"invocation": {
"parameters": null,
"uri": "invocation.example.com/cosign-testing",
"event_id": "",
"builder.id": ""
},
"scanner": {
"uri": "fakescanner.example.com/cosign-testing",
"version": "",
"db": {
"uri": "",
"version": ""
},
"result": null
},
"metadata": {
"scanStartedOn": "2022-04-12T00:00:00Z",
"scanFinishedOn": "2022-04-12T00:10:00Z"
}
}
`
ref, err := name.ParseReference(imgName)
if err != nil {
t.Fatal(err)
}
regOpts := options.RegistryOptions{}
ociremoteOpts, err := regOpts.ClientOpts(ctx)
if err != nil {
t.Fatal(err)
}

for i := 0; i < 102; i++ {
vulnAttestationPath := filepath.Join(td, fmt.Sprintf("attestation-%d.vuln.json", i))
if err := os.WriteFile(vulnAttestationPath, []byte(vulnAttestation), 0600); err != nil {
t.Fatal(err)
}

// Attest to create a vuln attestation
must(attest.AttestCmd(ctx, ko, options.RegistryOptions{}, imgName, "", "", false, vulnAttestationPath, false,
"vuln", false, 30*time.Second, false), t)
}

_, err = cosign.FetchAttestationsForReference(ctx, ref, ociremoteOpts...)
if err == nil {
t.Fatalf("Expected an error, but 'err' was 'nil'")
}
expectedError := "maximum number of attestations on an image is 100, found 102"
if err.Error() != expectedError {
t.Errorf("Exted the error to be: '%s' but it was '%s'", expectedError, err.Error())
}
}

func TestAttestationReplace(t *testing.T) {
repo, stop := reg(t)
defer stop()
Expand Down Expand Up @@ -523,6 +600,38 @@ func TestDuplicateSign(t *testing.T) {
}
}

func TestExcessiveSignatures(t *testing.T) {
repo, stop := reg(t)
defer stop()
td := t.TempDir()

imgName := path.Join(repo, "cosign-e2e")

_, _, cleanup := mkimage(t, imgName)
defer cleanup()

ctx := context.Background()

for i := 0; i < 102; i++ {
_, privKeyPath, _ := keypair(t, td)

// Sign the image
ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}
so := options.SignOptions{
Upload: true,
}
must(sign.SignCmd(ro, ko, so, []string{imgName}), t)
}
err := download.SignatureCmd(ctx, options.RegistryOptions{}, imgName)
if err == nil {
t.Fatal("Expected an error, but 'err' was 'nil'")
}
expectedErr := "maximum number of signatures on an image is 100, found 102"
if err.Error() != expectedErr {
t.Fatalf("Expected the error '%s', but got the error '%s'", expectedErr, err.Error())
}
}

func TestKeyURLVerify(t *testing.T) {
// TODO: re-enable once distroless images are being signed by the new client
t.Skip()
Expand Down

0 comments on commit ea92927

Please sign in to comment.