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:
parent
a05ba731dd
commit
2f599ab017
3 changed files with 78 additions and 35 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue