Go describe role 구현

1 개요[ | ]

Go describe role 구현
Go describe clusterrole 구현
package main

import (
	"fmt"
	"reflect"
	"sort"
	"strings"

	"gopkg.in/yaml.v3"
)

var yamls = []string{
	`
kind: ClusterRole
metadata:
  name: system:public-info-viewer
rules:
- nonResourceURLs:
  - /healthz
  - /livez
  - /readyz
  - /version
  - /version/
  verbs:
  - get
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-admin
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: view
rules:
- apiGroups:
  - cert-manager.io
  resources:
  - certificates
  - certificaterequests
  - issuers
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - acme.cert-manager.io
  resources:
  - challenges
  - orders
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - notification.toolkit.fluxcd.io
  - source.toolkit.fluxcd.io
  - helm.toolkit.fluxcd.io
  - image.toolkit.fluxcd.io
  - kustomize.toolkit.fluxcd.io
  resources:
  - '*'
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - persistentvolumeclaims/status
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - services/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - controllerrevisions
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - replicasets
  - replicasets/scale
  - replicasets/status
  - statefulsets
  - statefulsets/scale
  - statefulsets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  - horizontalpodautoscalers/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - cronjobs/status
  - jobs
  - jobs/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - ingresses
  - ingresses/status
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicasets/status
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  - poddisruptionbudgets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - ingresses/status
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - get
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - watch
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: system:controller:bootstrap-signer
  namespace: kube-public
rules:
- apiGroups:
  - ""
  resources:
  - configmaps
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resourceNames:
  - cluster-info
  resources:
  - configmaps
  verbs:
  - update
- apiGroups:
  - ""
  - events.k8s.io
  resources:
  - events
  verbs:
  - create
  - patch
  - update
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: edit
rules:
- apiGroups:
  - cert-manager.io
  resources:
  - certificates
  - certificaterequests
  - issuers
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - cert-manager.io
  resources:
  - certificates/status
  verbs:
  - update
- apiGroups:
  - acme.cert-manager.io
  resources:
  - challenges
  - orders
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - cert-manager.io
  resources:
  - certificates
  - certificaterequests
  - issuers
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - acme.cert-manager.io
  resources:
  - challenges
  - orders
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - notification.toolkit.fluxcd.io
  - source.toolkit.fluxcd.io
  - helm.toolkit.fluxcd.io
  - image.toolkit.fluxcd.io
  - kustomize.toolkit.fluxcd.io
  resources:
  - '*'
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - notification.toolkit.fluxcd.io
  - source.toolkit.fluxcd.io
  - helm.toolkit.fluxcd.io
  - image.toolkit.fluxcd.io
  - kustomize.toolkit.fluxcd.io
  resources:
  - '*'
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  - secrets
  - services/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - impersonate
- apiGroups:
  - ""
  resources:
  - pods
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - replicationcontrollers
  - replicationcontrollers/scale
  - secrets
  - serviceaccounts
  - services
  - services/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - apps
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - replicasets
  - replicasets/scale
  - statefulsets
  - statefulsets/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - ingresses
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - networkpolicies
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - delete
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - deletecollection
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - patch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - update
- apiGroups:
  - ""
  resources:
  - pods/eviction
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - serviceaccounts/token
  verbs:
  - create
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - create
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - delete
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - deletecollection
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - get
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - list
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - patch
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - update
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - watch
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - persistentvolumeclaims/status
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - services/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - controllerrevisions
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - replicasets
  - replicasets/scale
  - replicasets/status
  - statefulsets
  - statefulsets/scale
  - statefulsets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  - horizontalpodautoscalers/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - cronjobs/status
  - jobs
  - jobs/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - ingresses
  - ingresses/status
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicasets/status
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  - poddisruptionbudgets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - ingresses/status
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - get
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - watch
`,
}

type Role struct {
	ApiVersion string   `yaml:"apiVersion"`
	Kind       string   `yaml:"kind"`
	Metadata   Metadata `yaml:"metadata"`
	Rules      []Rule   `yaml:"rules"`
}

type Metadata struct {
	Name      string `yaml:"name"`
	Namespace string `yaml:"namespace,omitempty"`
}

