Skip to content

Commit

Permalink
add new ignore status
Browse files Browse the repository at this point in the history
Signed-off-by: Markus Blaschke <[email protected]>
  • Loading branch information
mblaschke committed Oct 9, 2023
1 parent 3efb981 commit 08ca7d9
Show file tree
Hide file tree
Showing 16 changed files with 140 additions and 53 deletions.
2 changes: 1 addition & 1 deletion auditor/auditor.keyvaultaccesspolicies.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (auditor *AzureAuditor) auditKeyvaultAccessPolicies(ctx context.Context, lo
matchingRuleId, status := auditor.config.KeyvaultAccessPolicies.Validate(object)
report.Add(object, matchingRuleId, status)

if !status && auditor.config.KeyvaultAccessPolicies.IsMetricsEnabled() {
if status.IsDeny() && auditor.config.KeyvaultAccessPolicies.IsMetricsEnabled() {
violationMetric.AddInfo(
auditor.config.KeyvaultAccessPolicies.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
)
Expand Down
2 changes: 1 addition & 1 deletion auditor/auditor.loganalytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (auditor *AzureAuditor) auditLogAnalytics(ctx context.Context, logger *zap.
matchingRuleId, status := config.Validate(object)
report.Add(object, matchingRuleId, status)

if !status && config.IsMetricsEnabled() {
if status.IsDeny() && config.IsMetricsEnabled() {
violationMetric.AddInfo(
config.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
)
Expand Down
23 changes: 14 additions & 9 deletions auditor/auditor.report.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

yaml "gopkg.in/yaml.v3"

"github.com/webdevops/azure-auditor/auditor/types"
"github.com/webdevops/azure-auditor/auditor/validator"
)

Expand All @@ -25,15 +26,16 @@ type (
}

AzureAuditorReportSummary struct {
Ok int64
Failed int64
Ignore int64
Deny int64
Allow int64
}

AzureAuditorReportLine struct {
Resource map[string]interface{} `json:"resource"`
RuleID string `json:"rule"`
GroupBy interface{} `json:"groupBy"`
Status bool `json:"status"`
Status string `json:"status"`
Count uint64 `json:"count"`
}
)
Expand Down Expand Up @@ -73,7 +75,7 @@ func (report *AzureAuditorReport) Clear() {
report.Lines = []*AzureAuditorReportLine{}
}

func (report *AzureAuditorReport) Add(resource *validator.AzureObject, ruleID string, status bool) {
func (report *AzureAuditorReport) Add(resource *validator.AzureObject, ruleID string, status types.RuleStatus) {
report.lock.Lock()
defer report.lock.Unlock()

Expand All @@ -82,13 +84,16 @@ func (report *AzureAuditorReport) Add(resource *validator.AzureObject, ruleID st
&AzureAuditorReportLine{
Resource: *resource,
RuleID: ruleID,
Status: status,
Status: status.String(),
},
)

if status {
report.Summary.Ok++
} else {
report.Summary.Failed++
switch status {
case types.RuleStatusIgnore:
report.Summary.Ignore++
case types.RuleStatusDeny:
report.Summary.Deny++
case types.RuleStatusAllow:
report.Summary.Allow++
}
}
2 changes: 1 addition & 1 deletion auditor/auditor.resourcegraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (auditor *AzureAuditor) auditResourceGraph(ctx context.Context, logger *zap
matchingRuleId, status := config.Validate(object)
report.Add(object, matchingRuleId, status)

if !status && config.IsMetricsEnabled() {
if status.IsDeny() && config.IsMetricsEnabled() {
violationMetric.AddInfo(
config.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
)
Expand Down
2 changes: 1 addition & 1 deletion auditor/auditor.resourcegroups.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (auditor *AzureAuditor) auditResourceGroups(ctx context.Context, logger *za
matchingRuleId, status := auditor.config.ResourceGroups.Validate(object)
report.Add(object, matchingRuleId, status)

if !status && auditor.config.ResourceGroups.IsMetricsEnabled() {
if status.IsDeny() && auditor.config.ResourceGroups.IsMetricsEnabled() {
violationMetric.AddInfo(
auditor.config.ResourceGroups.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
)
Expand Down
2 changes: 1 addition & 1 deletion auditor/auditor.resourceproviderfeatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (auditor *AzureAuditor) auditResourceProviderFeatures(ctx context.Context,
matchingRuleId, status := auditor.config.ResourceProviderFeatures.Validate(object)
report.Add(object, matchingRuleId, status)

if !status && auditor.config.ResourceProviderFeatures.IsMetricsEnabled() {
if status.IsDeny() && auditor.config.ResourceProviderFeatures.IsMetricsEnabled() {
violationMetric.AddInfo(
auditor.config.ResourceProviderFeatures.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
)
Expand Down
2 changes: 1 addition & 1 deletion auditor/auditor.resourceproviders.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (auditor *AzureAuditor) auditResourceProviders(ctx context.Context, logger
matchingRuleId, status := auditor.config.ResourceProviders.Validate(object)
report.Add(object, matchingRuleId, status)

if !status && auditor.config.ResourceProviders.IsMetricsEnabled() {
if status.IsDeny() && auditor.config.ResourceProviders.IsMetricsEnabled() {
violationMetric.AddInfo(
auditor.config.ResourceProviders.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
)
Expand Down
2 changes: 1 addition & 1 deletion auditor/auditor.roleassignments.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (auditor *AzureAuditor) auditRoleAssignments(ctx context.Context, logger *z
matchingRuleId, status := auditor.config.RoleAssignments.Validate(object)
report.Add(object, matchingRuleId, status)

if !status && auditor.config.RoleAssignments.IsMetricsEnabled() {
if status.IsDeny() && auditor.config.RoleAssignments.IsMetricsEnabled() {
violationMetric.AddInfo(
auditor.config.RoleAssignments.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
)
Expand Down
51 changes: 51 additions & 0 deletions auditor/types/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package types

import (
"strings"
)

type RuleStatus int

var (
RuleStatusIgnore RuleStatus = -1
RuleStatusDeny RuleStatus = 0
RuleStatusAllow RuleStatus = 1
)

func StringToRuleStatus(val string) RuleStatus {
val = strings.TrimSpace(val)
val = strings.ToLower(val)

switch strings.ToLower(val) {
case "-1", "ignore":
return RuleStatusIgnore
case "0", "false", "deny":
return RuleStatusDeny
case "1", "true", "allow":
return RuleStatusAllow
}
return RuleStatusDeny
}

func (s RuleStatus) String() (ret string) {
ret = "unknown"
switch s {
case RuleStatusIgnore:
ret = "ignore"
case RuleStatusDeny:
ret = "deny"
case RuleStatusAllow:
ret = "allow"
}
return
}

func (s RuleStatus) IsIgnore() bool {
return s == RuleStatusIgnore
}
func (s RuleStatus) IsDeny() bool {
return s == RuleStatusDeny
}
func (s RuleStatus) IsAllow() bool {
return s == RuleStatusAllow
}
10 changes: 6 additions & 4 deletions auditor/validator/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"strings"

"github.com/prometheus/client_golang/prometheus"

"github.com/webdevops/azure-auditor/auditor/types"
)

type (
Expand Down Expand Up @@ -97,7 +99,7 @@ func (validation *AuditConfigValidation) CreatePrometheusMetricFromAzureObject(o
return labels
}

func (validation *AuditConfigValidation) Validate(object *AzureObject) (string, bool) {
func (validation *AuditConfigValidation) Validate(object *AzureObject) (string, types.RuleStatus) {
resourceID := object.ResourceID()

if validation.Rules != nil {
Expand All @@ -108,7 +110,7 @@ func (validation *AuditConfigValidation) Validate(object *AzureObject) (string,
continue
} else {
// valid is not valid, returning here
return rule.Rule, rule.handleRuleStatus(object, false)
return rule.Rule, rule.handleRuleStatus(object, types.RuleStatusDeny)
}
}

Expand All @@ -127,7 +129,7 @@ func (validation *AuditConfigValidation) Validate(object *AzureObject) (string,
continue
} else {
// valid is not valid, returning here
return rule.Rule, rule.handleRuleStatus(object, false)
return rule.Rule, rule.handleRuleStatus(object, types.RuleStatusDeny)
}
}

Expand All @@ -138,5 +140,5 @@ func (validation *AuditConfigValidation) Validate(object *AzureObject) (string,
}
}

return "__DEFAULTDENY__", false
return "__DEFAULTDENY__", types.RuleStatusDeny
}
18 changes: 11 additions & 7 deletions auditor/validator/validation.rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/robertkrimen/otto"
_ "github.com/robertkrimen/otto/underscore"
"go.uber.org/zap"

"github.com/webdevops/azure-auditor/auditor/types"
)

type (
Expand Down Expand Up @@ -179,13 +181,13 @@ func (matcher *AuditConfigValidationRule) UnmarshalYAML(unmarshal func(interface
return nil
}

func (rule *AuditConfigValidationRule) handleRuleStatus(object *AzureObject, status bool) bool {
func (rule *AuditConfigValidationRule) handleRuleStatus(object *AzureObject, status types.RuleStatus) types.RuleStatus {
atomic.AddInt64(&rule.Stats.Matches, 1)
if Logger != nil {
Logger.With(
zap.String("resourceID", object.ResourceID()),
zap.String("rule", rule.Rule),
zap.Bool("validationStatus", status),
zap.String("validationStatus", status.String()),
).Debugf("validation status: \"%v\"", status)
}
return status
Expand All @@ -195,16 +197,18 @@ func (matcher *AuditConfigValidationRule) IsActionContinue() bool {
return matcher.Action == "continue"
}

func (matcher *AuditConfigValidationRule) ValidationStatus() *bool {
func (matcher *AuditConfigValidationRule) ValidationStatus() (ret *types.RuleStatus) {
switch strings.ToLower(matcher.Action) {
case "ignore":
ret = &types.RuleStatusIgnore
case "deny":
return to.BoolPtr(false)
ret = &types.RuleStatusDeny
case "allow":
return to.BoolPtr(true)
ret = &types.RuleStatusAllow
case "continue":
return nil
ret = nil
}
return nil
return
}

func (matcher *AuditConfigValidationRule) IsMatching(object *AzureObject) bool {
Expand Down
30 changes: 22 additions & 8 deletions auditor/validator/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ test:
regexp: "^barfoo"
action: continue
- rule: ignoretest
resourcegroup.name: barfoo
action: ignore
- rule: name
resourcegroup.name: foobar
action: allow
Expand All @@ -44,7 +48,7 @@ test:
"resourcegroup.tag.foobar": "barfoo",
},
)
if _, status := config.Test.Validate(obj); !status {
if _, status := config.Test.Validate(obj); !status.IsAllow() {
t.Errorf("expected matching object, got: %v", status)
}

Expand All @@ -54,7 +58,17 @@ test:
"resourcegroup.tag.barfoo": "foobar",
},
)
if _, status := config.Test.Validate(obj); status {
if _, status := config.Test.Validate(obj); !status.IsDeny() {
t.Errorf("expected NOT matching object, got: %v", status)
}

obj = NewAzureObject(
map[string]interface{}{
"resourcegroup.name": "barfoo",
"resourcegroup.tag.foobar": "barfoo",
},
)
if _, status := config.Test.Validate(obj); !status.IsIgnore() {
t.Errorf("expected NOT matching object, got: %v", status)
}
}
Expand Down Expand Up @@ -122,7 +136,7 @@ test:
"principal.type": "group",
},
)
if ruleId, status := config.Test.Validate(obj); !status {
if ruleId, status := config.Test.Validate(obj); !status.IsAllow() {
t.Errorf("expected matching object, got: %v by rule %v", status, ruleId)
}

Expand All @@ -134,7 +148,7 @@ test:
"principal.type": "group",
},
)
if ruleId, status := config.Test.Validate(obj); status {
if ruleId, status := config.Test.Validate(obj); !status.IsDeny() {
t.Errorf("expected NOT matching object, got: %v by rule %v", status, ruleId)
}

Expand Down Expand Up @@ -173,7 +187,7 @@ test:
"principal.type": "group",
},
)
if ruleId, status := config.Test.Validate(obj); !status {
if ruleId, status := config.Test.Validate(obj); !status.IsAllow() {
t.Errorf("expected matching object, got: %v by rule %v", status, ruleId)
}

Expand All @@ -185,7 +199,7 @@ test:
"principal.type": "group",
},
)
if ruleId, status := config.Test.Validate(obj); status || ruleId != "deny" {
if ruleId, status := config.Test.Validate(obj); !status.IsDeny() || ruleId != "deny" {
t.Errorf("expected NOT matching object with rule deny, got: %v by rule %v", status, ruleId)
}

Expand Down Expand Up @@ -215,7 +229,7 @@ test:
"resourcegroup.tag.updated": time.Now().Format("YYYY-MM-DD"),
},
)
if ruleId, status := config.Test.Validate(obj); !status {
if ruleId, status := config.Test.Validate(obj); !status.IsAllow() {
t.Errorf("expected matching object, got: %v by rule %v", status, ruleId)
}

Expand All @@ -224,7 +238,7 @@ test:
"resourcegroup.tag.updated": "2000-01-01",
},
)
if ruleId, status := config.Test.Validate(obj); status || ruleId != "deny" {
if ruleId, status := config.Test.Validate(obj); !status.IsDeny() || ruleId != "deny" {
t.Errorf("expected NOT matching object with rule deny, got: %v by rule %v", status, ruleId)
}

Expand Down
4 changes: 4 additions & 0 deletions example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ resourceGroups:
resourcegroup.location: { regexp: "westeurope" }
action: continue

- rule: ignoretest
resourcegroup.name: barfoo
action: ignore

- rule: no-tag-owner-devteam0
resourcegroup.tag.owner:
mode: optional
Expand Down
Loading

0 comments on commit 08ca7d9

Please sign in to comment.