Skip to content

Commit 558b3a1

Browse files
authored
Merge pull request #1610 from lcarva/EC-334
Add acceptance tests to cover param for v-e-c Task
2 parents d5e039a + 0575b92 commit 558b3a1

5 files changed

Lines changed: 272 additions & 23 deletions

File tree

acceptance/kubernetes/kind/kubernetes.go

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -244,20 +244,20 @@ func (k *kindCluster) CreateNamespace(ctx context.Context) (context.Context, err
244244
return ctx, applyConfiguration(ctx, k, yaml)
245245
}
246246

247-
// stringParam generates a Tekton Parameter optionally expanding the
248-
// `${NAMESPACE}` and `${POLICY_NAME}` variables
249-
func stringParam(name, value string, t *testState) pipeline.Param {
250-
v := os.Expand(value, func(variable string) string {
251-
switch variable {
252-
case "NAMESPACE":
253-
return t.namespace
254-
case "POLICY_NAME":
255-
return t.policy
256-
case "REGISTRY":
257-
return t.registry
258-
}
247+
// stringParam generates a Tekton Parameter optionally expanding certain variables
248+
func stringParam(ctx context.Context, name, value string, t *testState) pipeline.Param {
249+
vars := map[string]string{
250+
"NAMESPACE": t.namespace,
251+
"POLICY_NAME": t.policy,
252+
"REGISTRY": t.registry,
253+
}
254+
publicKeys := crypto.PublicKeysFrom(ctx)
255+
for name, key := range publicKeys {
256+
vars[fmt.Sprintf("%s_PUBLIC_KEY", name)] = key
257+
}
259258

260-
return ""
259+
v := os.Expand(value, func(variable string) string {
260+
return vars[variable]
261261
})
262262

263263
return pipeline.Param{
@@ -281,7 +281,7 @@ func (k *kindCluster) RunTask(ctx context.Context, version, name, workspace stri
281281

282282
tknParams := make([]pipeline.Param, 0, len(params))
283283
for n, v := range params {
284-
tknParams = append(tknParams, stringParam(n, v, t))
284+
tknParams = append(tknParams, stringParam(ctx, n, v, t))
285285
}
286286

287287
timeout, err := time.ParseDuration("10m")
@@ -309,9 +309,9 @@ func (k *kindCluster) RunTask(ctx context.Context, version, name, workspace stri
309309
ResolverRef: pipeline.ResolverRef{
310310
Resolver: "bundles",
311311
Params: []pipeline.Param{
312-
stringParam("bundle", fmt.Sprintf("registry.image-registry.svc.cluster.local:%d/ec-task-bundle:%s", k.registryPort, version), t),
313-
stringParam("name", name, t),
314-
stringParam("kind", "task", t),
312+
stringParam(ctx, "bundle", fmt.Sprintf("registry.image-registry.svc.cluster.local:%d/ec-task-bundle:%s", k.registryPort, version), t),
313+
stringParam(ctx, "name", name, t),
314+
stringParam(ctx, "kind", "task", t),
315315
},
316316
},
317317
},
@@ -400,10 +400,16 @@ func (k *kindCluster) TaskInfo(ctx context.Context) (*types.TaskInfo, error) {
400400
return nil, err
401401
}
402402

403+
envVars, err := k.envVars(ctx, t.namespace, tr.Status.PodName, s.Container)
404+
if err != nil {
405+
return nil, err
406+
}
407+
403408
info.Steps = append(info.Steps, types.Step{
404-
Name: s.Name,
405-
Status: s.Terminated.Reason,
406-
Logs: logs,
409+
Name: s.Name,
410+
Status: s.Terminated.Reason,
411+
Logs: logs,
412+
EnvVars: envVars,
407413
})
408414
}
409415

@@ -437,3 +443,22 @@ func (k *kindCluster) logs(ctx context.Context, namespace, pod, container string
437443

438444
return string(bytes), nil
439445
}
446+
447+
func (k *kindCluster) envVars(ctx context.Context, namespace, podName, containerName string) (map[string]string, error) {
448+
pod, err := k.client.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{})
449+
if err != nil {
450+
return nil, err
451+
}
452+
453+
for _, container := range pod.Spec.Containers {
454+
if container.Name != containerName {
455+
continue
456+
}
457+
envVars := make(map[string]string)
458+
for _, env := range container.Env {
459+
envVars[env.Name] = env.Value
460+
}
461+
return envVars, nil
462+
}
463+
return nil, fmt.Errorf("could not find %q container in %q pod", containerName, podName)
464+
}

acceptance/kubernetes/kubernetes.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,59 @@ func taskResultsShouldMatchTheSnapshot(ctx context.Context) error {
381381
return snaps.MatchSnapshot(ctx, "results", string(j), nil)
382382
}
383383

384+
func taskLogsShouldContain(ctx context.Context, stepName, needle string) error {
385+
c := testenv.FetchState[ClusterState](ctx)
386+
387+
if err := mustBeUp(ctx, *c); err != nil {
388+
return err
389+
}
390+
391+
info, err := c.cluster.TaskInfo(ctx)
392+
if err != nil {
393+
return err
394+
}
395+
396+
var found bool
397+
for _, step := range info.Steps {
398+
if step.Name == stepName {
399+
if strings.Contains(step.Logs, needle) {
400+
found = true
401+
}
402+
}
403+
}
404+
405+
if !found {
406+
return fmt.Errorf("not able to find %q in the %q step logs", needle, stepName)
407+
}
408+
409+
return nil
410+
}
411+
412+
func stepEnvVarShouldBe(ctx context.Context, stepName, envName, want string) error {
413+
c := testenv.FetchState[ClusterState](ctx)
414+
415+
if err := mustBeUp(ctx, *c); err != nil {
416+
return err
417+
}
418+
419+
info, err := c.cluster.TaskInfo(ctx)
420+
if err != nil {
421+
return err
422+
}
423+
424+
for _, step := range info.Steps {
425+
if step.Name != stepName {
426+
continue
427+
}
428+
got := step.EnvVars[envName]
429+
if got != want {
430+
return fmt.Errorf("unexpected value for the %q env var in the %q step: got %q, want %q", envName, step.Name, got, want)
431+
}
432+
return nil
433+
}
434+
return fmt.Errorf("step %q not found when looking for the %q env var", stepName, envName)
435+
}
436+
384437
// AddStepsTo adds cluster-related steps to the context
385438
func AddStepsTo(sc *godog.ScenarioContext) {
386439
sc.Step(`^a stub cluster running$`, startAndSetupState(stub.Start))
@@ -395,6 +448,8 @@ func AddStepsTo(sc *godog.ScenarioContext) {
395448
sc.Step(`^an Snapshot named "([^"]*)" with specification$`, createNamedSnapshot)
396449
sc.Step(`^an Snapshot named "([^"]*)" with (\d+) components signed with "([^"]*)" key`, createNamedSnapshotWithManyComponents)
397450
sc.Step(`^the task logs for step "([^"]*)" should match the snapshot$`, taskLogsShouldMatchTheSnapshot)
451+
sc.Step(`^the task logs for step "([^"]*)" should contain "([^"]*)"$`, taskLogsShouldContain)
452+
sc.Step(`^the task env var for step "([^"]*)" named "([^"]*)" should be set to "([^"]*)"$`, stepEnvVarShouldBe)
398453
sc.Step(`^the task results should match the snapshot$`, taskResultsShouldMatchTheSnapshot)
399454
sc.Step(`^policy configuration named "([^"]*)" with (\d+) policy sources from "([^"]*)"$`, createNamedPolicyWithManySources)
400455
// stop usage of the cluster once a test is done, godog will call this

acceptance/kubernetes/types/types.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ type TaskInfo struct {
4444
}
4545

4646
type Step struct {
47-
Name string
48-
Status string
49-
Logs string
47+
Name string
48+
Status string
49+
Logs string
50+
EnvVars map[string]string
5051
}

features/__snapshots__/task_validate_image.snap

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,3 +1261,95 @@ true
12611261
"effective-time": "${TIMESTAMP}"
12621262
}
12631263
---
1264+
1265+
[PUBLIC_KEY param overwrites key from policy:report - 1]
1266+
components:
1267+
- attestations:
1268+
- predicateBuildType: https://tekton.dev/attestations/chains/pipelinerun@v2
1269+
predicateType: https://slsa.dev/provenance/v0.2
1270+
signatures:
1271+
- keyid: ""
1272+
sig: ${ATTESTATION_SIGNATURE_acceptance/public-key-param}
1273+
type: https://in-toto.io/Statement/v0.1
1274+
containerImage: ${REGISTRY}/acceptance/public-key-param@sha256:${REGISTRY_acceptance/public-key-param:latest_DIGEST}
1275+
name: ""
1276+
signatures:
1277+
- keyid: ""
1278+
sig: ${IMAGE_SIGNATURE_acceptance/public-key-param}
1279+
source: {}
1280+
success: true
1281+
successes:
1282+
- metadata:
1283+
code: builtin.attestation.signature_check
1284+
description: The attestation signature matches available signing materials.
1285+
title: Attestation signature check passed
1286+
msg: Pass
1287+
- metadata:
1288+
code: builtin.attestation.syntax_check
1289+
description: The attestation has correct syntax.
1290+
title: Attestation syntax check passed
1291+
msg: Pass
1292+
- metadata:
1293+
code: builtin.image.signature_check
1294+
description: The image signature matches available signing materials.
1295+
title: Image signature check passed
1296+
msg: Pass
1297+
ec-version: ${EC_VERSION}
1298+
effective-time: "${TIMESTAMP}"
1299+
key: |
1300+
${__known_PUBLIC_KEY}
1301+
policy:
1302+
publicKey: |
1303+
${____known_PUBLIC_KEY}
1304+
success: true
1305+
1306+
---
1307+
1308+
[PUBLIC_KEY param overwrites key from policy:results - 1]
1309+
{
1310+
"TEST_OUTPUT": "{\"timestamp\":\"${TIMESTAMP}\",\"namespace\":\"\",\"successes\":3,\"failures\":0,\"warnings\":0,\"result\":\"SUCCESS\"}\n"
1311+
}
1312+
---
1313+
1314+
[Titles and descriptions can be excluded:report - 1]
1315+
components:
1316+
- attestations:
1317+
- predicateBuildType: https://tekton.dev/attestations/chains/pipelinerun@v2
1318+
predicateType: https://slsa.dev/provenance/v0.2
1319+
signatures:
1320+
- keyid: ""
1321+
sig: ${ATTESTATION_SIGNATURE_acceptance/info}
1322+
type: https://in-toto.io/Statement/v0.1
1323+
containerImage: ${REGISTRY}/acceptance/info@sha256:${REGISTRY_acceptance/info:latest_DIGEST}
1324+
name: ""
1325+
signatures:
1326+
- keyid: ""
1327+
sig: ${IMAGE_SIGNATURE_acceptance/info}
1328+
source: {}
1329+
success: true
1330+
successes:
1331+
- metadata:
1332+
code: builtin.attestation.signature_check
1333+
msg: Pass
1334+
- metadata:
1335+
code: builtin.attestation.syntax_check
1336+
msg: Pass
1337+
- metadata:
1338+
code: builtin.image.signature_check
1339+
msg: Pass
1340+
ec-version: ${EC_VERSION}
1341+
effective-time: "${TIMESTAMP}"
1342+
key: |
1343+
${__known_PUBLIC_KEY}
1344+
policy:
1345+
publicKey: |
1346+
${____known_PUBLIC_KEY}
1347+
success: true
1348+
1349+
---
1350+
1351+
[Titles and descriptions can be excluded:results - 1]
1352+
{
1353+
"TEST_OUTPUT": "{\"timestamp\":\"${TIMESTAMP}\",\"namespace\":\"\",\"successes\":3,\"failures\":0,\"warnings\":0,\"result\":\"SUCCESS\"}\n"
1354+
}
1355+
---

features/task_validate_image.feature

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Feature: Verify Enterprise Contract Tekton Tasks
44
Background:
55
Given a cluster running
66
Given stub tuf running
7+
Given stub git daemon running
78

89
Scenario: Golden container image
910
Given a working namespace
@@ -259,3 +260,78 @@ Feature: Verify Enterprise Contract Tekton Tasks
259260
And the task logs for step "assert" should match the snapshot
260261
And the task logs for step "report-json" should match the snapshot
261262
And the task results should match the snapshot
263+
264+
Scenario: Titles and descriptions can be excluded
265+
Given a working namespace
266+
And a key pair named "known"
267+
And an image named "acceptance/info"
268+
And a valid image signature of "acceptance/info" image signed by the "known" key
269+
And a valid attestation of "acceptance/info" signed by the "known" key
270+
And a cluster policy with content:
271+
```
272+
{"publicKey": ${known_PUBLIC_KEY}}
273+
```
274+
When version 0.1 of the task named "verify-enterprise-contract" is run with parameters:
275+
| IMAGES | {"components": [{"containerImage": "${REGISTRY}/acceptance/info"}]} |
276+
| POLICY_CONFIGURATION | ${NAMESPACE}/${POLICY_NAME} |
277+
| IGNORE_REKOR | true |
278+
| INFO | false |
279+
Then the task should succeed
280+
And the task logs for step "report" should match the snapshot
281+
And the task results should match the snapshot
282+
283+
Scenario: Effective-time is honored
284+
Given a working namespace
285+
And a key pair named "known"
286+
And an image named "acceptance/effective-time"
287+
And a valid image signature of "acceptance/effective-time" image signed by the "known" key
288+
And a valid attestation of "acceptance/effective-time" signed by the "known" key
289+
And a cluster policy with content:
290+
```
291+
{"publicKey": ${known_PUBLIC_KEY}}
292+
```
293+
When version 0.1 of the task named "verify-enterprise-contract" is run with parameters:
294+
| IMAGES | {"components": [{"containerImage": "${REGISTRY}/acceptance/effective-time"}]} |
295+
| POLICY_CONFIGURATION | ${NAMESPACE}/${POLICY_NAME} |
296+
| IGNORE_REKOR | true |
297+
| EFFECTIVE_TIME | 2020-01-01T00:00:00Z |
298+
Then the task should succeed
299+
And the task logs for step "validate" should contain "Using provided effective time 2020-01-01T00:00:00Z"
300+
301+
Scenario: SSL_CERT_DIR environment variable is customized
302+
Given a working namespace
303+
And a key pair named "known"
304+
And an image named "acceptance/ssl-cert-dir"
305+
And a valid image signature of "acceptance/ssl-cert-dir" image signed by the "known" key
306+
And a valid attestation of "acceptance/ssl-cert-dir" signed by the "known" key
307+
And a cluster policy with content:
308+
```
309+
{"publicKey": ${known_PUBLIC_KEY}}
310+
```
311+
When version 0.1 of the task named "verify-enterprise-contract" is run with parameters:
312+
| IMAGES | {"components": [{"containerImage": "${REGISTRY}/acceptance/ssl-cert-dir"}]} |
313+
| POLICY_CONFIGURATION | ${NAMESPACE}/${POLICY_NAME} |
314+
| IGNORE_REKOR | true |
315+
| SSL_CERT_DIR | /spam/certs |
316+
Then the task should succeed
317+
And the task env var for step "validate" named "SSL_CERT_DIR" should be set to "/tekton-custom-certs:/etc/ssl/certs:/etc/pki/tls/certs:/system/etc/security/cacerts:/spam/certs"
318+
319+
Scenario: PUBLIC_KEY param overwrites key from policy
320+
Given a working namespace
321+
And a key pair named "known"
322+
And an image named "acceptance/public-key-param"
323+
And a valid image signature of "acceptance/public-key-param" image signed by the "known" key
324+
And a valid attestation of "acceptance/public-key-param" signed by the "known" key
325+
And a valid attestation of "acceptance/public-key-param" signed by the "known" key
326+
And a cluster policy with content:
327+
```
328+
{"publicKey": "ignored"}
329+
```
330+
When version 0.1 of the task named "verify-enterprise-contract" is run with parameters:
331+
| IMAGES | {"components": [{"containerImage": "${REGISTRY}/acceptance/public-key-param"}]} |
332+
| POLICY_CONFIGURATION | ${NAMESPACE}/${POLICY_NAME} |
333+
| PUBLIC_KEY | ${known_PUBLIC_KEY} |
334+
| IGNORE_REKOR | true |
335+
Then the task should succeed
336+
And the task logs for step "report" should match the snapshot
337+
And the task results should match the snapshot

0 commit comments

Comments
 (0)