type Rule struct {
	Verbs           []string `yaml:"verbs"`
	APIGroups       []string `yaml:"apiGroups"`
	Resources       []string `yaml:"resources"`
	ResourceNames   []string `yaml:"resourceNames"`
	NonResourceURLs []string `yaml:"nonResourceURLs"`
}

func transposeNonResourceURLs(rules []Rule) []Rule {
	var newRules []Rule
	for _, rule := range rules {
		if len(rule.NonResourceURLs) < 2 {
			newRules = append(newRules, rule)
			continue
		}
		var newRule = rule
		for _, url := range rule.NonResourceURLs {
			newRule.NonResourceURLs = []string{url}
			newRules = append(newRules, newRule)
		}
	}
	return newRules
}

type SortableRuleSlice []Rule

func (s SortableRuleSlice) Len() int      { return len(s) }
func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortableRuleSlice) Less(i, j int) bool {
	// {Verbs:[*] APIGroups:[] Resources:[*.*] ResourceNames:[] NonResourceURLs:[]}
	// {Verbs:[*] APIGroups:[] Resources:[] ResourceNames:[] NonResourceURLs:[*]}
	// {Verbs:[create delete deletecollection patch update get list watch] APIGroups:[] Resources:[services] ResourceNames:[] NonResourceURLs:[]}
	// {Verbs:[create delete deletecollection patch update get list watch] APIGroups:[acme.cert-manager.io] Resources:[challenges.acme.cert-manager.io] ResourceNames:[] NonResourceURLs:[]}
	return strings.Compare(fmt.Sprintf("%+v", s[i]), fmt.Sprintf("%+v", s[j])) < 0
}

func describe(role Role) {
	rules := []Rule{}
	for _, r := range role.Rules {
		if len(r.APIGroups) == 0 {
			rules = append(rules, Rule{
				Verbs:           r.Verbs,
				Resources:       []string{},
				ResourceNames:   r.ResourceNames,
				NonResourceURLs: r.NonResourceURLs,
			})
			continue
		}
		for _, apiGroup := range r.APIGroups {
			var postfix = ""
			if len(apiGroup) > 0 {
				postfix += "." + apiGroup
			}
			for _, resource := range r.Resources {
				var parts = strings.Split(resource, "/")
				if len(parts) == 1 {
					resource = resource + postfix
				} else {
					resource = parts[0] + postfix + "/" + parts[1]
				}
				var resources = []string{resource}
				var idx = -1
				for i, rule := range rules {
					if !reflect.DeepEqual(rule.Resources, resources) {
						continue
					}
					if !reflect.DeepEqual(rule.NonResourceURLs, r.NonResourceURLs) {
						continue
					}
					if !reflect.DeepEqual(rule.ResourceNames, r.ResourceNames) {
						continue
					}
					idx = i
					break
				}
				if idx >= 0 {
					rules[idx].Verbs = append(rules[idx].Verbs, r.Verbs...)
				} else {
					rules = append(rules, Rule{
						Verbs:           r.Verbs,
						APIGroups:       []string{apiGroup},
						Resources:       resources,
						ResourceNames:   r.ResourceNames,
						NonResourceURLs: r.NonResourceURLs,
					})
				}
			}
		}
	}
	rules = transposeNonResourceURLs(rules)
	sort.Stable(SortableRuleSlice(rules))

	fmt.Println("---")
	fmt.Println("Kind:", role.Kind)
	fmt.Println("Name:", role.Metadata.Name)
	if role.Kind == "Role" {
		fmt.Println("Namespace:", role.Metadata.Namespace)
	}
	fmt.Println("PolicyRule:")
	fmt.Printf("  %-50s  %v  %v  %s\n", "Resources", "Non-Resource URLs", "Resource Names", "Verbs")
	for _, r := range rules {
		var resource = ""
		if len(r.Resources) > 0 {
			resource = r.Resources[0]
		}
		fmt.Printf("  %-50s  %v  %v  %s\n", resource, r.NonResourceURLs, r.ResourceNames, r.Verbs)
	}
}

func main() {
	var role Role
	for _, y := range yamls {
		yaml.Unmarshal([]byte(y), &role)
		describe(role)
	}
}

2 같이 보기[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}