This is the last part of TAP blog post and I am sure that you have enjoyed reading the first 6 parts and learned something new. Feel free to comment on the post to provide your feedback and also let me know if you have any other question, will try helping you.
In this blog post, I will talk about adding testing and security components in the supply chain. So far, we have been looking at just the deployment part and pretty much TBS was doing the work but now we will look at Tekton, Grype packages too.
Before we start working on the practical part, Let’s understand the different supply chain profiles available with TAP as of today. “Honestly, I don’t know how to have our own custom profile, but i will work on it and let you know later.”
Out of the Box Basic Supply Chain

When we installed TAP with Full profile, Basic profile was installed automatically and that you can find in tap-values.yaml file too. Look for the below section.

As you can see, In the basic supply chain, there are two steps before application is deployed. We have been dealing with those so far.
Out of the Box with Testing Supply Chain

In this profile, we can bring up another hook for Test Code. By default, Tekton is used but you can have other tools too. I do not have supported list yet but will get that for you as soon i get.
Before we can use the Testing supply chain, we need to update the tap package. Let’s update the package now and include testing supply chain.
– Edit tap-values.yaml file and include the following changes.
supply_chain: testing
ootb_supply_chain_testing:
registry:
server: "<replace the registry server>"
repository: "build-service"
– Now, update the tap package by running the following command.
$ tanzu package installed update tap --package-name tap.tanzu.vmware.com --version 0.4.0 -n tap-install -f tap-values.yml
| Updating installed package 'tap'
- Getting package install for 'tap' I1229 15:43:40.593130 22917 request.go:665] Waited for 1.045695997s due to client-side throttling, not priority and fairness, request: GET:https://F971DC6D64DE4B4EE58DC3CDF5C2A68A.gr7.us-east-2.eks.amazonaws.com/apis/kpack.io/v1alpha2?timeout=32s
\ Getting package install for 'tap'
| Getting package metadata for 'tap.tanzu.vmware.com'
| Updating secret 'tap-tap-install-values'
| Updating package install for 'tap'
- Waiting for 'PackageInstall' reconciliation for 'tap'
Updated installed package 'tap' in namespace 'tap-install'
Let’s test the testing supply chain
– Create the Tekton pipeline for testing the application.
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: developer-defined-tekton-pipeline
labels:
apps.tanzu.vmware.com/pipeline: test # (!) required
spec:
params:
- name: source-url # (!) required
- name: source-revision # (!) required
tasks:
- name: test
params:
- name: source-url
value: $(params.source-url)
- name: source-revision
value: $(params.source-revision)
taskSpec:
params:
- name: source-url
- name: source-revision
steps:
- name: test
image: gradle
script: |-
cd `mktemp -d`
wget -qO- $(params.source-url) | tar xvz
./mvnw test
– Save the content in a yaml file and apply it on a k8s cluster.
$ k apply -f pipeline.yaml
pipeline.tekton.dev/developer-defined-tekton-pipeline created
– Deploy the application by running the following command.
tanzu apps workload create tanzu-java-web-app \
> --git-repo https://github.com/sample-accelerators/tanzu-java-web-app \
> --git-branch main \
> --type web \
> --label apps.tanzu.vmware.com/has-tests=true \
> --yes
Create workload:
1 + |---
2 + |apiVersion: carto.run/v1alpha1
3 + |kind: Workload
4 + |metadata:
5 + | labels:
6 + | apps.tanzu.vmware.com/has-tests: "true"
7 + | apps.tanzu.vmware.com/workload-type: web
8 + | name: tanzu-java-web-app
9 + | namespace: default
10 + |spec:
11 + | source:
12 + | git:
13 + | ref:
14 + | branch: main
15 + | url: https://github.com/sample-accelerators/tanzu-java-web-app
Created workload "tanzu-java-web-app"
– Now notice the new object, Pipeline Run
kubectl get workload,gitrepository,pipelinerun,images.kpack,podintent,app,services.serving
NAME AGE
workload.carto.run/tanzu-java-web-app 11s
NAME URL READY STATUS AGE
gitrepository.source.toolkit.fluxcd.io/tanzu-java-web-app https://github.com/sample-accelerators/tanzu-java-web-app True Fetched revision: main/ee4bcbc5bb3c0cb8b9b7db06d0a83b50ee7ed231 8s
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
pipelinerun.tekton.dev/tanzu-java-web-app-n2lmg Unknown Running 1s
– Wait for few mins to complete the pipeline run.
– Once testing is completed, you will see the build part will start and finally application is deployed. Run the below command to get the other objects.
$ kubectl get workload,gitrepository,pipelinerun,images.kpack,podintent,app,services.serving
NAME AGE
workload.carto.run/tanzu-java-web-app 17s
NAME URL READY STATUS AGE
gitrepository.source.toolkit.fluxcd.io/tanzu-java-web-app https://github.com/sample-accelerators/tanzu-java-web-app True Fetched revision: main/ee4bcbc5bb3c0cb8b9b7db06d0a83b50ee7ed231 14s
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
pipelinerun.tekton.dev/tanzu-java-web-app-n2lmg Unknown Running 7s
NAME DESCRIPTION SINCE-DEPLOY AGE
app.kappctrl.k14s.io/tanzu-java-web-app Reconcile succeeded 4s 4s
NAME URL LATESTCREATED LATESTREADY READY REASON
service.serving.knative.dev/tanzu-java-web-app http://tanzu-java-web-app.default.example.com tanzu-java-web-app-00001 Unknown RevisionMissing
– If you are interested in seeing the ran test, view the pod logs. e.g. below is the pod log
$ k logs tanzu-java-web-app-crxhl-test-pod
------truncated output-----
viewResolver
welcomePageHandlerMapping
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.185 s - in com.example.springboot.HelloControllerTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 26.457 s
[INFO] Finished at: 2021-12-28T06:13:05Z
[INFO] ------------------------------------------------------------------------
So now we understood that how to bring Testing supply chain and leverage Tekton to test the code.
Out of the Box with Testing and Scanning Supply Chain

