1
0
Fork 0
mirror of https://github.com/gocsaf/csaf.git synced 2025-12-22 11:55:40 +01:00

Avoid duplicate errors checking and logging when loading pmds.

This commit is contained in:
Sascha L. Teichmann 2022-07-23 16:11:54 +02:00
parent 1b0e5b4238
commit 58ec57e1cb

View file

@ -36,7 +36,11 @@ type LoadedProviderMetadata struct {
// LoadProviderMetadataFromURL loads a provider metadata from a given URL. // LoadProviderMetadataFromURL loads a provider metadata from a given URL.
// Returns nil if the document was not found. // Returns nil if the document was not found.
func LoadProviderMetadataFromURL(client util.Client, url string) *LoadedProviderMetadata { func LoadProviderMetadataFromURL(
client util.Client,
url string,
already map[string]*LoadedProviderMetadata,
) *LoadedProviderMetadata {
res, err := client.Get(url) res, err := client.Get(url)
@ -56,21 +60,40 @@ func LoadProviderMetadataFromURL(client util.Client, url string) *LoadedProvider
tee := io.TeeReader(res.Body, hash) tee := io.TeeReader(res.Body, hash)
if err := json.NewDecoder(tee).Decode(&result.Document); err != nil { err = json.NewDecoder(tee).Decode(&result.Document)
result.Messages = []string{fmt.Sprintf("%s: Decoding JSON failed: %v", url, err)} // Before checking the err lets check if we had the same
return &result // document before. If so it will have failed parsing before.
}
result.Hash = hash.Sum(nil) result.Hash = hash.Sum(nil)
errors, err := ValidateProviderMetadata(result.Document) var key string
if already != nil {
key = string(result.Hash)
if r, ok := already[key]; ok {
return r
}
}
// write it back as loaded
storeLoaded := func() {
if already != nil {
already[key] = &result
}
}
// We have loaded it the first time.
if err != nil { if err != nil {
result.Messages = []string{ result.Messages = []string{fmt.Sprintf("%s: Decoding JSON failed: %v", url, err)}
fmt.Sprintf("%s: Validating against JSON schema failed: %v", url, err)} storeLoaded()
return &result return &result
} }
if len(errors) > 0 { switch errors, err := ValidateProviderMetadata(result.Document); {
case err != nil:
result.Messages = []string{
fmt.Sprintf("%s: Validating against JSON schema failed: %v", url, err)}
case len(errors) > 0:
result.Messages = []string{ result.Messages = []string{
fmt.Sprintf("%s: Validating against JSON schema failed: %v", url, err)} fmt.Sprintf("%s: Validating against JSON schema failed: %v", url, err)}
for _, msg := range errors { for _, msg := range errors {
@ -78,13 +101,18 @@ func LoadProviderMetadataFromURL(client util.Client, url string) *LoadedProvider
} }
} }
storeLoaded()
return &result return &result
} }
// LoadProviderMetadatasFromSecurity loads a secturity.txt, // LoadProviderMetadatasFromSecurity loads a secturity.txt,
// extracts and the CSAF urls from the document. // extracts and the CSAF urls from the document.
// Returns nil if no url was successfully found. // Returns nil if no url was successfully found.
func LoadProviderMetadatasFromSecurity(client util.Client, path string) []*LoadedProviderMetadata { func LoadProviderMetadatasFromSecurity(
client util.Client,
path string,
already map[string]*LoadedProviderMetadata,
) []*LoadedProviderMetadata {
res, err := client.Get(path) res, err := client.Get(path)
@ -108,7 +136,7 @@ func LoadProviderMetadatasFromSecurity(client util.Client, path string) []*Loade
// Load the URLs // Load the URLs
for _, url := range urls { for _, url := range urls {
if result := LoadProviderMetadataFromURL(client, url); result != nil { if result := LoadProviderMetadataFromURL(client, url, already); result != nil {
results = append(results, result) results = append(results, result)
} }
} }
@ -133,19 +161,30 @@ func LoadProviderMetadataForDomain(
} }
} }
// As many URLs may lead to the same content only log once per content.
alreadyLogged := map[*LoadedProviderMetadata]string{}
lg := func(result *LoadedProviderMetadata, url string) { lg := func(result *LoadedProviderMetadata, url string) {
if result == nil { if result == nil {
logging("%s not found.", url) logging("%q not found.", url)
} else { return
for _, msg := range result.Messages { }
logging(msg) if other := alreadyLogged[result]; other != "" {
} logging("%q is same %q.", url, other)
return
}
alreadyLogged[result] = url
for _, msg := range result.Messages {
logging(msg)
} }
} }
// keey track of already loaded pmds.
already := map[string]*LoadedProviderMetadata{}
// check direct path // check direct path
if strings.HasPrefix(domain, "https://") { if strings.HasPrefix(domain, "https://") {
result := LoadProviderMetadataFromURL(client, domain) result := LoadProviderMetadataFromURL(client, domain, already)
lg(result, domain) lg(result, domain)
return result return result
} }
@ -155,7 +194,7 @@ func LoadProviderMetadataForDomain(
// First try well-know path // First try well-know path
wellknownURL := "https://" + domain + "/.well-known/csaf/provider-metadata.json" wellknownURL := "https://" + domain + "/.well-known/csaf/provider-metadata.json"
wellknownResult := LoadProviderMetadataFromURL(client, wellknownURL) wellknownResult := LoadProviderMetadataFromURL(client, wellknownURL, already)
lg(wellknownResult, wellknownURL) lg(wellknownResult, wellknownURL)
// We have a candidate. // We have a candidate.
@ -165,7 +204,7 @@ func LoadProviderMetadataForDomain(
// Next load the PMDs from security.txt // Next load the PMDs from security.txt
secURL := "https://" + domain + "/.well-known/security.txt" secURL := "https://" + domain + "/.well-known/security.txt"
secResults := LoadProviderMetadatasFromSecurity(client, secURL) secResults := LoadProviderMetadatasFromSecurity(client, secURL, already)
if secResults == nil { if secResults == nil {
logging("%s failed to load.", secURL) logging("%s failed to load.", secURL)
@ -175,9 +214,7 @@ func LoadProviderMetadataForDomain(
for _, result := range secResults { for _, result := range secResults {
if len(result.Messages) > 0 { if len(result.Messages) > 0 {
for _, msg := range result.Messages { lg(result, result.URL)
logging(msg)
}
} else { } else {
secGoods = append(secGoods, result) secGoods = append(secGoods, result)
} }
@ -222,7 +259,7 @@ func LoadProviderMetadataForDomain(
// Last resort: fall back to DNS. // Last resort: fall back to DNS.
dnsURL := "https://csaf.data.security." + domain dnsURL := "https://csaf.data.security." + domain
dnsResult := LoadProviderMetadataFromURL(client, dnsURL) dnsResult := LoadProviderMetadataFromURL(client, dnsURL, already)
lg(dnsResult, dnsURL) lg(dnsResult, dnsURL)
return dnsResult return dnsResult
} }