0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-30 22:34:13 -05:00

fix(cli): do not show signatures and fix tls verification client side (#904)

Issues fixed:
- the cli calls reaching out to the catalog endpoint used to request signature manifests
- resty was used instead of the cli http client to check if the discovery api was available
but it did not take into account TLS verification configuration
(testing locally withself-signed certificates did not work)

(cherry picked from commit ca42031ae9b1ceb459f5cd4f86cb82b3c9f78157)
Signed-off-by: Andrei Aaron <andaaron@cisco.com>
This commit is contained in:
Andrei Aaron 2022-10-23 09:44:20 +03:00 committed by GitHub
parent ac6c6a844c
commit 1d9c88c313
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 71 deletions

View file

@ -4,19 +4,14 @@
package cli
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"path"
"github.com/briandowns/spinner"
"github.com/spf13/cobra"
"gopkg.in/resty.v1"
zotErrors "zotregistry.io/zot/errors"
"zotregistry.io/zot/pkg/api/constants"
)
func NewCveCommand(searchService SearchService) *cobra.Command {
@ -142,74 +137,10 @@ type cveFlagVariables struct {
debug *bool
}
type field struct {
Name string `json:"name"`
}
type schemaList struct {
Data struct {
Schema struct {
QueryType struct {
Fields []field `json:"fields"`
} `json:"queryType"` //nolint:tagliatelle // graphQL schema
} `json:"__schema"` //nolint:tagliatelle // graphQL schema
} `json:"data"`
}
func containsGQLQuery(queryList []field, query string) bool {
for _, q := range queryList {
if q.Name == query {
return true
}
}
return false
}
func checkExtEndPoint(serverURL string) bool {
client := resty.New()
extEndPoint, err := combineServerAndEndpointURL(serverURL, fmt.Sprintf("%s%s",
constants.RoutePrefix, constants.ExtOciDiscoverPrefix))
if err != nil {
return false
}
//nolint: gosec
resp, err := client.R().Get(extEndPoint)
if err != nil || resp.StatusCode() != http.StatusOK {
return false
}
searchEndPoint, _ := combineServerAndEndpointURL(serverURL, constants.FullSearchPrefix)
query := `
{
__schema() {
queryType {
fields {
name
}
}
}
}`
resp, err = client.R().Get(searchEndPoint + "?query=" + url.QueryEscape(query))
if err != nil || resp.StatusCode() != http.StatusOK {
return false
}
queryList := &schemaList{}
_ = json.Unmarshal(resp.Body(), queryList)
return containsGQLQuery(queryList.Data.Schema.QueryType.Fields, "ImageList")
}
func searchCve(searchConfig searchConfig) error {
var searchers []searcher
if checkExtEndPoint(*searchConfig.servURL) {
if checkExtEndPoint(searchConfig) {
searchers = getCveSearchersGQL()
} else {
searchers = getCveSearchers()

100
pkg/cli/discover.go Normal file
View file

@ -0,0 +1,100 @@
//go:build search
// +build search
package cli
import (
"context"
"fmt"
distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"
"zotregistry.io/zot/pkg/api/constants"
)
type field struct {
Name string `json:"name"`
}
type schemaList struct {
Data struct {
Schema struct {
QueryType struct {
Fields []field `json:"fields"`
} `json:"queryType"` //nolint:tagliatelle // graphQL schema
} `json:"__schema"` //nolint:tagliatelle // graphQL schema
} `json:"data"`
Errors []errorGraphQL `json:"errors"`
}
func containsGQLQuery(queryList []field, query string) bool {
for _, q := range queryList {
if q.Name == query {
return true
}
}
return false
}
func checkExtEndPoint(config searchConfig) bool {
username, password := getUsernameAndPassword(*config.user)
ctx := context.Background()
discoverEndPoint, err := combineServerAndEndpointURL(*config.servURL, fmt.Sprintf("%s%s",
constants.RoutePrefix, constants.ExtOciDiscoverPrefix))
if err != nil {
return false
}
discoverResponse := &distext.ExtensionList{}
_, err = makeGETRequest(ctx, discoverEndPoint, username, password, *config.verifyTLS,
*config.debug, &discoverResponse, config.resultWriter)
if err != nil {
return false
}
searchEnabled := false
for _, extension := range discoverResponse.Extensions {
if extension.Name == "_zot" {
for _, endpoint := range extension.Endpoints {
if endpoint == constants.FullSearchPrefix {
searchEnabled = true
}
}
}
}
if !searchEnabled {
return false
}
searchEndPoint, _ := combineServerAndEndpointURL(*config.servURL, constants.FullSearchPrefix)
query := `
{
__schema() {
queryType {
fields {
name
}
}
}
}`
queryResponse := &schemaList{}
err = makeGraphQLRequest(ctx, searchEndPoint, query, username, password, *config.verifyTLS,
*config.debug, queryResponse, config.resultWriter)
if err != nil {
return false
}
if err = checkResultGraphQLQuery(ctx, err, queryResponse.Errors); err != nil {
return false
}
return containsGQLQuery(queryResponse.Data.Schema.QueryType.Fields, "ImageList")
}

View file

@ -138,7 +138,7 @@ func setupImageFlags(imageCmd *cobra.Command, searchImageParams map[string]*stri
func searchImage(searchConfig searchConfig) error {
var searchers []searcher
if checkExtEndPoint(*searchConfig.servURL) {
if checkExtEndPoint(searchConfig) {
searchers = getImageSearchersGQL()
} else {
searchers = getImageSearchers()

View file

@ -324,6 +324,15 @@ func getImage(ctx context.Context, config searchConfig, username, password, imag
}
for _, tag := range tagList.Tags {
hasTagPrefix := strings.HasPrefix(tag, "sha256-")
hasTagSuffix := strings.HasSuffix(tag, ".sig")
// check if it's an image or a signature
// we don't want to show signatures in cli responses
if hasTagPrefix && hasTagSuffix {
continue
}
wtgrp.Add(1)
go addManifestCallToPool(ctx, config, pool, username, password, imageName, tag, rch, wtgrp)