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

wip #5

Closed
wants to merge 1 commit into from
Closed
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
25 changes: 25 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Build the manager binary
FROM ghcr.io/cybozu/golang:1.23-jammy AS builder

# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download

# Copy the go source
COPY cmd/cilium-agent-proxy/ cmd/cilium-agent-proxy/

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o cilium-agent-proxy ./cmd/cilium-agent-proxy

# Compose the manager container
FROM ghcr.io/cybozu/ubuntu:22.04
LABEL org.opencontainers.image.source=https://github.com/cybozu-go/network-policy-viewer

WORKDIR /
COPY --from=builder /work/cilium-agent-proxy /

USER 10000:10000
ENTRYPOINT ["/cilium-agent-proxy"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ clean:
.PHONY: build
build: ## Build network-policy-viewer
mkdir -p $(BIN_DIR)
go build -trimpath -ldflags "-w -s" -o $(BIN_DIR)/npv main.go
go build -trimpath -ldflags "-w -s" -o $(BIN_DIR)/npv ./cmd/npv

.PHONY: check-generate
check-generate:
Expand Down
7 changes: 7 additions & 0 deletions cmd/cilium-agent-proxy/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "github.com/cybozu-go/network-policy-viewer/cmd/cilium-agent-proxy/sub"

func main() {
sub.Execute()
}
28 changes: 28 additions & 0 deletions cmd/cilium-agent-proxy/sub/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package sub

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
Use: "cilium-agent-proxy",
Short: "cilium-agent proxy",
Long: `cilium-agent proxy`,

RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
return subMain()
},
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
109 changes: 109 additions & 0 deletions cmd/cilium-agent-proxy/sub/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package sub

import (
"context"
"fmt"
"io"
"net"
"net/http"
"regexp"
"strconv"
)

const socketPath = "/var/run/cilium/cilium.sock"

var (
endpointPattern *regexp.Regexp
identityPattern *regexp.Regexp
)

func handleEndpoint(w http.ResponseWriter, r *http.Request) {
match := endpointPattern.FindStringSubmatch(r.URL.Path)
if match == nil || len(match) < 2 {
fmt.Fprint(w, "error\n")
return
}
client := http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", socketPath)
},
},
}

// Convert to number to avoid possible parameter injection
endpoint, err := strconv.Atoi(match[1])
if err != nil {
fmt.Fprint(w, "error\n")
return
}

url := fmt.Sprintf("http://localhost/v1/endpoint/%d", endpoint)
resp, err := client.Get(url)
if err != nil {
fmt.Fprint(w, "error\n")
return
}

io.Copy(w, resp.Body)
}

func handleIdentity(w http.ResponseWriter, r *http.Request) {
match := identityPattern.FindStringSubmatch(r.URL.Path)
if match == nil || len(match) < 2 {
fmt.Fprint(w, "error\n")
return
}
client := http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", socketPath)
},
},
}

// Convert to number to avoid possible parameter injection
identity, err := strconv.Atoi(match[1])
if err != nil {
fmt.Fprint(w, "error\n")
return
}

url := fmt.Sprintf("http://localhost/v1/identity/%d", identity)
resp, err := client.Get(url)
if err != nil {
fmt.Fprint(w, "error\n")
return
}

io.Copy(w, resp.Body)
}

func handlePolicy(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "policy")
}

func subMain() error {
pattern, err := regexp.Compile(`^/endpoint/(?P<endpoint>\d+)$`)
endpointPattern = pattern
if err != nil {
return err
}

pattern, err = regexp.Compile(`^/identity/(?P<identity>\d+)$`)
identityPattern = pattern
if err != nil {
return err
}

server := http.Server{
Addr: ":8080",
Handler: nil,
}

http.HandleFunc("/endpoint/", handleEndpoint)
http.HandleFunc("/identity/", handleIdentity)
http.HandleFunc("/policy/", handlePolicy)

return server.ListenAndServe()
}
2 changes: 1 addition & 1 deletion cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func runDump(ctx context.Context, w io.Writer, name string) error {
return err
}

