Skip to content

Commit

Permalink
Feat/rsa keys (#59)
Browse files Browse the repository at this point in the history
* test: added rsa generation

This allows the test framework to generate RSA keys

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* chore: use another port for k3d registry

The port 5000 is used in mac for some other server.

* feat: new rsa E2E test

Additionally bumped dependencies & code to go 1.23

* feat: added RSA key support in verification process

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* chore: formatting

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* feat: new test case for RSA

Also moved port back to 5000

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* refactor: use port variable

To make the tests easier to maintain, a variable was introduced for the port used in the ephemeral private registry used.

* refactor: use constants for images

This makes the tests somewhat easier to maintain and read.

* chore: more resilient cleanup

The cleanup method can now be called always when a test is run using the framework, as it cleans up whatever is there and ignores the rest.

* fix: rsa keys now properly generated

The keys had to be also imported to the cosign format to be usable for signing containers. Additionally, this commit refactors the signing method to use the CLI directly and not the cobra command, which was kind of unintuitive.

An additional test, which doesn't run per default was added to test whether the sign method really works.

* chore: formatting

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* fix: signing and RSA public key fixes

Since the switch to the `sign` module, the signatures of the ephemeral images being used in tests were not uploaded to the repository.
This resulted in test failure, as the public key had no signature to verify.

Additionally, the errors with the RSA private key not being suited for image signing and verification are also solved in this commit.
The proper encoding algorithms are now used and the the correct values are returned. The imported public key and the generated one are now the same,
and the signing private key has the correct header now.

WIP.

* test: added signImage test for RSA

A simple test locke behind an env variable to test whether an RSA key can be
used to sign a container image. In the future, this test should be an autonomous integration test
and not be connected to the busybox image created during the E2E preparation

* chore: fixed E2E test

Housekeeping commit to refactor the tests so they use the new keypath
argument, which allows them more flexibility and opens up for a future
refactoring to simplify the test suite and allow to run the same test
suite for multiple input keys (ECDSA, RSA).

* chore: removed double @@

This was a typo

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* docs: explanation of dns flag in e2e tests [skip ci]

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* Refactor E2E test suite + add RSA tests (#60)

* refactor: own struct for keys

The tests have been refactored to use a dedicated struct for the private
and public keys, which contains the key itself and the path to it.

This will allow a bigger refactoring of the E2E tests, so that each test case can
be run independently of what type of key is used for signing & validation

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* refactor: use private key variable

Instead of hardcoding the path in all tests, the value is derived from the previously
unused private key variable returned. This way, the tests can now be refactored to run
by only passing the key creation function

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

* refactor: [WIP] framework wraps testing.T

The framework struct has been refactored to abstract the golang testing framework.
This allows the E2E test cases to be written without having to create a new framework for each test.
The framework functions now do not have to do a lot of micromanagement and cleanup; they just check
whether an error has happened and they return. This allows for new functions to be written without having
to think about whether to fail the test or not.

The cleanup function takes care of the final step; cleaning up everything and then deciding whether the test
failed or passed.

Additionally, a new type is introduced, which will be used to wrap the tests cases, so they can be
run used t.Run.

* refactor: use new testing schema

The test cases are now refactored to accept a signing function, so that
the same test can be run regardless of RSA/ECDSA key without having to
write too much duplicate code.

The new fuction type is used for the signing function and each test case
must now return the set of actions required for the use case to be
tested, wrapped in a func which returns testing.T, so it may be run by
the t.Run method.

* chore: added E2E variable

Added variable so that the additional E2E test is also executed. This
test must be refactored in a future commit/ removed, as it depends on an
image already being present on the machine running the test.

* test: added rsa tests cases

Each case tests for ECDSA keys is now also tested for RSA keys.

The tests were also accelerated by reducing the delay between checks
from 5s to 500m

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

---------

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>

---------

Signed-off-by: Bruno Bressi <bruno.bressi@telekom.de>
  • Loading branch information
puffitos authored Sep 20, 2024
1 parent 8ca3b49 commit af61ddd
Show file tree
Hide file tree
Showing 17 changed files with 1,121 additions and 765 deletions.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Makefile
*.key
*.pub
*.png
hack/
manifests/
chart/
README.md
6 changes: 3 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ on:
push:
branches:
- main
tags:
- '*'
tags:
- "*"

jobs:
build:
Expand All @@ -28,7 +28,7 @@ jobs:
- name: Install Cosign
uses: sigstore/cosign-installer@main
with:
cosign-release: 'v2.2.0'
cosign-release: "v2.4.0"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
Expand Down
24 changes: 11 additions & 13 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ linters-settings:
min-complexity: 15
gofmt:
rewrite-rules:
- pattern: 'interface{}'
replacement: 'any'
- pattern: "interface{}"
replacement: "any"
goimports:
local-prefixes: github.com/golangci/golangci-lint
gomnd:
Expand All @@ -35,15 +35,14 @@ linters-settings:
- condition
- return
ignored-numbers:
- '0'
- '1'
- '2'
- '3'
- "0"
- "1"
- "2"
- "3"
ignored-functions:
- strings.SplitN

govet:
check-shadowing: true
settings:
printf:
funcs:
Expand Down Expand Up @@ -72,7 +71,7 @@ linters:
- dogsled
- dupl
- errcheck
- exportloopref
- copyloopvar
- funlen
- gocheckcompilerdirectives
- gochecknoinits
Expand All @@ -81,7 +80,7 @@ linters:
- gocyclo
- gofmt
- goimports
- gomnd
- mnd
- goprintffuncname
- gosec
- gosimple
Expand All @@ -99,9 +98,8 @@ linters:
- unused
- whitespace

run:
timeout: 5m
skip-files:
issues:
exclude-files:
- .*_test\.go
skip-dirs:
exclude-dirs:
- test/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# build stage
FROM golang:1.21 AS build-env
FROM golang:1.23 AS build-env
WORKDIR /app
COPY . /app
RUN useradd -u 10001 webhook && \
Expand Down
43 changes: 24 additions & 19 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
PORT := 5000

#############
### TESTS ###
#############

.PHONY: test-e2e
test-e2e:
@echo "Running e2e tests..."
@go test -v -race -count 1 ./test/
@export COSIGN_E2E="42" && go test -v -race -count 1 ./test/

.PHONY: test-unit
test-unit:
Expand All @@ -17,9 +20,9 @@ test-unit:

e2e-cluster:
@echo "Creating registry..."
@k3d registry create registry.localhost --port 5000
@k3d registry create registry.localhost --port $(PORT)
@echo "Adding registry to cluster..."
@k3d cluster create cosign-tests --registry-use k3d-registry.localhost:5000
@uname -m | grep -q 'Darwin' && export K3D_FIX_DNS=0; k3d cluster create cosign-tests --registry-use k3d-registry.localhost:$(PORT)
@echo "Create test namespace..."
@kubectl create namespace test-cases

Expand All @@ -33,39 +36,41 @@ e2e-images:
@echo "Checking for cosign.key..."
@test -f cosign.key || (echo "cosign.key not found. Run 'make e2e-keys' to generate the pairs needed for the tests." && exit 1)
@echo "Building test image..."
@docker build -t k3d-registry.localhost:5000/cosignwebhook:dev .
@docker build -t k3d-registry.localhost:$(PORT)/cosignwebhook:dev .
@echo "Pushing test image..."
@docker push k3d-registry.localhost:5000/cosignwebhook:dev
@docker push k3d-registry.localhost:$(PORT)/cosignwebhook:dev
@echo "Signing test image..."
@export COSIGN_PASSWORD="" && \
cosign sign --tlog-upload=false --key cosign.key k3d-registry.localhost:5000/cosignwebhook:dev
cosign sign --tlog-upload=false --key cosign.key k3d-registry.localhost:$(PORT)/cosignwebhook:dev
@echo "Importing test image to cluster..."
@k3d image import k3d-registry.localhost:5000/cosignwebhook:dev --cluster cosign-tests
@k3d image import k3d-registry.localhost:$(PORT)/cosignwebhook:dev --cluster cosign-tests
@echo "Building busybox image..."
@docker pull busybox:latest
@echo "Tagging & pushing busybox images..."
@docker tag busybox:latest k3d-registry.localhost:5000/busybox:first
@docker tag busybox:latest k3d-registry.localhost:5000/busybox:second
@docker push k3d-registry.localhost:5000/busybox --all-tags
@docker tag busybox:latest k3d-registry.localhost:$(PORT)/busybox:first
@docker tag busybox:latest k3d-registry.localhost:$(PORT)/busybox:second
@docker push k3d-registry.localhost:$(PORT)/busybox --all-tags
@echo "Signing busybox images..."
@export COSIGN_PASSWORD="" && \
cosign sign --tlog-upload=false --key cosign.key k3d-registry.localhost:5000/busybox:first && \
cosign sign --tlog-upload=false --key second.key k3d-registry.localhost:5000/busybox:second
cosign sign --tlog-upload=false --key cosign.key k3d-registry.localhost:$(PORT)/busybox:first && \
cosign sign --tlog-upload=false --key cosign.key k3d-registry.localhost:$(PORT)/busybox:first && \
cosign sign --tlog-upload=false --key second.key k3d-registry.localhost:$(PORT)/busybox:second

e2e-deploy:
@echo "Deploying test image..."
@helm upgrade -i cosignwebhook chart -n cosignwebhook --create-namespace \
--set image.repository=k3d-registry.localhost:5000/cosignwebhook \
--set image.repository=k3d-registry.localhost:$(PORT)/cosignwebhook \
--set image.tag=dev \
--set-file cosign.scwebhook.key=cosign.pub \
--set logLevel=debug \
--wait --debug
--wait --debug --atomic

e2e-prep: e2e-cluster e2e-keys e2e-images e2e-deploy

e2e-cleanup:
@echo "Cleaning up..."
@helm uninstall cosignwebhook -n cosignwebhook
@k3d registry delete k3d-registry.localhost
@k3d cluster delete cosign-tests
@rm -f cosign.pub cosign.key second.pub second.key
@echo "Cleaning up test env..."
@k3d registry delete registry.localhost || echo "Deleting k3d registry failed. Continuing..."
@helm uninstall cosignwebhook -n cosignwebhook || echo "Uninstalling cosignwebhook helm release failed. Continuing..."
@k3d cluster delete cosign-tests || echo "Deleting cosign tests k3d cluster failed. Continuing..."
@rm -f cosign.pub cosign.key second.pub second.key || echo "Removing files failed. Continuing..."
@echo "Done."
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ make test-e2e
### E2E tests

The E2E tests require a running kubernetes cluster. Currently, the namespace and webhook are deployed via helper make
targets. To run the tests the following is required:
targets. To only run the tests, the following is required:

* docker
* cosign (v2)

To run the E2E tests, the following steps are required (in order):
To run the whole E2E tests, the following steps are required (in order):

* create a k3d local cluster for the tests and a local iamge registry (`make e2e-cluster`)
* signing keys are generated (`make e2e-keys`)
Expand All @@ -167,6 +167,8 @@ up the E2E setup, run `make e2e-cleanup`.
This will delete everything created by the E2E preparation. If you've already created the cluster and the keys, and
you're actively testing new code, you may run `make e2e-images e2e-deploy test-e2e` to test your changes.

In case you're running the tests on Apple devices, you may need to use deactivate the k3s dns fix (already implemented in the makefile). If your containers in the cluster don't start by skipping the fix, you may set `K3S_FIX_DNS` back to `1` in the `e2e-cluster` target.

## Local build

```bash
Expand Down
18 changes: 9 additions & 9 deletions chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,17 @@ affinity: {}
cosign:
image:
repository: ghcr.io/sigstore/cosign/cosign
tag: v2.0.0
tag: v2.4.0
pullPolicy: IfNotPresent
sccosign:
key: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhyQCx0E9wQWSFI9ULGwy3BuRklnt
IqozONbbdbqz11hlRJy9c7SG+hdcFl9jE9uE/dwtuwU2MqU9T/cN0YkWww==
-----END PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhyQCx0E9wQWSFI9ULGwy3BuRklnt
IqozONbbdbqz11hlRJy9c7SG+hdcFl9jE9uE/dwtuwU2MqU9T/cN0YkWww==
-----END PUBLIC KEY-----
scwebhook:
key: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENDN3HpXY2weMYRuuJbZnNczrOyns
ZvVnR15G9EILCH8+elXkYy+4U70mR++XIL0iD8NhZ3kxfpFjxyHlnG5Snw==
-----END PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENDN3HpXY2weMYRuuJbZnNczrOyns
ZvVnR15G9EILCH8+elXkYy+4U70mR++XIL0iD8NhZ3kxfpFjxyHlnG5Snw==
-----END PUBLIC KEY-----
Loading

0 comments on commit af61ddd

Please sign in to comment.