Skip to content

Commit

Permalink
inits trace/export feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mhausenblas committed Jul 28, 2019
1 parent 41b5c3d commit 9c20286
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Makefile
@@ -1,4 +1,4 @@
rbiam_version:= v0.2
rbiam_version:= v0.3

.PHONY: build

Expand Down
60 changes: 60 additions & 0 deletions export.go
@@ -0,0 +1,60 @@
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"strings"
"time"
)

// exportRaw exports the trace as a raw dump in JSON format into a file
// in the current working directory with a name of 'rbiam-trace-NNNNNNNNNN' with
// the NNNNNNNNNN being the Unix timestamp of the creation time, for example:
// rbiam-trace-1564315687.json
func exportRaw(trace []string, ag *AccessGraph) (string, error) {
dump := ""
for _, item := range trace {
itype := strings.TrimPrefix(strings.Split(item, "]")[0], "[")
ikey := strings.TrimSpace(strings.Split(item, "]")[1])
switch itype {
case "IAM role":
b, err := json.Marshal(ag.Roles[ikey])
if err != nil {
return "", err
}
dump = fmt.Sprintf("%v\n%v", dump, string(b))
case "IAM policy":
b, err := json.Marshal(ag.Policies[ikey])
if err != nil {
return "", err
}
dump = fmt.Sprintf("%v\n%v", dump, string(b))
case "Kubernetes service account":
b, err := json.Marshal(ag.ServiceAccounts[ikey])
if err != nil {
return "", err
}
dump = fmt.Sprintf("%v\n%v", dump, string(b))
case "Kubernetes secret":
b, err := json.Marshal(ag.Secrets[ikey])
if err != nil {
return "", err
}
dump = fmt.Sprintf("%v\n%v", dump, string(b))
case "Kubernetes pod":
b, err := json.Marshal(ag.Pods[ikey])
if err != nil {
return "", err
}
dump = fmt.Sprintf("%v\n%v", dump, string(b))
}
}

filename := fmt.Sprintf("rbiam-trace-%v.json", time.Now().Unix())
err := ioutil.WriteFile(filename, []byte(dump), 0644)
if err != nil {
return "", err
}
return filename, nil
}
2 changes: 2 additions & 0 deletions interaction.go
Expand Up @@ -15,6 +15,8 @@ func toplevel(d prompt.Document) []prompt.Suggest {
{Text: "k8s-pods", Description: "Select a Kubernetes pod to explore"},
{Text: "history", Description: "Show the history of selected items"},
{Text: "sync", Description: "Synchronize the local state with IAM and Kubernetes"},
{Text: "trace", Description: "Start tracing"},
{Text: "export-raw", Description: "Stop tracing and export trace to JSON dump in current working directory"},
{Text: "help", Description: "Explain how it works and show available commands"},
{Text: "quit", Description: "Terminate the interactive session and quit"},
}
Expand Down
38 changes: 34 additions & 4 deletions main.go
Expand Up @@ -29,13 +29,11 @@ func main() {
fmt.Println("Gathering info from IAM and Kubernetes. This may take a bit, please stand by ...")
ag = NewAccessGraph(cfg)
// fmt.Println(ag)

tracecntr := 0
tracemode := false
cursel := "help" // make sure to first show the help to guide users what to do
for {
switch cursel {
case "sync":
fmt.Println("Gathering info from IAM and Kubernetes. This may take a bit, please stand by ...")
ag = NewAccessGraph(cfg)
case "iam-user":
presult(formatCaller(ag))
case "iam-roles":
Expand All @@ -45,6 +43,9 @@ func main() {
if role, ok := ag.Roles[targetrole]; ok {
presult(formatRole(&role))
appendhist("IAM role", targetrole)
if tracemode {
tracecntr++
}
}
case "iam-policies":
targetpolicy := prompt.Input(" ↪ ", selectPolicy,
Expand All @@ -53,6 +54,9 @@ func main() {
if policy, ok := ag.Policies[targetpolicy]; ok {
presult(formatPolicy(&policy))
appendhist("IAM policy", targetpolicy)
if tracemode {
tracecntr++
}
}
case "k8s-sa":
targetsa := prompt.Input(" ↪ ", selectSA,
Expand All @@ -61,6 +65,9 @@ func main() {
if sa, ok := ag.ServiceAccounts[targetsa]; ok {
presult(formatSA(&sa))
appendhist("Kubernetes service account", targetsa)
if tracemode {
tracecntr++
}
}
case "k8s-secrets":
targetsec := prompt.Input(" ↪ ", selectSecret,
Expand All @@ -69,6 +76,9 @@ func main() {
if secret, ok := ag.Secrets[targetsec]; ok {
presult(formatSecret(&secret))
appendhist("Kubernetes secret", targetsec)
if tracemode {
tracecntr++
}
}
case "k8s-pods":
targetpod := prompt.Input(" ↪ ", selectPod,
Expand All @@ -77,9 +87,27 @@ func main() {
if pod, ok := ag.Pods[targetpod]; ok {
presult(formatPod(&pod))
appendhist("Kubernetes pod", targetpod)
if tracemode {
tracecntr++
}
}
case "history":
dumphist()
case "sync":
fmt.Println("Gathering info from IAM and Kubernetes. This may take a bit, please stand by ...")
ag = NewAccessGraph(cfg)
case "trace":
tracemode = true
tracecntr = 0
presult("Starting to trace now. Use an 'export-xxx' command to stop tracing and export to one of the supported formats.\n")
case "export-raw":
tracemode = false
fn, err := exportRaw(history[0:tracecntr], ag)
if err != nil {
pwarning(fmt.Sprintf("Can't export trace: %v\n", err))
continue
}
presult(fmt.Sprintf("Raw trace exported to %v\n", fn))
case "help":
presult(fmt.Sprintf("\nThis is rbIAM in version %v\n\n", Version))
presult(strings.Repeat("-", 80))
Expand All @@ -92,6 +120,8 @@ func main() {
presult("- k8s-pods … to look up a Kubernetes pod\n")
presult("- history … show history\n")
presult("- sync … to refresh the local data\n")
presult("- trace … start tracing\n")
presult("- export-raw … stop tracing and export trace to JSON dump in current working directory\n")
presult(strings.Repeat("-", 80))
presult("\n\nNote: simply start typing and/or use the tab and cursor keys to select.\n")
presult("CTRL+L clears the screen and if you're stuck type 'help' or 'quit' to leave.\n\n")
Expand Down

0 comments on commit 9c20286

Please sign in to comment.