mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 18:15:42 +01:00
Try to minimize redundant downloads.
This commit is contained in:
parent
9967bfffe6
commit
594e6b4b0d
3 changed files with 80 additions and 39 deletions
|
|
@ -74,6 +74,14 @@ func (o *options) prepare() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// protectedAccess returns true if we have client certificates or
|
||||||
|
// extra http headers configured.
|
||||||
|
// This may be a wrong assumption, because the certs are not checked
|
||||||
|
// for their domain and custom headers may have other purposes.
|
||||||
|
func (o *options) protectedAccess() bool {
|
||||||
|
return len(o.clientCerts) > 0 || len(o.ExtraHeader) > 0
|
||||||
|
}
|
||||||
|
|
||||||
// writeJSON writes the JSON encoding of the given report to the given stream.
|
// writeJSON writes the JSON encoding of the given report to the given stream.
|
||||||
// It returns nil, otherwise an error.
|
// It returns nil, otherwise an error.
|
||||||
func writeJSON(report *Report, w io.WriteCloser) error {
|
func writeJSON(report *Report, w io.WriteCloser) error {
|
||||||
|
|
|
||||||
|
|
@ -407,12 +407,8 @@ func (p *processor) checkRedirect(r *http.Request, via []*http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *processor) httpClient() util.Client {
|
// fullClient returns a fully configure HTTP client.
|
||||||
|
func (p *processor) fullClient() util.Client {
|
||||||
if p.client != nil {
|
|
||||||
return p.client
|
|
||||||
}
|
|
||||||
|
|
||||||
hClient := http.Client{}
|
hClient := http.Client{}
|
||||||
|
|
||||||
hClient.CheckRedirect = p.checkRedirect
|
hClient.CheckRedirect = p.checkRedirect
|
||||||
|
|
@ -452,8 +448,29 @@ func (p *processor) httpClient() util.Client {
|
||||||
Limiter: rate.NewLimiter(rate.Limit(*p.opts.Rate), 1),
|
Limiter: rate.NewLimiter(rate.Limit(*p.opts.Rate), 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
p.client = client
|
// basicClient returns a http Client w/o certs and headers.
|
||||||
|
func (p *processor) basicClient() *http.Client {
|
||||||
|
if p.opts.Insecure {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
return &http.Client{Transport: tr}
|
||||||
|
}
|
||||||
|
return &http.Client{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// httpClient returns a cached HTTP client to be used to
|
||||||
|
// download remote ressources.
|
||||||
|
func (p *processor) httpClient() util.Client {
|
||||||
|
|
||||||
|
if p.client != nil {
|
||||||
|
return p.client
|
||||||
|
}
|
||||||
|
|
||||||
|
p.client = p.fullClient()
|
||||||
return p.client
|
return p.client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
@ -26,7 +25,7 @@ type rolieLabelChecker struct {
|
||||||
feedLabel csaf.TLPLabel
|
feedLabel csaf.TLPLabel
|
||||||
|
|
||||||
advisories map[csaf.TLPLabel]util.Set[string]
|
advisories map[csaf.TLPLabel]util.Set[string]
|
||||||
basicClient *http.Client
|
openClient util.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// tlpLevel returns an inclusion order of TLP colors.
|
// tlpLevel returns an inclusion order of TLP colors.
|
||||||
|
|
@ -55,17 +54,6 @@ func tlpLabel(label *csaf.TLPLabel) csaf.TLPLabel {
|
||||||
return csaf.TLPLabelUnlabeled
|
return csaf.TLPLabelUnlabeled
|
||||||
}
|
}
|
||||||
|
|
||||||
// createBasicClient creates and returns a http Client
|
|
||||||
func (p *processor) createBasicClient() *http.Client {
|
|
||||||
if p.opts.Insecure {
|
|
||||||
tr := &http.Transport{
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
}
|
|
||||||
return &http.Client{Transport: tr}
|
|
||||||
}
|
|
||||||
return &http.Client{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check tests if in advisory is in the right TLP color of the
|
// check tests if in advisory is in the right TLP color of the
|
||||||
// currently tested feed.
|
// currently tested feed.
|
||||||
func (ca *rolieLabelChecker) check(
|
func (ca *rolieLabelChecker) check(
|
||||||
|
|
@ -109,23 +97,38 @@ func (ca *rolieLabelChecker) check(
|
||||||
advisory, advisoryLabel, ca.feedURL, ca.feedLabel)
|
advisory, advisoryLabel, ca.feedURL, ca.feedLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := ca.basicClient.Get(advisory)
|
// If we have an open client then the actual data was downloaded
|
||||||
|
// through an authorizing client.
|
||||||
|
if ca.openClient != nil {
|
||||||
switch {
|
switch {
|
||||||
case advisoryRank == 1:
|
// If we are checking WHITE and we have a test client
|
||||||
|
// and we get a status forbidden then the access is not open.
|
||||||
|
case ca.feedLabel == csaf.TLPLabelWhite:
|
||||||
p.badWhitePermissions.use()
|
p.badWhitePermissions.use()
|
||||||
|
res, err := ca.openClient.Get(advisory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.badWhitePermissions.error("Unexpected Error %v when trying to fetch: %s", err, advisory)
|
p.badWhitePermissions.error(
|
||||||
|
"Unexpected Error %v when trying to fetch: %s", err, advisory)
|
||||||
} else if res.StatusCode == http.StatusForbidden {
|
} else if res.StatusCode == http.StatusForbidden {
|
||||||
// TODO: Differentiate between error and warning based on whether the advisory appears in a not access protected location as well.
|
p.badWhitePermissions.error(
|
||||||
p.badWhitePermissions.warn("Advisory %s of TLP level WHITE is access protected.", advisory)
|
"Advisory %s of TLP level WHITE is access protected.", advisory)
|
||||||
}
|
}
|
||||||
case advisoryRank > 2:
|
|
||||||
p.badAmberRedPermissions.use()
|
|
||||||
if err != nil {
|
|
||||||
p.badAmberRedPermissions.error("Unexpected Error %v when trying to fetch: %s", err, advisory)
|
|
||||||
} else if res.StatusCode == http.StatusOK {
|
|
||||||
p.badAmberRedPermissions.error("Advisory %s of TLP level %v is not properly access protected.", advisory, advisoryLabel)
|
|
||||||
|
|
||||||
|
// If we are checking AMBER or above we need to download
|
||||||
|
// the data again with the open client.
|
||||||
|
// If this does not result in status forbidden the
|
||||||
|
// server may be wrongly configured.
|
||||||
|
case ca.feedLabel >= csaf.TLPLabelAmber:
|
||||||
|
p.badAmberRedPermissions.use()
|
||||||
|
res, err := ca.openClient.Get(advisory)
|
||||||
|
if err != nil {
|
||||||
|
p.badAmberRedPermissions.error(
|
||||||
|
"Unexpected Error %v when trying to fetch: %s", err, advisory)
|
||||||
|
} else if res.StatusCode == http.StatusOK {
|
||||||
|
p.badAmberRedPermissions.error(
|
||||||
|
"Advisory %s of TLP level %v is not properly access protected.", advisory, advisoryLabel)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -168,9 +171,9 @@ func (p *processor) processROLIEFeeds(feeds [][]csaf.Feed) error {
|
||||||
advisories[feed] = advs
|
advisories[feed] = advs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.labelChecker = &rolieLabelChecker{
|
p.labelChecker = &rolieLabelChecker{
|
||||||
advisories: map[csaf.TLPLabel]util.Set[string]{},
|
advisories: map[csaf.TLPLabel]util.Set[string]{},
|
||||||
basicClient: p.createBasicClient(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 2: check for integrity.
|
// Phase 2: check for integrity.
|
||||||
|
|
@ -208,6 +211,19 @@ func (p *processor) processROLIEFeeds(feeds [][]csaf.Feed) error {
|
||||||
p.labelChecker.feedURL = feedURL.String()
|
p.labelChecker.feedURL = feedURL.String()
|
||||||
p.labelChecker.feedLabel = label
|
p.labelChecker.feedLabel = label
|
||||||
|
|
||||||
|
// If we are using an authorizing client
|
||||||
|
// we need a an open client to check
|
||||||
|
// WHITE, AMBER and RED feeds.
|
||||||
|
var openClient util.Client
|
||||||
|
if (label == csaf.TLPLabelWhite || label >= csaf.TLPLabelAmber) &&
|
||||||
|
p.opts.protectedAccess() {
|
||||||
|
openClient = p.basicClient()
|
||||||
|
}
|
||||||
|
p.labelChecker.openClient = openClient
|
||||||
|
|
||||||
|
// TODO: Issue a warning if we want check AMBER+ without an
|
||||||
|
// authorizing client.
|
||||||
|
|
||||||
if err := p.integrity(files, feedBase, rolieMask, p.badProviderMetadata.add); err != nil {
|
if err := p.integrity(files, feedBase, rolieMask, p.badProviderMetadata.add); err != nil {
|
||||||
if err != errContinue {
|
if err != errContinue {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue