github.com/argoproj/argo-cd@v1.8.7/cmd/argocd-util/commands/project_allowlist.go (about) 1 package commands 2 3 import ( 4 "bufio" 5 "io" 6 "io/ioutil" 7 "os" 8 "strings" 9 10 "github.com/ghodss/yaml" 11 "github.com/spf13/cobra" 12 rbacv1 "k8s.io/api/rbac/v1" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 15 "k8s.io/apimachinery/pkg/runtime/schema" 16 "k8s.io/client-go/discovery" 17 "k8s.io/client-go/kubernetes/scheme" 18 "k8s.io/client-go/tools/clientcmd" 19 20 "github.com/argoproj/argo-cd/util/errors" 21 22 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1" 23 "github.com/argoproj/argo-cd/util/cli" 24 25 // load the gcp plugin (required to authenticate against GKE clusters). 26 _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" 27 // load the oidc plugin (required to authenticate with OpenID Connect). 28 _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" 29 // load the azure plugin (required to authenticate with AKS clusters). 30 _ "k8s.io/client-go/plugin/pkg/client/auth/azure" 31 ) 32 33 // NewProjectAllowListGenCommand generates a project from clusterRole 34 func NewProjectAllowListGenCommand() *cobra.Command { 35 var ( 36 clientConfig clientcmd.ClientConfig 37 out string 38 ) 39 var command = &cobra.Command{ 40 Use: "generate-allow-list CLUSTERROLE_PATH PROJ_NAME", 41 Short: "Generates project allow list from the specified clusterRole file", 42 Run: func(c *cobra.Command, args []string) { 43 if len(args) != 2 { 44 c.HelpFunc()(c, args) 45 os.Exit(1) 46 } 47 clusterRoleFileName := args[0] 48 projName := args[1] 49 50 var writer io.Writer 51 if out == "-" { 52 writer = os.Stdout 53 } else { 54 f, err := os.Create(out) 55 errors.CheckError(err) 56 bw := bufio.NewWriter(f) 57 writer = bw 58 defer func() { 59 err = bw.Flush() 60 errors.CheckError(err) 61 err = f.Close() 62 errors.CheckError(err) 63 }() 64 } 65 66 globalProj := generateProjectAllowList(clientConfig, clusterRoleFileName, projName) 67 68 yamlBytes, err := yaml.Marshal(globalProj) 69 errors.CheckError(err) 70 71 _, err = writer.Write(yamlBytes) 72 errors.CheckError(err) 73 }, 74 } 75 clientConfig = cli.AddKubectlFlagsToCmd(command) 76 command.Flags().StringVarP(&out, "out", "o", "-", "Output to the specified file instead of stdout") 77 78 return command 79 } 80 81 func generateProjectAllowList(clientConfig clientcmd.ClientConfig, clusterRoleFileName string, projName string) v1alpha1.AppProject { 82 yamlBytes, err := ioutil.ReadFile(clusterRoleFileName) 83 errors.CheckError(err) 84 var obj unstructured.Unstructured 85 err = yaml.Unmarshal(yamlBytes, &obj) 86 errors.CheckError(err) 87 88 clusterRole := &rbacv1.ClusterRole{} 89 err = scheme.Scheme.Convert(&obj, clusterRole, nil) 90 errors.CheckError(err) 91 92 config, err := clientConfig.ClientConfig() 93 errors.CheckError(err) 94 disco, err := discovery.NewDiscoveryClientForConfig(config) 95 errors.CheckError(err) 96 serverResources, err := disco.ServerPreferredResources() 97 errors.CheckError(err) 98 99 resourceList := make([]metav1.GroupKind, 0) 100 for _, rule := range clusterRole.Rules { 101 if len(rule.APIGroups) <= 0 { 102 continue 103 } 104 105 canCreate := false 106 for _, verb := range rule.Verbs { 107 if strings.EqualFold(verb, "Create") { 108 canCreate = true 109 break 110 } 111 } 112 113 if !canCreate { 114 continue 115 } 116 117 ruleApiGroup := rule.APIGroups[0] 118 for _, ruleResource := range rule.Resources { 119 for _, apiResourcesList := range serverResources { 120 gv, err := schema.ParseGroupVersion(apiResourcesList.GroupVersion) 121 if err != nil { 122 gv = schema.GroupVersion{} 123 } 124 if ruleApiGroup == gv.Group { 125 for _, apiResource := range apiResourcesList.APIResources { 126 if apiResource.Name == ruleResource { 127 resourceList = append(resourceList, metav1.GroupKind{Group: ruleApiGroup, Kind: apiResource.Kind}) 128 } 129 } 130 } 131 } 132 } 133 } 134 globalProj := v1alpha1.AppProject{ 135 TypeMeta: metav1.TypeMeta{ 136 Kind: "AppProject", 137 APIVersion: "argoproj.io/v1alpha1", 138 }, 139 ObjectMeta: metav1.ObjectMeta{Name: projName}, 140 Spec: v1alpha1.AppProjectSpec{}, 141 } 142 globalProj.Spec.NamespaceResourceWhitelist = resourceList 143 return globalProj 144 }