Skip to content

Commit 2f599ab

Browse files
author
Paul Schwabauer
authored
Fix aggregator URL handling (gocsaf#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
1 parent a05ba73 commit 2f599ab

File tree

3 files changed

+78
-35
lines changed

3 files changed

+78
-35
lines changed

cmd/csaf_aggregator/indices.go

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -183,19 +183,26 @@ func (w *worker) writeROLIENoSummaries(label string) error {
183183

184184
fname := "csaf-feed-tlp-" + labelFolder + ".json"
185185

186-
feedURL := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
187-
w.provider.Name + "/" + labelFolder + "/" + fname
186+
feedURL, err := w.getProviderBaseURL()
187+
if err != nil {
188+
return err
189+
}
190+
feedURL = feedURL.JoinPath(labelFolder, fname)
188191

189192
links := []csaf.Link{{
190193
Rel: "self",
191-
HRef: feedURL,
194+
HRef: feedURL.String(),
192195
}}
193196

194197
if w.provider.serviceDocument(w.processor.cfg) {
198+
serviceURL, err := w.getProviderBaseURL()
199+
if err != nil {
200+
return err
201+
}
202+
serviceURL = serviceURL.JoinPath("service.json")
195203
links = append(links, csaf.Link{
196-
Rel: "service",
197-
HRef: w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
198-
w.provider.Name + "/service.json",
204+
Rel: "service",
205+
HRef: serviceURL.String(),
199206
})
200207
}
201208

@@ -223,8 +230,11 @@ func (w *worker) writeROLIE(label string, summaries []summary) error {
223230

224231
fname := "csaf-feed-tlp-" + labelFolder + ".json"
225232

226-
feedURL := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
227-
w.provider.Name + "/" + labelFolder + "/" + fname
233+
feedURL, err := w.getProviderBaseURL()
234+
if err != nil {
235+
return err
236+
}
237+
feedURL = feedURL.JoinPath(labelFolder, fname)
228238

229239
entries := make([]*csaf.Entry, len(summaries))
230240

@@ -236,26 +246,29 @@ func (w *worker) writeROLIE(label string, summaries []summary) error {
236246
for i := range summaries {
237247
s := &summaries[i]
238248

239-
csafURL := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
240-
w.provider.Name + "/" + label + "/" +
241-
strconv.Itoa(s.summary.InitialReleaseDate.Year()) + "/" +
242-
s.filename
249+
csafURL, err := w.getProviderBaseURL()
250+
if err != nil {
251+
return err
252+
}
253+
csafURLString := csafURL.JoinPath(label,
254+
strconv.Itoa(s.summary.InitialReleaseDate.Year()),
255+
s.filename).String()
243256

244257
entries[i] = &csaf.Entry{
245258
ID: s.summary.ID,
246259
Titel: s.summary.Title,
247260
Published: csaf.TimeStamp(s.summary.InitialReleaseDate),
248261
Updated: csaf.TimeStamp(s.summary.CurrentReleaseDate),
249262
Link: []csaf.Link{
250-
{Rel: "self", HRef: csafURL},
251-
{Rel: "hash", HRef: csafURL + ".sha256"},
252-
{Rel: "hash", HRef: csafURL + ".sha512"},
253-
{Rel: "signature", HRef: csafURL + ".asc"},
263+
{Rel: "self", HRef: csafURLString},
264+
{Rel: "hash", HRef: csafURLString + ".sha256"},
265+
{Rel: "hash", HRef: csafURLString + ".sha512"},
266+
{Rel: "signature", HRef: csafURLString + ".asc"},
254267
},
255268
Format: format,
256269
Content: csaf.Content{
257270
Type: "application/json",
258-
Src: csafURL,
271+
Src: csafURLString,
259272
},
260273
}
261274
if s.summary.Summary != "" {
@@ -267,14 +280,18 @@ func (w *worker) writeROLIE(label string, summaries []summary) error {
267280

268281
links := []csaf.Link{{
269282
Rel: "self",
270-
HRef: feedURL,
283+
HRef: feedURL.String(),
271284
}}
272285

273286
if w.provider.serviceDocument(w.processor.cfg) {
287+
serviceURL, err := w.getProviderBaseURL()
288+
if err != nil {
289+
return err
290+
}
291+
serviceURL = serviceURL.JoinPath("service.json")
274292
links = append(links, csaf.Link{
275-
Rel: "service",
276-
HRef: w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
277-
w.provider.Name + "/service.json",
293+
Rel: "service",
294+
HRef: serviceURL.String(),
278295
})
279296
}
280297

@@ -344,12 +361,15 @@ func (w *worker) writeService() error {
344361
for _, ts := range labels {
345362
feedName := "csaf-feed-tlp-" + ts + ".json"
346363

347-
href := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
348-
w.provider.Name + "/" + ts + "/" + feedName
364+
hrefURL, err := w.getProviderBaseURL()
365+
if err != nil {
366+
return err
367+
}
368+
hrefURL = hrefURL.JoinPath(ts, feedName)
349369

350370
collection := csaf.ROLIEServiceWorkspaceCollection{
351371
Title: "CSAF feed (TLP:" + strings.ToUpper(ts) + ")",
352-
HRef: href,
372+
HRef: hrefURL.String(),
353373
Categories: categories,
354374
}
355375
collections = append(collections, collection)

cmd/csaf_aggregator/mirror.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,13 @@ func (w *worker) mirrorInternal() (*csaf.AggregatorCSAFProvider, error) {
103103
}
104104

105105
// Add us as a mirror.
106+
mirror, err := w.getProviderBaseURL()
107+
if err != nil {
108+
return nil, err
109+
}
106110
mirrorURL := csaf.ProviderURL(
107-
fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/provider-metadata.json",
108-
w.processor.cfg.Domain, w.provider.Name))
111+
mirror.JoinPath("provider-metadata.json").String(),
112+
)
109113

110114
acp.Mirrors = []csaf.ProviderURL{
111115
mirrorURL,
@@ -128,8 +132,12 @@ func (w *worker) writeProviderMetadata() error {
128132

129133
fname := filepath.Join(w.dir, "provider-metadata.json")
130134

135+
prefixURL, err := w.getProviderBaseURL()
136+
if err != nil {
137+
return err
138+
}
131139
pm := csaf.NewProviderMetadataPrefix(
132-
w.processor.cfg.Domain+"/.well-known/csaf-aggregator/"+w.provider.Name,
140+
prefixURL.String(),
133141
w.labelsFromSummaries())
134142

135143
// Fill in directory URLs if needed.
@@ -139,9 +147,8 @@ func (w *worker) writeProviderMetadata() error {
139147
labels = append(labels, label)
140148
}
141149
sort.Strings(labels)
142-
prefix := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" + w.provider.Name + "/"
143150
for _, label := range labels {
144-
pm.AddDirectoryDistribution(prefix + label)
151+
pm.AddDirectoryDistribution(prefixURL.JoinPath(label).String())
145152
}
146153
}
147154

@@ -188,9 +195,12 @@ func (w *worker) mirrorPGPKeys(pm *csaf.ProviderMetadata) error {
188195
return err
189196
}
190197

198+
keyURL, err := w.getProviderBaseURL()
199+
if err != nil {
200+
return err
201+
}
191202
localKeyURL := func(fingerprint string) string {
192-
return fmt.Sprintf("%s/.well-known/csaf-aggregator/%s/openpgp/%s.asc",
193-
w.processor.cfg.Domain, w.provider.Name, fingerprint)
203+
return keyURL.JoinPath("openpgp", (fingerprint + ".asc")).String()
194204
}
195205

196206
for i := range pm.PGPKeys {
@@ -240,8 +250,8 @@ func (w *worker) mirrorPGPKeys(pm *csaf.ProviderMetadata) error {
240250
}
241251

242252
// replace the URL
243-
url := localKeyURL(fingerprint)
244-
pgpKey.URL = &url
253+
u := localKeyURL(fingerprint)
254+
pgpKey.URL = &u
245255
}
246256

247257
// If we have public key configured copy it into the new folder
@@ -308,15 +318,15 @@ func (w *worker) createAggregatorProvider() (*csaf.AggregatorCSAFProvider, error
308318
var (
309319
lastUpdated = csaf.TimeStamp(lastUpdatedT)
310320
role = csaf.MetadataRole(roleS)
311-
url = csaf.ProviderURL(urlS)
321+
providerURL = csaf.ProviderURL(urlS)
312322
)
313323

314324
return &csaf.AggregatorCSAFProvider{
315325
Metadata: &csaf.AggregatorCSAFProviderMetadata{
316326
LastUpdated: &lastUpdated,
317327
Publisher: &pub,
318328
Role: &role,
319-
URL: &url,
329+
URL: &providerURL,
320330
},
321331
}, nil
322332
}

cmd/csaf_aggregator/processor.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package main
1111
import (
1212
"fmt"
1313
"log/slog"
14+
"net/url"
1415
"os"
1516
"path/filepath"
1617

@@ -112,6 +113,18 @@ func (w *worker) locateProviderMetadata(domain string) error {
112113
return nil
113114
}
114115

116+
// getProviderBaseURL returns the base URL for the provider.
117+
func (w *worker) getProviderBaseURL() (*url.URL, error) {
118+
baseURL, err := url.Parse(w.processor.cfg.Domain)
119+
if err != nil {
120+
return nil, err
121+
}
122+
baseURL = baseURL.JoinPath(".well-known",
123+
"csaf-aggregator",
124+
w.provider.Name)
125+
return baseURL, nil
126+
}
127+
115128
// removeOrphans removes the directories that are not in the providers list.
116129
func (p *processor) removeOrphans() error {
117130

0 commit comments

Comments
 (0)