Tanzu Application Platform – Store (SBoMs)

Reading Time: 3 mins

Overview

Supply Chain Security Tools – Store saves software bills of materials (SBoMs) to a database and allows you to query for image, source, package, and vulnerability relationships. It integrates with Supply Chain Security Tools – Scan to automatically store the resulting source and image vulnerability reports. It accepts any CycloneDX input and outputs in both human-readable and machine-readable formats, including JSON, text, and CycloneDX.

Prerequisites

  • Ensure to complete the TAP install with OOTB test and scan, refer to steps here
  • postgres database (optional) – By default, Postgres database and an API backend is created during the installation of tanzu packages. If you are planning to use an external postgres DB refer to doc
  • insight CLI, Grype
  • Service accounts and access token

insight CLI and Grype

Install insight CLI

  • Login to Tanzu network and download the tarball based on your operating system, for this demo I choose insight-1.0.1_darwin_amd64 for mac
# On the command line, make the download "insight-1.0.1_darwin_amd64" binary file executable:

chmod ugo+x insight-1.0.1_darwin_amd64

# Move the binary file into a directory that is on your PATH:

mv insight-1.0.1_darwin_amd64 /usr/local/bin/insight

# verify the version

insight version

Grype

Service accounts and access token

You can create two types of service accounts, In this demo, I have used Read-write service account.

  1. Read-only service account – only able to use GET API requests
kubectl apply -f - -o yaml << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: metadata-store-ro
  namespace: metadata-store
rules:
- resources: ["all"]
  verbs: ["get"]
  apiGroups: [ "metadata-store/v1" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metadata-store-ro
  namespace: metadata-store
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: metadata-store-ro
subjects:
- kind: ServiceAccount
  name: metadata-store-read-client
  namespace: metadata-store
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metadata-store-read-client
  namespace: metadata-store
automountServiceAccountToken: false
EOF

(OR)

     2. Read-write service account – full access to the API requests

kubectl apply -f - -o yaml << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: metadata-store-read-write
  namespace: metadata-store
rules:
- resources: ["all"]
  verbs: ["get", "create", "update"]
  apiGroups: [ "metadata-store/v1" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metadata-store-read-write
  namespace: metadata-store
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: metadata-store-read-write
subjects:
- kind: ServiceAccount
  name: metadata-store-read-write-client
  namespace: metadata-store
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metadata-store-read-write-client
  namespace: metadata-store
automountServiceAccountToken: false
EOF

Access Token: 

To retrieve the read-write access token run the following command:

kubectl get secret $(kubectl get sa -n metadata-store metadata-store-read-write-client -o json | jq -r '.secrets[0].name') -n metadata-store -o json | jq -r '.data.token' | base64 -d

Setting the access token: 

  • When using the CLI, you’ll need to set the METADATA_STORE_ACCESS_TOKEN environment variable, or use the --access-token flag.
$ export METADATA_STORE_ACCESS_TOKEN=$(kubectl get secrets -n metadata-store -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='metadata-store-read-write-client')].data.token}" | base64 -d)

Connection to database:

The connection to the Store requires TLS encryption. Follow the instructions below to set up the TLS connection depending on which type of service is being used: For this demo, I have used LoadBalancer. 

  1. Using LoadBalancer
  2. Using NodePort — commonly used with local clusters such as kind, or minikube

LoadBalancer

  • If you are using a LoadBalancer configuration, you need to find the external IP of the metadata-store-app service using below command:
kubectl get service/metadata-store-app --namespace metadata-store -o=jsonpath='{.status.loadBalancer.ingress[0].ip}'
  • Add the IP entry mapping to metadata-store-app.metadata-store.svc.cluster.local in /etc/hosts like shown below:

The CA certificate is generated by cert manager. Run the following command to get the CA certificate:

kubectl get secret app-tls-cert -n metadata-store -o json | jq -r '.data."ca.crt"' | base64 -d > /tmp/ca.crt

insight CLI configuration

# Set the target endpoint and CA certificate by running:

insight config set-target https://metadata-store-app.metadata-store.svc.cluster.local:8443 --ca-cert /tmp/ca.crt

#
insight health
{"message":"Successfully Reached Metadata Store!"}

 

Though the data can be added by posting CycloneDX files using many methods, In this demo I will be adding it through Insight CLI:

Generate a CycloneDX File

To use Grype to scan an image and generate an image report in CycloneDX format.

# For this demo, I would be using acr repo which I have used while creating workload in TAP. 

# Authenticate to acr using docker login , syntax: docker login -u <username> -p <password>

docker login tapdemoacr.azurecr.io -u tapdemoacr -p hGQ9wrongonefd3o
# To use Grype to scan an image and generate an image report in CycloneDX format. syntax: grype REPO:TAG -o cyclonedx > NAME

# Where: REPO is the name of your repository, TAG is the name of a tag, IMAGE-CVE-REPORT is the resulting file name of the Grype image scan report

grype tapdemoacr.azurecr.io/build-service:latest -o cyclonedx > image-cve-report

 ✔ Vulnerability DB        [no update available]
 ✔ Loaded image
 ✔ Parsed image
 ✔ Cataloged packages      [96 packages]
 ✔ Scanned image           [82 vulnerabilities]
# To use a CycloneDX-formatted image report:

$ insight image create --cyclonedxtype xml --path image-cve-report

# For this demo I picked a random cve id from the report to see the vulnerability packages: 

$ insight vuln get --cveid CVE-2020-16156
1. CVE-2020-16156 (Medium)
Packages:
	1. perl-base@5.26.1-6ubuntu0.5

# To see the list of the images tagged with the vulnerability: 

$ insight vuln images --cveid CVE-2020-16156
1. 	ID:       	1
	Registry:  	tapdemoacr.azurecr.io
	Image Name:	supply-chain/tanzu-java-web-app-tap-install
	Digest:    	sha256:2ea135cbc1058af2662bf08a5e6ebf3041b64f6aebfe13b5ebfe618b1648d190
	Packages:
	1. perl-base@5.26.1-6ubuntu0.5
	CVEs:
		1. CVE-2020-16156 (Medium)
2. 	ID:       	3
	Registry:  	tapdemoacr.azurecr.io
	Image Name:	build-service
	Digest:    	sha256:bceaec7f98f3ba34025d71322ca606db7c650a3748617848e4f52a643c541859
	Packages:
	1. perl-base@5.26.1-6ubuntu0.5
	CVEs:
		1. CVE-2020-16156 (Medium)
# To see the affected images of specific package

insight package images --name perl-base
1. 	ID:       	1
	Registry:  	tapdemoacr.azurecr.io
	Image Name:	supply-chain/tanzu-java-web-app-tap-install
	Digest:    	sha256:2ea135cbc1058af2662bf08a5e6ebf3041b64f6aebfe13b5ebfe618b1648d190
	Packages:
	1. perl-base@5.26.1-6ubuntu0.5
	CVEs:
		1. CVE-2020-16156 (Medium)
2. 	ID:       	3
	Registry:  	tapdemoacr.azurecr.io
	Image Name:	build-service
	Digest:    	sha256:bceaec7f98f3ba34025d71322ca606db7c650a3748617848e4f52a643c541859
	Packages:
	1. perl-base@5.26.1-6ubuntu0.5
	CVEs:
		1. CVE-2020-16156 (Medium)
# To list the packages and corresponding CVE's of a specific digest: 

insight image get --digest sha256:2ea135cbc1058af2662bf08a5e6ebf3041b64f6aebfe13b5ebfe618b1648d190
ID:       	1
Registry:  	tapdemoacr.azurecr.io
Image Name:	supply-chain/tanzu-java-web-app-tap-install
Digest:    	sha256:2ea135cbc1058af2662bf08a5e6ebf3041b64f6aebfe13b5ebfe618b1648d190
Packages:
	1. helper@9.0.3
	2. BellSoft Liberica JRE@11.0.14
	3. helper@3.0.2
	4. HdrHistogram@2.1.12
	5. LatencyUtils@2.0.3
	6. jackson-annotations@2.12.6
	7. jackson-core@2.12.6
	8. jackson-databind@2.12.6
	9. jackson-datatype-jdk8@2.12.6
	10. jackson-datatype-jsr310@2.12.6
	11. jackson-module-parameter-names@2.12.6
	12. jakarta.annotation-api@1.3.5
	13. jul-to-slf4j@1.7.32
	14. log4j-api@2.17.0
	CVEs:
		1. GHSA-8489-44mv-ggj8 (Medium)
		2. CVE-2021-44832 (Medium)
		2. CVE-2021-44832 (Unknown)
		2. CVE-2021-44832 (Unknown)
	15. log4j-to-slf4j@2.17.0
	CVEs:
		1. CVE-2021-44832 (Medium)
		1. CVE-2021-44832 (Unknown)
		1. CVE-2021-44832 (Unknown)

 

Demo Video: