Skip to content

Commit

Permalink
Merge pull request #643 from kubescape/fix/handling-istion-gateways
Browse files Browse the repository at this point in the history
Supporting gateways from different namespaces
  • Loading branch information
slashben authored Dec 2, 2024
2 parents 5ba3a4e + 5cbc797 commit bedef41
Show file tree
Hide file tree
Showing 10 changed files with 559 additions and 13 deletions.
44 changes: 31 additions & 13 deletions rules/exposure-to-internet-via-istio-ingress/raw.rego
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,33 @@ deny[msga] {
virtualservice := input[_]
virtualservice.kind == "VirtualService"

# Get the namescape of the VirtualService
vs_ns := get_namespace(virtualservice)
# Looping over the gateways of the VirtualService
vs_gw_name := virtualservice.spec.gateways[_]
# Get the namespace of the Gateway
vs_gw = get_vs_gw_ns(vs_ns, vs_gw_name)

# Check if the VirtualService is connected to a Gateway
gateway := input[_]
gateway.kind == "Gateway"

is_same_namespace(gateway, virtualservice)
virtualservice.spec.gateways[_] == gateway.metadata.name
gateway.metadata.name == vs_gw.name
get_namespace(gateway) == vs_gw.namespace

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


# Check if the Istio Ingress Gateway is exposed to the internet
is_exposed_service(istioingressgateway)

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

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

msga := {
"alertMessage": sprintf("workload '%v' is exposed through virtualservice '%v'", [wl.metadata.name, virtualservice.metadata.name]),
Expand All @@ -54,14 +59,14 @@ deny[msga] {
"k8sApiObjects": [wl]
},
"relatedObjects": [
{
{
"object": virtualservice,
"reviewPaths": result,
"failedPaths": result,
"reviewPaths": failedPaths,
"failedPaths": failedPaths,
},
{
"object": connected_service,
}
{
"object": connected_service,
}
]
}
}
Expand All @@ -79,6 +84,20 @@ get_namespace(obj) = namespace {
namespace := "default"
}

get_vs_gw_ns(vs_ns, vs_gw_name) = {"name": name, "namespace": ns} {
# Check if there is a / in the gateway name
count(split(vs_gw_name, "/")) == 2
ns := split(vs_gw_name, "/")[0]
name := split(vs_gw_name, "/")[1]
}

get_vs_gw_ns(vs_ns, vs_gw_name) = {"name": name, "namespace": ns} {
# Check if there is no / in the gateway name
count(split(vs_gw_name, "/")) == 1
ns := vs_ns
name := vs_gw_name
}

is_same_namespace(obj1, obj2) {
obj1.metadata.namespace == obj2.metadata.namespace
}
Expand Down Expand Up @@ -141,4 +160,3 @@ get_fqsn(ns, dest_host) = fqsn {
}



Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
[
{
"alertMessage": "workload 'nginx' is exposed through virtualservice 'int-0721'",
"failedPaths": [],
"reviewPaths": null,
"deletePaths": null,
"fixPaths": [],
"ruleStatus": "",
"packagename": "armo_builtins",
"alertScore": 7,
"alertObject": {
"k8sApiObjects": [
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"app": "int-0721",
"context": "default",
"name": "int-0721",
"role": "app"
},
"name": "nginx"
}
}
]
},
"relatedObjects": [
{
"object": {
"apiVersion": "networking.istio.io/v1beta1",
"kind": "VirtualService",
"metadata": {
"creationTimestamp": "2024-04-15T08:56:16Z",
"generation": 2,
"labels": {
"app": "int-0721",
"context": "default",
"name": "int-0721",
"owner": "int-0721",
"owner-namespace": "kt-itinternal",
"role": "app"
},
"name": "int-0721",
"namespace": "kt-itinternal"
},
"spec": {
"gateways": [
"kt-connections/prod-lan-gateway",
"kt-connections/sdfsdfs-gateway",
"kt-connections/api-public",
"kt-connections/aaaaa-public",
"kt-connections/mydddd-public"
],
"hosts": [
"api.stg.prod.lan"
],
"http": [
{
"corsPolicy": {
"allowHeaders": [
"authorization",
"Origin",
"Content-Type",
"Accept"
],
"allowMethods": [
"POST",
"GET",
"OPTIONS",
"PUT",
"PATCH",
"DELETE"
],
"allowOrigins": [
{
"regex": ".*"
}
]
},
"match": [
{
"authority": {
"exact": "api.stg.prod.lan"
},
"uri": {
"prefix": "/int/0698/"
}
}
],
"name": "api-http-stgprodlan",
"rewrite": {
"uri": "/"
},
"route": [
{
"destination": {
"host": "int-0721.kt-itinternal.svc.cluster.local",
"port": {
"number": 8080
}
},
"headers": {
"request": {
"set": {
"X-Forwarded-Prefix": "/int/0698",
"X-Forwarded-Proto": "https"
}
}
}
}
]
}
]
}
},
"failedPaths": [
"spec.http[0].routes[0].destination.host"
],
"reviewPaths": [
"spec.http[0].routes[0].destination.host"
],
"deletePaths": null,
"fixPaths": null
},
{
"object": {
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"creationTimestamp": "2024-04-15T09:00:11Z",
"labels": {
"app": "int-0721",
"context": "default",
"name": "int-0721",
"owner": "int-0721",
"owner-namespace": "kt-itinternal",
"role": "app"
},
"name": "int-0721",
"namespace": "kt-itinternal",
"ownerReferences": [
{
"apiVersion": "msss/v1alpha1",
"blockOwnerDeletion": true,
"controller": true,
"kind": "Microservice",
"name": "int-0721",
"uid": "14a69d5b-249c-487d-9500-645bda6a4c56"
}
],
"resourceVersion": "3779885629",
"uid": "0428cb70-5d8f-4345-8ef2-5b0a249e0793"
},
"spec": {
"clusterIP": "10.81.208.49",
"clusterIPs": [
"10.81.208.49"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"name": "http",
"port": 8080,
"protocol": "TCP",
"targetPort": 8080
}
],
"selector": {
"app": "int-0721",
"context": "default",
"name": "int-0721",
"role": "app"
},
"sessionAffinity": "None",
"type": "ClusterIP"
},
"status": {
"loadBalancer": {}
}
},
"failedPaths": null,
"reviewPaths": null,
"deletePaths": null,
"fixPaths": null
}
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
annotations:
meta.helm.sh/release-name: legacy-compatibility
meta.helm.sh/release-namespace: kt-itinternal
creationTimestamp: "2023-03-16T10:18:13Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
name: prod-lan-gateway
namespace: kt-itinternal
resourceVersion: "713118464"
uid: 46cb8274-3569-4b4a-952a-52037a352715
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- legacy.stg.prod.lan
port:
name: http
number: 80
protocol: HTTP
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: int-0721
context: default
name: int-0721
role: app
name: nginx
namespace: kt-itinternal
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2024-11-19T19:33:45Z"
lastUpdateTime: "2024-11-19T19:33:45Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2024-11-19T19:33:37Z"
lastUpdateTime: "2024-11-19T19:33:45Z"
message: ReplicaSet "nginx-7854ff8877" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: prod-lan-gateway
namespace: kt-connections
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- legacy.stg.prod.lan
port:
name: http
number: 80
protocol: HTTP
Loading

0 comments on commit bedef41

Please sign in to comment.