Skip to content

Commit 08ca7d9

Browse files
committed
add new ignore status
Signed-off-by: Markus Blaschke <mblaschke82@gmail.com>
1 parent 3efb981 commit 08ca7d9

16 files changed

+140
-53
lines changed

auditor/auditor.keyvaultaccesspolicies.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (auditor *AzureAuditor) auditKeyvaultAccessPolicies(ctx context.Context, lo
2424
matchingRuleId, status := auditor.config.KeyvaultAccessPolicies.Validate(object)
2525
report.Add(object, matchingRuleId, status)
2626

27-
if !status && auditor.config.KeyvaultAccessPolicies.IsMetricsEnabled() {
27+
if status.IsDeny() && auditor.config.KeyvaultAccessPolicies.IsMetricsEnabled() {
2828
violationMetric.AddInfo(
2929
auditor.config.KeyvaultAccessPolicies.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
3030
)

auditor/auditor.loganalytics.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (auditor *AzureAuditor) auditLogAnalytics(ctx context.Context, logger *zap.
4040
matchingRuleId, status := config.Validate(object)
4141
report.Add(object, matchingRuleId, status)
4242

43-
if !status && config.IsMetricsEnabled() {
43+
if status.IsDeny() && config.IsMetricsEnabled() {
4444
violationMetric.AddInfo(
4545
config.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
4646
)

auditor/auditor.report.go

+14-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
yaml "gopkg.in/yaml.v3"
1111

12+
"github.com/webdevops/azure-auditor/auditor/types"
1213
"github.com/webdevops/azure-auditor/auditor/validator"
1314
)
1415

@@ -25,15 +26,16 @@ type (
2526
}
2627

2728
AzureAuditorReportSummary struct {
28-
Ok int64
29-
Failed int64
29+
Ignore int64
30+
Deny int64
31+
Allow int64
3032
}
3133

3234
AzureAuditorReportLine struct {
3335
Resource map[string]interface{} `json:"resource"`
3436
RuleID string `json:"rule"`
3537
GroupBy interface{} `json:"groupBy"`
36-
Status bool `json:"status"`
38+
Status string `json:"status"`
3739
Count uint64 `json:"count"`
3840
}
3941
)
@@ -73,7 +75,7 @@ func (report *AzureAuditorReport) Clear() {
7375
report.Lines = []*AzureAuditorReportLine{}
7476
}
7577

76-
func (report *AzureAuditorReport) Add(resource *validator.AzureObject, ruleID string, status bool) {
78+
func (report *AzureAuditorReport) Add(resource *validator.AzureObject, ruleID string, status types.RuleStatus) {
7779
report.lock.Lock()
7880
defer report.lock.Unlock()
7981

@@ -82,13 +84,16 @@ func (report *AzureAuditorReport) Add(resource *validator.AzureObject, ruleID st
8284
&AzureAuditorReportLine{
8385
Resource: *resource,
8486
RuleID: ruleID,
85-
Status: status,
87+
Status: status.String(),
8688
},
8789
)
8890

89-
if status {
90-
report.Summary.Ok++
91-
} else {
92-
report.Summary.Failed++
91+
switch status {
92+
case types.RuleStatusIgnore:
93+
report.Summary.Ignore++
94+
case types.RuleStatusDeny:
95+
report.Summary.Deny++
96+
case types.RuleStatusAllow:
97+
report.Summary.Allow++
9398
}
9499
}

auditor/auditor.resourcegraph.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (auditor *AzureAuditor) auditResourceGraph(ctx context.Context, logger *zap
2424
matchingRuleId, status := config.Validate(object)
2525
report.Add(object, matchingRuleId, status)
2626

27-
if !status && config.IsMetricsEnabled() {
27+
if status.IsDeny() && config.IsMetricsEnabled() {
2828
violationMetric.AddInfo(
2929
config.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
3030
)

auditor/auditor.resourcegroups.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func (auditor *AzureAuditor) auditResourceGroups(ctx context.Context, logger *za
2121
matchingRuleId, status := auditor.config.ResourceGroups.Validate(object)
2222
report.Add(object, matchingRuleId, status)
2323

24-
if !status && auditor.config.ResourceGroups.IsMetricsEnabled() {
24+
if status.IsDeny() && auditor.config.ResourceGroups.IsMetricsEnabled() {
2525
violationMetric.AddInfo(
2626
auditor.config.ResourceGroups.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
2727
)

auditor/auditor.resourceproviderfeatures.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (auditor *AzureAuditor) auditResourceProviderFeatures(ctx context.Context,
2222
matchingRuleId, status := auditor.config.ResourceProviderFeatures.Validate(object)
2323
report.Add(object, matchingRuleId, status)
2424

25-
if !status && auditor.config.ResourceProviderFeatures.IsMetricsEnabled() {
25+
if status.IsDeny() && auditor.config.ResourceProviderFeatures.IsMetricsEnabled() {
2626
violationMetric.AddInfo(
2727
auditor.config.ResourceProviderFeatures.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
2828
)

auditor/auditor.resourceproviders.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func (auditor *AzureAuditor) auditResourceProviders(ctx context.Context, logger
2323
matchingRuleId, status := auditor.config.ResourceProviders.Validate(object)
2424
report.Add(object, matchingRuleId, status)
2525

26-
if !status && auditor.config.ResourceProviders.IsMetricsEnabled() {
26+
if status.IsDeny() && auditor.config.ResourceProviders.IsMetricsEnabled() {
2727
violationMetric.AddInfo(
2828
auditor.config.ResourceProviders.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
2929
)

auditor/auditor.roleassignments.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func (auditor *AzureAuditor) auditRoleAssignments(ctx context.Context, logger *z
2525
matchingRuleId, status := auditor.config.RoleAssignments.Validate(object)
2626
report.Add(object, matchingRuleId, status)
2727

28-
if !status && auditor.config.RoleAssignments.IsMetricsEnabled() {
28+
if status.IsDeny() && auditor.config.RoleAssignments.IsMetricsEnabled() {
2929
violationMetric.AddInfo(
3030
auditor.config.RoleAssignments.CreatePrometheusMetricFromAzureObject(object, matchingRuleId),
3131
)

auditor/types/const.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package types
2+
3+
import (
4+
"strings"
5+
)
6+
7+
type RuleStatus int
8+
9+
var (
10+
RuleStatusIgnore RuleStatus = -1
11+
RuleStatusDeny RuleStatus = 0
12+
RuleStatusAllow RuleStatus = 1
13+
)
14+
15+
func StringToRuleStatus(val string) RuleStatus {
16+
val = strings.TrimSpace(val)
17+
val = strings.ToLower(val)
18+
19+
switch strings.ToLower(val) {
20+
case "-1", "ignore":
21+
return RuleStatusIgnore
22+
case "0", "false", "deny":
23+
return RuleStatusDeny
24+
case "1", "true", "allow":
25+
return RuleStatusAllow
26+
}
27+
return RuleStatusDeny
28+
}
29+
30+
func (s RuleStatus) String() (ret string) {
31+
ret = "unknown"
32+
switch s {
33+
case RuleStatusIgnore:
34+
ret = "ignore"
35+
case RuleStatusDeny:
36+
ret = "deny"
37+
case RuleStatusAllow:
38+
ret = "allow"
39+
}
40+
return
41+
}
42+
43+
func (s RuleStatus) IsIgnore() bool {
44+
return s == RuleStatusIgnore
45+
}
46+
func (s RuleStatus) IsDeny() bool {
47+
return s == RuleStatusDeny
48+
}
49+
func (s RuleStatus) IsAllow() bool {
50+
return s == RuleStatusAllow
51+
}

auditor/validator/validation.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"strings"
55

66
"github.com/prometheus/client_golang/prometheus"
7+
8+
"github.com/webdevops/azure-auditor/auditor/types"
79
)
810

911
type (
@@ -97,7 +99,7 @@ func (validation *AuditConfigValidation) CreatePrometheusMetricFromAzureObject(o
9799
return labels
98100
}
99101

100-
func (validation *AuditConfigValidation) Validate(object *AzureObject) (string, bool) {
102+
func (validation *AuditConfigValidation) Validate(object *AzureObject) (string, types.RuleStatus) {
101103
resourceID := object.ResourceID()
102104

103105
if validation.Rules != nil {
@@ -108,7 +110,7 @@ func (validation *AuditConfigValidation) Validate(object *AzureObject) (string,
108110
continue
109111
} else {
110112
// valid is not valid, returning here
111-
return rule.Rule, rule.handleRuleStatus(object, false)
113+
return rule.Rule, rule.handleRuleStatus(object, types.RuleStatusDeny)
112114
}
113115
}
114116

@@ -127,7 +129,7 @@ func (validation *AuditConfigValidation) Validate(object *AzureObject) (string,
127129
continue
128130
} else {
129131
// valid is not valid, returning here
130-
return rule.Rule, rule.handleRuleStatus(object, false)
132+
return rule.Rule, rule.handleRuleStatus(object, types.RuleStatusDeny)
131133
}
132134
}
133135

@@ -138,5 +140,5 @@ func (validation *AuditConfigValidation) Validate(object *AzureObject) (string,
138140
}
139141
}
140142

141-
return "__DEFAULTDENY__", false
143+
return "__DEFAULTDENY__", types.RuleStatusDeny
142144
}

auditor/validator/validation.rule.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"github.com/robertkrimen/otto"
1515
_ "github.com/robertkrimen/otto/underscore"
1616
"go.uber.org/zap"
17+
18+
"github.com/webdevops/azure-auditor/auditor/types"
1719
)
1820

1921
type (
@@ -179,13 +181,13 @@ func (matcher *AuditConfigValidationRule) UnmarshalYAML(unmarshal func(interface
179181
return nil
180182
}
181183

182-
func (rule *AuditConfigValidationRule) handleRuleStatus(object *AzureObject, status bool) bool {
184+
func (rule *AuditConfigValidationRule) handleRuleStatus(object *AzureObject, status types.RuleStatus) types.RuleStatus {
183185
atomic.AddInt64(&rule.Stats.Matches, 1)
184186
if Logger != nil {
185187
Logger.With(
186188
zap.String("resourceID", object.ResourceID()),
187189
zap.String("rule", rule.Rule),
188-
zap.Bool("validationStatus", status),
190+
zap.String("validationStatus", status.String()),
189191
).Debugf("validation status: \"%v\"", status)
190192
}
191193
return status
@@ -195,16 +197,18 @@ func (matcher *AuditConfigValidationRule) IsActionContinue() bool {
195197
return matcher.Action == "continue"
196198
}
197199

198-
func (matcher *AuditConfigValidationRule) ValidationStatus() *bool {
200+
func (matcher *AuditConfigValidationRule) ValidationStatus() (ret *types.RuleStatus) {
199201
switch strings.ToLower(matcher.Action) {
202+
case "ignore":
203+
ret = &types.RuleStatusIgnore
200204
case "deny":
201-
return to.BoolPtr(false)
205+
ret = &types.RuleStatusDeny
202206
case "allow":
203-
return to.BoolPtr(true)
207+
ret = &types.RuleStatusAllow
204208
case "continue":
205-
return nil
209+
ret = nil
206210
}
207-
return nil
211+
return
208212
}
209213

210214
func (matcher *AuditConfigValidationRule) IsMatching(object *AzureObject) bool {

auditor/validator/validator_test.go

+22-8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ test:
2626
regexp: "^barfoo"
2727
action: continue
2828
29+
- rule: ignoretest
30+
resourcegroup.name: barfoo
31+
action: ignore
32+
2933
- rule: name
3034
resourcegroup.name: foobar
3135
action: allow
@@ -44,7 +48,7 @@ test:
4448
"resourcegroup.tag.foobar": "barfoo",
4549
},
4650
)
47-
if _, status := config.Test.Validate(obj); !status {
51+
if _, status := config.Test.Validate(obj); !status.IsAllow() {
4852
t.Errorf("expected matching object, got: %v", status)
4953
}
5054

@@ -54,7 +58,17 @@ test:
5458
"resourcegroup.tag.barfoo": "foobar",
5559
},
5660
)
57-
if _, status := config.Test.Validate(obj); status {
61+
if _, status := config.Test.Validate(obj); !status.IsDeny() {
62+
t.Errorf("expected NOT matching object, got: %v", status)
63+
}
64+
65+
obj = NewAzureObject(
66+
map[string]interface{}{
67+
"resourcegroup.name": "barfoo",
68+
"resourcegroup.tag.foobar": "barfoo",
69+
},
70+
)
71+
if _, status := config.Test.Validate(obj); !status.IsIgnore() {
5872
t.Errorf("expected NOT matching object, got: %v", status)
5973
}
6074
}
@@ -122,7 +136,7 @@ test:
122136
"principal.type": "group",
123137
},
124138
)
125-
if ruleId, status := config.Test.Validate(obj); !status {
139+
if ruleId, status := config.Test.Validate(obj); !status.IsAllow() {
126140
t.Errorf("expected matching object, got: %v by rule %v", status, ruleId)
127141
}
128142

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

@@ -173,7 +187,7 @@ test:
173187
"principal.type": "group",
174188
},
175189
)
176-
if ruleId, status := config.Test.Validate(obj); !status {
190+
if ruleId, status := config.Test.Validate(obj); !status.IsAllow() {
177191
t.Errorf("expected matching object, got: %v by rule %v", status, ruleId)
178192
}
179193

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

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

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

example.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ resourceGroups:
8080
resourcegroup.location: { regexp: "westeurope" }
8181
action: continue
8282

83+
- rule: ignoretest
84+
resourcegroup.name: barfoo
85+
action: ignore
86+
8387
- rule: no-tag-owner-devteam0
8488
resourcegroup.tag.owner:
8589
mode: optional

0 commit comments

Comments
 (0)