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

Merge pull request #1 from csaf-poc/golint-fixes

Fix golint warnings.
This commit is contained in:
Fadi Abbud 2021-11-26 10:48:23 +01:00 committed by GitHub
commit 606897b20f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 122 additions and 49 deletions

View file

@ -248,7 +248,7 @@ func (c *controller) upload(rw http.ResponseWriter, r *http.Request) {
return err
}
feedURL := csaf.JsonURL(
feedURL := csaf.JSONURL(
c.cfg.Domain + "/.well-known/csaf/" + ts + "/" + feedName)
tlpLabel := csaf.TLPLabel(strings.ToUpper(ts))

View file

@ -26,7 +26,7 @@ const (
type extraction struct {
id string
title string
publisher *csaf.CSAFPublisher
publisher *csaf.Publisher
initialReleaseDate time.Time
currentReleaseDate time.Time
summary string
@ -109,7 +109,7 @@ func (e *extraction) extractPublisher(path extractFunc) error {
if err := enc.Encode(p); err != nil {
return err
}
e.publisher = new(csaf.CSAFPublisher)
e.publisher = new(csaf.Publisher)
if err := json.Unmarshal(buf.Bytes(), e.publisher); err != nil {
return err
}

View file

@ -42,9 +42,8 @@ func createSecurity(c *config) error {
f, "CSAF: %s/.well-known/csaf/provider-metadata.json\n",
c.Domain)
return f.Close()
} else {
return err
}
return err
}
return nil
}

View file

@ -24,7 +24,7 @@ func newProviderMetadata(cfg *config) *csaf.ProviderMetadata {
var (
ts = string(t)
feedName = "csaf-feed-tlp-" + ts + ".json"
feedURL = csaf.JsonURL(
feedURL = csaf.JSONURL(
cfg.Domain + "/.well-known/csaf/" + ts + "/" + feedName)
tlpLabel = csaf.TLPLabel(strings.ToUpper(ts))
)

View file

@ -10,14 +10,20 @@ import (
"time"
)
// TLPLabel is the traffic light policy of the CSAF.
type TLPLabel string
const (
// TLPLabelUnlabeled is the 'UNLABELED' policy.
TLPLabelUnlabeled = "UNLABELED"
TLPLabelWhite = "WHITE"
TLPLabelGreen = "GREEN"
TLPLabelAmber = "AMBER"
TLPLabelRed = "RED"
// TLPLabelWhite is the 'WHITE' policy.
TLPLabelWhite = "WHITE"
// TLPLabelGreen is the 'GREEN' policy.
TLPLabelGreen = "GREEN"
// TLPLabelAmber is the 'AMBER' policy.
TLPLabelAmber = "AMBER"
// TLPLabelRed is the 'RED' policy.
TLPLabelRed = "RED"
)
var tlpLabelPattern = alternativesUnmarshal(
@ -27,47 +33,63 @@ var tlpLabelPattern = alternativesUnmarshal(
string("AMBER"),
string("RED"))
type JsonURL string
// JSONURL is an URL to JSON document.
type JSONURL string
var jsonURLPattern = patternUnmarshal(`\.json$`)
// Feed is CSAF feed.
type Feed struct {
Summary string `json:"summary"`
TLPLabel *TLPLabel `json:"tlp_label"` // required
URL *JsonURL `json:"url"` // required
URL *JSONURL `json:"url"` // required
}
// ROLIE is the ROLIE extension of the CSAF feed.
type ROLIE struct {
Categories []JsonURL `json:"categories,omitempty"`
Categories []JSONURL `json:"categories,omitempty"`
Feeds []Feed `json:"feeds"` // required
Services []JsonURL `json:"services,omitempty"`
Services []JSONURL `json:"services,omitempty"`
}
// Distribution is a distribution of a CSAF feed.
type Distribution struct {
DirectoryURL string `json:"directory_url,omitempty"`
Rolie []ROLIE `json:"rolie"`
}
// TimeStamp represents a time stamp in a CSAF feed.
type TimeStamp time.Time
// Fingerprint is the fingerprint of a OpenPGP key used to sign
// the CASF documents.
type Fingerprint string
var fingerprintPattern = patternUnmarshal(`^[0-9a-fA-F]{40,}$`)
// PGPKey is location and the fingerprint of the key
// used to sign the CASF documents.
type PGPKey struct {
Fingerprint Fingerprint `json:"fingerprint,omitempty"`
URL *string `json:"url"` // required
}
type CSAFCategory string
// Category is the category of the CSAF feed.
type Category string
const (
CSAFCategoryCoordinator CSAFCategory = "coordinator"
CSAFCategoryDiscoverer CSAFCategory = "discoverer"
CSAFCategoryOther CSAFCategory = "other"
CSAFCategoryTranslator CSAFCategory = "translator"
CSAFCategoryUser CSAFCategory = "user"
CSAFCategoryVendor CSAFCategory = "vendor"
// CSAFCategoryCoordinator is the "coordinator" category.
CSAFCategoryCoordinator Category = "coordinator"
// CSAFCategoryDiscoverer is the "discoverer" category.
CSAFCategoryDiscoverer Category = "discoverer"
// CSAFCategoryOther is the "other" category.
CSAFCategoryOther Category = "other"
// CSAFCategoryTranslator is the "translator" category.
CSAFCategoryTranslator Category = "translator"
// CSAFCategoryUser is the "user" category.
CSAFCategoryUser Category = "user"
// CSAFCategoryVendor is the "vendor" category.
CSAFCategoryVendor Category = "vendor"
)
var csafCategoryPattern = alternativesUnmarshal(
@ -78,25 +100,32 @@ var csafCategoryPattern = alternativesUnmarshal(
string(CSAFCategoryUser),
string(CSAFCategoryVendor))
type CSAFPublisher struct {
Category *CSAFCategory `json:"category"` // required
Name *string `json:"name"` // required
Namespace *string `json:"namespace"` // required
ContactDetails string `json:"contact_details,omitempty"`
IssuingAuthority string `json:"issuing_authority,omitempty"`
// Publisher is the publisher of the feed.
type Publisher struct {
Category *Category `json:"category"` // required
Name *string `json:"name"` // required
Namespace *string `json:"namespace"` // required
ContactDetails string `json:"contact_details,omitempty"`
IssuingAuthority string `json:"issuing_authority,omitempty"`
}
// MetadataVersion is the metadata version of the feed.
type MetadataVersion string
// MetadataVersion20 is the current version of the schema.
const MetadataVersion20 MetadataVersion = "2.0"
var metadataVersionPattern = alternativesUnmarshal(string(MetadataVersion20))
// MetadataRole is the role of the feed.
type MetadataRole string
const (
MetadataRolePublisher MetadataRole = "csaf_publisher"
MetadataRoleProvider MetadataRole = "csaf_provider"
// MetadataRolePublisher is the "csaf_publisher" role.
MetadataRolePublisher MetadataRole = "csaf_publisher"
// MetadataRoleProvider is the "csaf_provider" role.
MetadataRoleProvider MetadataRole = "csaf_provider"
// MetadataRoleTrustedProvider is the "csaf_trusted_provider" role.
MetadataRoleTrustedProvider MetadataRole = "csaf_trusted_provider"
)
@ -105,10 +134,12 @@ var metadataRolePattern = alternativesUnmarshal(
string(MetadataRoleProvider),
string(MetadataRoleTrustedProvider))
// ProviderURL is the URL of the provider document.
type ProviderURL string
var providerURLPattern = patternUnmarshal(`/provider-metadata\.json$`)
// ProviderMetadata contains the metadata of the provider.
type ProviderMetadata struct {
CanonicalURL *ProviderURL `json:"canonical_url"` // required
Distributions []Distribution `json:"distributions,omitempty"`
@ -117,7 +148,7 @@ type ProviderMetadata struct {
MetadataVersion *MetadataVersion `json:"metadata_version"` // required
MirrorOnCSAFAggregators *bool `json:"mirror_on_CSAF_aggregators"` // required
PGPKeys []PGPKey `json:"pgp_keys,omitempty"`
Publisher *CSAFPublisher `json:"publisher"` // required
Publisher *Publisher `json:"publisher"` // required
Role *MetadataRole `json:"role"` // required
}
@ -144,6 +175,7 @@ func alternativesUnmarshal(alternatives ...string) func([]byte) (string, error)
}
}
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (tl *TLPLabel) UnmarshalText(data []byte) error {
s, err := tlpLabelPattern(data)
if err == nil {
@ -152,14 +184,16 @@ func (tl *TLPLabel) UnmarshalText(data []byte) error {
return err
}
func (ju *JsonURL) UnmarshalText(data []byte) error {
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (ju *JSONURL) UnmarshalText(data []byte) error {
s, err := jsonURLPattern(data)
if err == nil {
*ju = JsonURL(s)
*ju = JSONURL(s)
}
return err
}
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (pu *ProviderURL) UnmarshalText(data []byte) error {
s, err := providerURLPattern(data)
if err == nil {
@ -168,14 +202,16 @@ func (pu *ProviderURL) UnmarshalText(data []byte) error {
return err
}
func (cc *CSAFCategory) UnmarshalText(data []byte) error {
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (cc *Category) UnmarshalText(data []byte) error {
s, err := csafCategoryPattern(data)
if err == nil {
*cc = CSAFCategory(s)
*cc = Category(s)
}
return err
}
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (fp *Fingerprint) UnmarshalText(data []byte) error {
s, err := fingerprintPattern(data)
if err == nil {
@ -184,6 +220,7 @@ func (fp *Fingerprint) UnmarshalText(data []byte) error {
return err
}
// UnmarshalText implements the encoding.TextUnmarshaller interface.
func (ts *TimeStamp) UnmarshalText(data []byte) error {
t, err := time.Parse(time.RFC3339, string(data))
if err != nil {
@ -193,10 +230,12 @@ func (ts *TimeStamp) UnmarshalText(data []byte) error {
return nil
}
// MarshalText implements the encoding.TextMarshaller interface.
func (ts TimeStamp) MarshalText() ([]byte, error) {
return []byte(time.Time(ts).Format(time.RFC3339)), nil
}
// Defaults fills the correct default values into the provider metadata.
func (pmd *ProviderMetadata) Defaults() {
if pmd.Role == nil {
role := MetadataRoleProvider
@ -216,6 +255,8 @@ func (pmd *ProviderMetadata) Defaults() {
}
}
// Validate checks if the feed is valid.
// Returns an error if the validation fails otherwise nil.
func (f *Feed) Validate() error {
switch {
case f.TLPLabel == nil:
@ -226,6 +267,8 @@ func (f *Feed) Validate() error {
return nil
}
// Validate checks if the ROLIE extension is valid.
// Returns an error if the validation fails otherwise nil.
func (r *ROLIE) Validate() error {
if len(r.Feeds) < 1 {
return errors.New("ROLIE needs at least one feed")
@ -238,7 +281,9 @@ func (r *ROLIE) Validate() error {
return nil
}
func (cp *CSAFPublisher) Validate() error {
// Validate checks if the publisher is valid.
// Returns an error if the validation fails otherwise nil.
func (cp *Publisher) Validate() error {
switch {
case cp == nil:
return errors.New("publisher is mandatory")
@ -252,6 +297,8 @@ func (cp *CSAFPublisher) Validate() error {
return nil
}
// Validate checks if the PGPKey is valid.
// Returns an error if the validation fails otherwise nil.
func (pk *PGPKey) Validate() error {
if pk.URL == nil {
return errors.New("pgp_key[].url is mandatory")
@ -259,6 +306,8 @@ func (pk *PGPKey) Validate() error {
return nil
}
// Validate checks if the distribution is valid.
// Returns an error if the validation fails otherwise nil.
func (d *Distribution) Validate() error {
for i := range d.Rolie {
if err := d.Rolie[i].Validate(); err != nil {
@ -268,6 +317,8 @@ func (d *Distribution) Validate() error {
return nil
}
// Validate checks if the provider metadata is valid.
// Returns an error if the validation fails otherwise nil.
func (pmd *ProviderMetadata) Validate() error {
switch {
@ -298,11 +349,16 @@ func (pmd *ProviderMetadata) Validate() error {
return nil
}
// SetLastUpdated updates the last updated timestamp of the feed.
func (pmd *ProviderMetadata) SetLastUpdated(t time.Time) {
ts := TimeStamp(t.UTC())
pmd.LastUpdated = &ts
}
// SetPGP sets the fingerprint and URL of the OpenPGP key
// of the feed. If the feed already has a key with
// given fingerprint the URL updated.
// If there is no such key it is append to the list of keys.
func (pmd *ProviderMetadata) SetPGP(fingerprint, url string) {
for i := range pmd.PGPKeys {
if pmd.PGPKeys[i].Fingerprint == Fingerprint(fingerprint) {
@ -316,21 +372,26 @@ func (pmd *ProviderMetadata) SetPGP(fingerprint, url string) {
})
}
// NewProviderMetadata creates a new provider with the given URL.
// Valid default values are set and the feed is considered to
// be updated recently.
func NewProviderMetadata(canonicalURL string) *ProviderMetadata {
pmd := new(ProviderMetadata)
pmd.Defaults()
pmd.SetLastUpdated(time.Now())
pm := new(ProviderMetadata)
pm.Defaults()
pm.SetLastUpdated(time.Now())
cu := ProviderURL(canonicalURL)
pmd.CanonicalURL = &cu
return pmd
pm.CanonicalURL = &cu
return pm
}
func (pm *ProviderMetadata) Save(w io.Writer) error {
// Save saves a metadata provider to a writer.
func (pmd *ProviderMetadata) Save(w io.Writer) error {
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
return enc.Encode(pm)
return enc.Encode(pmd)
}
// LoadProviderMetadata loads a metadata provider from a reader.
func LoadProviderMetadata(r io.Reader) (*ProviderMetadata, error) {
var pmd ProviderMetadata

View file

@ -7,30 +7,36 @@ import (
"time"
)
// Link for ROLIE.
type Link struct {
Rel string `json:"rel"`
HRef string `json:"href"`
}
type Category struct {
// ROLIECategory for ROLIE.
type ROLIECategory struct {
Scheme string `json:"scheme"`
Term string `json:"term"`
}
// Summary for ROLIE.
type Summary struct {
Content string `json:"content"`
}
// Content for ROLIE.
type Content struct {
Type string `json:"type"`
Src string `json:"src"`
}
// Format for ROLIE.
type Format struct {
Schema string `json:"schema"`
Version string `json:"version"`
}
// Entry for ROLIE.
type Entry struct {
ID string `json:"id"`
Titel string `json:"title"`
@ -42,15 +48,17 @@ type Entry struct {
Format Format `json:"format"`
}
// ROLIEFeed is a ROLIE feed.
type ROLIEFeed struct {
ID string `json:"id"`
Title string `json:"title"`
Link []Link `json:"link,omitempty"`
Category []Category `json:"category,omitempty"`
Updated TimeStamp `json:"updated"`
Entry []*Entry `json:"entry,omitempty"`
ID string `json:"id"`
Title string `json:"title"`
Link []Link `json:"link,omitempty"`
Category []ROLIECategory `json:"category,omitempty"`
Updated TimeStamp `json:"updated"`
Entry []*Entry `json:"entry,omitempty"`
}
// LoadROLIEFeed loads a ROLIE feed from a reader.
func LoadROLIEFeed(r io.Reader) (*ROLIEFeed, error) {
dec := json.NewDecoder(r)
var rf ROLIEFeed
@ -60,12 +68,15 @@ func LoadROLIEFeed(r io.Reader) (*ROLIEFeed, error) {
return &rf, nil
}
// Save saves a ROLIE feed to a writer.
func (rf *ROLIEFeed) Save(w io.Writer) error {
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
return enc.Encode(rf)
}
// EntryByID looks up an entry by its ID.
// Returns nil if no such entry was found.
func (rf *ROLIEFeed) EntryByID(id string) *Entry {
for _, entry := range rf.Entry {
if entry.ID == id {
@ -75,6 +86,8 @@ func (rf *ROLIEFeed) EntryByID(id string) *Entry {
return nil
}
// SortEntriesByUpdated sorts all the entries in the feed
// by their update times.
func (rf *ROLIEFeed) SortEntriesByUpdated() {
entries := rf.Entry
sort.Slice(entries, func(i, j int) bool {