The Tanzu Application Catalog CLI (TAC CLI) is a tool that provides a complete understanding of the assets available for your organization. It can fetch container and Helm chart metadata containing key information about each asset's components, latest releases, security scans, dependencies, and more.

It gives users complete control of their application's lifecycle by providing updated information on the assets in their catalog.

IMPORTANT: The Tanzu Application Catalog (TAC) CLI is currently in beta and is subject to change. Please be aware all commands showcased here, are attached to a demo environment. If you intend to follow them for your environment, results will vary.

Log in to TAC

TAC CLI uses VMware Cloud API tokens. Tokens are generated at https://console.cloud.vmware.com/csp/gateway/portal/#/user/tokens. To get the API token, select the proper organization and the TAC user scope. The tac login command will guide you through the process:

$ tac login

For non-interactive mode use tac login --api-token ********** --context-name MyName.

TAC will generate a configuration file at ~/.tac/config.yml with the login configuration that will be used for all connections. Note that you may repeat this process as many times as you wish, as you can store multiple contexts. Contexts can be listed / removed with the tac config command:

$ tac config list

Current Name 		Api Token 		Organization ID
*    My Name 	**** 			1231-2342-2342-2340-3453

Use tac config set to configure the default context. In the example below there is more than one:

$ tac config set My Name

Retrieve assets

To retrieve all assets available for your organization, execute the following command:

$ tac get apps

Here is an example of the metadata of a Helm chart:

[
   {
  "asset_type": "HELM_CHART",
  "assets": [
   {
    "asset_type": "HELM_CHART",
    "bitnami_app_id": "wildfly",
    "dependencies": [
     {
      "asset_type": "DOCKER_IMAGE",
      "bitnami_app_id": "wildfly",
      "dependencies": null,
      "description": "Wildfly is a lightweight, open source application server, formerly known as JBoss, that implements the latest enterprise Java standards.",
      "id": "0080599d3063a6716d84fbd45b7e66b6bd0b3057",
      "labels": {
       "branch": "20",
       "distro": "centos-7",
       "registry": "myregistry"
      },
      "name": "WildFly",
      "parents": null,
      "released_at": "2020-07-09T04:24:12.000+00:00",
      "releases": null,
      "revision": "1",
      "status": "RELEASED",
      "version": "20.0.1"
     }
    ],
    "description": "Wildfly is a lightweight, open source application server, formerly known as JBoss, that implements the latest enterprise Java standards.",
    "id": "78de5fbe36967ee094bf5618648461dc7585221b",
    "labels": {
     "branch": "20",
     "distro": "centos-7"
    },
    "name": "WildFly",
    "parents": null,
    "released_at": "2020-07-08T04:02:16.000+00:00",
    "releases": null,
    "revision": "0",
    "status": "RELEASED",
    "version": "20.0.1"
   }
  ],
  "bitnami_app_id": "wildfly"
 },
 {
  "asset_type": "HELM_CHART",
  "assets": [
   {
    "asset_type": "HELM_CHART",
    "bitnami_app_id": "wordpress",
    "dependencies": [
     {
      "asset_type": "DOCKER_IMAGE",
      "bitnami_app_id": "wordpress",
      "dependencies": null,
      "description": "WordPress is the world's most popular blogging and content management platform. Powerful yet simple, everyone from students to global corporations use it to build beautiful, functional websites.",
      "id": "da9a46272b09c3aba272458bf5fcddd087d9ada3",
      "labels": {
       "branch": "5",
       "distro": "centos-7",
       "registry": "myregistry"
      },
      "name": "WordPress",
      "parents": null,
      "released_at": "2020-07-09T01:29:19.000+00:00",
      "releases": null,
      "revision": "23",
      "status": "RELEASED",
      "version": "5.4.2"
     }
    ],
    "description": "WordPress is the world's most popular blogging and content management platform. Powerful yet simple, everyone from students to global corporations use it to build beautiful, functional websites.",
    "id": "7439ac670a4071789825fdb02a6c23658a5bb36a",
    "labels": {
     "branch": "5",
     "distro": "centos-7"
    },
    "name": "WordPress",
    "parents": null,
    "released_at": "2020-07-09T01:49:51.000+00:00",
    "releases": null,
    "revision": "6",
    "status": "RELEASED",
    "version": "5.4.2"
   }
  ],
  "bitnami_app_id": "wordpress"
 },
 ...
]

Note in the previous listing, that the response Helm Charts have their dependencies under dependencies attribute.

Get asset ID

Given the asset ID, you can retrieve its details, including its tags, releases, dependencies, and different reports generated during its TAC build lifecycle. Use the tac get app ASSET_ID command as shown below:

$ tac get app 307bbd0a79bf131cf1dd660027a0759910d68641

Here is an example:

{
 "asset_type": "DOCKER_IMAGE",
 "bitnami_app_id": "apache",
 "dependencies": [],
 "description": "Apache HTTP Server is an open-source HTTP server. The goal of this project is to provide a secure, efficient and extensible server that provides HTTP services in sync with the current HTTP standards.",
 "id": "307bbd0a79bf131cf1dd660027a0759910d68641",
 "labels": {
  "branch": "2.4",
  "distro": "centos-7",
  "registry": "myregistry"
 },
 "name": "Apache",
 "parents": [
  {
   "asset_type": "HELM_CHART",
   "bitnami_app_id": "apache",
   "dependencies": null,
   "description": "Apache HTTP Server is an open-source HTTP server. The goal of this project is to provide a secure, efficient and extensible server that provides HTTP services in sync with the current HTTP standards.",
   "id": "87826e7b88c7cc3e87ab9d397d4d030cded428e3",
   "labels": {
    "branch": "2.4",
    "distro": "centos-7"
   },
   "name": "Apache",
   "parents": null,
   "released_at": "2020-06-19T09:45:09.000+00:00",
   "releases": null,
   "revision": "3",
   "status": "RELEASED",
   "version": "2.4.43"
  }
 ],
 "released_at": "2020-07-08T18:38:24.000+00:00",
 "releases": [
  {
   "artifact": {
    "antivirus_scan_result": {
     "filename": "clamav-antivirus-scan.log",
     "id": "96f45bf9ff169817c138bb9e49e64acf922cb8320512381c5606330ffbcdb020"
    },
    "cve_scan_result": {
     "filename": "cve-scanner-output.json",
     "id": "f8a5a26e3056eb6fb06deeb3dbccfd88ae74900200c98c70b5966bbb7ec9d4de"
    },
    "vulnerability_cvrf_report": {
     "filename": "vulnerability-cvrf-report.xml",
     "id": "1e41e10e03bbe2ce04e5e90d109a6326c7b342b2837b95aff55a6504f72793ec"
    },
    "image_reference": [
     {
      "digest": "gcr.io/my-repo/apache@sha256:eff033992f8bffb59b533c075f10ea52cbe4c5ed923867a7a9b6991404735915",
      "tags": [
       "gcr.io/my-repo/apache:2.4-centos-7",
       "gcr.io/my-repo/apache:2.4.43-centos-7-r97",
       "gcr.io/my-repo/apache:2.4",
       "gcr.io/my-repo/apache:2.4.43",
       "gcr.io/my-repo/apache:latest"
      ]
     }
    ],
    "test_results": [
     {
      "archive": {
       "filename": "docker-compose-tests-output.tar.gz",
       "id": "303a898038d70b284390083cb1ebb6539cd941d2f4f4da37d0ad95b7de561310"
      },
      "platform": "docker-compose"
     },
     {
      "archive": {
       "filename": "gke-helm-chart-tests-output.tar.gz",
       "id": "a4ad4a8a4ac87ed5ae814edd081945c46025e9aea4b7292a71e50f0a03306541"
      },
      "platform": "gke-helm-chart"
     }
    ]
   },
   "released_at": "2020-07-08T18:38:24.000+00:00",
   "revision": "87",
   "version": "2.4.43"
  }
 ],
 "revision": "87",
 "status": "RELEASED",
 "version": "2.4.43"
}

Finally, you can download reports by using the tac app artifact artifact_id command:

$ tac get artifact 96f45bf9ff169817c138bb9e49e64acf922cb8320512381c5606330ffbcdb020

Artifact successfully saved at /tmp/clamav-antivirus-scan.log

Download asset metadata

Here is a composite example of using the TAC CLI to download the antivirus and metadata reports for an artifact from the catalog, such as Redis. To achieve this, the TAC CLI is used to obtain asset metadata, which in turn is used to obtain release information and corresponding reports.

In these examples, use jq tool to automate JSON parsing.

$ tac get apps --asset-type container | jq '.[]'  | jq 'select(.assets[0].name == "Redis")'
{
  "asset_type": "DOCKER_IMAGE",
  "assets": [
    {
      "asset_type": "DOCKER_IMAGE",
      "bitnami_app_id": "redis",
      "dependencies": [],
      "description": "Redis is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.",
      "id": "f1ffc29677f166980eebd3574e56d39d3159ec35",
      "labels": {
        "branch": "5.0",
        "distro": "centos-7",
        "registry": "my-registry"
      },
      "name": "Redis",
      "released_at": "2020-09-23T22:32:12.000+00:00",
      "revision": "133",
      "status": "RELEASED",
      "version": "5.0.9"
    }
  ],
  "bitnami_app_id": "redis"
}

Get Redis details

Using the above the example, you can get the asset ID easily:

$ ASSET_ID=`tac get apps --asset-type container | jq '.[]' | jq 'select(.assets[0].name == "Redis").assets[0].id' -r`

echo $ASSET_ID
f1ffc29677f166980eebd3574e56d39d3159ec35

Query for its details:

$ tac get app $ASSET_ID
{
  // application details
  ...
  ...
   "releases": [
  {
   "artifact": {
    "antivirus_scan_result": {
     "filename": "clamav-antivirus-scan.log",
     "id": "752c5550df453ac884489ff3db775ff18378919129c99e42b038e122727c225e",
     "namespace": "my-environment"
    },
    "asset_spec": {
     "filename": "asset-spec.json",
     "id": "a6feff0e6de0c021b112feca3b7ec448353a97386ef17b5e564bbee8b8252561",
     "namespace": "my-environment"
    },
    "cve_scan_result": {
     "filename": "cve-scanner-output.json",
     "id": "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
     "namespace": "my-environment"
    },
    "vulnerability_cvrf_report": {
     "filename": "vulnerability-cvrf-report.xml",
     "id": "1e41e10e03bbe2ce04e5e90d109a6326c7b342b2837b95aff55a6504f72793ec",
     "namespace": "my-environment"
    },
    "image_reference": [
     {
      "contentDigest": "sha256:53035fd9215cf4f581163baaf31f96ad571b048103b75346f3250b2334ba64d9",
      "digest": "gcr.io/myregistry/demo/bitnami/redis@sha256:71049fbb140af99fe17bd5eadf28302ae56d81a50bfe18fa855d7e21db74fd27",
      "repoDigests": [
       "gcr.io/myregistry/demo/bitnami/redis@sha256:71049fbb140af99fe17bd5eadf28302ae56d81a50bfe18fa855d7e21db74fd27"
      ],
      "tags": [
        "gcr.io/myregistry/demo/bitnami/redis:5.0-centos-7",
        "gcr.io/myregistry/demo/bitnami/redis:5.0.9-centos-7-r74",
        "gcr.io/myregistry/demo/bitnami/redis:5.0",
        "gcr.io/myregistry/demo/bitnami/redis:5.0.9"
      ]
     }
    ],
    "test_results": [
     {
      "archive": {
       "filename": "test-results.tar.gz",
       "id": "aa134c27135d5afb47665b789dae5abfc1506b60028a467354a0b7d129341c88",
       "namespace": "my-environment"
      },
      "platform": ""
     }
    ]
   },
   "dependencies": [],
   "id": "6f95e5909cc53fe0423240cf19a793d0c58f788efc4854abc203a56a9194055a",
   "parents": [],
   "released_at": "2020-09-23T22:32:12.000+00:00",
   "revision": "133",
   "version": "5.0.9"
  }
 ],
 "revision": "133",
 "status": "RELEASED",
 "version": "5.0.9"
}

