Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting gateways from different namespaces #643

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading