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. [email protected]

# 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. [email protected]
CVEs:
1. CVE-2020-16156 (Medium)
2. ID: 3
Registry: tapdemoacr.azurecr.io
Image Name: build-service
Digest: sha256:bceaec7f98f3ba34025d71322ca606db7c650a3748617848e4f52a643c541859
Packages:
1. [email protected]
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. [email protected]
CVEs:
1. CVE-2020-16156 (Medium)
2. ID: 3
Registry: tapdemoacr.azurecr.io
Image Name: build-service
Digest: sha256:bceaec7f98f3ba34025d71322ca606db7c650a3748617848e4f52a643c541859
Packages:
1. [email protected]
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. [email protected]
2. BellSoft Liberica [email protected]
3. [email protected]
4. [email protected]
5. [email protected]
6. [email protected]
7. [email protected]
8. [email protected]
9. [email protected]
10. [email protected]
11. [email protected]
12. [email protected]
13. [email protected]
14. [email protected]
CVEs:
1. GHSA-8489-44mv-ggj8 (Medium)
2. CVE-2021-44832 (Medium)
2. CVE-2021-44832 (Unknown)
2. CVE-2021-44832 (Unknown)
15. [email protected]
CVEs:
1. CVE-2021-44832 (Medium)
1. CVE-2021-44832 (Unknown)
1. CVE-2021-44832 (Unknown)

 

Demo Video: