mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 11:55:40 +01:00
commit
892a0b941b
6 changed files with 158 additions and 21 deletions
|
|
@ -131,6 +131,19 @@ func (w *worker) writeProviderMetadata() error {
|
||||||
w.processor.cfg.Domain+"/.well-known/csaf-aggregator/"+w.provider.Name,
|
w.processor.cfg.Domain+"/.well-known/csaf-aggregator/"+w.provider.Name,
|
||||||
w.labelsFromSummaries())
|
w.labelsFromSummaries())
|
||||||
|
|
||||||
|
// Fill in directory URLs if needed.
|
||||||
|
if w.provider.writeIndices(w.processor.cfg) {
|
||||||
|
labels := make([]string, 0, len(w.summaries))
|
||||||
|
for label := range w.summaries {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Figure out the role
|
// Figure out the role
|
||||||
var role csaf.MetadataRole
|
var role csaf.MetadataRole
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -395,12 +395,21 @@ func (p *processor) integrity(
|
||||||
|
|
||||||
var data bytes.Buffer
|
var data bytes.Buffer
|
||||||
|
|
||||||
|
makeAbs := func(u *url.URL) *url.URL {
|
||||||
|
if u.IsAbs() {
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
return util.JoinURLPath(b, u.String())
|
||||||
|
}
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
fp, err := url.Parse(f.URL())
|
fp, err := url.Parse(f.URL())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg(ErrorType, "Bad URL %s: %v", f, err)
|
lg(ErrorType, "Bad URL %s: %v", f, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
fp = makeAbs(fp)
|
||||||
|
|
||||||
u := b.ResolveReference(fp).String()
|
u := b.ResolveReference(fp).String()
|
||||||
if p.markChecked(u, mask) {
|
if p.markChecked(u, mask) {
|
||||||
continue
|
continue
|
||||||
|
|
@ -492,6 +501,7 @@ func (p *processor) integrity(
|
||||||
lg(ErrorType, "Bad URL %s: %v", x.url(), err)
|
lg(ErrorType, "Bad URL %s: %v", x.url(), err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
hu = makeAbs(hu)
|
||||||
hashFile := b.ResolveReference(hu).String()
|
hashFile := b.ResolveReference(hu).String()
|
||||||
p.checkTLS(hashFile)
|
p.checkTLS(hashFile)
|
||||||
if res, err = client.Get(hashFile); err != nil {
|
if res, err = client.Get(hashFile); err != nil {
|
||||||
|
|
@ -527,6 +537,7 @@ func (p *processor) integrity(
|
||||||
lg(ErrorType, "Bad URL %s: %v", f.SignURL(), err)
|
lg(ErrorType, "Bad URL %s: %v", f.SignURL(), err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
su = makeAbs(su)
|
||||||
sigFile := b.ResolveReference(su).String()
|
sigFile := b.ResolveReference(su).String()
|
||||||
p.checkTLS(sigFile)
|
p.checkTLS(sigFile)
|
||||||
|
|
||||||
|
|
@ -822,9 +833,10 @@ func (p *processor) checkChanges(base string, mask whereType) error {
|
||||||
if p.ageAccept != nil && !p.ageAccept(t) {
|
if p.ageAccept != nil && !p.ageAccept(t) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
path := r[pathColumn]
|
||||||
times, files =
|
times, files =
|
||||||
append(times, t),
|
append(times, t),
|
||||||
append(files, csaf.PlainAdvisoryFile(r[pathColumn]))
|
append(files, csaf.PlainAdvisoryFile(path))
|
||||||
}
|
}
|
||||||
return times, files, nil
|
return times, files, nil
|
||||||
}()
|
}()
|
||||||
|
|
@ -877,6 +889,16 @@ func (p *processor) processROLIEFeeds(domain string, feeds [][]csaf.Feed) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// empty checks if list of strings contains at least one none empty string.
|
||||||
|
func empty(arr []string) bool {
|
||||||
|
for _, s := range arr {
|
||||||
|
if s != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (p *processor) checkCSAFs(domain string) error {
|
func (p *processor) checkCSAFs(domain string) error {
|
||||||
// Check for ROLIE
|
// Check for ROLIE
|
||||||
rolie, err := p.expr.Eval("$.distributions[*].rolie.feeds", p.pmd)
|
rolie, err := p.expr.Eval("$.distributions[*].rolie.feeds", p.pmd)
|
||||||
|
|
@ -898,16 +920,39 @@ func (p *processor) checkCSAFs(domain string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No rolie feeds
|
// No rolie feeds -> try directory_urls.
|
||||||
|
directoryURLs, err := p.expr.Eval(
|
||||||
|
"$.distributions[*].directory_url", p.pmd)
|
||||||
|
|
||||||
|
var dirURLs []string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
p.badProviderMetadata.warn("extracting directory URLs failed: %v.", err)
|
||||||
|
} else {
|
||||||
|
var ok bool
|
||||||
|
dirURLs, ok = util.AsStrings(directoryURLs)
|
||||||
|
if !ok {
|
||||||
|
p.badProviderMetadata.warn("directory URLs are not strings.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not found -> fall back to PMD url
|
||||||
|
if empty(dirURLs) {
|
||||||
pmdURL, err := url.Parse(p.pmdURL)
|
pmdURL, err := url.Parse(p.pmdURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
base, err := util.BaseURL(pmdURL)
|
baseURL, err := util.BaseURL(pmdURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
dirURLs = []string{baseURL}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, base := range dirURLs {
|
||||||
|
if base == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err := p.checkIndex(base, indexMask); err != nil && err != errContinue {
|
if err := p.checkIndex(base, indexMask); err != nil && err != errContinue {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -915,6 +960,7 @@ func (p *processor) checkCSAFs(domain string) error {
|
||||||
if err := p.checkChanges(base, changesMask); err != nil && err != errContinue {
|
if err := p.checkChanges(base, changesMask); err != nil && err != errContinue {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,17 @@ func createProviderMetadata(c *config, wellknownCSAF string) error {
|
||||||
pm := csaf.NewProviderMetadataDomain(c.CanonicalURLPrefix, c.modelTLPs())
|
pm := csaf.NewProviderMetadataDomain(c.CanonicalURLPrefix, c.modelTLPs())
|
||||||
c.ProviderMetaData.apply(pm)
|
c.ProviderMetaData.apply(pm)
|
||||||
|
|
||||||
|
// We have directory based distributions.
|
||||||
|
if c.WriteIndices {
|
||||||
|
// Every TLP as a distribution?
|
||||||
|
for _, t := range c.TLPs {
|
||||||
|
if t != tlpCSAF {
|
||||||
|
pm.AddDirectoryDistribution(
|
||||||
|
c.CanonicalURLPrefix + "/.well-known/csaf/" + string(t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
key, err := loadCryptoKeyFromFile(c.OpenPGPPublicKey)
|
key, err := loadCryptoKeyFromFile(c.OpenPGPPublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot load public key: %v", err)
|
return fmt.Errorf("cannot load public key: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,16 @@ func NewAdvisoryFileProcessor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// empty checks if list of strings contains at least one none empty string.
|
||||||
|
func empty(arr []string) bool {
|
||||||
|
for _, s := range arr {
|
||||||
|
if s != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Process extracts the adivisory filenames and passes them with
|
// Process extracts the adivisory filenames and passes them with
|
||||||
// the corresponding label to fn.
|
// the corresponding label to fn.
|
||||||
func (afp *AdvisoryFileProcessor) Process(
|
func (afp *AdvisoryFileProcessor) Process(
|
||||||
|
|
@ -133,7 +143,37 @@ func (afp *AdvisoryFileProcessor) Process(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No rolie feeds -> try to load files from index.txt
|
// No rolie feeds -> try to load files from index.txt
|
||||||
files, err := afp.loadIndex(lg)
|
|
||||||
|
directoryURLs, err := afp.expr.Eval(
|
||||||
|
"$.distributions[*].directory_url", afp.doc)
|
||||||
|
|
||||||
|
var dirURLs []string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
lg("extracting directory URLs failed: %v\n", err)
|
||||||
|
} else {
|
||||||
|
var ok bool
|
||||||
|
dirURLs, ok = util.AsStrings(directoryURLs)
|
||||||
|
if !ok {
|
||||||
|
lg("directory_urls are not strings.\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not found -> fall back to PMD url
|
||||||
|
if empty(dirURLs) {
|
||||||
|
baseURL, err := util.BaseURL(afp.base)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dirURLs = []string{baseURL}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, base := range dirURLs {
|
||||||
|
if base == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := afp.loadIndex(base, lg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -141,6 +181,7 @@ func (afp *AdvisoryFileProcessor) Process(
|
||||||
if err := fn(TLPLabelWhite, files); err != nil {
|
if err := fn(TLPLabelWhite, files); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} // TODO: else scan directories?
|
} // TODO: else scan directories?
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -148,12 +189,10 @@ func (afp *AdvisoryFileProcessor) Process(
|
||||||
// loadIndex loads baseURL/index.txt and returns a list of files
|
// loadIndex loads baseURL/index.txt and returns a list of files
|
||||||
// prefixed by baseURL/.
|
// prefixed by baseURL/.
|
||||||
func (afp *AdvisoryFileProcessor) loadIndex(
|
func (afp *AdvisoryFileProcessor) loadIndex(
|
||||||
|
baseURL string,
|
||||||
lg func(string, ...interface{}),
|
lg func(string, ...interface{}),
|
||||||
) ([]AdvisoryFile, error) {
|
) ([]AdvisoryFile, error) {
|
||||||
baseURL, err := util.BaseURL(afp.base)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
base, err := url.Parse(baseURL)
|
base, err := url.Parse(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,18 @@ func (pmd *ProviderMetadata) Defaults() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddDirectoryDistribution adds a directory based distribution
|
||||||
|
// with a given url to the provider metadata.
|
||||||
|
func (pmd *ProviderMetadata) AddDirectoryDistribution(url string) {
|
||||||
|
// Avoid duplicates.
|
||||||
|
for i := range pmd.Distributions {
|
||||||
|
if pmd.Distributions[i].DirectoryURL == url {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pmd.Distributions = append(pmd.Distributions, Distribution{DirectoryURL: url})
|
||||||
|
}
|
||||||
|
|
||||||
// Validate checks if the feed is valid.
|
// Validate checks if the feed is valid.
|
||||||
// Returns an error if the validation fails otherwise nil.
|
// Returns an error if the validation fails otherwise nil.
|
||||||
func (f *Feed) Validate() error {
|
func (f *Feed) Validate() error {
|
||||||
|
|
|
||||||
16
util/json.go
16
util/json.go
|
|
@ -166,3 +166,19 @@ func (pe *PathEval) Strings(
|
||||||
}
|
}
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsStrings transforms an []interface{string, string,... }
|
||||||
|
// to a []string.
|
||||||
|
func AsStrings(x interface{}) ([]string, bool) {
|
||||||
|
strs, ok := x.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
res := make([]string, 0, len(strs))
|
||||||
|
for _, y := range strs {
|
||||||
|
if s, ok := y.(string); ok {
|
||||||
|
res = append(res, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, true
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue