Skip to content

Commit 041c201

Browse files
authored
Improve blocked traffic detection in Otterize Cloud by reporting container port names (#308)
1 parent e8004e0 commit 041c201

File tree

5 files changed

+283
-5
lines changed

5 files changed

+283
-5
lines changed

src/mapper/pkg/cloudclient/generated.go

Lines changed: 21 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/mapper/pkg/cloudclient/schema.graphql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ type FeatureFlags {
899899
enableInternetIntentsSuggestions: Boolean
900900
enableIAMIntentsSuggestions: Boolean
901901
enableNetworkPoliciesInAccessGraph: Boolean
902+
enableTrafficFromTCPResolveDestBugfixInAccessGraph: Boolean
902903
}
903904

904905
type Finding {
@@ -1248,6 +1249,7 @@ input InputFeatureFlags {
12481249
enableInternetIntentsSuggestions: Boolean
12491250
enableIAMIntentsSuggestions: Boolean
12501251
enableNetworkPoliciesInAccessGraph: Boolean
1252+
enableTrafficFromTCPResolveDestBugfixInAccessGraph: Boolean
12511253
}
12521254

12531255
""" Findings filter """
@@ -1740,6 +1742,7 @@ input K8sResourceLoadBalancerIngressInput {
17401742
input K8sResourceServiceInput {
17411743
spec: K8sResourceServiceSpecInput!
17421744
status: K8sResourceServiceStatusInput
1745+
targetNamedPorts: [NamedPortInput!]
17431746
}
17441747

17451748
input K8sResourceServiceLoadBalancerIngressInput {
@@ -2314,6 +2317,12 @@ type Mutation {
23142317
): Boolean!
23152318
}
23162319

2320+
input NamedPortInput {
2321+
name: String!
2322+
port: Int!
2323+
protocol: K8sPortProtocol!
2324+
}
2325+
23172326
type Namespace {
23182327
id: ID!
23192328
name: String!
@@ -2556,6 +2565,9 @@ type Query {
25562565
clientServiceId: ID!
25572566
serverServiceId: ID!
25582567
): [NetworkPolicy!]!
2568+
serviceNetworkPolicies(
2569+
serviceId: ID!
2570+
): [NetworkPolicy!]!
25592571
""" Get edge connections count """
25602572
edgeConnectionsCount(
25612573
clientId: ID!
@@ -3115,6 +3127,8 @@ scalar String
31153127
type TLSConfiguration {
31163128
caCertificate: String
31173129
certificate: String
3130+
caCertificateFingerprint: String
3131+
certificateFingerprint: String
31183132
}
31193133

31203134
input TLSConfigurationInput {

src/mapper/pkg/resourcevisibility/model_convertion.go

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package resourcevisibility
22

33
import (
4+
"cmp"
5+
"context"
46
"github.com/otterize/intents-operator/src/shared/errors"
57
"github.com/otterize/network-mapper/src/mapper/pkg/cloudclient"
68
"github.com/otterize/nilable"
79
"github.com/samber/lo"
810
"github.com/sirupsen/logrus"
11+
"golang.org/x/exp/slices"
912
corev1 "k8s.io/api/core/v1"
1013
networkingv1 "k8s.io/api/networking/v1"
1114
"k8s.io/apimachinery/pkg/util/intstr"
15+
"sigs.k8s.io/controller-runtime/pkg/client"
1216
)
1317

1418
func convertPortProtocol(protocol corev1.Protocol) (*cloudclient.K8sPortProtocol, error) {
@@ -294,7 +298,7 @@ func convertIngressLoadBalancerStatus(status networkingv1.IngressStatus) (nilabl
294298
return nilable.From(ingressStatusInput), nil
295299
}
296300

297-
func convertServiceResource(service corev1.Service) (cloudclient.K8sResourceServiceInput, error) {
301+
func convertServiceResource(ctx context.Context, k8sClient client.Client, service corev1.Service) (cloudclient.K8sResourceServiceInput, error) {
298302
ports := make([]cloudclient.K8sServicePort, 0)
299303
for _, port := range service.Spec.Ports {
300304
protocol, err := convertPortProtocol(port.Protocol)
@@ -391,6 +395,11 @@ func convertServiceResource(service corev1.Service) (cloudclient.K8sResourceServ
391395
input.Status = status
392396
}
393397

398+
targetNamedPorts := getRelatedPodsNamedPortsMap(ctx, k8sClient, &service)
399+
if len(targetNamedPorts) > 0 {
400+
input.TargetNamedPorts = targetNamedPorts
401+
}
402+
394403
return input, nil
395404
}
396405

@@ -565,3 +574,60 @@ func convertIngressResource(ingress networkingv1.Ingress) (cloudclient.K8sResour
565574

566575
return input, true, nil
567576
}
577+
578+
func getRelatedPodsNamedPortsMap(ctx context.Context, k8sClient client.Client, service *corev1.Service) []cloudclient.NamedPortInput {
579+
if len(service.Spec.Selector) == 0 {
580+
return nil
581+
}
582+
relatedPods := &corev1.PodList{}
583+
labelSelector := client.MatchingLabels(service.Spec.Selector)
584+
err := k8sClient.List(ctx, relatedPods, labelSelector, client.InNamespace(service.Namespace))
585+
if err != nil {
586+
logrus.WithFields(logrus.Fields{"service": service.Name, "namespace": service.Namespace}).WithError(err).Errorf("Failed listing pods for service")
587+
return nil
588+
}
589+
590+
namedPorts := make([]cloudclient.NamedPortInput, 0)
591+
for _, pod := range relatedPods.Items {
592+
for _, container := range pod.Spec.Containers {
593+
for _, port := range container.Ports {
594+
if port.Name == "" {
595+
continue // We are only interested in named ports
596+
}
597+
namedPorts = append(namedPorts, cloudclient.NamedPortInput{
598+
Name: port.Name,
599+
Port: int(port.ContainerPort),
600+
Protocol: convertProtocolToCloudFormat(port.Protocol),
601+
})
602+
}
603+
}
604+
}
605+
606+
namedPorts = lo.Uniq(namedPorts)
607+
slices.SortFunc(namedPorts, func(a, b cloudclient.NamedPortInput) int {
608+
if cmp.Compare(a.Name, b.Name) != 0 {
609+
return cmp.Compare(a.Name, b.Name)
610+
}
611+
if cmp.Compare(a.Port, b.Port) != 0 {
612+
return cmp.Compare(a.Port, b.Port)
613+
}
614+
if cmp.Compare(a.Protocol, b.Protocol) != 0 {
615+
return cmp.Compare(a.Protocol, b.Protocol)
616+
}
617+
return 0
618+
})
619+
return namedPorts
620+
}
621+
622+
func convertProtocolToCloudFormat(proto corev1.Protocol) cloudclient.K8sPortProtocol {
623+
switch proto {
624+
case corev1.ProtocolTCP:
625+
return cloudclient.K8sPortProtocolTcp
626+
case corev1.ProtocolUDP:
627+
return cloudclient.K8sPortProtocolUdp
628+
case corev1.ProtocolSCTP:
629+
return cloudclient.K8sPortProtocolSctp
630+
default:
631+
return cloudclient.K8sPortProtocolTcp
632+
}
633+
}

src/mapper/pkg/resourcevisibility/svc_reconciler.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ func (r *ServiceReconciler) getCachedValue(servicesToReport []cloudclient.K8sSer
120120
}
121121

122122
func reportedServicesCacheValuePart(service cloudclient.K8sServiceInput) string {
123-
return fmt.Sprintf("%s-%s-%s", service.ResourceName, service.OtterizeServer, service.Service.Spec.Type.Item)
123+
namedPortsStr := ""
124+
for _, namedPort := range service.Service.TargetNamedPorts {
125+
namedPortsStr += fmt.Sprintf("%s-%d-%s", namedPort.Name, namedPort.Port, namedPort.Protocol)
126+
}
127+
return fmt.Sprintf("%s-%s-%s-%s", service.ResourceName, service.OtterizeServer, service.Service.Spec.Type.Item, namedPortsStr)
124128
}
125129

126130
func (r *ServiceReconciler) convertToCloudServices(ctx context.Context, services []corev1.Service) ([]cloudclient.K8sServiceInput, error) {
@@ -153,7 +157,7 @@ func (r *ServiceReconciler) convertToCloudService(ctx context.Context, service c
153157
return cloudclient.K8sServiceInput{}, false, nil
154158
}
155159

156-
serviceInput, err := convertServiceResource(service)
160+
serviceInput, err := convertServiceResource(ctx, r.Client, service)
157161
if err != nil {
158162
return cloudclient.K8sServiceInput{}, false, errors.Wrap(err)
159163
}

0 commit comments

Comments
 (0)