generated from cybozu-go/neco-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Write cilium-agent-proxy in Go (#11)
* Move CLI entry point * Write cilium-agent-proxy in Go * Return policy information from cilium-agent-proxy * Push cilium-agent-proxy on release * Reflect comments * Renamed sub to app Signed-off-by: Daichi Sakaue <[email protected]>
- Loading branch information
Showing
18 changed files
with
304 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# 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/ | ||
COPY Makefile Makefile | ||
|
||
# Build | ||
RUN make build-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 bin/download/cilium / | ||
COPY --from=builder /work/bin/cilium-agent-proxy / | ||
|
||
ENTRYPOINT ["/cilium-agent-proxy"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package app | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"log/slog" | ||
"net/http" | ||
"os/exec" | ||
"path/filepath" | ||
"strconv" | ||
) | ||
|
||
const ( | ||
ciliumPath = "/cilium" | ||
) | ||
|
||
func runCommand(path string, input []byte, args ...string) ([]byte, []byte, error) { | ||
stdout := new(bytes.Buffer) | ||
stderr := new(bytes.Buffer) | ||
cmd := exec.Command(path, args...) | ||
cmd.Stdout = stdout | ||
cmd.Stderr = stderr | ||
if input != nil { | ||
cmd.Stdin = bytes.NewReader(input) | ||
} | ||
if err := cmd.Run(); err != nil { | ||
_, file := filepath.Split(path) | ||
return stdout.Bytes(), stderr.Bytes(), fmt.Errorf("%s failed with %s: stderr=%s", file, err, stderr) | ||
} | ||
return stdout.Bytes(), stderr.Bytes(), nil | ||
} | ||
|
||
func renderJSON(w http.ResponseWriter, path string, data []byte, status int) { | ||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(status) | ||
if _, err := w.Write(data); err != nil { | ||
slog.Error("failed to write response", slog.String("path", path)) | ||
} | ||
} | ||
|
||
func renderError(w http.ResponseWriter, path string, message string, status int) { | ||
slog.Info(message, slog.String("path", path), slog.Int("status", status)) | ||
ret := make(map[string]string) | ||
ret["error"] = message | ||
ret["status"] = strconv.Itoa(status) | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(status) | ||
if err := json.NewEncoder(w).Encode(ret); err != nil { | ||
slog.Error("failed to write response", slog.String("path", path)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package app | ||
|
||
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() | ||
}, | ||
} | ||
|
||
func Execute() { | ||
if err := rootCmd.Execute(); err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package app | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"io" | ||
"net" | ||
"net/http" | ||
"strconv" | ||
) | ||
|
||
const socketPath = "/var/run/cilium/cilium.sock" | ||
|
||
var ( | ||
socketClient *http.Client | ||
) | ||
|
||
func handleEndpoint(w http.ResponseWriter, r *http.Request) { | ||
param := r.URL.Path[len("/v1/endpoint/"):] | ||
if len(param) == 0 { | ||
renderError(w, r.URL.Path, "failed to read endpoint ID", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
// Convert to number to avoid parameter injection | ||
endpoint, err := strconv.Atoi(param) | ||
if err != nil { | ||
renderError(w, r.URL.Path, "failed to read endpoint ID", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
url := fmt.Sprintf("http://localhost/v1/endpoint/%d", endpoint) | ||
resp, err := socketClient.Get(url) | ||
if err != nil { | ||
renderError(w, r.URL.Path, "failed to call Cilium API", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
buf := new(bytes.Buffer) | ||
io.Copy(buf, resp.Body) | ||
renderJSON(w, r.URL.Path, buf.Bytes(), http.StatusOK) | ||
} | ||
|
||
func handleIdentity(w http.ResponseWriter, r *http.Request) { | ||
param := r.URL.Path[len("/v1/identity/"):] | ||
if len(param) == 0 { | ||
renderError(w, r.URL.Path, "failed to read identity", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
// Convert to number to avoid parameter injection | ||
identity, err := strconv.Atoi(param) | ||
if err != nil { | ||
renderError(w, r.URL.Path, "failed to read identity", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
url := fmt.Sprintf("http://localhost/v1/identity/%d", identity) | ||
resp, err := socketClient.Get(url) | ||
if err != nil { | ||
renderError(w, r.URL.Path, "failed to call Cilium API", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
buf := new(bytes.Buffer) | ||
io.Copy(buf, resp.Body) | ||
renderJSON(w, r.URL.Path, buf.Bytes(), http.StatusOK) | ||
} | ||
|
||
func handlePolicy(w http.ResponseWriter, r *http.Request) { | ||
param := r.URL.Path[len("/policy/"):] | ||
if len(param) == 0 { | ||
renderError(w, r.URL.Path, "failed to read endpoint ID", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
// Convert to number to avoid parameter injection | ||
endpoint, err := strconv.Atoi(param) | ||
if err != nil { | ||
renderError(w, r.URL.Path, "failed to read endpoint ID", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
stdout, _, err := runCommand(ciliumPath, nil, "bpf", "policy", "get", strconv.Itoa(endpoint), "-ojson") | ||
if err != nil { | ||
renderError(w, r.URL.Path, "failed to read BPF map", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
renderJSON(w, r.URL.Path, stdout, http.StatusOK) | ||
} | ||
|
||
func subMain() error { | ||
socketClient = &http.Client{ | ||
Transport: &http.Transport{ | ||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { | ||
return net.Dial("unix", socketPath) | ||
}, | ||
}, | ||
} | ||
|
||
server := http.Server{ | ||
Addr: ":8080", | ||
Handler: nil, | ||
} | ||
|
||
http.HandleFunc("/v1/endpoint/", handleEndpoint) | ||
http.HandleFunc("/v1/identity/", handleIdentity) | ||
http.HandleFunc("/policy/", handlePolicy) | ||
|
||
return server.ListenAndServe() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/app" | ||
|
||
func main() { | ||
app.Execute() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package cmd | ||
package app | ||
|
||
import ( | ||
"bytes" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package cmd | ||
package app | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package cmd | ||
package app | ||
|
||
import ( | ||
"fmt" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/npv/app" | ||
|
||
func main() { | ||
app.Execute() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.