diff --git a/pkg/kubehound/graph/edge/endpoint_expose_public.go b/pkg/kubehound/graph/edge/endpoint_expose_public.go index 210009603..f8a027882 100644 --- a/pkg/kubehound/graph/edge/endpoint_expose_public.go +++ b/pkg/kubehound/graph/edge/endpoint_expose_public.go @@ -1,83 +1,111 @@ package edge -import ( - "context" - "fmt" +// import ( +// "context" +// "fmt" - "github.com/DataDog/KubeHound/pkg/kubehound/graph/adapter" - "github.com/DataDog/KubeHound/pkg/kubehound/graph/types" - "github.com/DataDog/KubeHound/pkg/kubehound/models/converter" - "github.com/DataDog/KubeHound/pkg/kubehound/storage/cache" - "github.com/DataDog/KubeHound/pkg/kubehound/storage/storedb" - "github.com/DataDog/KubeHound/pkg/kubehound/store/collections" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" -) +// "github.com/DataDog/KubeHound/pkg/kubehound/graph/adapter" +// "github.com/DataDog/KubeHound/pkg/kubehound/graph/types" +// "github.com/DataDog/KubeHound/pkg/kubehound/models/converter" +// "github.com/DataDog/KubeHound/pkg/kubehound/storage/cache" +// "github.com/DataDog/KubeHound/pkg/kubehound/storage/storedb" +// "github.com/DataDog/KubeHound/pkg/kubehound/store/collections" +// "go.mongodb.org/mongo-driver/bson" +// "go.mongodb.org/mongo-driver/bson/primitive" +// ) -func init() { - Register(&EndpointExposePublic{}, RegisterDefault) -} +// func init() { +// Register(&EndpointExposePublic{}, RegisterDefault) +// } -type EndpointExposePublic struct { - BaseEdge -} +// type EndpointExposePublic struct { +// BaseEdge +// } -type endpointExposeGroup struct { - Endpoint primitive.ObjectID `bson:"_id" json:"endpoint_id"` - Container primitive.ObjectID `bson:"container_id" json:"container_id"` -} +// type endpointExposeGroup struct { +// Endpoint primitive.ObjectID `bson:"_id" json:"endpoint_id"` +// Container primitive.ObjectID `bson:"container_id" json:"container_id"` +// } -func (e *EndpointExposePublic) Label() string { - return "ENDPOINT_EXPOSE" -} +// func (e *EndpointExposePublic) Label() string { +// return "ENDPOINT_EXPOSE" +// } -func (e *EndpointExposePublic) Name() string { - return "EndpointExposePublic" -} +// func (e *EndpointExposePublic) Name() string { +// return "EndpointExposePublic" +// } -func (e *EndpointExposePublic) Processor(ctx context.Context, oic *converter.ObjectIDConverter, entry any) (any, error) { - typed, ok := entry.(*endpointExposeGroup) - if !ok { - return nil, fmt.Errorf("invalid type passed to processor: %T", entry) - } +// func (e *EndpointExposePublic) Processor(ctx context.Context, oic *converter.ObjectIDConverter, entry any) (any, error) { +// typed, ok := entry.(*endpointExposeGroup) +// if !ok { +// return nil, fmt.Errorf("invalid type passed to processor: %T", entry) +// } - return adapter.GremlinEdgeProcessor(ctx, oic, e.Label(), typed.Endpoint, typed.Container) -} +// return adapter.GremlinEdgeProcessor(ctx, oic, e.Label(), typed.Endpoint, typed.Container) +// } -func (e *EndpointExposePublic) Stream(ctx context.Context, store storedb.Provider, c cache.CacheReader, - callback types.ProcessEntryCallback, complete types.CompleteQueryCallback) error { +// func (e *EndpointExposePublic) Stream(ctx context.Context, store storedb.Provider, c cache.CacheReader, +// callback types.ProcessEntryCallback, complete types.CompleteQueryCallback) error { - endpoints := adapter.MongoDB(store).Collection(collections.EndpointName) +// endpoints := adapter.MongoDB(store).Collection(collections.EndpointName) - pipeline := []bson.M{ - // Match bindings that have at least one subject - { - "$match": bson.M{ - "subjects": bson.M{ - "$exists": true, - "$ne": bson.A{}, - }, - }, - }, - // Flatten the subjects set - { - "$unwind": "$subjects", - }, - // Project a role id / identity id pair - { - "$project": bson.M{ - "_id": 0, - "role_id": 1, - "identity_id": "$subjects.identity_id", - }, - }, - } +// // Find endpoints with has_slice +// // Find the container with same pod name / namespace / port +// // return container id +// pipeline := []bson.M{ +// // Match element with an associated slice +// { +// "$match": bson.M{ +// "has_slice": true, +// }, +// }, +// // Retrieve the target pod name and namespace as well as the container port +// { +// "$lookup": bson.M{ +// "as": "matchContainers", +// "from": "containers", +// "let": bson.M{ +// "pod": "$pod_name", +// "podNS": "$pod_namespace", +// "port": "$port.port", +// "proto": "$port.protocol", +// }, +// "pipeline": []bson.M{ +// // Find the container matching our specification +// { +// "$match": bson.M{"$or": bson.A{ +// bson.M{"$expr": bson.M{ +// "$eq": bson.A{ +// "$k8.objectmeta.namespace", "$$roleNamespace", +// }, +// }}, +// bson.M{"is_namespaced": false}, +// }}, +// }, +// { +// "$project": bson.M{ +// "_id": 1, +// }, +// }, +// }, +// }, +// }, +// { +// "$unwind": "$matchContainers", +// }, +// { +// "$project": bson.M{$e +// "_id": 1, +// "container_id": "$matchContainers._id", +// }, +// }, +// } - cur, err := endpoints.Aggregate(context.Background(), pipeline) - if err != nil { - return err - } - defer cur.Close(ctx) +// cur, err := endpoints.Aggregate(context.Background(), pipeline) +// if err != nil { +// return err +// } +// defer cur.Close(ctx) - return adapter.MongoCursorHandler[endpointExposeGroup](ctx, cur, callback, complete) -} +// return adapter.MongoCursorHandler[endpointExposeGroup](ctx, cur, callback, complete) +// } diff --git a/pkg/kubehound/models/converter/graph.go b/pkg/kubehound/models/converter/graph.go index 3de354402..d55f75526 100644 --- a/pkg/kubehound/models/converter/graph.go +++ b/pkg/kubehound/models/converter/graph.go @@ -27,7 +27,7 @@ func (c *GraphConverter) Container(input *store.Container, parent *store.Pod) (* App: input.Ownership.Application, Team: input.Ownership.Team, Service: input.Ownership.Service, - Namespace: parent.K8.Namespace, + Namespace: input.Inherited.Namespace, Name: input.K8.Name, Image: input.K8.Image, Command: input.K8.Command, diff --git a/pkg/kubehound/models/converter/store.go b/pkg/kubehound/models/converter/store.go index d19af2e53..97e767fb7 100644 --- a/pkg/kubehound/models/converter/store.go +++ b/pkg/kubehound/models/converter/store.go @@ -55,6 +55,7 @@ func (c *StoreConverter) Container(_ context.Context, input types.ContainerType, Inherited: store.ContainerInherited{ PodName: parent.K8.Name, NodeName: parent.K8.Spec.NodeName, + Namespace: parent.K8.Namespace, HostPID: parent.K8.Spec.HostPID, HostIPC: parent.K8.Spec.HostIPC, HostNetwork: parent.K8.Spec.HostNetwork, @@ -338,17 +339,24 @@ func (c *StoreConverter) Identity(_ context.Context, input *store.BindSubject, p func (c *StoreConverter) Endpoint(_ context.Context, addr discoveryv1.Endpoint, port discoveryv1.EndpointPort, parent types.EndpointType) (*store.Endpoint, error) { + // Ensure our assumption that the target is always a pod holds + if addr.TargetRef.Kind != "Pod" { + return nil, fmt.Errorf("unexpected endpoint target %#v", addr.TargetRef) + } + output := &store.Endpoint{ - Id: store.ObjectID(), - Name: fmt.Sprintf("%s::%s::%s", parent.Name, addr.TargetRef.Name, *port.Name), - HasSlice: true, - ServiceName: parent.Labels["kubernetes.io/service-name"], // TODO tidy - AddressType: parent.AddressType, - Backend: addr, - Port: port, - Ownership: store.ExtractOwnership(parent.ObjectMeta.Labels), - K8: parent.ObjectMeta, - Access: shared.EndpointAccessExternal, // If created via the ingestion pipeline the endpoint corresponds to a k8s endpoint slice + Id: store.ObjectID(), + PodName: addr.TargetRef.Name, + PodNamespace: addr.TargetRef.Namespace, + Name: fmt.Sprintf("%s::%s::%s", parent.Name, addr.TargetRef.Name, *port.Name), + HasSlice: true, + ServiceName: parent.Labels["kubernetes.io/service-name"], // TODO tidy + AddressType: parent.AddressType, + Backend: addr, + Port: port, + Ownership: store.ExtractOwnership(parent.ObjectMeta.Labels), + K8: parent.ObjectMeta, + Access: shared.EndpointAccessExternal, // If created via the ingestion pipeline the endpoint corresponds to a k8s endpoint slice } if addr.NodeName != nil { @@ -360,8 +368,6 @@ func (c *StoreConverter) Endpoint(_ context.Context, addr discoveryv1.Endpoint, output.Namespace = parent.Namespace } - // NB: NodeId, PodId, ContainerId will be set by a subsequent step (PodIngest) - return output, nil } @@ -369,13 +375,14 @@ func (c *StoreConverter) EndpointPrivate(_ context.Context, port *corev1.Contain pod *store.Pod, container *store.Container) (*store.Endpoint, error) { output := &store.Endpoint{ - Id: store.ObjectID(), - ContainerId: container.Id, - PodName: pod.K8.Name, - ServiceName: fmt.Sprintf("%s::%s::%s", port.Name, pod.K8.Namespace, pod.K8.Name), - Name: fmt.Sprintf("%s::%s::%d", container.K8.Name, pod.K8.Status.HostIP, port.ContainerPort), - NodeName: pod.K8.Spec.NodeName, - AddressType: "IPv4", // TODO figure out address tyoe from inpout + Id: store.ObjectID(), + ContainerId: container.Id, + PodName: pod.K8.Name, + PodNamespace: pod.K8.Namespace, + ServiceName: fmt.Sprintf("%s::%s::%s", port.Name, pod.K8.Namespace, pod.K8.Name), + Name: fmt.Sprintf("%s::%s::%d", container.K8.Name, pod.K8.Status.HostIP, port.ContainerPort), + NodeName: pod.K8.Spec.NodeName, + AddressType: "IPv4", // TODO figure out address tyoe from inpout Backend: discoveryv1.Endpoint{ // TODO other fields Addresses: []string{pod.K8.Status.PodIP}, diff --git a/pkg/kubehound/models/store/endpoint.go b/pkg/kubehound/models/store/endpoint.go index c92bb0d3b..8050ab84f 100644 --- a/pkg/kubehound/models/store/endpoint.go +++ b/pkg/kubehound/models/store/endpoint.go @@ -27,6 +27,7 @@ type Endpoint struct { Id primitive.ObjectID `bson:"_id"` ContainerId primitive.ObjectID `bson:"container_id"` PodName string `bson:"pod_name"` + PodNamespace string `bson:"pod_namespace"` NodeName string `bson:"node_name"` IsNamespaced bool `bson:"is_namespaced"` Namespace string `bson:"namespace"` diff --git a/pkg/kubehound/models/store/models.go b/pkg/kubehound/models/store/models.go index 0c9da3067..e6eb8426b 100644 --- a/pkg/kubehound/models/store/models.go +++ b/pkg/kubehound/models/store/models.go @@ -11,6 +11,7 @@ import ( // security related information. Any capabilities derived from the containing Pod are set ONLY on the container (and // inheritance/override rules applied) type ContainerInherited struct { + Namespace string `bson:"namespace"` PodName string `bson:"pod_name"` NodeName string `bson:"node_name"` HostPID bool `bson:"host_pid"`