Skip to content

Commit

Permalink
Merge pull request #45809 from CaoShuFeng/non-resource-url-create-rol…
Browse files Browse the repository at this point in the history
…ebinding

Automatic merge from submit-queue

support NonResourceURL for kubectl create clusterrole

Release note:
```release-note
add --non-resource-url to kubectl create clusterrole
```
  • Loading branch information
Kubernetes Submit Queue committed May 26, 2017
2 parents 6d64131 + 93e50b1 commit 899b6c0
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 5 deletions.
3 changes: 3 additions & 0 deletions hack/make-rules/test-cmd-util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3125,6 +3125,9 @@ runTests() {
kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods:'
kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':'
kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.resourceNames}}{{.}}:{{end}}{{end}}" 'foo:'
kubectl create "${kube_flags[@]}" clusterrole url-reader --verb=get --non-resource-url=/logs/* --non-resource-url=/healthz/*
kube::test::get_object_assert clusterrole/url-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:'
kube::test::get_object_assert clusterrole/url-reader "{{range.rules}}{{range.nonResourceURLs}}{{.}}:{{end}}{{end}}" '/logs/\*:/healthz/\*:'

# test `kubectl create rolebinding/clusterrolebinding`
# test `kubectl set subject rolebinding/clusterrolebinding`
Expand Down
1 change: 1 addition & 0 deletions hack/verify-flags/known-flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ node-sync-period
no-headers
no-headers
non-masquerade-cidr
non-resource-url
no-suggestions
no-suggestions
num-nodes
Expand Down
65 changes: 63 additions & 2 deletions pkg/kubectl/cmd/create_clusterrole.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package cmd

import (
"fmt"
"io"

"github.com/spf13/cobra"
Expand All @@ -42,11 +43,18 @@ var (
kubectl create clusterrole foo --verb=get,list,watch --resource=rs.extensions
# Create a ClusterRole named "foo" with SubResource specified
kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status`))
kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status
# Create a ClusterRole name "foo" with NonResourceURL specified
kubectl create clusterrole "foo" --verb=get --non-resource-url=/logs/*`))

// Valid nonResource verb list for validation.
validNonResourceVerbs = []string{"*", "get", "post", "put", "delete", "patch", "head", "options"}
)

type CreateClusterRoleOptions struct {
*CreateRoleOptions
NonResourceURLs []string
}

// ClusterRole is a command to ease creating ClusterRoles.
Expand All @@ -72,16 +80,69 @@ func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command
cmdutil.AddPrinterFlags(cmd)
cmdutil.AddDryRunFlag(cmd)
cmd.Flags().StringSliceVar(&c.Verbs, "verb", []string{}, "verb that applies to the resources contained in the rule")
cmd.Flags().StringSliceVar(&c.NonResourceURLs, "non-resource-url", []string{}, "a partial url that user should have access to.")
cmd.Flags().StringSlice("resource", []string{}, "resource that the rule applies to")
cmd.Flags().StringArrayVar(&c.ResourceNames, "resource-name", []string{}, "resource in the white list that the rule applies to, repeat this flag for multiple items")

return cmd
}

func (c *CreateClusterRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
// Remove duplicate nonResourceURLs
nonResourceURLs := []string{}
for _, n := range c.NonResourceURLs {
if !arrayContains(nonResourceURLs, n) {
nonResourceURLs = append(nonResourceURLs, n)
}
}
c.NonResourceURLs = nonResourceURLs

return c.CreateRoleOptions.Complete(f, cmd, args)
}

func (c *CreateClusterRoleOptions) Validate() error {
if c.Name == "" {
return fmt.Errorf("name must be specified")
}

// validate verbs.
if len(c.Verbs) == 0 {
return fmt.Errorf("at least one verb must be specified")
}

if len(c.Resources) == 0 && len(c.NonResourceURLs) == 0 {
return fmt.Errorf("one of resource or nonResourceURL must be specified")
}

// validate resources
if len(c.Resources) > 0 {
for _, v := range c.Verbs {
if !arrayContains(validResourceVerbs, v) {
return fmt.Errorf("invalid verb: '%s'", v)
}
}
if err := c.validateResource(); err != nil {
return err
}
}

//validate non-resource-url
if len(c.NonResourceURLs) > 0 {
for _, v := range c.Verbs {
if !arrayContains(validNonResourceVerbs, v) {
return fmt.Errorf("invalid verb: '%s' for nonResourceURL", v)
}
}
}

return nil

}

func (c *CreateClusterRoleOptions) RunCreateRole() error {
clusterRole := &rbac.ClusterRole{}
clusterRole.Name = c.Name
rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames)
rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames, c.NonResourceURLs)
if err != nil {
return err
}
Expand Down
16 changes: 13 additions & 3 deletions pkg/kubectl/cmd/create_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ func (c *CreateRoleOptions) Validate() error {
return fmt.Errorf("at least one resource must be specified")
}

return c.validateResource()
}

func (c *CreateRoleOptions) validateResource() error {
for _, r := range c.Resources {
if len(r.Resource) == 0 {
return fmt.Errorf("resource must be specified if apiGroup/subresource specified")
Expand Down Expand Up @@ -263,14 +267,13 @@ func (c *CreateRoleOptions) Validate() error {
return err
}
}

return nil
}

func (c *CreateRoleOptions) RunCreateRole() error {
role := &rbac.Role{}
role.Name = c.Name
rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames)
rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames, []string{})
if err != nil {
return err
}
Expand Down Expand Up @@ -301,7 +304,7 @@ func arrayContains(s []string, e string) bool {
return false
}

func generateResourcePolicyRules(mapper meta.RESTMapper, verbs []string, resources []ResourceOptions, resourceNames []string) ([]rbac.PolicyRule, error) {
func generateResourcePolicyRules(mapper meta.RESTMapper, verbs []string, resources []ResourceOptions, resourceNames []string, nonResourceURLs []string) ([]rbac.PolicyRule, error) {
// groupResourceMapping is a apigroup-resource map. The key of this map is api group, while the value
// is a string array of resources under this api group.
// E.g. groupResourceMapping = {"extensions": ["replicasets", "deployments"], "batch":["jobs"]}
Expand Down Expand Up @@ -337,5 +340,12 @@ func generateResourcePolicyRules(mapper meta.RESTMapper, verbs []string, resourc
rules = append(rules, rule)
}

if len(nonResourceURLs) > 0 {
rule := rbac.PolicyRule{}
rule.Verbs = verbs
rule.NonResourceURLs = nonResourceURLs
rules = append(rules, rule)
}

return rules, nil
}

0 comments on commit 899b6c0

Please sign in to comment.