github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/cilium/cmd/preflight_k8s_valid_cnp.go (about) 1 // Copyright 2020 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "context" 19 "fmt" 20 "os" 21 "time" 22 23 "github.com/cilium/cilium/pkg/k8s" 24 v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 25 "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned/scheme" 26 "github.com/cilium/cilium/pkg/logging" 27 "github.com/cilium/cilium/pkg/option" 28 29 "github.com/spf13/cobra" 30 "github.com/spf13/viper" 31 apiextensionsinternal "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" 32 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 33 "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" 34 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 35 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 36 ) 37 38 var validateCNP = &cobra.Command{ 39 Use: "validate-cnp", 40 Short: "Validate Cilium Network Policies deployed in the cluster", 41 Long: `Before upgrading Cilium it is recommended to run this validation checker 42 to make sure the policies deployed are valid. The validator will verify if all policies 43 deployed in the cluster are valid, in case they are not, an error is printed and the 44 has an exit code -1 is returned.`, 45 Run: func(cmd *cobra.Command, args []string) { 46 err := validateCNPs() 47 if err != nil { 48 log.Error(err) 49 os.Exit(-1) 50 } 51 }, 52 } 53 54 const validateK8sPoliciesTimeout = 5 * time.Minute 55 56 func validateCNPs() error { 57 // The internal packages log things. Make sure they follow the setup of of 58 // the CLI tool. 59 logging.DefaultLogger.SetFormatter(log.Formatter) 60 61 log.Info("Setting up Kubernetes client") 62 63 k8sClientQPSLimit := viper.GetFloat64(option.K8sClientQPSLimit) 64 k8sClientBurst := viper.GetInt(option.K8sClientBurst) 65 66 k8s.Configure(k8sAPIServer, k8sKubeConfigPath, float32(k8sClientQPSLimit), k8sClientBurst) 67 68 if err := k8s.Init(); err != nil { 69 log.WithError(err).Fatal("Unable to connect to Kubernetes apiserver") 70 } 71 72 ctx, initCancel := context.WithTimeout(context.Background(), validateK8sPoliciesTimeout) 73 defer initCancel() 74 cnpErr := validateNPResources(ctx, "ciliumnetworkpolicies", "CiliumNetworkPolicy") 75 76 ctx, initCancel2 := context.WithTimeout(context.Background(), validateK8sPoliciesTimeout) 77 defer initCancel2() 78 ccnpErr := validateNPResources(ctx, "ciliumclusterwidenetworkpolicies", "CiliumClusterwideNetworkPolicy") 79 80 if cnpErr != nil { 81 return cnpErr 82 } 83 if ccnpErr != nil { 84 return ccnpErr 85 } 86 log.Info("All CCNPs and CNPs valid!") 87 return nil 88 } 89 90 func validateNPResources(ctx context.Context, name, shortName string) error { 91 var internal apiextensionsinternal.CustomResourceValidation 92 err := v1beta1.Convert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation( 93 &v2.CNPCRV, 94 &internal, 95 nil, 96 ) 97 if err != nil { 98 return err 99 } 100 validator, _, err := validation.NewSchemaValidator(&internal) 101 if err != nil { 102 return err 103 } 104 105 var policyErr error 106 var cnps unstructured.UnstructuredList 107 for { 108 opts := metav1.ListOptions{ 109 Limit: 25, 110 Continue: cnps.GetContinue(), 111 } 112 err = k8s.CiliumClient(). 113 Interface. 114 CiliumV2(). 115 RESTClient(). 116 Get(). 117 VersionedParams(&opts, scheme.ParameterCodec). 118 Resource(name). 119 Do(). 120 Into(&cnps) 121 if err != nil { 122 return err 123 } 124 125 for _, cnp := range cnps.Items { 126 cnpName := fmt.Sprintf("%s/%s", cnp.GetNamespace(), cnp.GetName()) 127 if errs := validation.ValidateCustomResource(nil, &cnp, validator); len(errs) > 0 { 128 log.Errorf("Validating %s '%s': unexpected validation error: %s", 129 shortName, cnpName, errs.ToAggregate()) 130 policyErr = fmt.Errorf("Found invalid %s", shortName) 131 } else { 132 log.Infof("Validating %s '%s': OK!", shortName, cnpName) 133 } 134 } 135 if cnps.GetContinue() == "" { 136 break 137 } 138 } 139 return policyErr 140 }