1
0
Fork 0
mirror of https://github.com/gocsaf/csaf.git synced 2025-12-22 11:55:40 +01:00

Add aggregator; improve itest workflow

* Factor JSON evaluation and  construction base URLs out of of checker.
* Move json path matching to util.
* Add csaf_aggregator (as additional command)
* Improve itest workflow to checkout the branch where it is running on.

resolve #105
resolve  #72

Co-authored-by: tschmidtb51 <65305130+tschmidtb51@users.noreply.github.com>
Co-authored-by: Bernhard Reiter <bernhard@intevation.de>
Co-authored-by: Fadi Abbud <fadi.abbud@intevation.de>
This commit is contained in:
Sascha L. Teichmann 2022-05-10 18:12:38 +02:00 committed by GitHub
parent 9da0589236
commit 8a1ebe0b7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 2789 additions and 88 deletions

View file

@ -37,11 +37,12 @@ const (
)
var tlpLabelPattern = alternativesUnmarshal(
string("UNLABELED"),
string("WHITE"),
string("GREEN"),
string("AMBER"),
string("RED"))
string(TLPLabelUnlabeled),
string(TLPLabelWhite),
string(TLPLabelGreen),
string(TLPLabelAmber),
string(TLPLabelRed),
)
// JSONURL is an URL to JSON document.
type JSONURL string
@ -162,6 +163,188 @@ type ProviderMetadata struct {
Role *MetadataRole `json:"role"` // required
}
// AggregatorCategory is the category of the aggregator.
type AggregatorCategory string
const (
// AggregatorAggregator represents the "aggregator" type of aggregators.
AggregatorAggregator AggregatorCategory = "aggregator"
// AggregatorLister represents the "listers" type of aggregators.
AggregatorLister AggregatorCategory = "lister"
)
var aggregatorCategoryPattern = alternativesUnmarshal(
string(AggregatorAggregator),
string(AggregatorLister),
)
// AggregatorVersion is the version of the aggregator.
type AggregatorVersion string
const (
// AggregatorVersion20 is version 2.0 of the aggregator.
AggregatorVersion20 AggregatorVersion = "2.0"
)
var aggregatorVersionPattern = alternativesUnmarshal(
string(AggregatorVersion20),
)
// AggregatorInfo reflects the 'aggregator' object in the aggregator.
type AggregatorInfo struct {
Category *AggregatorCategory `json:"category,omitempty" toml:"category"` // required
Name string `json:"name" toml:"name"` // required
ContactDetails string `json:"contact_details,omitempty" toml:"contact_details"`
IssuingAuthority string `json:"issuing_authority,omitempty" toml:"issuing_authority"`
Namespace string `json:"namespace" toml:"namespace"` // required
}
// AggregatorURL is the URL of the aggregator document.
type AggregatorURL string
var aggregatorURLPattern = patternUnmarshal(`/aggregator\.json$`)
// AggregatorCSAFProviderMetadata reflects 'csaf_providers.metadata' in an aggregator.
type AggregatorCSAFProviderMetadata struct {
LastUpdated *TimeStamp `json:"last_updated,omitempty"` // required
Publisher *Publisher `json:"publisher,omitempty"` // required
Role *MetadataRole `json:"role,omitempty"`
URL *ProviderURL `json:"url,omitempty"` // required
}
// AggregatorCSAFProvider reflects one 'csaf_trusted_provider' in an aggregator.
type AggregatorCSAFProvider struct {
Metadata *AggregatorCSAFProviderMetadata `json:"metadata,omitempty"` // required
Mirrors []ProviderURL `json:"mirrors,omitempty"` // required
}
// Aggregator is the CSAF Aggregator.
type Aggregator struct {
Aggregator *AggregatorInfo `json:"aggregator,omitempty"` // required
Version *AggregatorVersion `json:"aggregator_version,omitempty"` // required
CanonicalURL *AggregatorURL `json:"canonical_url,omitempty"` // required
CSAFProviders []*AggregatorCSAFProvider `json:"csaf_providers,omitempty"` // required
LastUpdated *TimeStamp `json:"last_updated,omitempty"` // required
}
// Validate validates the current state of the AggregatorCategory.
func (ac *AggregatorCategory) Validate() error {
if ac == nil {
return errors.New("aggregator.aggregator.category is mandatory")
}
return nil
}
// Validate validates the current state of the AggregatorVersion.
func (av *AggregatorVersion) Validate() error {
if av == nil {
return errors.New("aggregator.aggregator_version is mandatory")
}
return nil
}
// Validate validates the current state of the AggregatorURL.
func (au *AggregatorURL) Validate() error {
if au == nil {
return errors.New("aggregator.aggregator_url is mandatory")
}
return nil
}
// Validate validates the current state of the AggregatorInfo.
func (ai *AggregatorInfo) Validate() error {
if err := ai.Category.Validate(); err != nil {
return err
}
if ai.Name == "" {
return errors.New("aggregator.aggregator.name is mandatory")
}
if ai.Namespace == "" {
return errors.New("aggregator.aggregator.namespace is mandatory")
}
return nil
}
// Validate validates the current state of the AggregatorCSAFProviderMetadata.
func (acpm *AggregatorCSAFProviderMetadata) Validate() error {
if acpm == nil {
return errors.New("aggregator.csaf_providers[].metadata is mandatory")
}
if acpm.LastUpdated == nil {
return errors.New("aggregator.csaf_providers[].metadata.last_updated is mandatory")
}
if acpm.Publisher == nil {
return errors.New("aggregator.csaf_providers[].metadata.publisher is mandatory")
}
if err := acpm.Publisher.Validate(); err != nil {
return err
}
if acpm.URL == nil {
return errors.New("aggregator.csaf_providers[].metadata.url is mandatory")
}
return nil
}
// Validate validates the current state of the AggregatorCSAFProvider.
func (acp *AggregatorCSAFProvider) Validate() error {
if acp == nil {
return errors.New("aggregator.csaf_providers[] not allowed to be nil")
}
if err := acp.Metadata.Validate(); err != nil {
return err
}
return nil
}
// Validate validates the current state of the Aggregator.
func (a *Aggregator) Validate() error {
if err := a.Aggregator.Validate(); err != nil {
return err
}
if err := a.Version.Validate(); err != nil {
return err
}
if err := a.CanonicalURL.Validate(); err != nil {
return err
}
for _, provider := range a.CSAFProviders {
if err := provider.Validate(); err != nil {
return err
}
}
if a.LastUpdated == nil {
return errors.New("Aggregator.LastUpdate == nil")
}
return nil
}
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (ac *AggregatorCategory) UnmarshalText(data []byte) error {
s, err := aggregatorCategoryPattern(data)
if err == nil {
*ac = AggregatorCategory(s)
}
return err
}
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (av *AggregatorVersion) UnmarshalText(data []byte) error {
s, err := aggregatorVersionPattern(data)
if err == nil {
*av = AggregatorVersion(s)
}
return err
}
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (au *AggregatorURL) UnmarshalText(data []byte) error {
s, err := aggregatorURLPattern(data)
if err == nil {
*au = AggregatorURL(s)
}
return err
}
func patternUnmarshal(pattern string) func([]byte) (string, error) {
r := regexp.MustCompile(pattern)
return func(data []byte) (string, error) {
@ -485,3 +668,12 @@ func LoadProviderMetadata(r io.Reader) (*ProviderMetadata, error) {
return &pmd, nil
}
// WriteTo saves an AggregatorURL to a writer.
func (a *Aggregator) WriteTo(w io.Writer) (int64, error) {
nw := util.NWriter{Writer: w, N: 0}
enc := json.NewEncoder(&nw)
enc.SetIndent("", " ")
err := enc.Encode(a)
return nw.N, err
}