In the Testing supply chain profile, we understood that how to include Testing using Tekton. In this profile, there is scanning using Grype included too. As you notice in the above picture, there is Source code scanning and then container image scanning where grype is used. Since I have TAP Full profile installation is done, So I have all the packages running and we will update the tap package to include the new profile.
– Edit the tap-values.yaml file and include the below detail.
supply_chain: testing_scanning
ootb_supply_chain_testing_scanning:
registry:
server: "<replace the registry server>"
repository: "build-service"
– Save the details and run the update command for tanzu package update.
$ tanzu package installed update tap --package-name tap.tanzu.vmware.com --version 0.4.0 -n tap-install -f tap-values.yml
– During installation of the Grype Scanner as part of TAP, sample ScanTemplates are installed into the default namespace. If the workload is deployed into another namespace, these sample ScanTemplates also need to be present in the other namespace. View the default scan templates.
$ k get scantemplate
NAME AGE
blob-source-scan-template 25h
private-image-scan-template 25h
private-source-scan-template 25h
public-image-scan-template 25h
public-source-scan-template 25h
– Now, we need to create a Scan Policy for source code and container image.
$ kubectl apply -f - -o yaml << EOF
> ---
> apiVersion: scst-scan.apps.tanzu.vmware.com/v1alpha1
> kind: ScanPolicy
> metadata:
> name: scan-policy
> spec:
> regoFile: |
> package policies
>
> default isCompliant = false
>
> # Accepted Values: "Critical", "High", "Medium", "Low", "Negligible", "UnknownSeverity"
> violatingSeverities := ["Critical","High","UnknownSeverity"]
> ignoreCVEs := []
>
> contains(array, elem) = true {
> array[_] = elem
> } else = false { true }
>
> isSafe(match) {
> fails := contains(violatingSeverities, match.Ratings.Rating[_].Severity)
> not fails
> }
>
> isSafe(match) {
> ignore := contains(ignoreCVEs, match.Id)
> ignore
> }
>
> isCompliant = isSafe(input.currentVulnerability)
> EOF
apiVersion: scst-scan.apps.tanzu.vmware.com/v1alpha1
kind: ScanPolicy
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"scst-scan.apps.tanzu.vmware.com/v1alpha1","kind":"ScanPolicy","metadata":{"annotations":{},"name":"scan-policy","namespace":"default"},"spec":{"regoFile":"package policies\n\ndefault isCompliant = false\n\n# Accepted Values: \"Critical\", \"High\", \"Medium\", \"Low\", \"Negligible\", \"UnknownSeverity\"\nviolatingSeverities := [\"Critical\",\"High\",\"UnknownSeverity\"]\nignoreCVEs := []\n\ncontains(array, elem) = true {\n array[_] = elem\n} else = false { true }\n\nisSafe(match) {\n fails := contains(violatingSeverities, match.Ratings.Rating[_].Severity)\n not fails\n}\n\nisSafe(match) {\n ignore := contains(ignoreCVEs, match.Id)\n ignore\n}\n\nisCompliant = isSafe(input.currentVulnerability)\n"}}
creationTimestamp: "2021-12-28T06:07:22Z"
generation: 1
managedFields:
- apiVersion: scst-scan.apps.tanzu.vmware.com/v1alpha1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:spec:
.: {}
f:regoFile: {}
manager: kubectl-client-side-apply
operation: Update
time: "2021-12-28T06:07:22Z"
name: scan-policy
namespace: default
resourceVersion: "5223136"
uid: 78b2adf9-aca7-4ddd-81c4-259f900bb3c6
spec:
regoFile: |
package policies
default isCompliant = false
# Accepted Values: "Critical", "High", "Medium", "Low", "Negligible", "UnknownSeverity"
violatingSeverities := ["Critical","High","UnknownSeverity"]
ignoreCVEs := []
contains(array, elem) = true {
array[_] = elem
} else = false { true }
isSafe(match) {
fails := contains(violatingSeverities, match.Ratings.Rating[_].Severity)
not fails
}
isSafe(match) {
ignore := contains(ignoreCVEs, match.Id)
ignore
}
isCompliant = isSafe(input.currentVulnerability)
Events: <none>
– Now, Deploy the application.
$ tanzu apps workload create tanzu-java-web-app \
> --git-repo https://github.com/sample-accelerators/tanzu-java-web-app \
> --git-branch main \
> --type web \
> --label apps.tanzu.vmware.com/has-tests=true \
> --yes
Create workload:
1 + |---
2 + |apiVersion: carto.run/v1alpha1
3 + |kind: Workload
4 + |metadata:
5 + | labels:
6 + | apps.tanzu.vmware.com/has-tests: "true"
7 + | apps.tanzu.vmware.com/workload-type: web
8 + | name: tanzu-java-web-app
9 + | namespace: default
10 + |spec:
11 + | source:
12 + | git:
13 + | ref:
14 + | branch: main
15 + | url: https://github.com/sample-accelerators/tanzu-java-web-app
Created workload "tanzu-java-web-app"
– Validate the scan results.
# Image Scan
$ k get imagescan
NAME PHASE SCANNEDIMAGE AGE CRITICAL HIGH MEDIUM LOW UNKNOWN CVETOTAL
tanzu-java-web-app Completed 2m7s
# Source Scan
$ k get sourcescan
NAME PHASE SCANNEDREVISION SCANNEDREPOSITORY AGE CRITICAL HIGH MEDIUM LOW UNKNOWN CVETOTAL
tanzu-java-web-app Completed ee4bcbc5bb3c0cb8b9b7db06d0a83b50ee7ed231 http://source-controller.flux-system.svc.cluster.local./gitrepository/default/tanzu-java-web-app/ee4bcbc5bb3c0cb8b9b7db06d0a83b50ee7ed231.tar.gz 16m
Scan results are stored in a Metadata Store and I will write a separate blog on that.
That’s all from this post, hopefully you have enjoyed the TAP blogs and been helpful for you.
For more reference, Refer VMware TAP documentation.
https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/0.4/tap/GUID-getting-started.html