diff --git a/cmd/generate_cmd.go b/cmd/generate_cmd.go index 2a06667..0f21743 100644 --- a/cmd/generate_cmd.go +++ b/cmd/generate_cmd.go @@ -20,13 +20,13 @@ import ( ) func NewCommandGenerateClusterRole() *cobra.Command { - clusterContext := "" generateKind := "" allowedGroups := []string{} //expandGroups := []string{} allowedVerb := []string{} denyResources := []string{} + metadataFlag := &MetadataFlag{metadata: metav1.ObjectMeta{Name: ""}} // Support overrides cmd := &cobra.Command{ @@ -47,6 +47,8 @@ rbac-tool gen --generated-type=Role --deny-resources=secrets.,ingresses.extensio # Generate a Role with read-only (get,list) excluding secrets (core group) from core group, admissionregistration.k8s.io,storage.k8s.io,networking.k8s.io rbac-tool gen --generated-type=ClusterRole --deny-resources=secrets., --allowed-verbs=get,list --allowed-groups=,admissionregistration.k8s.io,storage.k8s.io,networking.k8s.io +# Generate a Role and customize the metadata of the generated object +rbac-tool gen --generated-type=Role --deny-resources=secrets.,ingresses.extensions --allowed-verbs=get,list --metadata='{"name": "my-role", "namespace":"my-namespace", "labels": {"app": "myapp"}, "annotations": {"generated-by": "rbac-tool"}}' `, Hidden: false, @@ -61,7 +63,7 @@ rbac-tool gen --generated-type=ClusterRole --deny-resources=secrets., --allowed- return err } - obj, err := generateRole(generateKind, computedPolicyRules) + obj, err := generateRole(generateKind, computedPolicyRules, &metadataFlag.metadata) if err != nil { return err } @@ -80,36 +82,46 @@ rbac-tool gen --generated-type=ClusterRole --deny-resources=secrets., --allowed- flags.StringSliceVar(&allowedGroups, "allowed-groups", []string{"*"}, "Comma separated list of API groups we would like to allow '*'") flags.StringSliceVar(&allowedVerb, "allowed-verbs", []string{"*"}, "Comma separated list of verbs to include. To include all use '*'") flags.StringSliceVar(&denyResources, "deny-resources", []string{""}, "Comma separated list of resource.group - for example secret. to deny secret (core group) access") + flags.Var(metadataFlag, "metadata", "Kubernetes object metadata as JSON") return cmd } -func generateRole(generateKind string, rules []rbacv1.PolicyRule) (string, error) { +func generateRole(generateKind string, rules []rbacv1.PolicyRule, metadata *metav1.ObjectMeta) (string, error) { var obj runtime.Object + md := *metadata if generateKind == "ClusterRole" { + if md.Name == "" { + md.Name = "custom-cluster-role" + } + md.Namespace = "" + obj = &rbacv1.ClusterRole{ TypeMeta: metav1.TypeMeta{ Kind: "ClusterRole", APIVersion: "rbac.authorization.k8s.io/v1", }, - ObjectMeta: metav1.ObjectMeta{ - Name: "custom-cluster-role", - }, - Rules: rules, + ObjectMeta: md, + Rules: rules, } } else { + if md.Name == "" { + md.Name = "custom-role" + } + if md.Namespace == "" { + md.Namespace = "mynamespace" + } + obj = &rbacv1.Role{ TypeMeta: metav1.TypeMeta{ Kind: "Role", APIVersion: "rbac.authorization.k8s.io/v1", }, - ObjectMeta: metav1.ObjectMeta{ - Name: "custom-role", - Namespace: "mynamespace", - }, - Rules: rules, + ObjectMeta: md, + Rules: rules, } + } serializer := k8sJson.NewSerializerWithOptions(k8sJson.DefaultMetaFactory, nil, nil, k8sJson.SerializerOptions{Yaml: true, Pretty: true, Strict: true}) diff --git a/cmd/metadata_arg.go b/cmd/metadata_arg.go new file mode 100644 index 0000000..695a757 --- /dev/null +++ b/cmd/metadata_arg.go @@ -0,0 +1,28 @@ +package cmd + +import ( + "encoding/json" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type MetadataFlag struct { + metadata metav1.ObjectMeta +} + +func (f *MetadataFlag) String() string { + b, err := json.Marshal(f.metadata) + if err != nil { + return "failed to marshal metadata object" + } + return string(b) +} + +func (f *MetadataFlag) Set(v string) error { + f.metadata = metav1.ObjectMeta{} + return json.Unmarshal([]byte(v), &f.metadata) +} + +func (f *MetadataFlag) Type() string { + return "json" +} diff --git a/cmd/show_permissions_cmd.go b/cmd/show_permissions_cmd.go index 2b15b8e..53483e2 100644 --- a/cmd/show_permissions_cmd.go +++ b/cmd/show_permissions_cmd.go @@ -28,6 +28,7 @@ func NewCommandGenerateShowPermissions() *cobra.Command { scope := "cluster" denyVerb := []string{} denyResource := []string{} + metadataFlag := &MetadataFlag{metadata: metav1.ObjectMeta{Name: ""}} // Support overrides cmd := &cobra.Command{ @@ -87,7 +88,7 @@ rbac-tool show --scope=namespaced --without-verbs=create,update,patch,delete,del if scope == "namespaced" { generateKind = "Role" } - obj, err := generateRole(generateKind, computedPolicyRules) + obj, err := generateRole(generateKind, computedPolicyRules, &metadataFlag.metadata) if err != nil { return err } @@ -106,6 +107,7 @@ rbac-tool show --scope=namespaced --without-verbs=create,update,patch,delete,del flags.StringSliceVar(&withVerb, "with-verbs", []string{"*"}, "Comma separated list of verbs to include. To include all use '*'") flags.StringSliceVar(&denyVerb, "without-verbs", []string{""}, "Comma separated list of verbs to exclude.") flags.StringSliceVar(&denyResource, "without-resources", []string{""}, "Comma separated list of resources to exclude. Syntax: .") + flags.Var(metadataFlag, "metadata", "Kubernetes object metadata as JSON") return cmd }