diff --git a/cmd/csaf_aggregator/indices.go b/cmd/csaf_aggregator/indices.go index 17c8d3a..976d9a3 100644 --- a/cmd/csaf_aggregator/indices.go +++ b/cmd/csaf_aggregator/indices.go @@ -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) diff --git a/cmd/csaf_aggregator/mirror.go b/cmd/csaf_aggregator/mirror.go index e7c5154..1ef5881 100644 --- a/cmd/csaf_aggregator/mirror.go +++ b/cmd/csaf_aggregator/mirror.go @@ -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 } diff --git a/cmd/csaf_aggregator/processor.go b/cmd/csaf_aggregator/processor.go index b22e839..0d41df8 100644 --- a/cmd/csaf_aggregator/processor.go +++ b/cmd/csaf_aggregator/processor.go @@ -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 {