TIP: Check out the releases field highlighted above to get detailed information about the versions available for the asset.

Get image tags

$ tac get app $ASSET_ID | jq ".releases[0].artifact.image_reference[0].tags"

[
  "gcr.io/myregistry/demo/bitnami/redis:5.0",
  "gcr.io/myregistry/demo/bitnami/redis:5.0-centos-7",
  "gcr.io/myregistry/demo/bitnami/redis:5.0.9"
  "gcr.io/myregistry/demo/bitnami/redis:5.0.9-centos-7-r74",
]

Get report contents

You can easily get a report identifier with:

$ REPORT_ID=`tac get app $ASSET_ID | jq ".releases[0].artifact.antivirus_scan_result.id" -r`

The same could be applied to cve_scan_result. Then, to download it just run the following command. The report will be saved to the current folder:

$ tac get artifact $REPORT_ID

Artifact successfully saved at /home/user/clamav-antivirus-scan.log

Verify asset specifications

Detailed information about an asset can be downloaded by executing the command tac metadata fetch:

$ tac metadata fetch --asset-id $ASSET_ID --dest ${PWD}/spec.json

Verifying specification file...
Verification OK
Asset specification successfully saved at /your/path/spec.json

From the above output, you can see how the specification was fetched, verified, and saved. Verification is enabled by default when fetching for asset specifications.

Once you have the asset specification downloaded, you can list all the artifacts that the asset contains and download them easily:

$ tac metadata artifacts ${PWD}/spec.json

Verifying specification file...
Verification OK
redis-cluster/antivirusScanResults
redis-cluster/testResults

You can, for example, download the test results:

$ tac metadata artifacts ${PWD}/spec.json redis-cluster/testResults --dest ${PWD}


Verifying specification file...
Verification OK
Artifact successfully saved at /your/path/test-results.tar.gz

As the spec file is digitally signed, the following command allows a user to verify that a given spec file matches its signature:

$ tac metadata verify /your/path/spec.json
Verification OK

In case the spec.json file is modified, verification will fail, as shown below:

$ tac metadata verify /your/path/modified.spec.json
Error: verification failed

This verification step is also performed as part of the tac metadata fetch ... command previously shown.

Retrieve older metadata

You can access older metadata for an asset by using the --digest flag of the TAC CLI and the digest of the artifact for which you wish to retrieve metadata.

$ tac metadata fetch --digest "sha256:caa17cf3d7ccc61d8e4397d626d3279465024710afa368b6c713d7ecde29a933"

The next sections describe how to obtain the digest for container images and Helm charts.

Obtain digest for a container image

In order to get the digest of any container image, simply run a docker inspect command.

Replace the CONTAINER_REGISTRY, ASSET, and TAG placeholders in the commands below with the actual container registry, container name, and container tag.

