Skip to content

Commit

Permalink
test: add CRL e2e test
Browse files Browse the repository at this point in the history
Signed-off-by: Junjie Gao <[email protected]>
  • Loading branch information
JeyJeyGao committed Nov 8, 2024
1 parent 6f2860a commit 3d8fb76
Show file tree
Hide file tree
Showing 15 changed files with 496 additions and 43 deletions.
15 changes: 7 additions & 8 deletions test/e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ go 1.23

require (
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/onsi/ginkgo/v2 v2.21.0
github.com/onsi/gomega v1.34.2
github.com/opencontainers/image-spec v1.1.0
oras.land/oras-go/v2 v2.5.0
)
Expand All @@ -15,17 +15,16 @@ require (
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
github.com/notaryproject/tspclient-go v0.2.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/veraison/go-cose v1.1.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/tools v0.24.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.26.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

Expand Down
34 changes: 16 additions & 18 deletions test/e2e/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
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/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
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=
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
Expand All @@ -30,20 +30,18 @@ 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.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=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
Expand Down
21 changes: 15 additions & 6 deletions test/e2e/internal/notation/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func Opts(options ...utils.HostOption) []utils.HostOption {
func BaseOptions() []utils.HostOption {
return Opts(
AuthOption("", ""),
AddKeyOption("e2e.key", "e2e.crt"),
AddKeyOption(filepath.Join(NotationE2ELocalKeysDir, "e2e.key"), filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTrustStoreOption("e2e", filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTrustPolicyOption("trustpolicy.json"),
)
Expand All @@ -141,18 +141,27 @@ func TimestampOptions(verifyTimestamp string) []utils.HostOption {

return Opts(
AuthOption("", ""),
AddKeyOption("e2e.key", "e2e.crt"),
AddKeyOption(filepath.Join(NotationE2ELocalKeysDir, "e2e.key"), filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTrustStoreOption("e2e", filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTimestampTrustStoreOption("e2e", filepath.Join(NotationE2EConfigPath, "timestamp", "globalsignTSARoot.cer")),
AddTimestampTrustStoreOption("e2e", filepath.Join(NotationE2EConfigPath, "timestamp", "DigiCertTSARootSHA384.cer")),
trustPolicyOption,
)
}

func CRLOptions() []utils.HostOption {
return Opts(
AuthOption("", ""),
AddKeyOption(filepath.Join(NotationE2EConfigPath, "crl", "leaf.key"), filepath.Join(NotationE2EConfigPath, "crl", "certchain_with_crl.pem")),
AddTrustStoreOption("e2e", filepath.Join(NotationE2EConfigPath, "crl", "root.crt")),
AddTrustPolicyOption("trustpolicy.json"),
)
}

func BaseOptionsWithExperimental() []utils.HostOption {
return Opts(
AuthOption("", ""),
AddKeyOption("e2e.key", "e2e.crt"),
AddKeyOption(filepath.Join(NotationE2ELocalKeysDir, "e2e.key"), filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTrustStoreOption("e2e", filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTrustPolicyOption("trustpolicy.json"),
EnableExperimental(),
Expand All @@ -163,7 +172,7 @@ func BaseOptionsWithExperimental() []utils.HostOption {
// testing environment.
func TestLoginOptions() []utils.HostOption {
return Opts(
AddKeyOption("e2e.key", "e2e.crt"),
AddKeyOption(filepath.Join(NotationE2ELocalKeysDir, "e2e.key"), filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTrustStoreOption("e2e", filepath.Join(NotationE2ELocalKeysDir, "e2e.crt")),
AddTrustPolicyOption("trustpolicy.json"),
AddConfigJsonOption("pass_credential_helper_config.json"),
Expand Down Expand Up @@ -193,9 +202,9 @@ func AuthOption(username, password string) utils.HostOption {

// AddKeyOption adds the test signingkeys.json, key and cert files to
// the notation directory.
func AddKeyOption(keyName, certName string) utils.HostOption {
func AddKeyOption(keyPath, certPath string) utils.HostOption {
return func(vhost *utils.VirtualHost) error {
return AddKeyPairs(vhost.AbsolutePath(NotationDirName), keyName, certName)
return AddKeyPairs(vhost.AbsolutePath(NotationDirName), keyPath, certPath)
}
}

Expand Down
20 changes: 11 additions & 9 deletions test/e2e/internal/notation/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,35 +53,37 @@ type SigningKeys struct {

// AddKeyPairs creates the signingkeys.json file and the localkeys directory
// with e2e.key and e2e.crt
func AddKeyPairs(dir, keyName, certName string) error {
func AddKeyPairs(destNotationConfigDir, srcKeyPath, srcCertPath string) error {
keyName := filepath.Base(srcKeyPath)
certName := filepath.Base(srcCertPath)
// create signingkeys.json files
if err := saveJSON(
generateSigningKeys(dir),
filepath.Join(dir, SigningKeysFileName)); err != nil {
generateSigningKeys(destNotationConfigDir, keyName, certName),
filepath.Join(destNotationConfigDir, SigningKeysFileName)); err != nil {
return err
}

// create localkeys directory
localKeysDir := filepath.Join(dir, LocalKeysDirName)
localKeysDir := filepath.Join(destNotationConfigDir, LocalKeysDirName)
os.MkdirAll(localKeysDir, 0700)

// copy key and cert files
if err := copyFile(filepath.Join(NotationE2ELocalKeysDir, keyName), filepath.Join(localKeysDir, "e2e.key")); err != nil {
if err := copyFile(srcKeyPath, filepath.Join(localKeysDir, keyName)); err != nil {
return err
}
return copyFile(filepath.Join(NotationE2ELocalKeysDir, certName), filepath.Join(localKeysDir, "e2e.crt"))
return copyFile(srcCertPath, filepath.Join(localKeysDir, certName))
}

// generateSigningKeys generates the signingkeys.json for notation.
func generateSigningKeys(dir string) *SigningKeys {
func generateSigningKeys(dir, keyName, certName string) *SigningKeys {
return &SigningKeys{
Default: "e2e",
Keys: []KeySuite{
{
Name: "e2e",
X509KeyPair: &X509KeyPair{
KeyPath: filepath.Join(dir, "localkeys", "e2e.key"),
CertificatePath: filepath.Join(dir, "localkeys", "e2e.crt"),
KeyPath: filepath.Join(dir, "localkeys", keyName),
CertificatePath: filepath.Join(dir, "localkeys", certName),
},
},
},
Expand Down
43 changes: 43 additions & 0 deletions test/e2e/internal/utils/crl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright The Notary Project Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package utils

import (
"fmt"
"net/http"
)

// CRLRevoke sends http post request to http://localhost:8080/revoke
func CRLRevoke() error {
url := "http://localhost:10086/revoke"
resp, err := http.Post(url, "application/json", nil)
if err != nil {
return err
}
defer resp.Body.Close()
fmt.Printf("CRL revoked with status code: %d\n", resp.StatusCode)
return nil
}

// CRLUnrevoke sends http post request to http://localhost:8080/unrevoke
func CRLUnrevoke() error {
url := "http://localhost:10086/unrevoke"
resp, err := http.Post(url, "application/json", nil)
if err != nil {
return err
}
defer resp.Body.Close()
fmt.Printf("CRL unrevoked with status code: %d\n", resp.StatusCode)
return nil
}
1 change: 1 addition & 0 deletions test/e2e/internal/utils/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,6 @@ func UserConfigEnv(dir string) map[string]string {
// create and set user dir for linux
return map[string]string{
"XDG_CONFIG_HOME": dir,
"XDG_CACHE_HOME": filepath.Join(dir, ".cache"),
}
}
11 changes: 9 additions & 2 deletions test/e2e/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ if [ ! -f "$NOTATION_E2E_OLD_BINARY_PATH" ]; then
fi

# install dependency
go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo@v2.11.0
go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo@v2.21.0

# build e2e plugin and tar.gz
PLUGIN_NAME=notation-e2e-plugin
Expand All @@ -95,9 +95,16 @@ esac

setup_registry

# run the download server in the background
python3 ./scripts/crl_server.py &
CRL_SERVER_PID=$!

# defer cleanup registry
function cleanup {
echo "Cleaning up..."
cleanup_registry
echo "Stopping CRL server..."
kill $CRL_SERVER_PID
}
trap cleanup EXIT

Expand All @@ -111,4 +118,4 @@ export NOTATION_E2E_PLUGIN_TAR_GZ_PATH=$CWD/plugin/bin/$PLUGIN_NAME.tar.gz
export NOTATION_E2E_MALICIOUS_PLUGIN_ARCHIVE_PATH=$CWD/testdata/malicious-plugin

# run tests
ginkgo -r -p -v
ginkgo -r -p -v --focus "notation CRL revocation check"
63 changes: 63 additions & 0 deletions test/e2e/scripts/crl_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright The Notary Project Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import http.server
import socketserver
import os

PORT = 10086
DATA_DIR = './testdata/config/crl'
revoke_flag = False


class CRLRequestHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
global revoke_flag
if self.path == '/leaf.crl':
file_name = 'leaf_revoked.crl' if revoke_flag else 'leaf.crl'
file_path = os.path.join(DATA_DIR, file_name)
print("crl path", file_path)
if os.path.exists(file_path):
self.send_response(200)
self.send_header('Content-Type', 'application/pkix-crl')
self.end_headers()
with open(file_path, 'rb') as f:
self.wfile.write(f.read())
else:
self.send_error(404, 'File Not Found')
else:
self.send_error(404, 'Not Found')
def do_POST(self):
global revoke_flag
if self.path == '/revoke':
revoke_flag = True
self.send_response(201)
self.end_headers()
self.wfile.write(b'ok')
elif self.path == '/unrevoke':
revoke_flag = False
self.send_response(201)
self.end_headers()
self.wfile.write(b'ok')
else:
self.send_error(404, 'Not Found')

class ReusableTCPServer(socketserver.TCPServer):
allow_reuse_address = True

with ReusableTCPServer(('', PORT), CRLRequestHandler) as httpd:
print(f"Serving at port {PORT}")
try:
httpd.serve_forever()
finally:
httpd.server_close()
Loading

0 comments on commit 3d8fb76

Please sign in to comment.