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

Fix aggregator URL handling (#631)

* Fix aggregator URL handling

Parts of the URL were not path escaped. This results in a wrong URL; if
the provider name contains characters that need to be escaped.

* Simplify JoinPath usage
This commit is contained in:
Paul Schwabauer 2025-04-02 17:05:29 +02:00 committed by GitHub
parent a05ba731dd
commit 2f599ab017
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 35 deletions

View file

@ -183,19 +183,26 @@ func (w *worker) writeROLIENoSummaries(label string) error {
fname := "csaf-feed-tlp-" + labelFolder + ".json" fname := "csaf-feed-tlp-" + labelFolder + ".json"
feedURL := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + feedURL, err := w.getProviderBaseURL()
w.provider.Name + "/" + labelFolder + "/" + fname if err != nil {
return err
}
feedURL = feedURL.JoinPath(labelFolder, fname)
links := []csaf.Link{{ links := []csaf.Link{{
Rel: "self", Rel: "self",
HRef: feedURL, HRef: feedURL.String(),
}} }}
if w.provider.serviceDocument(w.processor.cfg) { if w.provider.serviceDocument(w.processor.cfg) {
serviceURL, err := w.getProviderBaseURL()
if err != nil {
return err
}
serviceURL = serviceURL.JoinPath("service.json")
links = append(links, csaf.Link{ links = append(links, csaf.Link{
Rel: "service", Rel: "service",
HRef: w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + HRef: serviceURL.String(),
w.provider.Name + "/service.json",
}) })
} }
@ -223,8 +230,11 @@ func (w *worker) writeROLIE(label string, summaries []summary) error {
fname := "csaf-feed-tlp-" + labelFolder + ".json" fname := "csaf-feed-tlp-" + labelFolder + ".json"
feedURL := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + feedURL, err := w.getProviderBaseURL()
w.provider.Name + "/" + labelFolder + "/" + fname if err != nil {
return err
}
feedURL = feedURL.JoinPath(labelFolder, fname)
entries := make([]*csaf.Entry, len(summaries)) entries := make([]*csaf.Entry, len(summaries))
@ -236,10 +246,13 @@ func (w *worker) writeROLIE(label string, summaries []summary) error {
for i := range summaries { for i := range summaries {
s := &summaries[i] s := &summaries[i]
csafURL := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + csafURL, err := w.getProviderBaseURL()
w.provider.Name + "/" + label + "/" + if err != nil {
strconv.Itoa(s.summary.InitialReleaseDate.Year()) + "/" + return err
s.filename }
csafURLString := csafURL.JoinPath(label,
strconv.Itoa(s.summary.InitialReleaseDate.Year()),
s.filename).String()
entries[i] = &csaf.Entry{ entries[i] = &csaf.Entry{
ID: s.summary.ID, ID: s.summary.ID,
@ -247,15 +260,15 @@ func (w *worker) writeROLIE(label string, summaries []summary) error {
Published: csaf.TimeStamp(s.summary.InitialReleaseDate), Published: csaf.TimeStamp(s.summary.InitialReleaseDate),
Updated: csaf.TimeStamp(s.summary.CurrentReleaseDate), Updated: csaf.TimeStamp(s.summary.CurrentReleaseDate),
Link: []csaf.Link{ Link: []csaf.Link{
{Rel: "self", HRef: csafURL}, {Rel: "self", HRef: csafURLString},
{Rel: "hash", HRef: csafURL + ".sha256"}, {Rel: "hash", HRef: csafURLString + ".sha256"},
{Rel: "hash", HRef: csafURL + ".sha512"}, {Rel: "hash", HRef: csafURLString + ".sha512"},
{Rel: "signature", HRef: csafURL + ".asc"}, {Rel: "signature", HRef: csafURLString + ".asc"},
}, },
Format: format, Format: format,
Content: csaf.Content{ Content: csaf.Content{
Type: "application/json", Type: "application/json",
Src: csafURL, Src: csafURLString,
}, },
} }
if s.summary.Summary != "" { if s.summary.Summary != "" {
@ -267,14 +280,18 @@ func (w *worker) writeROLIE(label string, summaries []summary) error {
links := []csaf.Link{{ links := []csaf.Link{{
Rel: "self", Rel: "self",
HRef: feedURL, HRef: feedURL.String(),
}} }}
if w.provider.serviceDocument(w.processor.cfg) { if w.provider.serviceDocument(w.processor.cfg) {
serviceURL, err := w.getProviderBaseURL()
if err != nil {
return err
}
serviceURL = serviceURL.JoinPath("service.json")
links = append(links, csaf.Link{ links = append(links, csaf.Link{
Rel: "service", Rel: "service",
HRef: w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + HRef: serviceURL.String(),
w.provider.Name + "/service.json",
}) })
} }
@ -344,12 +361,15 @@ func (w *worker) writeService() error {
for _, ts := range labels { for _, ts := range labels {
feedName := "csaf-feed-tlp-" + ts + ".json" feedName := "csaf-feed-tlp-" + ts + ".json"
href := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + hrefURL, err := w.getProviderBaseURL()
w.provider.Name + "/" + ts + "/" + feedName if err != nil {
return err
}
hrefURL = hrefURL.JoinPath(ts, feedName)
collection := csaf.ROLIEServiceWorkspaceCollection{ collection := csaf.ROLIEServiceWorkspaceCollection{
Title: "CSAF feed (TLP:" + strings.ToUpper(ts) + ")", Title: "CSAF feed (TLP:" + strings.ToUpper(ts) + ")",
HRef: href, HRef: hrefURL.String(),
Categories: categories, Categories: categories,
} }
collections = append(collections, collection) collections = append(collections, collection)

View file

@ -103,9 +103,13 @@ func (w *worker) mirrorInternal() (*csaf.AggregatorCSAFProvider, error) {
} }
// Add us as a mirror. // Add us as a mirror.
mirror, err := w.getProviderBaseURL()
if err != nil {
return nil, err
}
mirrorURL := csaf.ProviderURL( mirrorURL := csaf.ProviderURL(
fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/provider-metadata.json", mirror.JoinPath("provider-metadata.json").String(),
w.processor.cfg.Domain, w.provider.Name)) )
acp.Mirrors = []csaf.ProviderURL{ acp.Mirrors = []csaf.ProviderURL{
mirrorURL, mirrorURL,
@ -128,8 +132,12 @@ func (w *worker) writeProviderMetadata() error {
fname := filepath.Join(w.dir, "provider-metadata.json") fname := filepath.Join(w.dir, "provider-metadata.json")
prefixURL, err := w.getProviderBaseURL()
if err != nil {
return err
}
pm := csaf.NewProviderMetadataPrefix( pm := csaf.NewProviderMetadataPrefix(
w.processor.cfg.Domain+"/.well-known/csaf-aggregator/"+w.provider.Name, prefixURL.String(),
w.labelsFromSummaries()) w.labelsFromSummaries())
// Fill in directory URLs if needed. // Fill in directory URLs if needed.
@ -139,9 +147,8 @@ func (w *worker) writeProviderMetadata() error {
labels = append(labels, label) labels = append(labels, label)
} }
sort.Strings(labels) sort.Strings(labels)
prefix := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + w.provider.Name + "/"
for _, label := range labels { for _, label := range labels {
pm.AddDirectoryDistribution(prefix + label) pm.AddDirectoryDistribution(prefixURL.JoinPath(label).String())
} }
} }
@ -188,9 +195,12 @@ func (w *worker) mirrorPGPKeys(pm *csaf.ProviderMetadata) error {
return err return err
} }
keyURL, err := w.getProviderBaseURL()
if err != nil {
return err
}
localKeyURL := func(fingerprint string) string { localKeyURL := func(fingerprint string) string {
return fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/openpgp/%s.asc", return keyURL.JoinPath("openpgp", (fingerprint + ".asc")).String()
w.processor.cfg.Domain, w.provider.Name, fingerprint)
} }
for i := range pm.PGPKeys { for i := range pm.PGPKeys {
@ -240,8 +250,8 @@ func (w *worker) mirrorPGPKeys(pm *csaf.ProviderMetadata) error {
} }
// replace the URL // replace the URL
url := localKeyURL(fingerprint) u := localKeyURL(fingerprint)
pgpKey.URL = &url pgpKey.URL = &u
} }
// If we have public key configured copy it into the new folder // If we have public key configured copy it into the new folder
@ -308,7 +318,7 @@ func (w *worker) createAggregatorProvider() (*csaf.AggregatorCSAFProvider, error
var ( var (
lastUpdated = csaf.TimeStamp(lastUpdatedT) lastUpdated = csaf.TimeStamp(lastUpdatedT)
role = csaf.MetadataRole(roleS) role = csaf.MetadataRole(roleS)
url = csaf.ProviderURL(urlS) providerURL = csaf.ProviderURL(urlS)
) )
return &csaf.AggregatorCSAFProvider{ return &csaf.AggregatorCSAFProvider{
@ -316,7 +326,7 @@ func (w *worker) createAggregatorProvider() (*csaf.AggregatorCSAFProvider, error
LastUpdated: &lastUpdated, LastUpdated: &lastUpdated,
Publisher: &pub, Publisher: &pub,
Role: &role, Role: &role,
URL: &url, URL: &providerURL,
}, },
}, nil }, nil
} }

View file

@ -11,6 +11,7 @@ package main
import ( import (
"fmt" "fmt"
"log/slog" "log/slog"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
@ -112,6 +113,18 @@ func (w *worker) locateProviderMetadata(domain string) error {
return nil return nil
} }
// getProviderBaseURL returns the base URL for the provider.
func (w *worker) getProviderBaseURL() (*url.URL, error) {
baseURL, err := url.Parse(w.processor.cfg.Domain)
if err != nil {
return nil, err
}
baseURL = baseURL.JoinPath(".well-known",
"csaf-aggregator",
w.provider.Name)
return baseURL, nil
}
// removeOrphans removes the directories that are not in the providers list. // removeOrphans removes the directories that are not in the providers list.
func (p *processor) removeOrphans() error { func (p *processor) removeOrphans() error {