Skip to content

Commit 5cbc797

Browse files
committed
Supporting gateways from different namespaces
Signed-off-by: Ben <[email protected]>
1 parent 5ba3a4e commit 5cbc797

File tree

10 files changed

+559
-13
lines changed

10 files changed

+559
-13
lines changed

rules/exposure-to-internet-via-istio-ingress/raw.rego

+31-13
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,33 @@ deny[msga] {
66
virtualservice := input[_]
77
virtualservice.kind == "VirtualService"
88

9+
# Get the namescape of the VirtualService
10+
vs_ns := get_namespace(virtualservice)
11+
# Looping over the gateways of the VirtualService
12+
vs_gw_name := virtualservice.spec.gateways[_]
13+
# Get the namespace of the Gateway
14+
vs_gw = get_vs_gw_ns(vs_ns, vs_gw_name)
15+
916
# Check if the VirtualService is connected to a Gateway
1017
gateway := input[_]
1118
gateway.kind == "Gateway"
12-
13-
is_same_namespace(gateway, virtualservice)
14-
virtualservice.spec.gateways[_] == gateway.metadata.name
19+
gateway.metadata.name == vs_gw.name
20+
get_namespace(gateway) == vs_gw.namespace
1521

1622
# Find the connected Istio Ingress Gateway that should be a LoadBalancer if it is exposed to the internet
1723
istioingressgateway := input[_]
1824
istioingressgateway.kind == "Service"
1925
istioingressgateway.metadata.namespace == "istio-system"
2026
gateway.spec.selector[_] == istioingressgateway.metadata.labels[_]
2127

22-
2328
# Check if the Istio Ingress Gateway is exposed to the internet
2429
is_exposed_service(istioingressgateway)
2530

2631
# Check if the VirtualService is connected to an workload
2732
# First, find the service that the VirtualService is connected to
2833
connected_service := input[_]
2934
connected_service.kind == "Service"
30-
fqsn := get_fqsn(get_namespace(virtualservice), virtualservice.spec.http[_].route[_].destination.host)
35+
fqsn := get_fqsn(get_namespace(virtualservice), virtualservice.spec.http[i].route[j].destination.host)
3136
target_ns := split(fqsn,".")[1]
3237
target_name := split(fqsn,".")[0]
3338
# Check if the service is in the same namespace as the VirtualService
@@ -42,7 +47,7 @@ deny[msga] {
4247
spec_template_spec_patterns[wl.kind]
4348
wl_connected_to_service(wl, connected_service)
4449

45-
result := svc_connected_to_virtualservice(connected_service, virtualservice)
50+
failedPaths := [sprintf("spec.http[%d].routes[%d].destination.host", [i,j])]
4651

4752
msga := {
4853
"alertMessage": sprintf("workload '%v' is exposed through virtualservice '%v'", [wl.metadata.name, virtualservice.metadata.name]),
@@ -54,14 +59,14 @@ deny[msga] {
5459
"k8sApiObjects": [wl]
5560
},
5661
"relatedObjects": [
57-
{
62+
{
5863
"object": virtualservice,
59-
"reviewPaths": result,
60-
"failedPaths": result,
64+
"reviewPaths": failedPaths,
65+
"failedPaths": failedPaths,
6166
},
62-
{
63-
"object": connected_service,
64-
}
67+
{
68+
"object": connected_service,
69+
}
6570
]
6671
}
6772
}
@@ -79,6 +84,20 @@ get_namespace(obj) = namespace {
7984
namespace := "default"
8085
}
8186

87+
get_vs_gw_ns(vs_ns, vs_gw_name) = {"name": name, "namespace": ns} {
88+
# Check if there is a / in the gateway name
89+
count(split(vs_gw_name, "/")) == 2
90+
ns := split(vs_gw_name, "/")[0]
91+
name := split(vs_gw_name, "/")[1]
92+
}
93+
94+
get_vs_gw_ns(vs_ns, vs_gw_name) = {"name": name, "namespace": ns} {
95+
# Check if there is no / in the gateway name
96+
count(split(vs_gw_name, "/")) == 1
97+
ns := vs_ns
98+
name := vs_gw_name
99+
}
100+
82101
is_same_namespace(obj1, obj2) {
83102
obj1.metadata.namespace == obj2.metadata.namespace
84103
}
@@ -141,4 +160,3 @@ get_fqsn(ns, dest_host) = fqsn {
141160
}
142161

143162

144-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
[
2+
{
3+
"alertMessage": "workload 'nginx' is exposed through virtualservice 'int-0721'",
4+
"failedPaths": [],
5+
"reviewPaths": null,
6+
"deletePaths": null,
7+
"fixPaths": [],
8+
"ruleStatus": "",
9+
"packagename": "armo_builtins",
10+
"alertScore": 7,
11+
"alertObject": {
12+
"k8sApiObjects": [
13+
{
14+
"apiVersion": "apps/v1",
15+
"kind": "Deployment",
16+
"metadata": {
17+
"labels": {
18+
"app": "int-0721",
19+
"context": "default",
20+
"name": "int-0721",
21+
"role": "app"
22+
},
23+
"name": "nginx"
24+
}
25+
}
26+
]
27+
},
28+
"relatedObjects": [
29+
{
30+
"object": {
31+
"apiVersion": "networking.istio.io/v1beta1",
32+
"kind": "VirtualService",
33+
"metadata": {
34+
"creationTimestamp": "2024-04-15T08:56:16Z",
35+
"generation": 2,
36+
"labels": {
37+
"app": "int-0721",
38+
"context": "default",
39+
"name": "int-0721",
40+
"owner": "int-0721",
41+
"owner-namespace": "kt-itinternal",
42+
"role": "app"
43+
},
44+
"name": "int-0721",
45+
"namespace": "kt-itinternal"
46+
},
47+
"spec": {
48+
"gateways": [
49+
"kt-connections/prod-lan-gateway",
50+
"kt-connections/sdfsdfs-gateway",
51+
"kt-connections/api-public",
52+
"kt-connections/aaaaa-public",
53+
"kt-connections/mydddd-public"
54+
],
55+
"hosts": [
56+
"api.stg.prod.lan"
57+
],
58+
"http": [
59+
{
60+
"corsPolicy": {
61+
"allowHeaders": [
62+
"authorization",
63+
"Origin",
64+
"Content-Type",
65+
"Accept"
66+
],
67+
"allowMethods": [
68+
"POST",
69+
"GET",
70+
"OPTIONS",
71+
"PUT",
72+
"PATCH",
73+
"DELETE"
74+
],
75+
"allowOrigins": [
76+
{
77+
"regex": ".*"
78+
}
79+
]
80+
},
81+
"match": [
82+
{
83+
"authority": {
84+
"exact": "api.stg.prod.lan"
85+
},
86+
"uri": {
87+
"prefix": "/int/0698/"
88+
}
89+
}
90+
],
91+
"name": "api-http-stgprodlan",
92+
"rewrite": {
93+
"uri": "/"
94+
},
95+
"route": [
96+
{
97+
"destination": {
98+
"host": "int-0721.kt-itinternal.svc.cluster.local",
99+
"port": {
100+
"number": 8080
101+
}
102+
},
103+
"headers": {
104+
"request": {
105+
"set": {
106+
"X-Forwarded-Prefix": "/int/0698",
107+
"X-Forwarded-Proto": "https"
108+
}
109+
}
110+
}
111+
}
112+
]
113+
}
114+
]
115+
}
116+
},
117+
"failedPaths": [
118+
"spec.http[0].routes[0].destination.host"
119+
],
120+
"reviewPaths": [
121+
"spec.http[0].routes[0].destination.host"
122+
],
123+
"deletePaths": null,
124+
"fixPaths": null
125+
},
126+
{
127+
"object": {
128+
"apiVersion": "v1",
129+
"kind": "Service",
130+
"metadata": {
131+
"creationTimestamp": "2024-04-15T09:00:11Z",
132+
"labels": {
133+
"app": "int-0721",
134+
"context": "default",
135+
"name": "int-0721",
136+
"owner": "int-0721",
137+
"owner-namespace": "kt-itinternal",
138+
"role": "app"
139+
},
140+
"name": "int-0721",
141+
"namespace": "kt-itinternal",
142+
"ownerReferences": [
143+
{
144+
"apiVersion": "msss/v1alpha1",
145+
"blockOwnerDeletion": true,
146+
"controller": true,
147+
"kind": "Microservice",
148+
"name": "int-0721",
149+
"uid": "14a69d5b-249c-487d-9500-645bda6a4c56"
150+
}
151+
],
152+
"resourceVersion": "3779885629",
153+
"uid": "0428cb70-5d8f-4345-8ef2-5b0a249e0793"
154+
},
155+
"spec": {
156+
"clusterIP": "10.81.208.49",
157+
"clusterIPs": [
158+
"10.81.208.49"
159+
],
160+
"internalTrafficPolicy": "Cluster",
161+
"ipFamilies": [
162+
"IPv4"
163+
],
164+
"ipFamilyPolicy": "SingleStack",
165+
"ports": [
166+
{
167+
"name": "http",
168+
"port": 8080,
169+
"protocol": "TCP",
170+
"targetPort": 8080
171+
}
172+
],
173+
"selector": {
174+
"app": "int-0721",
175+
"context": "default",
176+
"name": "int-0721",
177+
"role": "app"
178+
},
179+
"sessionAffinity": "None",
180+
"type": "ClusterIP"
181+
},
182+
"status": {
183+
"loadBalancer": {}
184+
}
185+
},
186+
"failedPaths": null,
187+
"reviewPaths": null,
188+
"deletePaths": null,
189+
"fixPaths": null
190+
}
191+
]
192+
}
193+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: networking.istio.io/v1beta1
2+
kind: Gateway
3+
metadata:
4+
annotations:
5+
meta.helm.sh/release-name: legacy-compatibility
6+
meta.helm.sh/release-namespace: kt-itinternal
7+
creationTimestamp: "2023-03-16T10:18:13Z"
8+
generation: 1
9+
labels:
10+
app.kubernetes.io/managed-by: Helm
11+
name: prod-lan-gateway
12+
namespace: kt-itinternal
13+
resourceVersion: "713118464"
14+
uid: 46cb8274-3569-4b4a-952a-52037a352715
15+
spec:
16+
selector:
17+
istio: ingressgateway
18+
servers:
19+
- hosts:
20+
- legacy.stg.prod.lan
21+
port:
22+
name: http
23+
number: 80
24+
protocol: HTTP
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
labels:
5+
app: int-0721
6+
context: default
7+
name: int-0721
8+
role: app
9+
name: nginx
10+
namespace: kt-itinternal
11+
spec:
12+
progressDeadlineSeconds: 600
13+
replicas: 1
14+
revisionHistoryLimit: 10
15+
selector:
16+
matchLabels:
17+
app: nginx
18+
strategy:
19+
rollingUpdate:
20+
maxSurge: 25%
21+
maxUnavailable: 25%
22+
type: RollingUpdate
23+
template:
24+
metadata:
25+
labels:
26+
app: nginx
27+
spec:
28+
containers:
29+
- image: nginx
30+
imagePullPolicy: Always
31+
name: nginx
32+
resources: {}
33+
terminationMessagePath: /dev/termination-log
34+
terminationMessagePolicy: File
35+
dnsPolicy: ClusterFirst
36+
restartPolicy: Always
37+
schedulerName: default-scheduler
38+
securityContext: {}
39+
terminationGracePeriodSeconds: 30
40+
status:
41+
availableReplicas: 1
42+
conditions:
43+
- lastTransitionTime: "2024-11-19T19:33:45Z"
44+
lastUpdateTime: "2024-11-19T19:33:45Z"
45+
message: Deployment has minimum availability.
46+
reason: MinimumReplicasAvailable
47+
status: "True"
48+
type: Available
49+
- lastTransitionTime: "2024-11-19T19:33:37Z"
50+
lastUpdateTime: "2024-11-19T19:33:45Z"
51+
message: ReplicaSet "nginx-7854ff8877" has successfully progressed.
52+
reason: NewReplicaSetAvailable
53+
status: "True"
54+
type: Progressing
55+
observedGeneration: 1
56+
readyReplicas: 1
57+
replicas: 1
58+
updatedReplicas: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: networking.istio.io/v1beta1
2+
kind: Gateway
3+
metadata:
4+
name: prod-lan-gateway
5+
namespace: kt-connections
6+
spec:
7+
selector:
8+
istio: ingressgateway
9+
servers:
10+
- hosts:
11+
- legacy.stg.prod.lan
12+
port:
13+
name: http
14+
number: 80
15+
protocol: HTTP

0 commit comments

Comments
 (0)