Skip to content

Commit

Permalink
bugtool: Add post-processing masking function for Envoy
Browse files Browse the repository at this point in the history
[upstream commit 48a9976]

This commit is to explicitly mask the below fields from Envoy config
dump:

- api_key (used in kafka L7 policy)
- TLSContext (used in Cilium NetworkPolicy)

One round of scanning on existing Cilium protobuf was done.

Related docs: https://www.envoyproxy.io/docs/envoy/latest/operations/admin#get--config_dump

Signed-off-by: Tam Mach <tam.mach@cilium.io>
  • Loading branch information
sayboras authored and julianwiedmann committed Jun 7, 2024
1 parent 224e288 commit 9eb25ba
Showing 1 changed file with 46 additions and 4 deletions.
50 changes: 46 additions & 4 deletions bugtool/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/cilium/cilium/pkg/components"
"github.com/cilium/cilium/pkg/defaults"
"github.com/cilium/cilium/pkg/option"
"github.com/cilium/cilium/pkg/safeio"
)

// BugtoolRootCmd is the top level command for the bugtool.
Expand Down Expand Up @@ -170,6 +171,18 @@ func isValidArchiveType(archiveType string) bool {

type postProcessFunc func(output []byte) ([]byte, error)

var envoySecretMask = jsonFieldMaskPostProcess([]string{
// Cilium LogEntry -> KafkaLogEntry{l7} -> KafkaLogEntry{api_key}
"api_key",
// This could be from one of the following:
// - Cilium NetworkPolicy -> PortNetworkPolicy{ingress_per_port_policies, egress_per_port_policies}
// -> PortNetworkPolicyRule{rules} -> TLSContext{downstream_tls_context, upstream_tls_context}
// - Upstream Envoy tls_certificate
"trusted_ca",
"certificate_chain",
"private_key",
})

func runTool() {
// Validate archive type
if !isValidArchiveType(archiveType) {
Expand Down Expand Up @@ -216,13 +229,13 @@ func runTool() {
}
} else {
if envoyDump {
if err := dumpEnvoy(cmdDir, "http://admin/config_dump?include_eds", "envoy-config.json"); err != nil {
if err := dumpEnvoy(cmdDir, "http://admin/config_dump?include_eds", "envoy-config.json", envoySecretMask); err != nil {
fmt.Fprintf(os.Stderr, "Unable to dump envoy config: %s\n", err)
}
}

if envoyMetrics {
if err := dumpEnvoy(cmdDir, "http://admin/stats/prometheus", "envoy-metrics.txt"); err != nil {
if err := dumpEnvoy(cmdDir, "http://admin/stats/prometheus", "envoy-metrics.txt", nil); err != nil {
fmt.Fprintf(os.Stderr, "Unable to retrieve envoy prometheus metrics: %s\n", err)
}
}
Expand Down Expand Up @@ -516,7 +529,7 @@ func dumpHubbleMetrics(rootDir string) error {
return downloadToFile(httpClient, url, filepath.Join(rootDir, "hubble-metrics.txt"))
}

func dumpEnvoy(rootDir string, resource string, fileName string) error {
func dumpEnvoy(rootDir string, resource string, fileName string, postProcess postProcessFunc) error {
// curl --unix-socket /var/run/cilium/envoy/sockets/admin.sock http:/admin/config_dump\?include_eds > dump.json
c := &http.Client{
Transport: &http.Transport{
Expand All @@ -525,7 +538,11 @@ func dumpEnvoy(rootDir string, resource string, fileName string) error {
},
},
}
return downloadToFile(c, resource, filepath.Join(rootDir, fileName))

if postProcess == nil {
return downloadToFile(c, resource, filepath.Join(rootDir, fileName))
}
return downloadToFileWithPostProcess(c, resource, filepath.Join(rootDir, fileName), postProcess)
}

func pprofTraces(rootDir string, pprofDebug int) error {
Expand Down Expand Up @@ -589,3 +606,28 @@ func downloadToFile(client *http.Client, url, file string) error {
_, err = io.Copy(out, resp.Body)
return err
}

// downloadToFileWithPostProcess downloads the content from the given URL and writes it to the given file.
// The content is then post-processed using the given postProcess function before being written to the file.
// Note: Please use downloadToFile instead of this function if no post-processing is required.
func downloadToFileWithPostProcess(client *http.Client, url, file string, postProcess postProcessFunc) error {
resp, err := client.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", resp.Status)
}

b, err := safeio.ReadAllLimit(resp.Body, safeio.MB)
if err != nil {
return err
}

b, err = postProcess(b)
if err != nil {
return err
}
return os.WriteFile(file, b, 0644)
}

0 comments on commit 9eb25ba

Please sign in to comment.