endpointID, err := getPodEndpointID(ctx, dynamicClient, rootOptions.namespace, name)
endpointID, _, err := getPodEndpointID(ctx, dynamicClient, rootOptions.namespace, name)
if err != nil {
return err
}
Expand Down
66 changes: 54 additions & 12 deletions cmd/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strconv"

"github.com/cilium/cilium/pkg/client"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -14,13 +15,17 @@ import (
"k8s.io/client-go/rest"
)

const (
directionEgress = "EGRESS"
directionIngress = "INGRESS"
)

func createClients(ctx context.Context, name string) (*kubernetes.Clientset, *dynamic.DynamicClient, *client.Client, error) {
config, err := rest.InClusterConfig()
if err != nil {
return nil, nil, nil, err
}

// Create Kubernetes Clients
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, nil, nil, err
Expand All @@ -31,19 +36,26 @@ func createClients(ctx context.Context, name string) (*kubernetes.Clientset, *dy
return nil, nil, nil, err
}

// Create Cilium Client
endpoint, err := getProxyEndpoint(ctx, clientset, rootOptions.namespace, name)
if err != nil {
return nil, nil, nil, err
}
ciliumClient, err := client.NewClient(endpoint)
ciliumClient, err := createCiliumClient(ctx, clientset, rootOptions.namespace, name)
if err != nil {
return nil, nil, nil, err
}

return clientset, dynamicClient, ciliumClient, err
}

func createCiliumClient(ctx context.Context, clientset *kubernetes.Clientset, namespace, name string) (*client.Client, error) {
endpoint, err := getProxyEndpoint(ctx, clientset, namespace, name)
if err != nil {
return nil, err
}
client, err := client.NewClient(endpoint)
if err != nil {
return nil, err
}
return client, nil
}

func getProxyEndpoint(ctx context.Context, c *kubernetes.Clientset, namespace, name string) (string, error) {
targetPod, err := c.CoreV1().Pods(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
Expand All @@ -67,7 +79,7 @@ func getProxyEndpoint(ctx context.Context, c *kubernetes.Clientset, namespace, n
return fmt.Sprintf("http://%s:%d", podIP, rootOptions.proxyPort), nil
}

func getPodEndpointID(ctx context.Context, d *dynamic.DynamicClient, namespace, name string) (int64, error) {
func getPodEndpointID(ctx context.Context, d *dynamic.DynamicClient, namespace, name string) (int64, int64, error) {
gvr := schema.GroupVersionResource{
Group: "cilium.io",
Version: "v2",
Expand All @@ -76,16 +88,46 @@ func getPodEndpointID(ctx context.Context, d *dynamic.DynamicClient, namespace,

ep, err := d.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return 0, err
return 0, 0, err
}

endpointID, found, err := unstructured.NestedInt64(ep.Object, "status", "id")
if err != nil {
return 0, err
return 0, 0, err
}
if !found {
return 0, 0, errors.New("CiliumEndpoint does not have .status.id")
}

endpointIdentity, found, err := unstructured.NestedInt64(ep.Object, "status", "identity", "id")
if err != nil {
return 0, 0, err
}
if !found {
return 0, errors.New("endpoint resource is broken")
return 0, 0, errors.New("CiliumEndpoint does not have .status.identity.id")
}

return endpointID, nil
return endpointID, endpointIdentity, nil
}

func listCiliumIDs(ctx context.Context, d *dynamic.DynamicClient) (*unstructured.UnstructuredList, error) {
gvr := schema.GroupVersionResource{
Group: "cilium.io",
Version: "v2",
Resource: "ciliumidentities",
}
return d.Resource(gvr).List(ctx, metav1.ListOptions{})
}

func findCiliumID(dict *unstructured.UnstructuredList, id int64) *unstructured.Unstructured {
if dict == nil {
return nil
}
name := strconv.FormatInt(id, 10)
for _, item := range dict.Items {
if item.GetName() == name {
return &item
}
}
return nil
}
13 changes: 13 additions & 0 deletions cmd/l3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cmd

import "github.com/spf13/cobra"

var l3Cmd = &cobra.Command{
Use: "l3",
Short: "inspect l3 rules",
Long: `inspect l3 rules`,
}

func init() {
rootCmd.AddCommand(l3Cmd)
}
Loading
Loading