From af219486375e8297365d2bfc4279f90298fd66bb Mon Sep 17 00:00:00 2001 From: wenlin Date: Thu, 5 Aug 2021 15:24:58 +0100 Subject: [PATCH 1/4] Make RBAC struct from GVRs --- pkg/permissions/generate.go | 38 +++++++++ pkg/permissions/generate_test.go | 138 ++++++++++++++++++++++--------- 2 files changed, 139 insertions(+), 37 deletions(-) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 452cca6b..3fcf44ec 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -6,6 +6,8 @@ import ( "github.com/jetstack/preflight/pkg/agent" "github.com/jetstack/preflight/pkg/datagatherer/k8s" + rbac "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func Generate(dataGatherers []agent.DataGatherer) string { @@ -37,3 +39,39 @@ rules: ss := strings.TrimSuffix(s, "---") return strings.TrimSuffix(ss, "\n") } + +func GenerateRoles(dataGatherer []agent.DataGatherer) []rbac.ClusterRole { + // make (out := []rbac.ClusterRole{}, length(dataGatherer)) + out := []rbac.ClusterRole{} + + for _, g := range dataGatherer { + if g.Kind != "k8s-dynamic" { + continue + } + + genericConfig := g.Config + dyConfig := genericConfig.(*k8s.ConfigDynamic) + + metaName := fmt.Sprint(dyConfig.GroupVersionResource.Resource) + + out = append(out, rbac.ClusterRole{ + metav1.TypeMeta{ + Kind: "ClusterRole", + APIVersion: "v1", + }, + metav1.ObjectMeta{ + Name: fmt.Sprintf("jetstack-secure-agent-%s-reader", metaName), + }, + []rbac.PolicyRule{ + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{fmt.Sprint(dyConfig.GroupVersionResource.Group)}, + Resources: []string{fmt.Sprintf(metaName)}, + }, + }, + nil, + }) + + } + return out +} diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index d0ff7750..ff382f6a 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -3,55 +3,119 @@ package permissions import ( "testing" + "github.com/d4l3k/messagediff" "github.com/jetstack/preflight/pkg/agent" "github.com/jetstack/preflight/pkg/datagatherer/k8s" + rbac "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" ) -func TestGenerate(t *testing.T) { - inputDatagatherers := []agent.DataGatherer{ +func TestGenerateRBAC(t *testing.T) { + // Use these test cases to check if Generate function is correct + testCases := []struct { + // expectedClusterRoles is the collection of ClusterRole + expectedClusterRoles []rbac.ClusterRole + dataGatherers []agent.DataGatherer + description string + }{ { - Name: "k8s/pods", - Kind: "k8s-dynamic", - Config: &k8s.ConfigDynamic{ - GroupVersionResource: schema.GroupVersionResource{ - Version: "v1", - Resource: "pods", + description: "Generate RBAC struct for pods datagatherer", + dataGatherers: []agent.DataGatherer{ + { + Name: "k8s/pods", + Kind: "k8s-dynamic", + Config: &k8s.ConfigDynamic{ + GroupVersionResource: schema.GroupVersionResource{ + Version: "v1", + Resource: "pods", + }, + }, + }, + { + Name: "k8s/secrets", + Kind: "k8s-dynamic", + Config: &k8s.ConfigDynamic{ + GroupVersionResource: schema.GroupVersionResource{ + Version: "v1", + Resource: "secrets", + }, + }, + }, + { + Name: "k8s/awspcaissuer", + Kind: "k8s-dynamic", + Config: &k8s.ConfigDynamic{ + GroupVersionResource: schema.GroupVersionResource{ + Group: "awspca.cert-manager.io", + Version: "v1", + Resource: "awspcaissuers", + }, + }, }, }, - }, - { - Name: "k8s/secrets", - Kind: "k8s-dynamic", - Config: &k8s.ConfigDynamic{ - GroupVersionResource: schema.GroupVersionResource{ - Version: "v1", - Resource: "secrets", + expectedClusterRoles: []rbac.ClusterRole{ + { + metav1.TypeMeta{ + Kind: "ClusterRole", + APIVersion: "v1", + }, + metav1.ObjectMeta{ + Name: "jetstack-secure-agent-pods-reader", + }, + []rbac.PolicyRule{ + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{""}, + Resources: []string{"pods"}, + }, + }, + nil, + }, + { + metav1.TypeMeta{ + Kind: "ClusterRole", + APIVersion: "v1", + }, + metav1.ObjectMeta{ + Name: "jetstack-secure-agent-secrets-reader", + }, + []rbac.PolicyRule{ + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{""}, + Resources: []string{"secrets"}, + }, + }, + nil, + }, + { + metav1.TypeMeta{ + Kind: "ClusterRole", + APIVersion: "v1", + }, + metav1.ObjectMeta{ + Name: "jetstack-secure-agent-awspcaissuers-reader", + }, + []rbac.PolicyRule{ + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"awspca.cert-manager.io"}, + Resources: []string{"awspcaissuers"}, + }, + }, + nil, }, }, }, + // Try adding more test cases } - expectedOutput := `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-secrets-reader -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list", "watch"]` - - if output := Generate(inputDatagatherers); output != expectedOutput { - t.Fatalf("unexpected output \n%s \n expected: \n%s", output, expectedOutput) + for _, input := range testCases { + got := GenerateRoles(input.dataGatherers) + if diff, equal := messagediff.PrettyDiff(input.expectedClusterRoles, got); !equal { + t.Errorf("%s:\n%s", input.description, diff) + t.Fatalf("unexpected difference in RBAC cluster role: \ngot \n%v\nwant\n%v", got, input.expectedClusterRoles) + } } - } From 2106ddfc0b65d8ebd56e74807e024d23142f1ee1 Mon Sep 17 00:00:00 2001 From: wenlin Date: Thu, 5 Aug 2021 17:05:21 +0100 Subject: [PATCH 2/4] Updated Config.go Update the DataGatherer struct --- pkg/agent/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/agent/config.go b/pkg/agent/config.go index ed0ee590..e224756c 100644 --- a/pkg/agent/config.go +++ b/pkg/agent/config.go @@ -44,9 +44,9 @@ type Endpoint struct { } type DataGatherer struct { - Kind string - Name string - DataPath string + Kind string `yaml:"kind"` + Name string `yaml:"name"` + DataPath string `yaml:"data_path"` Config datagatherer.Config } From 14e667f829e29d704443be01a98c79d409c3e992 Mon Sep 17 00:00:00 2001 From: wenlin Date: Fri, 6 Aug 2021 11:53:30 +0100 Subject: [PATCH 3/4] Fix generate.go Add missing field names and update APIVersion --- pkg/permissions/generate.go | 13 ++++++------- pkg/permissions/generate_test.go | 27 ++++++++++++--------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index 3fcf44ec..aae36133 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -55,21 +55,20 @@ func GenerateRoles(dataGatherer []agent.DataGatherer) []rbac.ClusterRole { metaName := fmt.Sprint(dyConfig.GroupVersionResource.Resource) out = append(out, rbac.ClusterRole{ - metav1.TypeMeta{ + TypeMeta: metav1.TypeMeta{ Kind: "ClusterRole", - APIVersion: "v1", + APIVersion: "rbac.authorization.k8s.io/v1", }, - metav1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("jetstack-secure-agent-%s-reader", metaName), }, - []rbac.PolicyRule{ + Rules: []rbac.PolicyRule{ { Verbs: []string{"get", "list", "watch"}, - APIGroups: []string{fmt.Sprint(dyConfig.GroupVersionResource.Group)}, - Resources: []string{fmt.Sprintf(metaName)}, + APIGroups: []string{dyConfig.GroupVersionResource.Group}, + Resources: []string{metaName}, }, }, - nil, }) } diff --git a/pkg/permissions/generate_test.go b/pkg/permissions/generate_test.go index ff382f6a..6428e9e2 100644 --- a/pkg/permissions/generate_test.go +++ b/pkg/permissions/generate_test.go @@ -56,55 +56,52 @@ func TestGenerateRBAC(t *testing.T) { }, expectedClusterRoles: []rbac.ClusterRole{ { - metav1.TypeMeta{ + TypeMeta: metav1.TypeMeta{ Kind: "ClusterRole", - APIVersion: "v1", + APIVersion: "rbac.authorization.k8s.io/v1", }, - metav1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "jetstack-secure-agent-pods-reader", }, - []rbac.PolicyRule{ + Rules: []rbac.PolicyRule{ { Verbs: []string{"get", "list", "watch"}, APIGroups: []string{""}, Resources: []string{"pods"}, }, }, - nil, }, { - metav1.TypeMeta{ + TypeMeta: metav1.TypeMeta{ Kind: "ClusterRole", - APIVersion: "v1", + APIVersion: "rbac.authorization.k8s.io/v1", }, - metav1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "jetstack-secure-agent-secrets-reader", }, - []rbac.PolicyRule{ + Rules: []rbac.PolicyRule{ { Verbs: []string{"get", "list", "watch"}, APIGroups: []string{""}, Resources: []string{"secrets"}, }, }, - nil, }, { - metav1.TypeMeta{ + TypeMeta: metav1.TypeMeta{ Kind: "ClusterRole", - APIVersion: "v1", + APIVersion: "rbac.authorization.k8s.io/v1", }, - metav1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "jetstack-secure-agent-awspcaissuers-reader", }, - []rbac.PolicyRule{ + Rules: []rbac.PolicyRule{ { Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"awspca.cert-manager.io"}, Resources: []string{"awspcaissuers"}, }, }, - nil, }, }, }, From 39e64be5eaab20e77d5c8b4a6d5fedb0a7006f1b Mon Sep 17 00:00:00 2001 From: wenlin Date: Fri, 6 Aug 2021 11:59:27 +0100 Subject: [PATCH 4/4] Update generate.go Delete unnessessary Sprintf and comment --- pkg/permissions/generate.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/permissions/generate.go b/pkg/permissions/generate.go index aae36133..1515fc8a 100644 --- a/pkg/permissions/generate.go +++ b/pkg/permissions/generate.go @@ -41,7 +41,6 @@ rules: } func GenerateRoles(dataGatherer []agent.DataGatherer) []rbac.ClusterRole { - // make (out := []rbac.ClusterRole{}, length(dataGatherer)) out := []rbac.ClusterRole{} for _, g := range dataGatherer { @@ -52,7 +51,7 @@ func GenerateRoles(dataGatherer []agent.DataGatherer) []rbac.ClusterRole { genericConfig := g.Config dyConfig := genericConfig.(*k8s.ConfigDynamic) - metaName := fmt.Sprint(dyConfig.GroupVersionResource.Resource) + metaName := dyConfig.GroupVersionResource.Resource out = append(out, rbac.ClusterRole{ TypeMeta: metav1.TypeMeta{