$ docker pull CONTAINER_REGISTRY/ASSET:TAG
$ docker inspect CONTAINER_REGISTRY/ASSET:TAG
[
  {
    "Id": "sha256:caa17cf3d7ccc61d8e4397d626d3279465024710afa368b6c713d7ecde29a933",
    "RepoTags": [],
    "RepoDigests": [
      "CONTAINER_REGISTRY/ASSET@SHA256"
    ],
    "Parent": "",
    "Comment": "",
    "Created": "2021-04-01T16:20:38.280454162Z",
    "Container": "e3cccef627e82a819c6fa3d8580532de7f8b0f6ceb25b2bd7197e543131818eb",
    "ContainerConfig": {
      "Hostname": "e3cccef627e8",
      "Domainname": "",
      "User": "1001",
      "AttachStdin": false,
      "AttachStdout": false,
      "AttachStderr": false,
      "ExposedPorts": {
        "9355/tcp": {}
      },
      ...

The digest for the container is the one from the Id field, in this case sha256:caa17cf3d7ccc61d8e4397d626d3279465024710afa368b6c713d7ecde29a933

After obtaining the digest, retrieve the metadata of this specific container with the following command:

 $ tac metadata fetch --digest "sha256:caa17cf3d7ccc61d8e4397d626d3279465024710afa368b6c713d7ecde29a933"

Obtain digest for a Helm chart

Obtaining the digest for a Helm chart depends on the nature of the Helm chart repository (standard or OCI).

Standard Helm Chart repository

For a standard Helm repository, download the specific chart and obtain the SHA-256 using a tool like shasum (macOS) or sha256sum (Linux).

Download the chart with helm fetch. This example uses a specific version of the Apache Kafka Helm chart. Replace the MY_REPO placeholder in the command below with a proper value.

$ helm fetch MY_REPO/kafka --version 12.13.1

Get the digest of the tarball:

# For macOS
$ shasum -a 256 kafka-12.13.1.tgz

15dfadb4155f83a7c8e1019ff5b176b714950a863f4d53342e24b42b09410643  kafka-12.13.1.tgz

# For Linux
$ sha256sum kafka-12.13.1.tgz

15dfadb4155f83a7c8e1019ff5b176b714950a863f4d53342e24b42b09410643  kafka-12.13.1.tgz

After obtaining the digest, use the tac metadata fetch command, as shown below, to retrieve the required metadata:

$ tac metadata fetch --digest "sha256:15dfadb4155f83a7c8e1019ff5b176b714950a863f4d53342e24b42b09410643"

OCI repository

If your charts are hosted on a Harbor OCI repository, run the following curl command to obtain the digest of the chart.

Replace the HARBOR_ENDPOINT, PROJECT_NAME, ASSET_PATH, and ASSET_VERSION placeholders in the command below by the Harbor endpoint, the project name, the path to the asset inside the project, and the asset version. Also, $HARBOR_USER and $HARBOR_PASSWORD variables should contain proper login credentials. jq is used only to reformat the result and make it more readable.

$ curl -s --user "$HARBOR_USER:$HARBOR_PASSWORD" -H "Accept:application/vnd.oci.image.manifest.v1+json" https://HARBOR_ENDPOINT/v2/PROJECT_NAME/ASSET_PATH/manifests/ASSET_VERSION | jq
{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.cncf.helm.config.v1+json",
    "digest": "sha256:3e04d5339a65f78f1b9a03290927e827d5ed4711aff7eb34e2c65eb71cd87da0",
    "size": 799
  },
  "layers": [
    {
      "mediaType": "application/tar+gzip",
      "digest": "sha256:eda74e3fb491c2a68e53782716639da7200208bac0f842f8b1581a22e241565a",
      "size": 60243,
      "annotations": {
        "org.opencontainers.image.title": "solr-0.3.0.tgz"
      }
    }
  ]
}

The digest is the value of the layer with "mediaType": "application/tar+gzip". In this example, the required digest is sha256:eda74e3fb491c2a68e53782716639da7200208bac0f842f8b1581a22e241565a

After obtaining the digest, use the tac metadata fetch command, as shown below, to retrieve the required metadata:

$ tac metadata fetch --digest "sha256:eda74e3fb491c2a68e53782716639da7200208bac0f842f8b1581a22e241565a"
check-circle-line exclamation-circle-line close-line
Scroll to top icon