Skip to content

Commit

Permalink
Merge pull request #16 from xentra-ai/svc
Browse files Browse the repository at this point in the history
Svc
  • Loading branch information
xunholy authored Sep 20, 2023
2 parents dd7f9bc + 5aa815d commit 8b5130d
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 33 deletions.
Binary file removed advisor/advisor
Binary file not shown.
29 changes: 15 additions & 14 deletions advisor/pkg/api/pod_traffic.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

v1 "k8s.io/api/core/v1"
v1beta1 "k8s.io/api/discovery/v1beta1"
)

type PodTraffic struct {
Expand All @@ -33,10 +32,10 @@ type PodDetail struct {
}

type SvcDetail struct {
SvcIp string `yaml:"svc_ip" json:"svc_ip"`
SvcName string `yaml:"svc_name" json:"svc_name"`
SvcNamespace string `yaml:"svc_namespace" json:"svc_namespace"`
EndPointSlice v1beta1.EndpointSlice `yaml:"endpoint_spec" json:"endpoint_spec"`
SvcIp string `yaml:"svc_ip" json:"svc_ip"`
SvcName string `yaml:"svc_name" json:"svc_name"`
SvcNamespace string `yaml:"svc_namespace" json:"svc_namespace"`
Service v1.Service `yaml:"service_spec" json:"service_spec"`
}

func GetPodTraffic(podName string) ([]PodTraffic, error) {
Expand Down Expand Up @@ -91,24 +90,25 @@ func GetPodSpec(ip string) (*PodDetail, error) {

// Check the HTTP status code.
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("received non-OK HTTP status code: %v", resp.StatusCode)
//fmt.Printf("received non-OK HTTP status code: %v", resp.StatusCode)
return nil, nil
}

var podDetails PodDetail
var details PodDetail

// Parse the JSON response and unmarshal it into the Go struct.
if err := json.NewDecoder(resp.Body).Decode(&podDetails); err != nil {
if err := json.NewDecoder(resp.Body).Decode(&details); err != nil {
fmt.Printf("Error decoding JSON: %v\n", err)
return nil, err
}

return &podDetails, nil
return &details, nil
}

func GetSvcSpec(svcIp string) (*SvcDetail, error) {

// Specify the URL of the RESTAPI endpoint you want to invoke.
apiURL := "http://127.0.0.1:9090//netpol/svc/" + svcIp
apiURL := "http://127.0.0.1:9090/netpol/svc/" + svcIp

// Send an HTTP GET request to the API endpoint.
resp, err := http.Get(apiURL)
Expand All @@ -120,16 +120,17 @@ func GetSvcSpec(svcIp string) (*SvcDetail, error) {

// Check the HTTP status code.
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("received non-OK HTTP status code: %v", resp.StatusCode)
//fmt.Printf("received non-OK HTTP status code: %v", resp.StatusCode)
return nil, nil
}

var svcDetail SvcDetail
var details SvcDetail

// Parse the JSON response and unmarshal it into the Go struct.
if err := json.NewDecoder(resp.Body).Decode(&svcDetail); err != nil {
if err := json.NewDecoder(resp.Body).Decode(&details); err != nil {
fmt.Printf("Error decoding JSON: %v\n", err)
return nil, err
}

return &svcDetail, nil
return &details, nil
}
27 changes: 22 additions & 5 deletions advisor/pkg/k8s/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,36 @@ package k8s
import (
"context"
"fmt"
"reflect"

api "github.com/arx-inc/advisor/pkg/api"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

// DetectLabels detects the labels of a pod.
func DetectSelectorLabels(clientset *kubernetes.Clientset, pod *v1.Pod) (map[string]string, error) {
ctx := context.TODO()
func DetectSelectorLabels(clientset *kubernetes.Clientset, origin interface{}) (map[string]string, error) {

fmt.Println(reflect.TypeOf(origin))
// You can use type assertion to check the specific type
switch o := origin.(type) {
case *v1.Pod:
return GetOwnerRef(clientset, o)
case *api.PodDetail:
return GetOwnerRef(clientset, &o.Pod)
case *api.SvcDetail:
var svc v1.Service
svc = o.Service
return svc.Spec.Selector, nil
default:
return nil, fmt.Errorf("unknown type")
}
}

// Check if the Pod has an owner
func GetOwnerRef(clientset *kubernetes.Clientset, pod *v1.Pod) (map[string]string, error) {
ctx := context.TODO()
// Check if the& Pod has an owner
if len(pod.OwnerReferences) > 0 {
owner := pod.OwnerReferences[0]

Expand Down Expand Up @@ -50,7 +69,5 @@ func DetectSelectorLabels(clientset *kubernetes.Clientset, pod *v1.Pod) (map[str
return nil, fmt.Errorf("unknown or unsupported owner kind: %s", owner.Kind)
}
}

// If we reach here, the Pod has no owner and we return its own labels
return pod.Labels, nil
}
61 changes: 47 additions & 14 deletions advisor/pkg/k8s/networkpolicies.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,54 +76,87 @@ func TransformToNetworkPolicy(podTraffic *[]api.PodTraffic, podDetail *api.PodDe
}

for _, traffic := range *podTraffic {

var origin interface{}
// TODO: Check PODCIDR and SVCCIDR to determine if IP originated from inside or outside the cluster

// Get pod spec for the pod that is sending traffic
origin, err := api.GetPodSpec(traffic.DstIP)
podOrigin, err := api.GetPodSpec(traffic.DstIP)
if err != nil {
// TODO: Handle errors, for now just continue as this is not a fatal error and it assumes the traffic originated from outside the cluster
fmt.Println("Get Pod Spec of origin", traffic.DstIP, err)
continue
} else if podOrigin != nil {
origin = podOrigin
}

peerSelectorLabels, err := DetectSelectorLabels(config.Clientset, &origin.Pod)
if err != nil {
// TODO: Handle errors, this would mean a controller was detected but may no longer exist due to the pod being deleted but still present in the database
fmt.Println("Detect Labels", origin.Name, err)
continue
// If we couldn't get the Pod details, try getting the Service details
if origin == nil {
svcOrigin, err := api.GetSvcSpec(traffic.DstIP)
if err != nil {
fmt.Println("Get Svc Spec of origin", traffic.DstIP, err)
continue
} else if svcOrigin != nil {
origin = svcOrigin
}
}

if origin == nil {
fmt.Println("Could not find details for origin assuming IP is external", traffic.DstIP)
}

var metadata metav1.ObjectMeta
var peerSelectorLabels map[string]string
peer := networkingv1.NetworkPolicyPeer{}
// If the traffic originated from in-cluster as either a pod or service
if origin != nil {
peerSelectorLabels, err = DetectSelectorLabels(config.Clientset, origin)
if err != nil {
// TODO: Handle errors, this would mean a controller was detected but may no longer exist due to the pod being deleted but still present in the database
fmt.Println("Detect Labels", origin, err)
continue
}
switch o := origin.(type) {
case *api.PodDetail:
metadata = o.Pod.ObjectMeta
case *api.SvcDetail:
metadata = o.Service.ObjectMeta
default:
fmt.Println("Unknown type for origin")
continue
}
peer = networkingv1.NetworkPolicyPeer{
PodSelector: &metav1.LabelSelector{
MatchLabels: peerSelectorLabels,
},
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{"kubernetes.io/metadata.name": origin.Pod.ObjectMeta.Namespace},
MatchLabels: map[string]string{"kubernetes.io/metadata.name": metadata.Namespace},
},
}
} else {
peer = networkingv1.NetworkPolicyPeer{
IPBlock: &networkingv1.IPBlock{
CIDR: traffic.DstIP + "/32",
},
}
}

protocol := traffic.Protocol
if traffic.TrafficType == "INGRESS" {
port := intstr.Parse(traffic.SrcPodPort)
ingressRules = append(ingressRules, networkingv1.NetworkPolicyIngressRule{
Ports: []networkingv1.NetworkPolicyPort{
{
Protocol: &traffic.Protocol,
Protocol: &protocol,
Port: &port,
},
},
From: []networkingv1.NetworkPolicyPeer{peer},
})
} else if traffic.TrafficType == "EGRESS" {
port := intstr.Parse(traffic.DstPort)

egressRules = append(egressRules, networkingv1.NetworkPolicyEgressRule{
Ports: []networkingv1.NetworkPolicyPort{
{
Protocol: &traffic.Protocol,
Protocol: &protocol,
Port: &port,
},
},
Expand All @@ -142,8 +175,8 @@ func TransformToNetworkPolicy(podTraffic *[]api.PodTraffic, podDetail *api.PodDe
Namespace: podDetail.Namespace,
// TODO: What labels should we use?
Labels: map[string]string{
"advisor.arx.io/managed-by": "arx",
"advisor.arx.io/version": "0.0.1",
"advisor.xentra.ai/managed-by": "xentra",
"advisor.xentra.ai/version": "0.0.1",
},
},
Spec: networkingv1.NetworkPolicySpec{
Expand Down

0 comments on commit 8b5130d

Please sign in to comment.