mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 05:40:11 +01:00
Empty rolie (#357)
* Create ROLIE feed if summaries are empty * Formatting, Remove sorting of 0 elements * Handle minimum entry length error as warning in checker * Use empty array instead of creating an empty array to reference * Change schema to allow for empty entry arrays * Use https://raw.githubusercontent.com/oasis-tcs/csaf/81b2663697958bc5f85d14372712a40028fb8338/csaf_2.0/json_schema/ROLIE_feed_json_schema.json as schema for ROLIE feeds * Change label name from empty to undefined * Change default of create_service_document for csaf_provider to true * Config * Count entries in csaf-checker, warn if there are none. * Add Comments to csaf/rolie.go's CountEntries function * Delete index.txt and changes.csv in aggregator if there are no entries. * Create an empty ROLIE feed document when setting up folders during create * nit: set update time stamp in structure init. * Instantiate label checker only once. * Ignore domain not having roles. * provider: Create empty entry section in ROLIE feed. * Stop check for domain if PMD check fails * Add missing continue statement * Report missing ROLIE feed entries in ROLIE feed, not Provider Metadata * Do not ommit empty entries in ROLIE feeds. * Fixed error handling problem introduced by faulty merge. Removed unused errStop handling while there. --------- Co-authored-by: JanHoefelmeyer <hoefelmeyer.jan@gmail.com> Co-authored-by: Sascha L. Teichmann <sascha.teichmann@intevation.de> Co-authored-by: JanHoefelmeyer <Jan Höfelmeyer jhoefelmeyer@intevation.de>
This commit is contained in:
parent
540d02d367
commit
b61912410a
8 changed files with 194 additions and 43 deletions
|
|
@ -91,6 +91,22 @@ func (w *worker) writeInterims(label string, summaries []summary) error {
|
||||||
|
|
||||||
func (w *worker) writeCSV(label string, summaries []summary) error {
|
func (w *worker) writeCSV(label string, summaries []summary) error {
|
||||||
|
|
||||||
|
fname := filepath.Join(w.dir, label, changesCSV)
|
||||||
|
|
||||||
|
// If we don't have any entries remove existing file.
|
||||||
|
if len(summaries) == 0 {
|
||||||
|
// Does it really exist?
|
||||||
|
if err := os.RemoveAll(fname); err != nil {
|
||||||
|
return fmt.Errorf("unable to remove %q: %w", fname, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(fname)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Do not sort in-place.
|
// Do not sort in-place.
|
||||||
ss := make([]summary, len(summaries))
|
ss := make([]summary, len(summaries))
|
||||||
copy(ss, summaries)
|
copy(ss, summaries)
|
||||||
|
|
@ -100,11 +116,6 @@ func (w *worker) writeCSV(label string, summaries []summary) error {
|
||||||
ss[j].summary.CurrentReleaseDate)
|
ss[j].summary.CurrentReleaseDate)
|
||||||
})
|
})
|
||||||
|
|
||||||
fname := filepath.Join(w.dir, label, changesCSV)
|
|
||||||
f, err := os.Create(fname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
out := util.NewFullyQuotedCSWWriter(f)
|
out := util.NewFullyQuotedCSWWriter(f)
|
||||||
|
|
||||||
record := make([]string, 2)
|
record := make([]string, 2)
|
||||||
|
|
@ -137,6 +148,16 @@ func (w *worker) writeCSV(label string, summaries []summary) error {
|
||||||
func (w *worker) writeIndex(label string, summaries []summary) error {
|
func (w *worker) writeIndex(label string, summaries []summary) error {
|
||||||
|
|
||||||
fname := filepath.Join(w.dir, label, indexTXT)
|
fname := filepath.Join(w.dir, label, indexTXT)
|
||||||
|
|
||||||
|
// If we don't have any entries remove existing file.
|
||||||
|
if len(summaries) == 0 {
|
||||||
|
// Does it really exist?
|
||||||
|
if err := os.RemoveAll(fname); err != nil {
|
||||||
|
return fmt.Errorf("unable to remove %q: %w", fname, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
f, err := os.Create(fname)
|
f, err := os.Create(fname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -157,6 +178,46 @@ func (w *worker) writeIndex(label string, summaries []summary) error {
|
||||||
return err2
|
return err2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *worker) writeROLIENoSummaries(label string) error {
|
||||||
|
|
||||||
|
labelFolder := strings.ToLower(label)
|
||||||
|
|
||||||
|
fname := "csaf-feed-tlp-" + labelFolder + ".json"
|
||||||
|
|
||||||
|
feedURL := w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
|
||||||
|
w.provider.Name + "/" + labelFolder + "/" + fname
|
||||||
|
|
||||||
|
links := []csaf.Link{{
|
||||||
|
Rel: "self",
|
||||||
|
HRef: feedURL,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if w.provider.serviceDocument(w.processor.cfg) {
|
||||||
|
links = append(links, csaf.Link{
|
||||||
|
Rel: "service",
|
||||||
|
HRef: w.processor.cfg.Domain + "/.well-known/csaf-aggregator/" +
|
||||||
|
w.provider.Name + "/service.json",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
rolie := &csaf.ROLIEFeed{
|
||||||
|
Feed: csaf.FeedData{
|
||||||
|
ID: "csaf-feed-tlp-" + strings.ToLower(label),
|
||||||
|
Title: "CSAF feed (TLP:" + strings.ToUpper(label) + ")",
|
||||||
|
Link: links,
|
||||||
|
Category: []csaf.ROLIECategory{{
|
||||||
|
Scheme: "urn:ietf:params:rolie:category:information-type",
|
||||||
|
Term: "csaf",
|
||||||
|
}},
|
||||||
|
Updated: csaf.TimeStamp(time.Now().UTC()),
|
||||||
|
Entry: []*csaf.Entry{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(w.dir, labelFolder, fname)
|
||||||
|
return util.WriteToFile(path, rolie)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *worker) writeROLIE(label string, summaries []summary) error {
|
func (w *worker) writeROLIE(label string, summaries []summary) error {
|
||||||
|
|
||||||
labelFolder := strings.ToLower(label)
|
labelFolder := strings.ToLower(label)
|
||||||
|
|
@ -311,6 +372,7 @@ func (w *worker) writeService() error {
|
||||||
func (w *worker) writeIndices() error {
|
func (w *worker) writeIndices() error {
|
||||||
|
|
||||||
if len(w.summaries) == 0 || w.dir == "" {
|
if len(w.summaries) == 0 || w.dir == "" {
|
||||||
|
w.writeROLIENoSummaries("undefined")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,6 @@ type reporter interface {
|
||||||
var (
|
var (
|
||||||
// errContinue indicates that the current check should continue.
|
// errContinue indicates that the current check should continue.
|
||||||
errContinue = errors.New("continue")
|
errContinue = errors.New("continue")
|
||||||
// errStop indicates that the current check should stop.
|
|
||||||
errStop = errors.New("stop")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type whereType byte
|
type whereType byte
|
||||||
|
|
@ -262,10 +260,9 @@ func (p *processor) run(domains []string) (*Report, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := p.checkDomain(d); err != nil {
|
if err := p.checkDomain(d); err != nil {
|
||||||
if err == errContinue || err == errStop {
|
log.Printf("Failed to find valid provider-metadata.json for domain %s: %v. "+
|
||||||
continue
|
"Continuing with next domain.", d, err)
|
||||||
}
|
continue
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
domain := &Domain{Name: d}
|
domain := &Domain{Name: d}
|
||||||
|
|
||||||
|
|
@ -354,17 +351,17 @@ func (p *processor) domainChecks(domain string) []func(*processor, string) error
|
||||||
return checks
|
return checks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkDomain runs a set of domain specific checks on a given
|
||||||
|
// domain.
|
||||||
func (p *processor) checkDomain(domain string) error {
|
func (p *processor) checkDomain(domain string) error {
|
||||||
|
|
||||||
for _, check := range p.domainChecks(domain) {
|
for _, check := range p.domainChecks(domain) {
|
||||||
if err := check(p, domain); err != nil && err != errContinue {
|
if err := check(p, domain); err != nil {
|
||||||
if err == errStop {
|
if err == errContinue {
|
||||||
return nil
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -503,12 +500,15 @@ func (p *processor) rolieFeedEntries(feed string) ([]csaf.AdvisoryFile, error) {
|
||||||
var rolieDoc any
|
var rolieDoc any
|
||||||
err = json.NewDecoder(bytes.NewReader(all)).Decode(&rolieDoc)
|
err = json.NewDecoder(bytes.NewReader(all)).Decode(&rolieDoc)
|
||||||
return rfeed, rolieDoc, err
|
return rfeed, rolieDoc, err
|
||||||
|
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.badProviderMetadata.error("Loading ROLIE feed failed: %v.", err)
|
p.badProviderMetadata.error("Loading ROLIE feed failed: %v.", err)
|
||||||
return nil, errContinue
|
return nil, errContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rfeed.CountEntries() == 0 {
|
||||||
|
p.badROLIEFeed.warn("No entries in %s", feed)
|
||||||
|
}
|
||||||
errors, err := csaf.ValidateROLIE(rolieDoc)
|
errors, err := csaf.ValidateROLIE(rolieDoc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1208,8 +1208,6 @@ func (p *processor) checkProviderMetadata(domain string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lpmd.Valid() {
|
if !lpmd.Valid() {
|
||||||
p.badProviderMetadata.error("No valid provider-metadata.json found.")
|
|
||||||
p.badProviderMetadata.error("STOPPING here - cannot perform other checks.")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const (
|
||||||
defaultWeb = "/var/www/html" // Default web path.
|
defaultWeb = "/var/www/html" // Default web path.
|
||||||
defaultNoWebUI = true
|
defaultNoWebUI = true
|
||||||
defaultUploadLimit = 50 * 1024 * 1024 // Default limit size of the uploaded file.
|
defaultUploadLimit = 50 * 1024 * 1024 // Default limit size of the uploaded file.
|
||||||
|
defaultServiceDocument = true
|
||||||
)
|
)
|
||||||
|
|
||||||
type providerMetadataConfig struct {
|
type providerMetadataConfig struct {
|
||||||
|
|
@ -226,7 +227,8 @@ func loadConfig() (*config, error) {
|
||||||
|
|
||||||
// Preset defaults
|
// Preset defaults
|
||||||
cfg := config{
|
cfg := config{
|
||||||
NoWebUI: defaultNoWebUI,
|
NoWebUI: defaultNoWebUI,
|
||||||
|
ServiceDocument: defaultServiceDocument,
|
||||||
}
|
}
|
||||||
|
|
||||||
md, err := toml.DecodeFile(path, &cfg)
|
md, err := toml.DecodeFile(path, &cfg)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||||
|
|
@ -153,10 +154,56 @@ func createFeedFolders(c *config, wellknown string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Create an empty ROLIE feed document
|
||||||
|
if err := createROLIEfeed(c, t, tlpLink); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createROLIEfeed creates an empty ROLIE feed
|
||||||
|
func createROLIEfeed(c *config, t tlp, folder string) error {
|
||||||
|
ts := string(t)
|
||||||
|
feedName := "csaf-feed-tlp-" + ts + ".json"
|
||||||
|
|
||||||
|
feed := filepath.Join(folder, feedName)
|
||||||
|
|
||||||
|
feedURL := csaf.JSONURL(
|
||||||
|
c.CanonicalURLPrefix +
|
||||||
|
"/.well-known/csaf/" + ts + "/" + feedName)
|
||||||
|
|
||||||
|
tlpLabel := csaf.TLPLabel(strings.ToUpper(ts))
|
||||||
|
|
||||||
|
links := []csaf.Link{{
|
||||||
|
Rel: "self",
|
||||||
|
HRef: string(feedURL),
|
||||||
|
}}
|
||||||
|
// If we have a service document we need to link it.
|
||||||
|
if c.ServiceDocument {
|
||||||
|
links = append(links, csaf.Link{
|
||||||
|
Rel: "service",
|
||||||
|
HRef: c.CanonicalURLPrefix + "/.well-known/csaf/service.json",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
rolie := &csaf.ROLIEFeed{
|
||||||
|
Feed: csaf.FeedData{
|
||||||
|
ID: "csaf-feed-tlp-" + ts,
|
||||||
|
Title: "CSAF feed (TLP:" + string(tlpLabel) + ")",
|
||||||
|
Link: links,
|
||||||
|
Category: []csaf.ROLIECategory{{
|
||||||
|
Scheme: "urn:ietf:params:rolie:category:information-type",
|
||||||
|
Term: "csaf",
|
||||||
|
}},
|
||||||
|
Updated: csaf.TimeStamp(time.Now().UTC()),
|
||||||
|
Entry: []*csaf.Entry{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.WriteToFile(feed, rolie)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// createOpenPGPFolder creates an openpgp folder besides
|
// createOpenPGPFolder creates an openpgp folder besides
|
||||||
// the provider-metadata.json in the csaf folder.
|
// the provider-metadata.json in the csaf folder.
|
||||||
func createOpenPGPFolder(c *config, wellknown string) error {
|
func createOpenPGPFolder(c *config, wellknown string) error {
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ func (c *controller) extendROLIE(
|
||||||
Scheme: "urn:ietf:params:rolie:category:information-type",
|
Scheme: "urn:ietf:params:rolie:category:information-type",
|
||||||
Term: "csaf",
|
Term: "csaf",
|
||||||
}},
|
}},
|
||||||
|
Entry: []*csaf.Entry{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ type FeedData struct {
|
||||||
Link []Link `json:"link,omitempty"`
|
Link []Link `json:"link,omitempty"`
|
||||||
Category []ROLIECategory `json:"category,omitempty"`
|
Category []ROLIECategory `json:"category,omitempty"`
|
||||||
Updated TimeStamp `json:"updated"`
|
Updated TimeStamp `json:"updated"`
|
||||||
Entry []*Entry `json:"entry,omitempty"`
|
Entry []*Entry `json:"entry"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ROLIEFeed is a ROLIE feed.
|
// ROLIEFeed is a ROLIE feed.
|
||||||
|
|
@ -238,3 +238,8 @@ func (rf *ROLIEFeed) SortEntriesByUpdated() {
|
||||||
return time.Time(entries[j].Updated).Before(time.Time(entries[i].Updated))
|
return time.Time(entries[j].Updated).Before(time.Time(entries[i].Updated))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountEntries returns the number of entries within the feed
|
||||||
|
func (rf *ROLIEFeed) CountEntries() int {
|
||||||
|
return len(rf.Feed.Entry)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,10 @@
|
||||||
"title": "Link",
|
"title": "Link",
|
||||||
"description": "Specifies the JSON link.",
|
"description": "Specifies the JSON link.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["rel", "href"],
|
"required": [
|
||||||
|
"rel",
|
||||||
|
"href"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"href": {
|
"href": {
|
||||||
"title": "Hyper reference",
|
"title": "Hyper reference",
|
||||||
|
|
@ -31,7 +34,9 @@
|
||||||
"title": "Relationship",
|
"title": "Relationship",
|
||||||
"description": "Contains the relationship value of the link.",
|
"description": "Contains the relationship value of the link.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["self"]
|
"enum": [
|
||||||
|
"self"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +47,10 @@
|
||||||
"title": "Link",
|
"title": "Link",
|
||||||
"description": "Specifies a single link.",
|
"description": "Specifies a single link.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["rel", "href"],
|
"required": [
|
||||||
|
"rel",
|
||||||
|
"href"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"href": {
|
"href": {
|
||||||
"title": "Hyper reference",
|
"title": "Hyper reference",
|
||||||
|
|
@ -61,13 +69,22 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["feed"],
|
"required": [
|
||||||
|
"feed"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"feed": {
|
"feed": {
|
||||||
"title": "CSAF ROLIE feed",
|
"title": "CSAF ROLIE feed",
|
||||||
"description": "Contains all information of the feed.",
|
"description": "Contains all information of the feed.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["id", "title", "link", "category", "updated", "entry"],
|
"required": [
|
||||||
|
"id",
|
||||||
|
"title",
|
||||||
|
"link",
|
||||||
|
"category",
|
||||||
|
"updated",
|
||||||
|
"entry"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"title": "ID",
|
"title": "ID",
|
||||||
|
|
@ -96,19 +113,26 @@
|
||||||
"title": "CSAF ROLIE category",
|
"title": "CSAF ROLIE category",
|
||||||
"description": "Contains the required ROLIE category value.",
|
"description": "Contains the required ROLIE category value.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["scheme", "term"],
|
"required": [
|
||||||
|
"scheme",
|
||||||
|
"term"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"scheme": {
|
"scheme": {
|
||||||
"title": "Scheme",
|
"title": "Scheme",
|
||||||
"description": "Contains the URI of the scheme to use.",
|
"description": "Contains the URI of the scheme to use.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["urn:ietf:params:rolie:category:information-type"]
|
"enum": [
|
||||||
|
"urn:ietf:params:rolie:category:information-type"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"term": {
|
"term": {
|
||||||
"title": "Term",
|
"title": "Term",
|
||||||
"description": "Contains the term that is valid in the context of the scheme.",
|
"description": "Contains the term that is valid in the context of the scheme.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["csaf"]
|
"enum": [
|
||||||
|
"csaf"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +143,10 @@
|
||||||
"title": "Category",
|
"title": "Category",
|
||||||
"description": "Specifies a single category.",
|
"description": "Specifies a single category.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["scheme", "term"],
|
"required": [
|
||||||
|
"scheme",
|
||||||
|
"term"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"scheme": {
|
"scheme": {
|
||||||
"title": "Scheme",
|
"title": "Scheme",
|
||||||
|
|
@ -146,7 +173,6 @@
|
||||||
"title": "List of Entries",
|
"title": "List of Entries",
|
||||||
"description": "Contains a list of feed entries.",
|
"description": "Contains a list of feed entries.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minItems": 1,
|
|
||||||
"uniqueItems": true,
|
"uniqueItems": true,
|
||||||
"items": {
|
"items": {
|
||||||
"title": "Entry",
|
"title": "Entry",
|
||||||
|
|
@ -193,13 +219,13 @@
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"summary": {
|
"summary": {
|
||||||
"title": "",
|
"title": "Summary",
|
||||||
"description": "",
|
"description": "Contains the summary of the CSAF document.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"content": {
|
"content": {
|
||||||
"title": "",
|
"title": "Content",
|
||||||
"description": "",
|
"description": "Contains the actual text of the summary.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +235,10 @@
|
||||||
"title": "Content of the entry",
|
"title": "Content of the entry",
|
||||||
"description": "Contains information about the content.",
|
"description": "Contains information about the content.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["type", "src"],
|
"required": [
|
||||||
|
"type",
|
||||||
|
"src"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"src": {
|
"src": {
|
||||||
"title": "Source Code",
|
"title": "Source Code",
|
||||||
|
|
@ -220,15 +249,20 @@
|
||||||
"title": "MIME type",
|
"title": "MIME type",
|
||||||
"description": "Contains the MIME type of the content.",
|
"description": "Contains the MIME type of the content.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["application/json"]
|
"enum": [
|
||||||
|
"application/json"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"format": {
|
"format": {
|
||||||
"title": "",
|
"title": "Format",
|
||||||
"description": "",
|
"description": "Contains information about the format of the entry.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["schema", "version"],
|
"required": [
|
||||||
|
"schema",
|
||||||
|
"version"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"title": "Schema of the entry",
|
"title": "Schema of the entry",
|
||||||
|
|
@ -240,9 +274,11 @@
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"title": "CSAF Version",
|
"title": "CSAF Version",
|
||||||
"description": "Contains the CSAF version the document was written in.",
|
"description": "Contains the CSAF version the document was written in.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["2.0"]
|
"enum": [
|
||||||
|
"2.0"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ The following example file documents all available configuration options:
|
||||||
#tlps = ["csaf", "white", "amber", "green", "red"]
|
#tlps = ["csaf", "white", "amber", "green", "red"]
|
||||||
|
|
||||||
# Make the provider create a ROLIE service document.
|
# Make the provider create a ROLIE service document.
|
||||||
#create_service_document = false
|
#create_service_document = true
|
||||||
|
|
||||||
# Make the provider create a ROLIE category document from a list of strings.
|
# Make the provider create a ROLIE category document from a list of strings.
|
||||||
# If a list item starts with `expr:`
|
# If a list item starts with `expr:`
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue