-
Notifications
You must be signed in to change notification settings - Fork 28
/
policy-node-port-range-check.rego
135 lines (112 loc) · 4.34 KB
/
policy-node-port-range-check.rego
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package kubernetes.admission.policy_nodeport_range
import data.kubernetes.namespaces
policy_metadata = {
# Set MagTape Policy Info
"name": "policy-nodeport-range",
"severity": "MED",
"errcode": "MT2002",
"targets": {"Service"},
}
kind = input.request.kind.kind
svc_type = input.request.object.spec.type
exception_val = "na"
matches {
# Verify request object type matches targets
# Verify service is of type NodePort
policy_metadata.targets[kind]
svc_type == "NodePort"
}
# Generate violation if nodePort Range is not within allocated range
deny[info] {
# ns_name: namespace connected to service trying to be deployed
# ports: where the hostport config is found within the service
# np_range: pull the information connected to the nodeportRange label in the namespace yaml config
ns_name := input.request.namespace
service_name := input.request.object.metadata.name
ports := input.request.object.spec.ports
port := ports[_]
np := port.nodePort
np_range := data.kubernetes.namespaces[ns_name].metadata.annotations["k8s.t-mobile.com/nodeportRange"]
port_in_range := check_nodeport_range(np, np_range)
# Build message to return
msg := sprintf("[FAIL] %v - nodePort %v %v for Service \"%v\" (%v)", [policy_metadata.severity, np, port_in_range, service_name, policy_metadata.errcode])
info := {
"name": policy_metadata.name,
"severity": policy_metadata.severity,
"errcode": policy_metadata.errcode,
"msg": msg,
}
}
# Generate violation if annotation contains anything besides #, commas, hyphen, or exception_val
deny[info] {
# ns_name: namespace connected to service trying to be deployed
# ports: where the hostport config is found within the service
# np_range: pull the information connected to the nodeportRange label in the namespace yaml config
ns_name := input.request.namespace
service_name := input.request.object.metadata.name
ports := input.request.object.spec.ports
port := ports[_]
np_range := data.kubernetes.namespaces[ns_name].metadata.annotations["k8s.t-mobile.com/nodeportRange"]
annotation_valid := check_annotation(np_range, exception_val)
# Build message to return
msg := sprintf("[FAIL] %v - Invalid data in nodePort annotation in \"%v\" namespace (%v)", [policy_metadata.severity, ns_name, policy_metadata.errcode])
info := {
"name": policy_metadata.name,
"severity": policy_metadata.severity,
"errcode": policy_metadata.errcode,
"msg": msg,
}
}
# Check_annotation accepts two values (np, np_range)
# Returns whether the nodeport range contains unknown symbols and is not the exception value
check_annotation(np_range, exception_val) {
not re_match(`^[-, ]*[0-9 ]+(?:-[0-9 ]+)?(,[0-9 ]+(?:-[0-9 ]+)?)*[-, ]*$`, trim_space(np_range))
lower(trim_space(np_range)) != exception_val
}
# Check_nodeport_range accepts two values (np, np_range)
# Returns whether the nodeport(np) is within the range(np_range)
check_nodeport_range(np, np_range) = "is out of defined range" {
contains(np_range, "-")
contains(np_range, ",")
re_match(`^[-, ]*[0-9 ]+(?:-[0-9 ]+)?(,[0-9 ]+(?:-[0-9 ]+)?)*[-, ]*$`, trim_space(np_range))
range_split := split(np_range, ",")
not range_matches_any(np, range_split)
}
else = "is out of defined range" {
contains(np_range, "-")
not contains(np_range, ",")
re_match(`^[-, ]*[0-9 ]+(?:-[0-9 ]+)?(,[0-9 ]+(?:-[0-9 ]+)?)*[-, ]*$`, trim_space(np_range))
not range_matches(np, np_range)
}
else = "is out of defined range" {
contains(np_range, ",")
not contains(np_range, "-")
re_match(`^[-, ]*[0-9 ]+(?:-[0-9 ]+)?(,[0-9 ]+(?:-[0-9 ]+)?)*[-, ]*$`, trim_space(np_range))
range_split := split(np_range, ",")
not range_matches_any(np, range_split)
}
else = "is out of defined range" {
not contains(np_range, ",")
not contains(np_range, "-")
re_match(`^\d+$`, trim_space(np_range))
to_number(trim_space(np_range)) != to_number(np)
}
range_matches_any(npNum, list) {
range_matches(npNum, list[_])
}
# Checks if nodePort is in comma separated list
range_matches(npNum, list) {
not contains(list, "-")
not contains(list, ",")
count(trim_space(list)) > 0
to_number(trim_space(list)) == to_number(npNum)
}
# Checks if nodePort is within range
range_matches(npNum, list) {
contains(list, "-")
range_split := split(list, "-")
count(trim_space(range_split[0])) > 0
count(trim_space(range_split[1])) > 0
to_number(npNum) >= to_number(trim_space(range_split[0]))
to_number(npNum) <= to_number(trim_space(range_split[1]))
}