Skip to content

Commit

Permalink
WIP EOD
Browse files Browse the repository at this point in the history
  • Loading branch information
d0g0x01 committed Aug 1, 2023
1 parent 17f97e2 commit 2057957
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 88 deletions.
164 changes: 96 additions & 68 deletions pkg/kubehound/graph/edge/endpoint_expose_public.go
Original file line number Diff line number Diff line change
@@ -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)
// }
2 changes: 1 addition & 1 deletion pkg/kubehound/models/converter/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
45 changes: 26 additions & 19 deletions pkg/kubehound/models/converter/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -360,22 +368,21 @@ 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
}

func (c *StoreConverter) EndpointPrivate(_ context.Context, port *corev1.ContainerPort,
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},
Expand Down
1 change: 1 addition & 0 deletions pkg/kubehound/models/store/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Endpoint struct {
Id primitive.ObjectID `bson:"_id"`

Check warning on line 27 in pkg/kubehound/models/store/endpoint.go

View workflow job for this annotation

GitHub Actions / linter

var-naming: struct field Id should be ID (revive)
ContainerId primitive.ObjectID `bson:"container_id"`

Check warning on line 28 in pkg/kubehound/models/store/endpoint.go

View workflow job for this annotation

GitHub Actions / linter

var-naming: struct field ContainerId should be ContainerID (revive)
PodName string `bson:"pod_name"`
PodNamespace string `bson:"pod_namespace"`
NodeName string `bson:"node_name"`
IsNamespaced bool `bson:"is_namespaced"`
Namespace string `bson:"namespace"`
Expand Down
1 change: 1 addition & 0 deletions pkg/kubehound/models/store/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down

0 comments on commit 2057957

Please sign in to comment.