Skip to content

Commit

Permalink
[feat] Dynamic policy dates (#88)
Browse files Browse the repository at this point in the history
Signed-off-by: Benji Visser <benji@093b.org>
  • Loading branch information
noqcks authored Jul 27, 2023
1 parent 4194222 commit 1b5c7fc
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 14 deletions.
8 changes: 6 additions & 2 deletions internal/xeolio/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ type Policy struct {
// the type of policy [eol]
PolicyType PolicyType `json:"policy_type"`
// the date which to start warning xeol scans
WarnDate string `json:"warn_date"`
WarnDate string `json:"warn_date,omitempty"`
// the date which to start failing xeol scans
DenyDate string `json:"deny_date"`
DenyDate string `json:"deny_date,omitempty"`
// the days before eol to start warning xeol scans
WarnDays *int `json:"warn_days,omitempty"`
// the days before eol to start failing xeol scans
DenyDays *int `json:"deny_days,omitempty"`
// the project name to match policy against. Valid when PolicyScope is 'project'
ProjectName string `json:"project_name,omitempty"`
//
Expand Down
66 changes: 54 additions & 12 deletions xeol/policy/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,27 +80,68 @@ func cycleOperatorMatch(m match.Match, policy xeolio.Policy) bool {
}
}

func warnMatch(policy xeolio.Policy) bool {
warnDate, err := time.Parse(DateLayout, policy.WarnDate)
if err != nil {
log.Debugf("Invalid policy warn date: %s", policy.WarnDate)
func warnMatch(policy *xeolio.Policy, match match.Match) bool {
var warnDate time.Time

if policy.WarnDate != "" {
var err error
warnDate, err = time.Parse(DateLayout, policy.WarnDate)
if err != nil {
log.Errorf("invalid policy warn date: %s", policy.WarnDate)
return false
}
}

if policy.WarnDays != nil {
eolDate, err := time.Parse(DateLayout, match.Cycle.Eol)
if err != nil {
log.Errorf("invalid eol date: %s, %s", match.Cycle.Eol, err)
return false
}
warnDate = eolDate.Add(time.Duration(*policy.WarnDays*-1) * time.Hour * 24)
}

if warnDate.IsZero() {
return false
}

if timeNow().After(warnDate) {
return true
}

return false
}

func denyMatch(policy xeolio.Policy) bool {
denyDate, err := time.Parse(DateLayout, policy.DenyDate)
if err != nil {
log.Debugf("Invalid policy deny date: %s", policy.DenyDate)
func denyMatch(policy *xeolio.Policy, match match.Match) bool {
var denyDate time.Time

if policy.DenyDate != "" {
var err error
denyDate, err = time.Parse(DateLayout, policy.DenyDate)
if err != nil {
log.Errorf("invalid policy deny date: %s", policy.DenyDate)
return false
}
}

if policy.DenyDays != nil {
eolDate, err := time.Parse(DateLayout, match.Cycle.Eol)
if err != nil {
log.Errorf("invalid eol date: %s, %s", match.Cycle.Eol, err)
return false
}
denyDate = eolDate.Add(time.Duration(*policy.DenyDays*-1) * time.Hour * 24)
policy.DenyDate = denyDate.Format(DateLayout)
}

if denyDate.IsZero() {
return false
}

if timeNow().After(denyDate) {
return true
}

return false
}

Expand Down Expand Up @@ -130,6 +171,7 @@ func evaluateMatches(policies []xeolio.Policy, matches match.Matches, projectNam
sort.Stable(ByPolicyScope(policies))

for _, policy := range policies {
policyCopy := policy
for _, match := range matches.Sorted() {
if evaluatedMatches[match.Cycle.ProductName] {
continue
Expand All @@ -147,13 +189,13 @@ func evaluateMatches(policies []xeolio.Policy, matches match.Matches, projectNam
}

// deny policy takes precedence over warn policy, so order is important here
if denyMatch(policy) {
results = append(results, createEvaluationResult(policy, match, PolicyTypeDeny))
if denyMatch(&policyCopy, match) {
results = append(results, createEvaluationResult(policyCopy, match, PolicyTypeDeny))
evaluatedMatches[match.Cycle.ProductName] = true
continue
}
if warnMatch(policy) {
results = append(results, createEvaluationResult(policy, match, PolicyTypeWarn))
if warnMatch(&policyCopy, match) {
results = append(results, createEvaluationResult(policyCopy, match, PolicyTypeWarn))
evaluatedMatches[match.Cycle.ProductName] = true
}
}
Expand Down
103 changes: 103 additions & 0 deletions xeol/policy/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import (
"github.com/xeol-io/xeol/xeol/pkg"
)

func Int(value int) *int {
return &value
}

func TestEvaluate(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -500,6 +504,105 @@ func TestEvaluate(t *testing.T) {
},
},
},
{
name: "test sliding global policy [deny]",
policy: []xeolio.Policy{
{
PolicyScope: xeolio.PolicyScopeGlobal,
PolicyType: xeolio.PolicyTypeEol,
WarnDays: Int(60),
DenyDays: Int(30),
},
},
matches: []match.Match{
{
Cycle: eol.Cycle{
ProductName: "foo",
ReleaseCycle: "1.3",
Eol: "2021-02-28",
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "foo",
Version: "1.3.0",
Type: syftPkg.RpmPkg,
},
},
},
want: []EvaluationResult{
{
Type: PolicyTypeDeny,
ProductName: "foo",
Cycle: "1.3",
},
},
},
{
name: "test sliding global policy [warn]",
policy: []xeolio.Policy{
{
PolicyScope: xeolio.PolicyScopeGlobal,
PolicyType: xeolio.PolicyTypeEol,
WarnDays: Int(60),
DenyDays: Int(30),
},
},
matches: []match.Match{
{
Cycle: eol.Cycle{
ProductName: "foo",
ReleaseCycle: "1.3",
Eol: "2021-03-28",
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "foo",
Version: "1.3.0",
Type: syftPkg.RpmPkg,
},
},
},
want: []EvaluationResult{
{
Type: PolicyTypeWarn,
ProductName: "foo",
Cycle: "1.3",
FailDate: "2021-02-26",
},
},
},
{
name: "test sliding global policy [deny, no warn]",
policy: []xeolio.Policy{
{
PolicyScope: xeolio.PolicyScopeGlobal,
PolicyType: xeolio.PolicyTypeEol,
DenyDays: Int(30),
},
},
matches: []match.Match{
{
Cycle: eol.Cycle{
ProductName: "foo",
ReleaseCycle: "1.3",
Eol: "2021-02-28",
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "foo",
Version: "1.3.0",
Type: syftPkg.RpmPkg,
},
},
},
want: []EvaluationResult{
{
Type: PolicyTypeDeny,
ProductName: "foo",
Cycle: "1.3",
},
},
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 1b5c7fc

Please sign in to comment.