Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions pipelines/test/tw/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This directory contains test pipelines for validating Wolfi packages. Use this i
| `emptypackage` | Validate empty packages | none |
| `gem-check` | Verify Ruby gems load correctly | none |
| `gem-installed` | Verify gem is installed and has content | none |
| `gen-tls-cert` | Generate a self-signed TLS cert for test setup | `cn` |
| `header-check` | Verify C/C++ headers compile | none |
| `help-check` | Verify binaries respond to --help | `bins` |
| `ldd-check` | Check for missing shared libraries | none |
Expand Down Expand Up @@ -321,6 +322,31 @@ Validates systemd service/unit files for proper formatting and best practices.

---

## Test Setup Helpers

Pipelines that fabricate test fixtures (not validators — they never assert on
package contents).

### `gen-tls-cert`
Generates a self-signed RSA X.509 certificate and private key on disk. Use it
to replace inline `openssl req -x509 ...` boilerplate in `test/daemon-check-output`
`setup:` blocks (webhook serving certs, dummy TLS for exporters, etc.).

**When to use:** Whenever a test needs a throwaway cert/key on disk before the
daemon under test starts.

**Inputs:**
- `cn` (required) - Subject Common Name
- `san` (optional) - subjectAltName value, e.g. `DNS:foo.svc,IP:127.0.0.1`
- `key-out` (optional, default: `/tmp/tls.key`) - Private key output path
- `cert-out` (optional, default: `/tmp/tls.crt`) - Certificate output path
- `days` (optional, default: `7`) - Validity in days (these are throwaway test certs)
- `key-bits` (optional, default: `2048`) - RSA key size

**Dependencies:** openssl

---

## Usage Examples

### Basic package type validation
Expand Down
110 changes: 110 additions & 0 deletions pipelines/test/tw/gen-tls-cert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: TLS test certificate generator

description: |
Generates a self-signed RSA X.509 certificate and private key suitable for
test setups (e.g. webhook/admission-controller serving certs in
`test/daemon-check-output` blocks). This is a setup helper, not a validator
— it never fails the test on content; it only fails if openssl cannot
produce the requested key/cert.

needs:
packages:
- openssl

inputs:
cn:
description: |
Subject Common Name to embed in the certificate.
Example: "webhook.azure-workload-identity-test.svc"
required: true
san:
description: |
Optional subjectAltName extension value, passed verbatim to
`openssl req -addext "subjectAltName=..."`.
Example: "DNS:webhook.svc,DNS:webhook.svc.cluster.local,IP:127.0.0.1"
If empty, no SAN extension is added.
required: false
default: ""
key-out:
description: |
Output path for the generated private key (PEM).
Parent directories are created if missing.
required: false
default: "/tmp/tls.key"
cert-out:
description: |
Output path for the generated certificate (PEM).
Parent directories are created if missing.
required: false
default: "/tmp/tls.crt"
days:
description: |
Certificate validity in days. Defaults to 7 because this pipeline is
only for throwaway test certs — override if your test legitimately
needs a longer-lived cert (e.g. clock-skew exercises).
required: false
default: "7"
key-bits:
description: |
RSA key size in bits.
required: false
default: "2048"

# USAGE EXAMPLES:
#
# Minimal serving cert at the default /tmp/tls.{key,crt} paths:
# - uses: test/tw/gen-tls-cert
# with:
# cn: webhook.svc
#
# Cert with SAN and custom output paths:
# - uses: test/tw/gen-tls-cert
# with:
# cn: actions-runner-controller-webhook-service.default.svc
# san: "DNS:actions-runner-controller-webhook-service.default.svc"
# key-out: /tmp/k8s-webhook-server/serving-certs/tls.key
# cert-out: /tmp/k8s-webhook-server/serving-certs/tls.crt
#
pipeline:
- name: "generate self-signed TLS certificate"
runs: |
set -e

cn="${{inputs.cn}}"
san="${{inputs.san}}"
key_out="${{inputs.key-out}}"
cert_out="${{inputs.cert-out}}"
days="${{inputs.days}}"
key_bits="${{inputs.key-bits}}"

if [ -z "${cn}" ] ; then
echo "FAIL: 'cn' input is required" >&2
exit 1
fi

mkdir -p "$(dirname "${key_out}")" "$(dirname "${cert_out}")"

addext_args=""
if [ -n "${san}" ] ; then
addext_args="-addext subjectAltName=${san}"
fi

# shellcheck disable=SC2086 # we want addext_args to split.
openssl req -x509 \
-newkey "rsa:${key_bits}" \
-nodes \
-days "${days}" \
-keyout "${key_out}" \
-out "${cert_out}" \
-subj "/CN=${cn}" \
${addext_args}

# Sanity check: the cert must be parseable and carry the requested CN.
subject=$(openssl x509 -in "${cert_out}" -noout -subject)
echo "${subject}"
if ! echo "${subject}" | grep -qF "CN=${cn}" ; then
echo "FAIL: generated cert subject [${subject}] does not contain CN=${cn}" >&2
exit 1
fi

echo "PASS: TLS test cert generated at ${cert_out} (key: ${key_out})"
102 changes: 102 additions & 0 deletions tests/manual/gen-tls-cert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package:
name: gen-tls-cert-test
version: "0.0.0"
epoch: 0
description: Manual tests for the test/tw/gen-tls-cert pipeline

environment:
contents:
packages:
- busybox
- wolfi-base

pipeline:
- runs: |
echo "Manual tests for gen-tls-cert pipeline"

subpackages:
# Positive case 1: minimal invocation, default paths.
- name: gen-tls-cert-test-minimal
description: "Positive: cn only, default /tmp/tls.{key,crt} paths"
pipeline:
- runs: |
mkdir -p ${{targets.contextdir}}/usr/share/doc/${{context.name}}
echo "placeholder" > ${{targets.contextdir}}/usr/share/doc/${{context.name}}/README
test:
environment:
contents:
packages:
- openssl
pipeline:
- uses: test/tw/gen-tls-cert
with:
cn: test.example.com
- name: Verify default key and cert exist and match
runs: |
set -e
test -s /tmp/tls.key
test -s /tmp/tls.crt
openssl x509 -in /tmp/tls.crt -noout -subject | grep -qF "CN=test.example.com"
# Ensure the cert and key actually correspond.
cert_mod=$(openssl x509 -noout -modulus -in /tmp/tls.crt | openssl md5)
key_mod=$(openssl rsa -noout -modulus -in /tmp/tls.key | openssl md5)
[ "${cert_mod}" = "${key_mod}" ]
echo "PASS: minimal gen-tls-cert produced a usable key+cert pair"

# Positive case 2: SAN, custom output paths, non-default validity.
- name: gen-tls-cert-test-san
description: "Positive: SAN extension, custom paths, days override"
pipeline:
- runs: |
mkdir -p ${{targets.contextdir}}/usr/share/doc/${{context.name}}
echo "placeholder" > ${{targets.contextdir}}/usr/share/doc/${{context.name}}/README
test:
environment:
contents:
packages:
- openssl
pipeline:
- uses: test/tw/gen-tls-cert
with:
cn: webhook.svc
san: "DNS:webhook.svc,DNS:webhook.svc.cluster.local"
key-out: /tmp/serving/tls.key
cert-out: /tmp/serving/tls.crt
days: "30"
- name: Verify SAN and custom paths
runs: |
set -e
test -s /tmp/serving/tls.key
test -s /tmp/serving/tls.crt
text=$(openssl x509 -in /tmp/serving/tls.crt -noout -text)
echo "${text}" | grep -qF "CN=webhook.svc"
echo "${text}" | grep -qF "DNS:webhook.svc"
echo "${text}" | grep -qF "DNS:webhook.svc.cluster.local"
echo "PASS: gen-tls-cert wrote SAN cert at custom path"

# Positive case 3: custom key size.
- name: gen-tls-cert-test-4096
description: "Positive: non-default key-bits=4096"
pipeline:
- runs: |
mkdir -p ${{targets.contextdir}}/usr/share/doc/${{context.name}}
echo "placeholder" > ${{targets.contextdir}}/usr/share/doc/${{context.name}}/README
test:
environment:
contents:
packages:
- openssl
pipeline:
- uses: test/tw/gen-tls-cert
with:
cn: bigkey.example.com
key-bits: "4096"
- name: Verify key size honors key-bits input
runs: |
set -e
# `openssl pkey -text` prints something like
# "Private-Key: (4096 bit, 2 primes)" on OpenSSL 3,
# "Private-Key: (4096 bit)" on OpenSSL 1.1.
# Grepping for the literal "4096 bit" covers both.
openssl pkey -in /tmp/tls.key -noout -text | grep -q "4096 bit"
echo "PASS: key-bits=4096 produced a 4096-bit key"