From 6f0add9c139882735cc532804396f1e508e7d2c0 Mon Sep 17 00:00:00 2001 From: "oluwole.fadeyi" Date: Thu, 12 Aug 2021 11:53:09 +0100 Subject: [PATCH 01/12] Add rbac generate unit tests Adds another test to test the RBAC generate function Related #250 Signed-off-by: oluwole.fadeyi --- pkg/permissions/generate.go | 4 ++ pkg/permissions/generate_test.go | 93 ++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 61711ea3..c299b940 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -113,3 +113,7 @@ func GenerateAgentRBACManifests(dataGatherers []agent.DataGatherer) AgentRBACMan return AgentRBACManifests } + +func generateFullManifest(dataGatherers []agent.DataGatherer) string { + +} diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index 8efbc6de..959657cf 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -11,6 +11,99 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) +func TestGenerateAgentRBACManifestsString(t *testing.T) { + testCases := []struct { + description string + dataGatherers []agent.DataGatherer + expectedRBACManifests string + }{ + { + description: "Generate ClusterRole and ClusterRoleBinding for simple pod dg use case", + dataGatherers: []agent.DataGatherer{ + { + Name: "k8s/pods", + Kind: "k8s-dynamic", + Config: &k8s.ConfigDynamic{ + GroupVersionResource: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + }, + }, + expectedRBACManifests: ` +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: jetstack-secure-agent-pods-reader +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: jetstack-secure-agent-pods-reader +roleRef: + kind: ClusterRole + name: jetstack-secure-agent-pods-reader + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: agent + namespace: jetstack-secure +`, + }, + { + description: "Generate ClusterRole and RoleBinding for simple pod dg with include namespace \"foobar\"", + dataGatherers: []agent.DataGatherer{ + { + Name: "k8s/pods", + Kind: "k8s-dynamic", + Config: &k8s.ConfigDynamic{ + IncludeNamespaces: []string{"foobar"}, + GroupVersionResource: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + }, + }, + expectedRBACManifests: ` +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: jetstack-secure-agent-pods-reader +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: jetstack-secure-agent-pods-reader + namespace: foobar +roleRef: + kind: ClusterRole + name: jetstack-secure-agent-pods-reader + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: agent + namespace: jetstack-secure +`, + }, + } + + for _, input := range testCases { + got := generateFullManifest(input.dataGatherers) + + td.Cmp(t, input.expectedRBACManifests, got) + } +} + func TestGenerateAgentRBACManifests(t *testing.T) { testCases := []struct { description string From 5821617e88f22b62fb60283c3ae941df2775162d Mon Sep 17 00:00:00 2001 From: wenlin Date: Thu, 12 Aug 2021 18:09:15 +0100 Subject: [PATCH 02/12] Convert RBAC into string WIP --- cmd/agent.go | 9 +++++++++ pkg/permissions/generate.go | 12 +++++++++++- pkg/permissions/generate_test.go | 9 ++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index 9de8e849..02a767d9 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -5,6 +5,7 @@ import ( "time" "github.com/jetstack/preflight/pkg/agent" + "github.com/jetstack/preflight/pkg/datagatherer" "github.com/spf13/cobra" ) @@ -27,6 +28,14 @@ var agentInfoCmd = &cobra.Command{ }, } +var agentRBACCmd = &cobra.Command{ + Use: "rbac", + Short: "print RBAC", + Long: `Print RBAC string by reading GVRs`, + Run: out := generateFullManifest(agent.DataGatherer) + fmt.Sprintf(out) +} + func init() { rootCmd.AddCommand(agentCmd) agentCmd.AddCommand(agentInfoCmd) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index c299b940..4da5f2ec 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -1,6 +1,7 @@ package permissions import ( + "encoding/json" "fmt" "github.com/jetstack/preflight/pkg/agent" @@ -115,5 +116,14 @@ func GenerateAgentRBACManifests(dataGatherers []agent.DataGatherer) AgentRBACMan } func generateFullManifest(dataGatherers []agent.DataGatherer) string { - + agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) + agentRBACString, err := json.Marshal(agentRBACManifestsStruct) + if err != nil { + fmt.Print(err) + } + var out string + for _, s := range agentRBACString { + out += string(s) + } + return out } diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index 959657cf..bc487994 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -3,6 +3,7 @@ package permissions import ( "testing" + "github.com/d4l3k/messagediff" "github.com/jetstack/preflight/pkg/agent" "github.com/jetstack/preflight/pkg/datagatherer/k8s" "github.com/maxatome/go-testdeep/td" @@ -99,8 +100,14 @@ subjects: for _, input := range testCases { got := generateFullManifest(input.dataGatherers) + // if input.expectedRBACManifests != got { + // t.Errorf("value mismatch, expected: %q \n got:%q", input.expectedRBACManifests, got) + // } - td.Cmp(t, input.expectedRBACManifests, got) + //td.Cmp(t, input.expectedRBACManifests, got) + if diff, equal := messagediff.PrettyDiff(input.expectedRBACManifests, got); !equal { + t.Fatalf("unexpected difference in RBAC cluster role: %v", diff) + } } } From f5ab6582ddfea3831b3b6292de681c6cbd25a06f Mon Sep 17 00:00:00 2001 From: wenlin Date: Fri, 20 Aug 2021 11:00:27 +0100 Subject: [PATCH 03/12] Print BRAC instring WIP --- cmd/agent.go | 29 +++++++- pkg/permissions/generate.go | 115 ++++++++++++++++++++++++++++--- pkg/permissions/generate_test.go | 10 ++- 3 files changed, 136 insertions(+), 18 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index 02a767d9..1440870b 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -2,10 +2,13 @@ package cmd import ( "fmt" + "io/ioutil" + "log" + "os" "time" "github.com/jetstack/preflight/pkg/agent" - "github.com/jetstack/preflight/pkg/datagatherer" + "github.com/jetstack/preflight/pkg/permissions" "github.com/spf13/cobra" ) @@ -32,13 +35,33 @@ var agentRBACCmd = &cobra.Command{ Use: "rbac", Short: "print RBAC", Long: `Print RBAC string by reading GVRs`, - Run: out := generateFullManifest(agent.DataGatherer) - fmt.Sprintf(out) + Run: func(cmd *cobra.Command, args []string) { + + file, err := os.Open(agent.ConfigFilePath) + if err != nil { + log.Fatalf("Failed to load config file for agent from: %s", agent.ConfigFilePath) + } + defer file.Close() + + b, err := ioutil.ReadAll(file) + if err != nil { + log.Fatalf("Failed to read config file: %s", err) + } + + config, err := agent.ParseConfig(b) + if err != nil { + log.Fatalf("Failed to parse config file: %s", err) + } + + out := permissions.GenerateFullManifest(config.DataGatherers) + fmt.Print(out) + }, } func init() { rootCmd.AddCommand(agentCmd) agentCmd.AddCommand(agentInfoCmd) + agentCmd.AddCommand(agentRBACCmd) agentCmd.PersistentFlags().StringVarP( &agent.ConfigFilePath, "agent-config-file", diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 4da5f2ec..967f8466 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -1,8 +1,8 @@ package permissions import ( - "encoding/json" "fmt" + "strings" "github.com/jetstack/preflight/pkg/agent" "github.com/jetstack/preflight/pkg/datagatherer/k8s" @@ -20,6 +20,81 @@ type AgentRBACManifests struct { RoleBindings []rbac.RoleBinding } +//******************************* +func AgentCLR(clusterRole []rbac.ClusterRole) string { + var got []string + for _, clr := range clusterRole { + var aG, rC, vB string + for _, rule := range clr.Rules { + aG = strings.Join(rule.APIGroups, " -\n") + rC = strings.Join(rule.Resources, " -\n") + vB = strings.Join(rule.Verbs, " -\n") + } + + got = append(got, fmt.Sprintf( + `apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: jetstack-secure-agent-pods-reader +rules: +- apiGroups: + -%s + resources: + -%s + verbs: + -%s`, aG, rC, vB)) + } + out := strings.Join(got, "\n") + return out +} + +//******************************* +func AgentCLRB(CLRB []rbac.ClusterRoleBinding) string { + var got []string + for _, clrb := range CLRB { + got = append(got, fmt.Sprintf( + `apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: %s +roleRef: + kind: ClusterRole + name: %s + apiGroup: +subjects: +- kind: %s + name: %s + namespace: %s`, clrb.ObjectMeta.Name, clrb.RoleRef.Name, clrb.Subjects[0].Kind, clrb.Subjects[0].Name, clrb.Subjects[0].Namespace)) + } + out := strings.Join(got, "\n") + return out +} + +//******************************* +func AgentRB(RB []rbac.RoleBinding) string { + var got []string + for _, rb := range RB { + got = append(got, fmt.Sprintf( + `apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: %s + namespaces:%s +roleRef: + kind: ClusterRole + name: %s + apiGroup: +subjects: +- kind: %s + name: %s + namespace: %s`, rb.ObjectMeta.Name, rb.ObjectMeta.Namespace, rb.RoleRef.Name, rb.Subjects[0].Kind, rb.Subjects[0].Name, rb.Subjects[0].Namespace)) + } + out := strings.Join(got, "\n") + return out +} + +//******************************* + const agentNamespace = "jetstack-secure" const agentSubjectName = "agent" @@ -115,15 +190,37 @@ func GenerateAgentRBACManifests(dataGatherers []agent.DataGatherer) AgentRBACMan return AgentRBACManifests } -func generateFullManifest(dataGatherers []agent.DataGatherer) string { +// func generateFullManifest(dataGatherers []agent.DataGatherer) string { +// agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) +// //agentRBACString, err := json.Marshal(agentRBACManifestsStruct) +// if err != nil { +// fmt.Print(err) +// } +// var out string +// for _, s := range agentRBACString { + +// out += s.String() +// } +// return out +// } + +func GenerateFullManifest(dataGatherers []agent.DataGatherer) string { agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) - agentRBACString, err := json.Marshal(agentRBACManifestsStruct) - if err != nil { - fmt.Print(err) - } + agentCLR := AgentCLR(agentRBACManifestsStruct.ClusterRoles) + agentCLRB := AgentCLRB(agentRBACManifestsStruct.ClusterRoleBindings) + agentRB := AgentRB(agentRBACManifestsStruct.RoleBindings) + + // fmt.Print(agentCLR) + // fmt.Print(agentCLRB) + // fmt.Print(agentRB) + var out string - for _, s := range agentRBACString { - out += string(s) - } + out = fmt.Sprintf( + `%s +--- +%s +--- +%s`, agentCLR, agentCLRB, agentRB) + return out } diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index bc487994..d65b3d9c 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -3,7 +3,6 @@ package permissions import ( "testing" - "github.com/d4l3k/messagediff" "github.com/jetstack/preflight/pkg/agent" "github.com/jetstack/preflight/pkg/datagatherer/k8s" "github.com/maxatome/go-testdeep/td" @@ -99,15 +98,14 @@ subjects: } for _, input := range testCases { - got := generateFullManifest(input.dataGatherers) + got := GenerateFullManifest(input.dataGatherers) // if input.expectedRBACManifests != got { // t.Errorf("value mismatch, expected: %q \n got:%q", input.expectedRBACManifests, got) // } - //td.Cmp(t, input.expectedRBACManifests, got) - if diff, equal := messagediff.PrettyDiff(input.expectedRBACManifests, got); !equal { - t.Fatalf("unexpected difference in RBAC cluster role: %v", diff) - } + td.Cmp(t, input.expectedRBACManifests, got) + //if diff, equal := messagediff.PrettyDiff(input.expectedRBACManifests, got); !equal { + // t.Fatalf("unexpected difference in RBAC cluster role: %v", diff) } } From 7f2dff9fbb7be755127f7b7e8fffbf92dac5650b Mon Sep 17 00:00:00 2001 From: wenlin Date: Fri, 20 Aug 2021 17:58:53 +0100 Subject: [PATCH 04/12] Fix RBAC string format WIP --- agent.yaml | 6 ++++++ pkg/permissions/generate.go | 17 +++++++---------- pkg/permissions/generate_test.go | 18 ++++++++++++------ 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/agent.yaml b/agent.yaml index 97183f8f..ecb58418 100644 --- a/agent.yaml +++ b/agent.yaml @@ -11,3 +11,9 @@ data-gatherers: name: "dummy-fail" config: always-fail: true + - kind: "k8s-dynamic" + name: "k8s/pods" + config: + resource-type: + resource: pods + version: v1 diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 967f8466..2115f26f 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -26,9 +26,9 @@ func AgentCLR(clusterRole []rbac.ClusterRole) string { for _, clr := range clusterRole { var aG, rC, vB string for _, rule := range clr.Rules { - aG = strings.Join(rule.APIGroups, " -\n") - rC = strings.Join(rule.Resources, " -\n") - vB = strings.Join(rule.Verbs, " -\n") + aG = strings.Join(rule.APIGroups, "\", \"") + rC = strings.Join(rule.Resources, "\", \"") + vB = strings.Join(rule.Verbs, "\", \"") } got = append(got, fmt.Sprintf( @@ -37,12 +37,9 @@ kind: ClusterRole metadata: name: jetstack-secure-agent-pods-reader rules: -- apiGroups: - -%s - resources: - -%s - verbs: - -%s`, aG, rC, vB)) +- apiGroups: ["%s"] + resources: ["%s"] + verbs: ["%s"]`, aG, rC, vB)) } out := strings.Join(got, "\n") return out @@ -76,7 +73,7 @@ func AgentRB(RB []rbac.RoleBinding) string { for _, rb := range RB { got = append(got, fmt.Sprintf( `apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: name: %s namespaces:%s diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index d65b3d9c..a86da92b 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -70,8 +70,7 @@ subjects: }, }, }, - expectedRBACManifests: ` -apiVersion: rbac.authorization.k8s.io/v1 + expectedRBACManifests: `apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: jetstack-secure-agent-pods-reader @@ -97,13 +96,20 @@ subjects: }, } + // for _, input := range testCases { + // got := GenerateFullManifest(input.dataGatherers) + // // if input.expectedRBACManifests != got { + // // t.Errorf("value mismatch, expected: %q \n got:%q", input.expectedRBACManifests, got) + // // } + + // td.Cmp(t, input.expectedRBACManifests, got) for _, input := range testCases { got := GenerateFullManifest(input.dataGatherers) - // if input.expectedRBACManifests != got { - // t.Errorf("value mismatch, expected: %q \n got:%q", input.expectedRBACManifests, got) - // } + if input.expectedRBACManifests != got { + t.Errorf("value mismatch, expected: %s \n got:%s", input.expectedRBACManifests, got) + } - td.Cmp(t, input.expectedRBACManifests, got) + //td.Cmp(t, input.expectedRBACManifests, got) //if diff, equal := messagediff.PrettyDiff(input.expectedRBACManifests, got); !equal { // t.Fatalf("unexpected difference in RBAC cluster role: %v", diff) } From a599b7a59fd2a83f57a1ed3305b80df86259359f Mon Sep 17 00:00:00 2001 From: wenlin Date: Mon, 23 Aug 2021 16:17:52 +0100 Subject: [PATCH 05/12] Match RBAC output string WIP --- pkg/permissions/generate.go | 39 ++++++++------------------------ pkg/permissions/generate_test.go | 9 +++----- 2 files changed, 13 insertions(+), 35 deletions(-) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 2115f26f..144fdedf 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -50,18 +50,19 @@ func AgentCLRB(CLRB []rbac.ClusterRoleBinding) string { var got []string for _, clrb := range CLRB { got = append(got, fmt.Sprintf( - `apiVersion: rbac.authorization.k8s.io/v1 + `--- +apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: %s roleRef: kind: ClusterRole name: %s - apiGroup: + apiGroup: %s subjects: - kind: %s name: %s - namespace: %s`, clrb.ObjectMeta.Name, clrb.RoleRef.Name, clrb.Subjects[0].Kind, clrb.Subjects[0].Name, clrb.Subjects[0].Namespace)) + namespace: %s`, clrb.ObjectMeta.Name, clrb.RoleRef.Name, clrb.RoleRef.APIGroup, clrb.Subjects[0].Kind, clrb.Subjects[0].Name, clrb.Subjects[0].Namespace)) } out := strings.Join(got, "\n") return out @@ -72,19 +73,20 @@ func AgentRB(RB []rbac.RoleBinding) string { var got []string for _, rb := range RB { got = append(got, fmt.Sprintf( - `apiVersion: rbac.authorization.k8s.io/v1 + `--- +apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: %s - namespaces:%s + namespace: %s roleRef: kind: ClusterRole name: %s - apiGroup: + apiGroup: %s subjects: - kind: %s name: %s - namespace: %s`, rb.ObjectMeta.Name, rb.ObjectMeta.Namespace, rb.RoleRef.Name, rb.Subjects[0].Kind, rb.Subjects[0].Name, rb.Subjects[0].Namespace)) + namespace: %s`, rb.ObjectMeta.Name, rb.ObjectMeta.Namespace, rb.RoleRef.Name, rb.RoleRef.APIGroup, rb.Subjects[0].Kind, rb.Subjects[0].Name, rb.Subjects[0].Namespace)) } out := strings.Join(got, "\n") return out @@ -187,36 +189,15 @@ func GenerateAgentRBACManifests(dataGatherers []agent.DataGatherer) AgentRBACMan return AgentRBACManifests } -// func generateFullManifest(dataGatherers []agent.DataGatherer) string { -// agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) -// //agentRBACString, err := json.Marshal(agentRBACManifestsStruct) -// if err != nil { -// fmt.Print(err) -// } -// var out string -// for _, s := range agentRBACString { - -// out += s.String() -// } -// return out -// } - func GenerateFullManifest(dataGatherers []agent.DataGatherer) string { agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) agentCLR := AgentCLR(agentRBACManifestsStruct.ClusterRoles) agentCLRB := AgentCLRB(agentRBACManifestsStruct.ClusterRoleBindings) agentRB := AgentRB(agentRBACManifestsStruct.RoleBindings) - // fmt.Print(agentCLR) - // fmt.Print(agentCLRB) - // fmt.Print(agentRB) - - var out string - out = fmt.Sprintf( + out := fmt.Sprintf( `%s ---- %s ---- %s`, agentCLR, agentCLRB, agentRB) return out diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index a86da92b..1ca33073 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -31,8 +31,7 @@ func TestGenerateAgentRBACManifestsString(t *testing.T) { }, }, }, - expectedRBACManifests: ` -apiVersion: rbac.authorization.k8s.io/v1 + expectedRBACManifests: `apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: jetstack-secure-agent-pods-reader @@ -52,8 +51,7 @@ roleRef: subjects: - kind: ServiceAccount name: agent - namespace: jetstack-secure -`, + namespace: jetstack-secure`, }, { description: "Generate ClusterRole and RoleBinding for simple pod dg with include namespace \"foobar\"", @@ -91,8 +89,7 @@ roleRef: subjects: - kind: ServiceAccount name: agent - namespace: jetstack-secure -`, + namespace: jetstack-secure`, }, } From 2b57d0a297d05a9abd5111d32dd1b87460de7fa9 Mon Sep 17 00:00:00 2001 From: wenlin Date: Tue, 24 Aug 2021 15:31:39 +0100 Subject: [PATCH 06/12] Print correct RBAC string to terminal --- pkg/permissions/generate.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 144fdedf..67f9e994 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -21,14 +21,14 @@ type AgentRBACManifests struct { } //******************************* -func AgentCLR(clusterRole []rbac.ClusterRole) string { +func AgentCLR(clusterRoles []rbac.ClusterRole) string { var got []string - for _, clr := range clusterRole { - var aG, rC, vB string + for _, clr := range clusterRoles { + var apiGroups, resources, verbs string for _, rule := range clr.Rules { - aG = strings.Join(rule.APIGroups, "\", \"") - rC = strings.Join(rule.Resources, "\", \"") - vB = strings.Join(rule.Verbs, "\", \"") + apiGroups = strings.Join(rule.APIGroups, "\", \"") + resources = strings.Join(rule.Resources, "\", \"") + verbs = strings.Join(rule.Verbs, "\", \"") } got = append(got, fmt.Sprintf( @@ -39,16 +39,16 @@ metadata: rules: - apiGroups: ["%s"] resources: ["%s"] - verbs: ["%s"]`, aG, rC, vB)) + verbs: ["%s"]`, apiGroups, resources, verbs)) } out := strings.Join(got, "\n") return out } //******************************* -func AgentCLRB(CLRB []rbac.ClusterRoleBinding) string { +func AgentCLRB(clusterRoleBindings []rbac.ClusterRoleBinding) string { var got []string - for _, clrb := range CLRB { + for _, clrb := range clusterRoleBindings { got = append(got, fmt.Sprintf( `--- apiVersion: rbac.authorization.k8s.io/v1 @@ -69,9 +69,9 @@ subjects: } //******************************* -func AgentRB(RB []rbac.RoleBinding) string { +func AgentRB(RoleBindings []rbac.RoleBinding) string { var got []string - for _, rb := range RB { + for _, rb := range RoleBindings { got = append(got, fmt.Sprintf( `--- apiVersion: rbac.authorization.k8s.io/v1 @@ -197,8 +197,7 @@ func GenerateFullManifest(dataGatherers []agent.DataGatherer) string { out := fmt.Sprintf( `%s -%s -%s`, agentCLR, agentCLRB, agentRB) +%s%s`, agentCLR, agentCLRB, agentRB) return out } From 0d508c01d7313c7ac092d2c6b919f5d70ab845c7 Mon Sep 17 00:00:00 2001 From: wenlin Date: Thu, 26 Aug 2021 10:09:35 +0100 Subject: [PATCH 07/12] Use yaml.umarshal to generate string WIP --- agent.yaml | 7 +- cmd/agent.go | 12 +-- go.mod | 5 +- pkg/permissions/generate.go | 138 ++++++++++++++----------------- pkg/permissions/generate_test.go | 30 ++++--- 5 files changed, 84 insertions(+), 108 deletions(-) diff --git a/agent.yaml b/agent.yaml index ecb58418..d3e950f8 100644 --- a/agent.yaml +++ b/agent.yaml @@ -11,9 +11,4 @@ data-gatherers: name: "dummy-fail" config: always-fail: true - - kind: "k8s-dynamic" - name: "k8s/pods" - config: - resource-type: - resource: pods - version: v1 + diff --git a/cmd/agent.go b/cmd/agent.go index 1440870b..51008436 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -4,7 +4,6 @@ import ( "fmt" "io/ioutil" "log" - "os" "time" "github.com/jetstack/preflight/pkg/agent" @@ -33,21 +32,14 @@ var agentInfoCmd = &cobra.Command{ var agentRBACCmd = &cobra.Command{ Use: "rbac", - Short: "print RBAC", + Short: "print the agent's minimal RBAC manifest", Long: `Print RBAC string by reading GVRs`, Run: func(cmd *cobra.Command, args []string) { - file, err := os.Open(agent.ConfigFilePath) - if err != nil { - log.Fatalf("Failed to load config file for agent from: %s", agent.ConfigFilePath) - } - defer file.Close() - - b, err := ioutil.ReadAll(file) + b, err := ioutil.ReadAll(agent.ConfigFilePath) if err != nil { log.Fatalf("Failed to read config file: %s", err) } - config, err := agent.ParseConfig(b) if err != nil { log.Fatalf("Failed to parse config file: %s", err) diff --git a/go.mod b/go.mod index cdc92c2e..e545010c 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/aws/aws-sdk-go v1.36.19 github.com/cenkalti/backoff v2.2.1+incompatible github.com/d4l3k/messagediff v1.2.1 - github.com/fatih/color v1.12.0 // indirect + github.com/fatih/color v1.12.0 github.com/go-playground/universal-translator v0.17.0 // indirect github.com/hashicorp/go-multierror v1.1.0 github.com/jetstack/version-checker v0.2.2-0.20201118163251-4bab9ef088ef @@ -21,7 +21,7 @@ require ( github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b // indirect github.com/kylelemons/godebug v1.1.0 github.com/leodido/go-urn v1.2.0 // indirect - github.com/maxatome/go-testdeep v1.9.2 // indirect + github.com/maxatome/go-testdeep v1.9.2 github.com/pkg/errors v0.9.1 github.com/pmylund/go-cache v2.1.0+incompatible github.com/sirupsen/logrus v1.7.0 @@ -39,6 +39,7 @@ require ( k8s.io/apimachinery v0.20.1 k8s.io/client-go v11.0.0+incompatible k8s.io/utils v0.0.0-20201110183641-67b214c5f920 + sigs.k8s.io/yaml v1.2.0 ) replace k8s.io/client-go => k8s.io/client-go v0.20.1 diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 67f9e994..3ab283a8 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -8,6 +8,7 @@ import ( "github.com/jetstack/preflight/pkg/datagatherer/k8s" rbac "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/yaml" ) // AgentRBACManifests is a wrapper around the various RBAC structs needed to grant the agent fine-grained permissions as per its dg configs @@ -20,80 +21,6 @@ type AgentRBACManifests struct { RoleBindings []rbac.RoleBinding } -//******************************* -func AgentCLR(clusterRoles []rbac.ClusterRole) string { - var got []string - for _, clr := range clusterRoles { - var apiGroups, resources, verbs string - for _, rule := range clr.Rules { - apiGroups = strings.Join(rule.APIGroups, "\", \"") - resources = strings.Join(rule.Resources, "\", \"") - verbs = strings.Join(rule.Verbs, "\", \"") - } - - got = append(got, fmt.Sprintf( - `apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: jetstack-secure-agent-pods-reader -rules: -- apiGroups: ["%s"] - resources: ["%s"] - verbs: ["%s"]`, apiGroups, resources, verbs)) - } - out := strings.Join(got, "\n") - return out -} - -//******************************* -func AgentCLRB(clusterRoleBindings []rbac.ClusterRoleBinding) string { - var got []string - for _, clrb := range clusterRoleBindings { - got = append(got, fmt.Sprintf( - `--- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: %s -roleRef: - kind: ClusterRole - name: %s - apiGroup: %s -subjects: -- kind: %s - name: %s - namespace: %s`, clrb.ObjectMeta.Name, clrb.RoleRef.Name, clrb.RoleRef.APIGroup, clrb.Subjects[0].Kind, clrb.Subjects[0].Name, clrb.Subjects[0].Namespace)) - } - out := strings.Join(got, "\n") - return out -} - -//******************************* -func AgentRB(RoleBindings []rbac.RoleBinding) string { - var got []string - for _, rb := range RoleBindings { - got = append(got, fmt.Sprintf( - `--- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: %s - namespace: %s -roleRef: - kind: ClusterRole - name: %s - apiGroup: %s -subjects: -- kind: %s - name: %s - namespace: %s`, rb.ObjectMeta.Name, rb.ObjectMeta.Namespace, rb.RoleRef.Name, rb.RoleRef.APIGroup, rb.Subjects[0].Kind, rb.Subjects[0].Name, rb.Subjects[0].Namespace)) - } - out := strings.Join(got, "\n") - return out -} - -//******************************* - const agentNamespace = "jetstack-secure" const agentSubjectName = "agent" @@ -189,15 +116,72 @@ func GenerateAgentRBACManifests(dataGatherers []agent.DataGatherer) AgentRBACMan return AgentRBACManifests } +func GenerateFullManifest0(dataGatherers []agent.DataGatherer) string { + agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) + agentCLR := agentCLR(agentRBACManifestsStruct.ClusterRoles) + agentCLRB := agentCLRB(agentRBACManifestsStruct.ClusterRoleBindings) + agentRB := agentRB(agentRBACManifestsStruct.RoleBindings) + + out := fmt.Sprintf( + `%s +%s%s`, agentCLR, agentCLRB, agentRB) + + return out +} + +func agentCLR(clusterRoles []rbac.ClusterRole) string { + var builder strings.Builder + for _, cb := range clusterRoles { + data, err := yaml.Marshal(cb) + if err != nil { + fmt.Print("Cluster Role fails to marshal") + } + + builder.Write(data) + builder.WriteString("\n---\n") + } + + return builder.String() +} +func agentRB(roleBindings []rbac.RoleBinding) string { + var builder strings.Builder + for _, cb := range roleBindings { + data, err := yaml.Marshal(cb) + if err != nil { + fmt.Print("Role Binding fails to marshal") + } + + builder.Write(data) + builder.WriteString("\n---\n") + } + + return builder.String() +} +func agentCLRB(clusterRoleBindings []rbac.ClusterRoleBinding) string { + var builder strings.Builder + for _, cb := range clusterRoleBindings { + data, err := yaml.Marshal(cb) + if err != nil { + fmt.Print("Cluster Role Binding fails to marshal") + } + + builder.Write(data) + builder.WriteString("\n---\n") + } + + return builder.String() +} + func GenerateFullManifest(dataGatherers []agent.DataGatherer) string { agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) - agentCLR := AgentCLR(agentRBACManifestsStruct.ClusterRoles) - agentCLRB := AgentCLRB(agentRBACManifestsStruct.ClusterRoleBindings) - agentRB := AgentRB(agentRBACManifestsStruct.RoleBindings) + agentCLR := agentCLR(agentRBACManifestsStruct.ClusterRoles) + agentCLRB := agentCLRB(agentRBACManifestsStruct.ClusterRoleBindings) + agentRB := agentRB(agentRBACManifestsStruct.RoleBindings) out := fmt.Sprintf( `%s %s%s`, agentCLR, agentCLRB, agentRB) return out + } diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index 1ca33073..6c561a28 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -71,35 +71,39 @@ subjects: expectedRBACManifests: `apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: jetstack-secure-agent-pods-reader + creationTimestamp: null + name: jetstack-secure-agent-pods-reader rules: -- apiGroups: [""] - resources: ["pods"] - verbs: ["get", "list", "watch"] +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + --- + apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: + creationTimestamp: null name: jetstack-secure-agent-pods-reader namespace: foobar roleRef: + apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: jetstack-secure-agent-pods-reader - apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: agent - namespace: jetstack-secure`, + namespace: jetstack-secure + +---`, }, } - // for _, input := range testCases { - // got := GenerateFullManifest(input.dataGatherers) - // // if input.expectedRBACManifests != got { - // // t.Errorf("value mismatch, expected: %q \n got:%q", input.expectedRBACManifests, got) - // // } - - // td.Cmp(t, input.expectedRBACManifests, got) for _, input := range testCases { got := GenerateFullManifest(input.dataGatherers) if input.expectedRBACManifests != got { From 5c7b6f8f0c074d70df57aeda19e890c6fc18b2a1 Mon Sep 17 00:00:00 2001 From: wenlin Date: Thu, 26 Aug 2021 14:06:15 +0100 Subject: [PATCH 08/12] Successfully print RBAC string to terminal --- agent.yaml | 7 ++++++- cmd/agent.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/agent.yaml b/agent.yaml index d3e950f8..ecb58418 100644 --- a/agent.yaml +++ b/agent.yaml @@ -11,4 +11,9 @@ data-gatherers: name: "dummy-fail" config: always-fail: true - + - kind: "k8s-dynamic" + name: "k8s/pods" + config: + resource-type: + resource: pods + version: v1 diff --git a/cmd/agent.go b/cmd/agent.go index 51008436..0935cd5c 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -36,7 +36,7 @@ var agentRBACCmd = &cobra.Command{ Long: `Print RBAC string by reading GVRs`, Run: func(cmd *cobra.Command, args []string) { - b, err := ioutil.ReadAll(agent.ConfigFilePath) + b, err := ioutil.ReadFile(agent.ConfigFilePath) if err != nil { log.Fatalf("Failed to read config file: %s", err) } From c3179c2bdc7009bacb6b22598a7dfbd2cb230c83 Mon Sep 17 00:00:00 2001 From: wenlin Date: Thu, 26 Aug 2021 23:11:47 +0100 Subject: [PATCH 09/12] Match output string WIP Print the seemly identical string but still fail because it differs from expected output --- pkg/permissions/generate_test.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index 6c561a28..512b628d 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -34,24 +34,35 @@ func TestGenerateAgentRBACManifestsString(t *testing.T) { expectedRBACManifests: `apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: jetstack-secure-agent-pods-reader + creationTimestamp: null + name: jetstack-secure-agent-pods-reader rules: -- apiGroups: [""] - resources: ["pods"] - verbs: ["get", "list", "watch"] +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + --- + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: + creationTimestamp: null name: jetstack-secure-agent-pods-reader roleRef: + apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: jetstack-secure-agent-pods-reader - apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: agent - namespace: jetstack-secure`, + namespace: jetstack-secure + +---`, }, { description: "Generate ClusterRole and RoleBinding for simple pod dg with include namespace \"foobar\"", @@ -107,7 +118,7 @@ subjects: for _, input := range testCases { got := GenerateFullManifest(input.dataGatherers) if input.expectedRBACManifests != got { - t.Errorf("value mismatch, expected: %s \n got:%s", input.expectedRBACManifests, got) + t.Errorf("value mismatch, expected: %s\n got: %s", input.expectedRBACManifests, got) } //td.Cmp(t, input.expectedRBACManifests, got) From 9416bd54a0a6acb3798078751d910680367b3519 Mon Sep 17 00:00:00 2001 From: wenlin Date: Fri, 27 Aug 2021 12:00:58 +0100 Subject: [PATCH 10/12] Print correct string to terminal and match expected output --- pkg/permissions/generate.go | 43 ++++++--------- pkg/permissions/generate_test.go | 91 ++++++++++++++++++++++++++++---- 2 files changed, 97 insertions(+), 37 deletions(-) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 3ab283a8..8894cd05 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -116,20 +116,7 @@ func GenerateAgentRBACManifests(dataGatherers []agent.DataGatherer) AgentRBACMan return AgentRBACManifests } -func GenerateFullManifest0(dataGatherers []agent.DataGatherer) string { - agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) - agentCLR := agentCLR(agentRBACManifestsStruct.ClusterRoles) - agentCLRB := agentCLRB(agentRBACManifestsStruct.ClusterRoleBindings) - agentRB := agentRB(agentRBACManifestsStruct.RoleBindings) - - out := fmt.Sprintf( - `%s -%s%s`, agentCLR, agentCLRB, agentRB) - - return out -} - -func agentCLR(clusterRoles []rbac.ClusterRole) string { +func createClusterRoleString(clusterRoles []rbac.ClusterRole) string { var builder strings.Builder for _, cb := range clusterRoles { data, err := yaml.Marshal(cb) @@ -137,13 +124,14 @@ func agentCLR(clusterRoles []rbac.ClusterRole) string { fmt.Print("Cluster Role fails to marshal") } + builder.WriteString("\n") builder.Write(data) - builder.WriteString("\n---\n") + builder.WriteString("---") } return builder.String() } -func agentRB(roleBindings []rbac.RoleBinding) string { +func createRoleBindingString(roleBindings []rbac.RoleBinding) string { var builder strings.Builder for _, cb := range roleBindings { data, err := yaml.Marshal(cb) @@ -151,13 +139,14 @@ func agentRB(roleBindings []rbac.RoleBinding) string { fmt.Print("Role Binding fails to marshal") } + builder.WriteString("\n") builder.Write(data) - builder.WriteString("\n---\n") + builder.WriteString("---") } return builder.String() } -func agentCLRB(clusterRoleBindings []rbac.ClusterRoleBinding) string { +func createClusterRoleBindingString(clusterRoleBindings []rbac.ClusterRoleBinding) string { var builder strings.Builder for _, cb := range clusterRoleBindings { data, err := yaml.Marshal(cb) @@ -165,8 +154,9 @@ func agentCLRB(clusterRoleBindings []rbac.ClusterRoleBinding) string { fmt.Print("Cluster Role Binding fails to marshal") } + builder.WriteString("\n") builder.Write(data) - builder.WriteString("\n---\n") + builder.WriteString("---") } return builder.String() @@ -174,13 +164,14 @@ func agentCLRB(clusterRoleBindings []rbac.ClusterRoleBinding) string { func GenerateFullManifest(dataGatherers []agent.DataGatherer) string { agentRBACManifestsStruct := GenerateAgentRBACManifests(dataGatherers) - agentCLR := agentCLR(agentRBACManifestsStruct.ClusterRoles) - agentCLRB := agentCLRB(agentRBACManifestsStruct.ClusterRoleBindings) - agentRB := agentRB(agentRBACManifestsStruct.RoleBindings) - - out := fmt.Sprintf( - `%s -%s%s`, agentCLR, agentCLRB, agentRB) + agentCLR := createClusterRoleString(agentRBACManifestsStruct.ClusterRoles) + agentCLRB := createClusterRoleBindingString(agentRBACManifestsStruct.ClusterRoleBindings) + agentRB := createRoleBindingString(agentRBACManifestsStruct.RoleBindings) + + out := fmt.Sprintf(`%s%s%s`, agentCLR, agentCLRB, agentRB) + out = strings.TrimPrefix(out, "\n") + out = strings.TrimSpace(out) + out = strings.ReplaceAll(out, "\n creationTimestamp: null", "") return out diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index 512b628d..fe50a2d5 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -34,7 +34,6 @@ func TestGenerateAgentRBACManifestsString(t *testing.T) { expectedRBACManifests: `apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - creationTimestamp: null name: jetstack-secure-agent-pods-reader rules: - apiGroups: @@ -45,13 +44,10 @@ rules: - get - list - watch - --- - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - creationTimestamp: null name: jetstack-secure-agent-pods-reader roleRef: apiGroup: rbac.authorization.k8s.io @@ -61,7 +57,6 @@ subjects: - kind: ServiceAccount name: agent namespace: jetstack-secure - ---`, }, { @@ -82,7 +77,6 @@ subjects: expectedRBACManifests: `apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - creationTimestamp: null name: jetstack-secure-agent-pods-reader rules: - apiGroups: @@ -93,13 +87,10 @@ rules: - get - list - watch - --- - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - creationTimestamp: null name: jetstack-secure-agent-pods-reader namespace: foobar roleRef: @@ -110,7 +101,85 @@ subjects: - kind: ServiceAccount name: agent namespace: jetstack-secure - +---`, + }, + { + description: "Generate multiple ClusterRoles and ClusterRoleBindings for simple pod and nodes dg use case", + dataGatherers: []agent.DataGatherer{ + { + Name: "k8s/pods", + Kind: "k8s-dynamic", + Config: &k8s.ConfigDynamic{ + GroupVersionResource: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + }, + { + Name: "k8s/nodes", + Kind: "k8s-dynamic", + Config: &k8s.ConfigDynamic{ + GroupVersionResource: schema.GroupVersionResource{ + Version: "v1", + Resource: "nodes", + }, + }, + }, + }, + expectedRBACManifests: `apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: jetstack-secure-agent-pods-reader +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: jetstack-secure-agent-nodes-reader +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: jetstack-secure-agent-pods-reader +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: jetstack-secure-agent-pods-reader +subjects: +- kind: ServiceAccount + name: agent + namespace: jetstack-secure +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: jetstack-secure-agent-nodes-reader +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: jetstack-secure-agent-nodes-reader +subjects: +- kind: ServiceAccount + name: agent + namespace: jetstack-secure ---`, }, } @@ -118,7 +187,7 @@ subjects: for _, input := range testCases { got := GenerateFullManifest(input.dataGatherers) if input.expectedRBACManifests != got { - t.Errorf("value mismatch, expected: %s\n got: %s", input.expectedRBACManifests, got) + t.Errorf("value mismatch, \n**********expected:******************************\n%s\n**********got:******************************\n%s", input.expectedRBACManifests, got) } //td.Cmp(t, input.expectedRBACManifests, got) From 101ee3b74c0184902a8684540b93aa42d20f56d0 Mon Sep 17 00:00:00 2001 From: wenlin Date: Fri, 27 Aug 2021 12:14:26 +0100 Subject: [PATCH 11/12] Change back to the original agent.yaml --- agent.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/agent.yaml b/agent.yaml index ecb58418..97183f8f 100644 --- a/agent.yaml +++ b/agent.yaml @@ -11,9 +11,3 @@ data-gatherers: name: "dummy-fail" config: always-fail: true - - kind: "k8s-dynamic" - name: "k8s/pods" - config: - resource-type: - resource: pods - version: v1 From 9858f689309c8164c4796a9e7fa6d3466ede2324 Mon Sep 17 00:00:00 2001 From: wenlin Date: Fri, 27 Aug 2021 12:17:33 +0100 Subject: [PATCH 12/12] Small refactoring --- pkg/permissions/generate_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index fe50a2d5..5591e4c1 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -189,10 +189,6 @@ subjects: if input.expectedRBACManifests != got { t.Errorf("value mismatch, \n**********expected:******************************\n%s\n**********got:******************************\n%s", input.expectedRBACManifests, got) } - - //td.Cmp(t, input.expectedRBACManifests, got) - //if diff, equal := messagediff.PrettyDiff(input.expectedRBACManifests, got); !equal { - // t.Fatalf("unexpected difference in RBAC cluster role: %v", diff) } }