From 4c0a3daf52c1f0936e05f6b8df8370b9436133c1 Mon Sep 17 00:00:00 2001
From: Patrick Zheng <patrickzheng@microsoft.com>
Date: Thu, 26 Sep 2024 12:58:18 +0800
Subject: [PATCH] feat: crl with file cache (#1043)

Signed-off-by: Patrick Zheng <patrickzheng@microsoft.com>
---
 cmd/notation/main.go              |  5 +++++
 cmd/notation/verify.go            | 27 ++++++++++++++++++++++++---
 cmd/notation/verify_test.go       | 13 +++++++++++++
 go.mod                            |  6 +++---
 go.sum                            | 12 ++++++------
 test/e2e/go.mod                   |  2 +-
 test/e2e/go.sum                   |  8 ++++----
 test/e2e/plugin/go.mod            |  8 ++++----
 test/e2e/plugin/go.sum            | 16 ++++++++--------
 test/e2e/suite/command/inspect.go |  4 ++--
 test/e2e/suite/command/verify.go  | 11 +++++++++++
 11 files changed, 81 insertions(+), 31 deletions(-)

diff --git a/cmd/notation/main.go b/cmd/notation/main.go
index 8d5be0e74..712668a9f 100644
--- a/cmd/notation/main.go
+++ b/cmd/notation/main.go
@@ -39,6 +39,11 @@ func main() {
 				dir.UserConfigDir = notationConfig
 			}
 
+			// update Notation cache directory
+			if notationCache := os.Getenv("NOTATION_CACHE"); notationCache != "" {
+				dir.UserCacheDir = notationCache
+			}
+
 			// update Notation Libexec directory (for plugins)
 			if notationLibexec := os.Getenv("NOTATION_LIBEXEC"); notationLibexec != "" {
 				dir.UserLibexecDir = notationLibexec
diff --git a/cmd/notation/verify.go b/cmd/notation/verify.go
index 536f3d898..8943c087c 100644
--- a/cmd/notation/verify.go
+++ b/cmd/notation/verify.go
@@ -29,6 +29,7 @@ import (
 	"github.com/notaryproject/notation-go/dir"
 	"github.com/notaryproject/notation-go/plugin"
 	"github.com/notaryproject/notation-go/verifier"
+	"github.com/notaryproject/notation-go/verifier/crl"
 	"github.com/notaryproject/notation-go/verifier/trustpolicy"
 	"github.com/notaryproject/notation-go/verifier/truststore"
 	"github.com/notaryproject/notation/cmd/notation/internal/experimental"
@@ -36,6 +37,8 @@ import (
 	"github.com/notaryproject/notation/internal/httputil"
 	"github.com/notaryproject/notation/internal/ioutil"
 	"github.com/spf13/cobra"
+
+	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
 )
 
 type verifyOpts struct {
@@ -229,14 +232,23 @@ func printMetadataIfPresent(outcome *notation.VerificationOutcome) {
 }
 
 func getVerifier(ctx context.Context) (notation.Verifier, error) {
-	policyDocument, err := trustpolicy.LoadOCIDocument()
+	// revocation check
+	ocspHttpClient := httputil.NewClient(ctx, &http.Client{Timeout: 2 * time.Second})
+	crlFetcher, err := corecrl.NewHTTPFetcher(httputil.NewClient(ctx, &http.Client{Timeout: 5 * time.Second}))
+	if err != nil {
+		return nil, err
+	}
+	cacheRoot, err := dir.CacheFS().SysPath(dir.PathCRLCache)
+	if err != nil {
+		return nil, err
+	}
+	crlFetcher.Cache, err = crl.NewFileCache(cacheRoot)
 	if err != nil {
 		return nil, err
 	}
-	x509TrustStore := truststore.NewX509TrustStore(dir.ConfigFS())
-	ocspHttpClient := httputil.NewClient(ctx, &http.Client{Timeout: 2 * time.Second})
 	revocationCodeSigningValidator, err := revocation.NewWithOptions(revocation.Options{
 		OCSPHTTPClient:   ocspHttpClient,
+		CRLFetcher:       crlFetcher,
 		CertChainPurpose: purpose.CodeSigning,
 	})
 	if err != nil {
@@ -244,11 +256,20 @@ func getVerifier(ctx context.Context) (notation.Verifier, error) {
 	}
 	revocationTimestampingValidator, err := revocation.NewWithOptions(revocation.Options{
 		OCSPHTTPClient:   ocspHttpClient,
+		CRLFetcher:       crlFetcher,
 		CertChainPurpose: purpose.Timestamping,
 	})
 	if err != nil {
 		return nil, err
 	}
+
+	// trust policy and trust store
+	policyDocument, err := trustpolicy.LoadOCIDocument()
+	if err != nil {
+		return nil, err
+	}
+	x509TrustStore := truststore.NewX509TrustStore(dir.ConfigFS())
+
 	return verifier.NewVerifierWithOptions(policyDocument, nil, x509TrustStore, plugin.NewCLIManager(dir.PluginFS()), verifier.VerifierOptions{
 		RevocationCodeSigningValidator:  revocationCodeSigningValidator,
 		RevocationTimestampingValidator: revocationTimestampingValidator,
diff --git a/cmd/notation/verify_test.go b/cmd/notation/verify_test.go
index e554ae2ee..23954e11f 100644
--- a/cmd/notation/verify_test.go
+++ b/cmd/notation/verify_test.go
@@ -16,6 +16,7 @@ package main
 import (
 	"context"
 	"reflect"
+	"runtime"
 	"testing"
 
 	"github.com/notaryproject/notation-go/dir"
@@ -93,4 +94,16 @@ func TestGetVerifier(t *testing.T) {
 			t.Fatalf("expected %s, but got %s", expectedErrMsg, err)
 		}
 	})
+
+	t.Run("failed to new crl file cache", func(t *testing.T) {
+		if runtime.GOOS == "windows" {
+			t.Skip("skipping test on Windows")
+		}
+		dir.UserCacheDir = "/cache"
+		expectedErrMsg := "failed to create crl file cache: mkdir /cache: permission denied"
+		_, err := getVerifier(context.Background())
+		if err == nil || err.Error() != expectedErrMsg {
+			t.Fatalf("expected %s, but got %s", expectedErrMsg, err)
+		}
+	})
 }
diff --git a/go.mod b/go.mod
index c2a72b393..1bd05a047 100644
--- a/go.mod
+++ b/go.mod
@@ -3,8 +3,8 @@ module github.com/notaryproject/notation
 go 1.23
 
 require (
-	github.com/notaryproject/notation-core-go v1.1.0
-	github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240814004621-3c5a659c1d1d
+	github.com/notaryproject/notation-core-go v1.2.0-rc.1
+	github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240926015724-84c2ec076201
 	github.com/notaryproject/tspclient-go v0.2.0
 	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/image-spec v1.1.0
@@ -28,7 +28,7 @@ require (
 	github.com/veraison/go-cose v1.1.0 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
 	golang.org/x/crypto v0.27.0 // indirect
-	golang.org/x/mod v0.19.0 // indirect
+	golang.org/x/mod v0.21.0 // indirect
 	golang.org/x/sync v0.6.0 // indirect
 	golang.org/x/sys v0.25.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 9d476de3e..9eade9e6f 100644
--- a/go.sum
+++ b/go.sum
@@ -35,10 +35,10 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
 github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
 github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
-github.com/notaryproject/notation-core-go v1.1.0 h1:xCybcONOKcCyPNihJUSa+jRNsyQFNkrk0eJVVs1kWeg=
-github.com/notaryproject/notation-core-go v1.1.0/go.mod h1:+6AOh41JPrnVLbW/19SJqdhVHwKgIINBO/np0e7nXJA=
-github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240814004621-3c5a659c1d1d h1:7/lNsNkauXRhFuQ7TXTBuJA9PjrLhVraaAHuoDisK5Q=
-github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240814004621-3c5a659c1d1d/go.mod h1:YpPRyhvDtpYVYGtRJ1PGZJhigT3mnl9jwqYj7tTBYVM=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1 h1:VMFlG+9a1JoNAQ3M96g8iqCq0cDRtE7XBaiTD8Ouvqw=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1/go.mod h1:b/70rA4OgOHlg0A7pb8zTWKJadFO6781zS3a37KHEJQ=
+github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240926015724-84c2ec076201 h1:2QBYa9Df+vMwMiaHaFqPoUiwfx5vcPEgM7KbusivTpw=
+github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240926015724-84c2ec076201/go.mod h1:F6zMQl3PhVdCsI1xlIjK66kCorUQhWkoMtlZdvJWxFI=
 github.com/notaryproject/notation-plugin-framework-go v1.0.0 h1:6Qzr7DGXoCgXEQN+1gTZWuJAZvxh3p8Lryjn5FaLzi4=
 github.com/notaryproject/notation-plugin-framework-go v1.0.0/go.mod h1:RqWSrTOtEASCrGOEffq0n8pSg2KOgKYiWqFWczRSics=
 github.com/notaryproject/tspclient-go v0.2.0 h1:g/KpQGmyk/h7j60irIRG1mfWnibNOzJ8WhLqAzuiQAQ=
@@ -79,8 +79,8 @@ golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
 golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
-golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
+golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
diff --git a/test/e2e/go.mod b/test/e2e/go.mod
index 195eb3189..8eb559a31 100644
--- a/test/e2e/go.mod
+++ b/test/e2e/go.mod
@@ -3,7 +3,7 @@ module github.com/notaryproject/notation/test/e2e
 go 1.23
 
 require (
-	github.com/notaryproject/notation-core-go v1.1.0
+	github.com/notaryproject/notation-core-go v1.2.0-rc.1
 	github.com/onsi/ginkgo/v2 v2.20.2
 	github.com/onsi/gomega v1.34.1
 	github.com/opencontainers/image-spec v1.1.0
diff --git a/test/e2e/go.sum b/test/e2e/go.sum
index 54a22c818..5b9cd34bb 100644
--- a/test/e2e/go.sum
+++ b/test/e2e/go.sum
@@ -10,8 +10,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA=
 github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
-github.com/notaryproject/notation-core-go v1.1.0 h1:xCybcONOKcCyPNihJUSa+jRNsyQFNkrk0eJVVs1kWeg=
-github.com/notaryproject/notation-core-go v1.1.0/go.mod h1:+6AOh41JPrnVLbW/19SJqdhVHwKgIINBO/np0e7nXJA=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1 h1:VMFlG+9a1JoNAQ3M96g8iqCq0cDRtE7XBaiTD8Ouvqw=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1/go.mod h1:b/70rA4OgOHlg0A7pb8zTWKJadFO6781zS3a37KHEJQ=
 github.com/notaryproject/tspclient-go v0.2.0 h1:g/KpQGmyk/h7j60irIRG1mfWnibNOzJ8WhLqAzuiQAQ=
 github.com/notaryproject/tspclient-go v0.2.0/go.mod h1:LGyA/6Kwd2FlM0uk8Vc5il3j0CddbWSHBj/4kxQDbjs=
 github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
@@ -30,8 +30,8 @@ github.com/veraison/go-cose v1.1.0 h1:AalPS4VGiKavpAzIlBjrn7bhqXiXi4jbMYY/2+UC+4
 github.com/veraison/go-cose v1.1.0/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4=
 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
-golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
+golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
+golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
 golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
diff --git a/test/e2e/plugin/go.mod b/test/e2e/plugin/go.mod
index 6aee06732..50b1f8928 100644
--- a/test/e2e/plugin/go.mod
+++ b/test/e2e/plugin/go.mod
@@ -4,8 +4,8 @@ go 1.23
 
 require (
 	github.com/golang-jwt/jwt v3.2.2+incompatible
-	github.com/notaryproject/notation-core-go v1.1.0
-	github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240814004621-3c5a659c1d1d
+	github.com/notaryproject/notation-core-go v1.2.0-rc.1
+	github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240926015724-84c2ec076201
 	github.com/notaryproject/notation-plugin-framework-go v1.0.0
 	github.com/spf13/cobra v1.7.0
 )
@@ -24,8 +24,8 @@ require (
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/veraison/go-cose v1.1.0 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
-	golang.org/x/crypto v0.26.0 // indirect
-	golang.org/x/mod v0.19.0 // indirect
+	golang.org/x/crypto v0.27.0 // indirect
+	golang.org/x/mod v0.21.0 // indirect
 	golang.org/x/sync v0.6.0 // indirect
 	oras.land/oras-go/v2 v2.5.0 // indirect
 )
diff --git a/test/e2e/plugin/go.sum b/test/e2e/plugin/go.sum
index f0873c469..a62b56746 100644
--- a/test/e2e/plugin/go.sum
+++ b/test/e2e/plugin/go.sum
@@ -37,10 +37,10 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
 github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
 github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
-github.com/notaryproject/notation-core-go v1.1.0 h1:xCybcONOKcCyPNihJUSa+jRNsyQFNkrk0eJVVs1kWeg=
-github.com/notaryproject/notation-core-go v1.1.0/go.mod h1:+6AOh41JPrnVLbW/19SJqdhVHwKgIINBO/np0e7nXJA=
-github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240814004621-3c5a659c1d1d h1:7/lNsNkauXRhFuQ7TXTBuJA9PjrLhVraaAHuoDisK5Q=
-github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240814004621-3c5a659c1d1d/go.mod h1:YpPRyhvDtpYVYGtRJ1PGZJhigT3mnl9jwqYj7tTBYVM=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1 h1:VMFlG+9a1JoNAQ3M96g8iqCq0cDRtE7XBaiTD8Ouvqw=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1/go.mod h1:b/70rA4OgOHlg0A7pb8zTWKJadFO6781zS3a37KHEJQ=
+github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240926015724-84c2ec076201 h1:2QBYa9Df+vMwMiaHaFqPoUiwfx5vcPEgM7KbusivTpw=
+github.com/notaryproject/notation-go v1.2.0-beta.1.0.20240926015724-84c2ec076201/go.mod h1:F6zMQl3PhVdCsI1xlIjK66kCorUQhWkoMtlZdvJWxFI=
 github.com/notaryproject/notation-plugin-framework-go v1.0.0 h1:6Qzr7DGXoCgXEQN+1gTZWuJAZvxh3p8Lryjn5FaLzi4=
 github.com/notaryproject/notation-plugin-framework-go v1.0.0/go.mod h1:RqWSrTOtEASCrGOEffq0n8pSg2KOgKYiWqFWczRSics=
 github.com/notaryproject/tspclient-go v0.2.0 h1:g/KpQGmyk/h7j60irIRG1mfWnibNOzJ8WhLqAzuiQAQ=
@@ -74,12 +74,12 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
 golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
-golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
+golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
+golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
-golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
+golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
diff --git a/test/e2e/suite/command/inspect.go b/test/e2e/suite/command/inspect.go
index a6f6c1880..8d04aa9e4 100644
--- a/test/e2e/suite/command/inspect.go
+++ b/test/e2e/suite/command/inspect.go
@@ -34,7 +34,7 @@ var (
 		"├── user defined attributes",
 		"│   └── (empty)",
 		"├── unsigned attributes",
-		"│   └── signingAgent: Notation/",
+		"│   └── signingAgent: notation-go/",
 		"├── certificates",
 		"│   └── SHA256 fingerprint:",
 		"issued to:",
@@ -57,7 +57,7 @@ var (
 		"├── user defined attributes",
 		"│   └── (empty)",
 		"├── unsigned attributes",
-		"signingAgent: Notation/",
+		"signingAgent: notation-go/",
 		"timestamp signature",
 		"timestamp:",
 		"certificates",
diff --git a/test/e2e/suite/command/verify.go b/test/e2e/suite/command/verify.go
index f5f8aa333..239b363b2 100644
--- a/test/e2e/suite/command/verify.go
+++ b/test/e2e/suite/command/verify.go
@@ -213,6 +213,17 @@ var _ = Describe("notation verify", func() {
 		})
 	})
 
+	It("NOTATION_CACHE", func() {
+		Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
+			notation.Exec("sign", artifact.ReferenceWithDigest()).
+				MatchKeyWords(SignSuccessfully)
+
+			vhost.UpdateEnv(map[string]string{"NOTATION_CACHE": vhost.AbsolutePath(NotationDirName)})
+			notation.Exec("verify", artifact.ReferenceWithDigest(), "-v").
+				MatchKeyWords(VerifySuccessfully)
+		})
+	})
+
 	It("with timestamp verification disabled", func() {
 		Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
 			notation.Exec("sign", "--timestamp-url", "http://timestamp.digicert.com", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "DigiCertTSARootSHA384.cer"), artifact.ReferenceWithDigest()).