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

Be more precise with conditional rules.

This commit is contained in:
Sascha L. Teichmann 2023-06-13 12:25:19 +02:00
parent 7eae607810
commit c7453a6448
3 changed files with 124 additions and 43 deletions

View file

@ -254,7 +254,16 @@ func (p *processor) run(domains []string) (*Report, error) {
continue continue
} }
for _, r := range buildReporters(*domain.Role) { rules := roleRequirements(*domain.Role)
// TODO: store error base on rules eval in report.
if rules == nil {
log.Printf(
"WARN: Cannot find requirement rules for role %q. Assuming trusted provider.\n",
*domain.Role)
rules = trustedProviderRules
}
for _, r := range rules.reporters() {
r.report(p, domain) r.report(p, domain)
} }

View file

@ -12,8 +12,6 @@ import (
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
"github.com/csaf-poc/csaf_distribution/v2/csaf"
) )
type ( type (
@ -72,46 +70,6 @@ var reporters = [23]reporter{
&mirrorReporter{baseReporter{num: 23, description: "Mirror"}}, &mirrorReporter{baseReporter{num: 23, description: "Mirror"}},
} }
var roleImplies = map[csaf.MetadataRole][]csaf.MetadataRole{
csaf.MetadataRoleProvider: {csaf.MetadataRolePublisher},
csaf.MetadataRoleTrustedProvider: {csaf.MetadataRoleProvider},
}
func requirements(role csaf.MetadataRole) [][2]int {
var own [][2]int
switch role {
case csaf.MetadataRoleTrustedProvider:
own = [][2]int{{18, 20}}
case csaf.MetadataRoleProvider:
// TODO: use commented numbers when TLPs should be checked.
own = [][2]int{{6 /* 5 */, 7}, {8, 10}, {11, 14}, {15, 17}}
case csaf.MetadataRolePublisher:
own = [][2]int{{1, 3 /* 4 */}}
}
for _, base := range roleImplies[role] {
own = append(own, requirements(base)...)
}
return own
}
// buildReporters initializes each report by assigning a number and description to it.
// It returns an array of the reporter interface type.
func buildReporters(role csaf.MetadataRole) []reporter {
var reps []reporter
reqs := requirements(role)
// sort to have them ordered by there number.
sort.Slice(reqs, func(i, j int) bool { return reqs[i][0] < reqs[j][0] })
for _, req := range reqs {
from, to := req[0]-1, req[1]-1
for i := from; i <= to; i++ {
if rep := reporters[i]; rep != nil {
reps = append(reps, rep)
}
}
}
return reps
}
func (bc *baseReporter) requirement(domain *Domain) *Requirement { func (bc *baseReporter) requirement(domain *Domain) *Requirement {
req := &Requirement{ req := &Requirement{
Num: bc.num, Num: bc.num,

114
cmd/csaf_checker/rules.go Normal file
View file

@ -0,0 +1,114 @@
// This file is Free Software under the MIT License
// without warranty, see README.md and LICENSES/MIT.txt for details.
//
// SPDX-License-Identifier: MIT
//
// SPDX-FileCopyrightText: 2023 German Federal Office for Information Security (BSI) <https://www.bsi.bund.de>
// Software-Engineering: 2023 Intevation GmbH <https://intevation.de>
package main
import (
"sort"
"github.com/csaf-poc/csaf_distribution/v2/csaf"
)
type ruleCondition int
const (
condAll ruleCondition = iota
condOneOf
)
type requirementRules struct {
cond ruleCondition
satisfies int
subs []*requirementRules
}
var (
publisherRules = &requirementRules{
cond: condAll,
subs: ruleAtoms(1, 2, 3 /* 4 */),
}
providerRules = &requirementRules{
cond: condAll,
subs: []*requirementRules{
publisherRules,
{cond: condOneOf, subs: ruleAtoms(8, 9, 10)},
{cond: condOneOf, subs: []*requirementRules{
{cond: condAll, subs: ruleAtoms(11, 12, 13, 14)},
{cond: condAll, subs: ruleAtoms(15, 16, 17)},
}},
},
}
trustedProviderRules = &requirementRules{
cond: condAll,
subs: []*requirementRules{
providerRules,
{cond: condAll, subs: ruleAtoms(18, 19, 20)},
},
}
)
func ruleAtoms(nums ...int) []*requirementRules {
rules := make([]*requirementRules, len(nums))
for i, num := range nums {
rules[i] = &requirementRules{
cond: condAll,
satisfies: num,
}
}
return rules
}
func (rules *requirementRules) reporters() []reporter {
if rules == nil {
return nil
}
var nums []int
var recurse func(*requirementRules)
recurse = func(rules *requirementRules) {
if rules.satisfies != 0 {
// There should not be any dupes
for _, n := range nums {
if n == rules.satisfies {
goto doRecurse
}
}
nums = append(nums, rules.satisfies)
}
doRecurse:
for _, sub := range rules.subs {
recurse(sub)
}
}
recurse(rules)
sort.Ints(nums)
reps := make([]reporter, len(nums))
for i, n := range nums {
reps[i] = reporters[n]
}
return reps
}
// roleRequirements returns the rules for the given role.
func roleRequirements(role csaf.MetadataRole) *requirementRules {
switch role {
case csaf.MetadataRoleTrustedProvider:
return trustedProviderRules
case csaf.MetadataRoleProvider:
return providerRules
case csaf.MetadataRolePublisher:
return publisherRules
default:
return nil
}
}