github.com/fafucoder/cilium@v1.6.11/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 "fmt" 19 "os" 20 21 "github.com/cilium/cilium/pkg/k8s" 22 v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 23 "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned/scheme" 24 "github.com/cilium/cilium/pkg/logging" 25 "github.com/cilium/cilium/pkg/option" 26 27 "github.com/spf13/cobra" 28 "github.com/spf13/viper" 29 apiextensionsinternal "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" 30 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 31 "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" 32 apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 33 k8sErrors "k8s.io/apimachinery/pkg/api/errors" 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 ( 55 ciliumGroup = "cilium.io" 56 ) 57 58 func validateCNPs() error { 59 // The internal packages log things. Make sure they follow the setup of of 60 // the CLI tool. 61 logging.DefaultLogger.SetFormatter(log.Formatter) 62 63 log.Info("Setting up Kubernetes client") 64 65 k8sClientQPSLimit := viper.GetFloat64(option.K8sClientQPSLimit) 66 k8sClientBurst := viper.GetInt(option.K8sClientBurst) 67 68 k8s.Configure(k8sAPIServer, k8sKubeConfigPath, float32(k8sClientQPSLimit), k8sClientBurst) 69 70 if err := k8s.Init(); err != nil { 71 log.WithError(err).Fatal("Unable to connect to Kubernetes apiserver") 72 } 73 74 restConfig, err := k8s.CreateConfig() 75 if err != nil { 76 return fmt.Errorf("Unable to create rest configuration for k8s CRD: %s", err) 77 } 78 apiExtensionsClient, err := apiextensionsclient.NewForConfig(restConfig) 79 if err != nil { 80 return fmt.Errorf("Unable to create API extensions clientset for k8s CRD: %s", err) 81 } 82 83 cnpErr := validateNPResources(apiExtensionsClient, &v2.CNPCRV, "ciliumnetworkpolicies", "CiliumNetworkPolicy") 84 85 if cnpErr != nil { 86 return cnpErr 87 } 88 log.Info("All CNPs valid!") 89 return nil 90 } 91 92 func validateNPResources(apiExtensionsClient apiextensionsclient.Interface, crv *v1beta1.CustomResourceValidation, name, shortName string) error { 93 // check if the crd is installed at all 94 _, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(name+"."+ciliumGroup, metav1.GetOptions{}) 95 switch { 96 case err == nil: 97 case k8sErrors.IsNotFound(err): 98 return nil 99 default: 100 return err 101 } 102 103 var internal apiextensionsinternal.CustomResourceValidation 104 err = v1beta1.Convert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation( 105 crv, 106 &internal, 107 nil, 108 ) 109 if err != nil { 110 return err 111 } 112 validator, _, err := validation.NewSchemaValidator(&internal) 113 if err != nil { 114 return err 115 } 116 117 var ( 118 policyErr error 119 cnps unstructured.UnstructuredList 120 ) 121 for { 122 opts := metav1.ListOptions{ 123 Limit: 25, 124 Continue: cnps.GetContinue(), 125 } 126 err = k8s.CiliumClient(). 127 Interface. 128 CiliumV2(). 129 RESTClient(). 130 Get(). 131 VersionedParams(&opts, scheme.ParameterCodec). 132 Resource(name). 133 Do(). 134 Into(&cnps) 135 if err != nil { 136 return err 137 } 138 139 for _, cnp := range cnps.Items { 140 cnpName := fmt.Sprintf("%s/%s", cnp.GetNamespace(), cnp.GetName()) 141 if errs := validation.ValidateCustomResource(nil, &cnp, validator); len(errs) > 0 { 142 log.Errorf("Validating %s '%s': unexpected validation error: %s", 143 shortName, cnpName, errs.ToAggregate()) 144 policyErr = fmt.Errorf("Found invalid %s", shortName) 145 } else { 146 log.Infof("Validating %s '%s': OK!", shortName, cnpName) 147 } 148 } 149 if cnps.GetContinue() == "" { 150 break 151 } 152 } 153 return policyErr 154 }