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

View file

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

View file

@ -11,6 +11,7 @@ package main
import (
"fmt"
"log/slog"
"net/url"
"os"
"path/filepath"
@ -112,6 +113,18 @@ func (w *worker) locateProviderMetadata(domain string) error {
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.
func (p *processor) removeOrphans() error {