github.phpd.cn/cilium/cilium@v1.6.12/pkg/k8s/apis/cilium.io/v2/register.go (about) 1 // Copyright 2017 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 v2 16 17 import ( 18 goerrors "errors" 19 "fmt" 20 "time" 21 22 k8sconst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io" 23 "github.com/cilium/cilium/pkg/k8s/version" 24 "github.com/cilium/cilium/pkg/option" 25 26 apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 27 apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 28 "k8s.io/apimachinery/pkg/api/errors" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/runtime" 31 "k8s.io/apimachinery/pkg/runtime/schema" 32 "k8s.io/apimachinery/pkg/util/wait" 33 34 goVersion "github.com/hashicorp/go-version" 35 ) 36 37 const ( 38 // CustomResourceDefinitionGroup is the name of the third party resource group 39 CustomResourceDefinitionGroup = k8sconst.GroupName 40 41 // CustomResourceDefinitionVersion is the current version of the resource 42 CustomResourceDefinitionVersion = "v2" 43 44 // CustomResourceDefinitionSchemaVersion is semver-conformant version of CRD schema 45 // Used to determine if CRD needs to be updated in cluster 46 CustomResourceDefinitionSchemaVersion = "1.15.1" 47 48 // CustomResourceDefinitionSchemaVersionKey is key to label which holds the CRD schema version 49 CustomResourceDefinitionSchemaVersionKey = "io.cilium.k8s.crd.schema.version" 50 51 // CNPKindDefinition is the kind name for Cilium Network Policy 52 CNPKindDefinition = "CiliumNetworkPolicy" 53 54 fqdnNameRegex = `^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\.?$` 55 56 fqdnPatternRegex = `^(([a-zA-Z0-9\*]|[a-zA-Z0-9\*][a-zA-Z0-9\-\*]*[a-zA-Z0-9\*])\.)*([A-Za-z0-9\*]|[A-Za-z0-9\*][A-Za-z0-9\-\*]*[A-Za-z0-9\*])\.?$` 57 ) 58 59 // SchemeGroupVersion is group version used to register these objects 60 var SchemeGroupVersion = schema.GroupVersion{ 61 Group: CustomResourceDefinitionGroup, 62 Version: CustomResourceDefinitionVersion, 63 } 64 65 // Resource takes an unqualified resource and returns a Group qualified GroupResource 66 func Resource(resource string) schema.GroupResource { 67 return SchemeGroupVersion.WithResource(resource).GroupResource() 68 } 69 70 var ( 71 // SchemeBuilder is needed by DeepCopy generator. 72 SchemeBuilder runtime.SchemeBuilder 73 // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. 74 localSchemeBuilder = &SchemeBuilder 75 76 // AddToScheme adds all types of this clientset into the given scheme. 77 // This allows composition of clientsets, like in: 78 // 79 // import ( 80 // "k8s.io/client-go/kubernetes" 81 // clientsetscheme "k8s.io/client-go/kuberentes/scheme" 82 // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 83 // ) 84 // 85 // kclientset, _ := kubernetes.NewForConfig(c) 86 // aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 87 AddToScheme = localSchemeBuilder.AddToScheme 88 89 comparableCRDSchemaVersion *goVersion.Version 90 ) 91 92 func init() { 93 comparableCRDSchemaVersion = goVersion.Must( 94 goVersion.NewVersion(CustomResourceDefinitionSchemaVersion)) 95 96 // We only register manually written functions here. The registration of the 97 // generated functions takes place in the generated files. The separation 98 // makes the code compile even when the generated files are missing. 99 localSchemeBuilder.Register(addKnownTypes) 100 } 101 102 // Adds the list of known types to api.Scheme. 103 func addKnownTypes(scheme *runtime.Scheme) error { 104 scheme.AddKnownTypes(SchemeGroupVersion, 105 &CiliumNetworkPolicy{}, 106 &CiliumNetworkPolicyList{}, 107 &CiliumEndpoint{}, 108 &CiliumEndpointList{}, 109 &CiliumNode{}, 110 &CiliumNodeList{}, 111 &CiliumIdentity{}, 112 &CiliumIdentityList{}, 113 ) 114 115 metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 116 return nil 117 } 118 119 // CreateCustomResourceDefinitions creates our CRD objects in the kubernetes 120 // cluster 121 func CreateCustomResourceDefinitions(clientset apiextensionsclient.Interface) error { 122 if err := createCNPCRD(clientset); err != nil { 123 return err 124 } 125 126 if err := createCEPCRD(clientset); err != nil { 127 return err 128 } 129 130 if err := createNodeCRD(clientset); err != nil { 131 return err 132 } 133 134 if option.Config.IdentityAllocationMode == option.IdentityAllocationModeCRD { 135 if err := createIdentityCRD(clientset); err != nil { 136 return err 137 } 138 } 139 140 return nil 141 } 142 143 // createCNPCRD creates and updates the CiliumNetworkPolicies CRD. It should be called 144 // on agent startup but is idempotent and safe to call again. 145 func createCNPCRD(clientset apiextensionsclient.Interface) error { 146 var ( 147 // CustomResourceDefinitionSingularName is the singular name of custom resource definition 148 CustomResourceDefinitionSingularName = "ciliumnetworkpolicy" 149 150 // CustomResourceDefinitionPluralName is the plural name of custom resource definition 151 CustomResourceDefinitionPluralName = "ciliumnetworkpolicies" 152 153 // CustomResourceDefinitionShortNames are the abbreviated names to refer to this CRD's instances 154 CustomResourceDefinitionShortNames = []string{"cnp", "ciliumnp"} 155 156 // CustomResourceDefinitionKind is the Kind name of custom resource definition 157 CustomResourceDefinitionKind = CNPKindDefinition 158 159 CRDName = CustomResourceDefinitionPluralName + "." + SchemeGroupVersion.Group 160 ) 161 162 res := &apiextensionsv1beta1.CustomResourceDefinition{ 163 ObjectMeta: metav1.ObjectMeta{ 164 Name: CRDName, 165 Labels: map[string]string{ 166 CustomResourceDefinitionSchemaVersionKey: CustomResourceDefinitionSchemaVersion, 167 }, 168 }, 169 Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ 170 Group: SchemeGroupVersion.Group, 171 Version: SchemeGroupVersion.Version, 172 Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ 173 Plural: CustomResourceDefinitionPluralName, 174 Singular: CustomResourceDefinitionSingularName, 175 ShortNames: CustomResourceDefinitionShortNames, 176 Kind: CustomResourceDefinitionKind, 177 }, 178 Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ 179 Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, 180 }, 181 Scope: apiextensionsv1beta1.NamespaceScoped, 182 Validation: &CNPCRV, 183 }, 184 } 185 // Kubernetes < 1.12 does not support having the field Type set in the root 186 // schema so we need to set it to empty if kube-apiserver does not supports 187 // it. 188 if !version.Capabilities().FieldTypeInCRDSchema { 189 res.Spec.Validation.OpenAPIV3Schema.Type = "" 190 } 191 192 return createUpdateCRD(clientset, "CiliumNetworkPolicy/v2", res) 193 } 194 195 // createCEPCRD creates and updates the CiliumEndpoint CRD. It should be called 196 // on agent startup but is idempotent and safe to call again. 197 func createCEPCRD(clientset apiextensionsclient.Interface) error { 198 var ( 199 // CustomResourceDefinitionSingularName is the singular name of custom resource definition 200 CustomResourceDefinitionSingularName = "ciliumendpoint" 201 202 // CustomResourceDefinitionPluralName is the plural name of custom resource definition 203 CustomResourceDefinitionPluralName = "ciliumendpoints" 204 205 // CustomResourceDefinitionShortNames are the abbreviated names to refer to this CRD's instances 206 CustomResourceDefinitionShortNames = []string{"cep", "ciliumep"} 207 208 // CustomResourceDefinitionKind is the Kind name of custom resource definition 209 CustomResourceDefinitionKind = "CiliumEndpoint" 210 211 CRDName = CustomResourceDefinitionPluralName + "." + SchemeGroupVersion.Group 212 ) 213 214 res := &apiextensionsv1beta1.CustomResourceDefinition{ 215 ObjectMeta: metav1.ObjectMeta{ 216 Name: CRDName, 217 }, 218 Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ 219 Group: SchemeGroupVersion.Group, 220 Version: SchemeGroupVersion.Version, 221 Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ 222 Plural: CustomResourceDefinitionPluralName, 223 Singular: CustomResourceDefinitionSingularName, 224 ShortNames: CustomResourceDefinitionShortNames, 225 Kind: CustomResourceDefinitionKind, 226 }, 227 AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{ 228 { 229 Name: "Endpoint ID", 230 Type: "integer", 231 Description: "Cilium endpoint id", 232 JSONPath: ".status.id", 233 }, 234 { 235 Name: "Identity ID", 236 Type: "integer", 237 Description: "Cilium identity id", 238 JSONPath: ".status.identity.id", 239 }, 240 { 241 Name: "Ingress Enforcement", 242 Type: "boolean", 243 Description: "Ingress enforcement in the endpoint", 244 JSONPath: ".status.policy.ingress.enforcing", 245 }, 246 { 247 Name: "Egress Enforcement", 248 Type: "boolean", 249 Description: "Egress enforcement in the endpoint", 250 JSONPath: ".status.policy.egress.enforcing", 251 }, 252 { 253 Name: "Endpoint State", 254 Type: "string", 255 Description: "Endpoint current state", 256 JSONPath: ".status.state", 257 }, 258 { 259 Name: "IPv4", 260 Type: "string", 261 Description: "Endpoint IPv4 address", 262 JSONPath: ".status.networking.addressing[0].ipv4", 263 }, 264 { 265 Name: "IPv6", 266 Type: "string", 267 Description: "Endpoint IPv6 address", 268 JSONPath: ".status.networking.addressing[0].ipv6", 269 }, 270 }, 271 Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ 272 Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, 273 }, 274 Scope: apiextensionsv1beta1.NamespaceScoped, 275 Validation: &cepCRV, 276 }, 277 } 278 279 return createUpdateCRD(clientset, "v2.CiliumEndpoint", res) 280 } 281 282 // createNodeCRD creates and updates the CiliumNode CRD. It should be called on 283 // agent startup but is idempotent and safe to call again. 284 func createNodeCRD(clientset apiextensionsclient.Interface) error { 285 res := &apiextensionsv1beta1.CustomResourceDefinition{ 286 ObjectMeta: metav1.ObjectMeta{ 287 Name: "ciliumnodes." + SchemeGroupVersion.Group, 288 }, 289 Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ 290 Group: SchemeGroupVersion.Group, 291 Version: SchemeGroupVersion.Version, 292 Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ 293 Plural: "ciliumnodes", 294 Singular: "ciliumnode", 295 ShortNames: []string{"cn"}, 296 Kind: "CiliumNode", 297 }, 298 Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ 299 Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, 300 }, 301 Scope: apiextensionsv1beta1.ClusterScoped, 302 }, 303 } 304 305 return createUpdateCRD(clientset, "v2.CiliumNode", res) 306 } 307 308 // createIdentityCRD creates and updates the CiliumIdentity CRD. It should be 309 // called on agent startup but is idempotent and safe to call again. 310 func createIdentityCRD(clientset apiextensionsclient.Interface) error { 311 312 var ( 313 // CustomResourceDefinitionSingularName is the singular name of custom resource definition 314 CustomResourceDefinitionSingularName = "ciliumidentity" 315 316 // CustomResourceDefinitionPluralName is the plural name of custom resource definition 317 CustomResourceDefinitionPluralName = "ciliumidentities" 318 319 // CustomResourceDefinitionShortNames are the abbreviated names to refer to this CRD's instances 320 CustomResourceDefinitionShortNames = []string{"ciliumid"} 321 322 // CustomResourceDefinitionKind is the Kind name of custom resource definition 323 CustomResourceDefinitionKind = "CiliumIdentity" 324 325 CRDName = CustomResourceDefinitionPluralName + "." + SchemeGroupVersion.Group 326 ) 327 328 res := &apiextensionsv1beta1.CustomResourceDefinition{ 329 ObjectMeta: metav1.ObjectMeta{ 330 Name: CRDName, 331 }, 332 Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ 333 Group: SchemeGroupVersion.Group, 334 Version: SchemeGroupVersion.Version, 335 Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ 336 Plural: CustomResourceDefinitionPluralName, 337 Singular: CustomResourceDefinitionSingularName, 338 ShortNames: CustomResourceDefinitionShortNames, 339 Kind: CustomResourceDefinitionKind, 340 }, 341 Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ 342 Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, 343 }, 344 Scope: apiextensionsv1beta1.ClusterScoped, 345 }, 346 } 347 348 return createUpdateCRD(clientset, "v2.CiliumIdentity", res) 349 } 350 351 // createUpdateCRD ensures the CRD object is installed into the k8s cluster. It 352 // will create or update the CRD and it's validation when needed 353 func createUpdateCRD(clientset apiextensionsclient.Interface, CRDName string, crd *apiextensionsv1beta1.CustomResourceDefinition) error { 354 scopedLog := log.WithField("name", CRDName) 355 356 clusterCRD, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.ObjectMeta.Name, metav1.GetOptions{}) 357 if errors.IsNotFound(err) { 358 scopedLog.Info("Creating CRD (CustomResourceDefinition)...") 359 clusterCRD, err = clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd) 360 // This occurs when multiple agents race to create the CRD. Since another has 361 // created it, it will also update it, hence the non-error return. 362 if errors.IsAlreadyExists(err) { 363 return nil 364 } 365 } 366 if err != nil { 367 return err 368 } 369 370 scopedLog.Debug("Checking if CRD (CustomResourceDefinition) needs update...") 371 if needsUpdate(clusterCRD) { 372 scopedLog.Info("Updating CRD (CustomResourceDefinition)...") 373 // Update the CRD with the validation schema. 374 err = wait.Poll(500*time.Millisecond, 60*time.Second, func() (bool, error) { 375 clusterCRD, err = clientset.ApiextensionsV1beta1(). 376 CustomResourceDefinitions().Get(crd.ObjectMeta.Name, metav1.GetOptions{}) 377 378 if err != nil { 379 return false, err 380 } 381 382 // This seems too permissive but we only get here if the version is 383 // different per needsUpdate above. If so, we want to update on any 384 // validation change including adding or removing validation. 385 if needsUpdate(clusterCRD) { 386 scopedLog.Debug("CRD validation is different, updating it...") 387 clusterCRD.ObjectMeta.Labels = crd.ObjectMeta.Labels 388 clusterCRD.Spec = crd.Spec 389 _, err = clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Update(clusterCRD) 390 if err == nil { 391 return true, nil 392 } 393 scopedLog.WithError(err).Debug("Unable to update CRD validation") 394 return false, err 395 } 396 397 return true, nil 398 }) 399 if err != nil { 400 scopedLog.WithError(err).Error("Unable to update CRD") 401 return err 402 } 403 } 404 405 // wait for the CRD to be established 406 scopedLog.Debug("Waiting for CRD (CustomResourceDefinition) to be available...") 407 err = wait.Poll(500*time.Millisecond, 60*time.Second, func() (bool, error) { 408 crd, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.ObjectMeta.Name, metav1.GetOptions{}) 409 if err != nil { 410 return false, err 411 } 412 for _, cond := range crd.Status.Conditions { 413 switch cond.Type { 414 case apiextensionsv1beta1.Established: 415 if cond.Status == apiextensionsv1beta1.ConditionTrue { 416 return true, err 417 } 418 case apiextensionsv1beta1.NamesAccepted: 419 if cond.Status == apiextensionsv1beta1.ConditionFalse { 420 scopedLog.WithError(goerrors.New(cond.Reason)).Error("Name conflict for CRD") 421 return false, err 422 } 423 } 424 } 425 return false, err 426 }) 427 if err != nil { 428 deleteErr := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(crd.ObjectMeta.Name, nil) 429 if deleteErr != nil { 430 return fmt.Errorf("unable to delete k8s %s CRD %s. Deleting CRD due: %s", CRDName, deleteErr, err) 431 } 432 return err 433 } 434 435 scopedLog.Info("CRD (CustomResourceDefinition) is installed and up-to-date") 436 return nil 437 } 438 439 func needsUpdate(clusterCRD *apiextensionsv1beta1.CustomResourceDefinition) bool { 440 441 if clusterCRD.Spec.Validation == nil { 442 // no validation detected 443 return true 444 } 445 v, ok := clusterCRD.Labels[CustomResourceDefinitionSchemaVersionKey] 446 if !ok { 447 // no schema version detected 448 return true 449 } 450 clusterVersion, err := goVersion.NewVersion(v) 451 if err != nil || clusterVersion.LessThan(comparableCRDSchemaVersion) { 452 // version in cluster is either unparsable or smaller than current version 453 return true 454 } 455 return false 456 } 457 458 func getStr(str string) *string { 459 return &str 460 } 461 462 func getInt64(i int64) *int64 { 463 return &i 464 } 465 466 var ( 467 // cepCRV is a minimal validation for CEP objects. Since only the agent is 468 // creating them, it is better to be permissive and have some data, if buggy, 469 // than to have no data in k8s. 470 cepCRV = apiextensionsv1beta1.CustomResourceValidation{ 471 OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{}, 472 } 473 474 CNPCRV = apiextensionsv1beta1.CustomResourceValidation{ 475 OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{ 476 // TODO: remove the following comment when we add checker 477 // to detect if we should install the CNP validation for k8s > 1.11 478 // with this line uncommented. 479 Type: "object", 480 Properties: properties, 481 }, 482 } 483 484 properties = map[string]apiextensionsv1beta1.JSONSchemaProps{ 485 "CIDR": CIDR, 486 "CIDRRule": CIDRRule, 487 "EgressRule": EgressRule, 488 "EndpointSelector": EndpointSelector, 489 "IngressRule": IngressRule, 490 "K8sServiceNamespace": K8sServiceNamespace, 491 "L7Rules": L7Rules, 492 "Label": Label, 493 "LabelSelector": LabelSelector, 494 "LabelSelectorRequirement": LabelSelectorRequirement, 495 "PortProtocol": PortProtocol, 496 "PortRule": PortRule, 497 "PortRuleHTTP": PortRuleHTTP, 498 "PortRuleKafka": PortRuleKafka, 499 "PortRuleL7": PortRuleL7, 500 "Rule": Rule, 501 "Service": Service, 502 "ServiceSelector": ServiceSelector, 503 "spec": spec, 504 "specs": specs, 505 } 506 507 CIDR = apiextensionsv1beta1.JSONSchemaProps{ 508 Description: "CIDR is a CIDR prefix / IP Block.", 509 Type: "string", 510 OneOf: []apiextensionsv1beta1.JSONSchemaProps{ 511 { 512 // IPv4 CIDR 513 Pattern: `^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4]` + 514 `[0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$`, 515 }, 516 { 517 // IPv6 CIDR 518 Pattern: `^s*((([0-9A-Fa-f]{1,4}:){7}(:|([0-9A-Fa-f]{1,4})))` + 519 `|(([0-9A-Fa-f]{1,4}:){6}:([0-9A-Fa-f]{1,4})?)` + 520 `|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){0,1}):([0-9A-Fa-f]{1,4})?))` + 521 `|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){0,2}):([0-9A-Fa-f]{1,4})?))` + 522 `|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){0,3}):([0-9A-Fa-f]{1,4})?))` + 523 `|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){0,4}):([0-9A-Fa-f]{1,4})?))` + 524 `|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){0,5}):([0-9A-Fa-f]{1,4})?))` + 525 `|(:(:|((:[0-9A-Fa-f]{1,4}){1,7}))))` + 526 `(%.+)?s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$`, 527 }, 528 }, 529 } 530 531 CIDRRule = apiextensionsv1beta1.JSONSchemaProps{ 532 Type: "object", 533 Description: "CIDRRule is a rule that specifies a CIDR prefix to/from which outside " + 534 "communication is allowed, along with an optional list of subnets within that CIDR " + 535 "prefix to/from which outside communication is not allowed.", 536 Required: []string{ 537 "cidr", 538 }, 539 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 540 "cidr": CIDR, 541 "except": { 542 Description: "ExceptCIDRs is a list of IP blocks which the endpoint subject to " + 543 "the rule is not allowed to initiate connections to. These CIDR prefixes " + 544 "should be contained within Cidr. These exceptions are only applied to the " + 545 "Cidr in this CIDRRule, and do not apply to any other CIDR prefixes in any " + 546 "other CIDRRules.", 547 Type: "array", 548 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 549 Schema: &CIDR, 550 }, 551 }, 552 }, 553 } 554 555 EgressRule = apiextensionsv1beta1.JSONSchemaProps{ 556 Type: "object", 557 Description: "EgressRule contains all rule types which can be applied at egress, i.e. " + 558 "network traffic that originates inside the endpoint and exits the endpoint " + 559 "selected by the endpointSelector.\n\n- All members of this structure are optional. " + 560 "If omitted or empty, the\n member will have no effect on the rule.\n\n- For now, " + 561 "combining ToPorts and ToCIDR in the same rule is not supported\n and such rules " + 562 "will be rejected. In the future, this will be supported and\n if if multiple " + 563 "members of the structure are specified, then all members\n must match in order " + 564 "for the rule to take effect.", 565 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 566 "toCIDR": { 567 Description: "ToCIDR is a list of IP blocks which the endpoint subject to the " + 568 "rule is allowed to initiate connections. This will match on the " + 569 "destination IP address of outgoing connections. Adding a prefix into " + 570 "ToCIDR or into ToCIDRSet with no ExcludeCIDRs is equivalent. Overlaps are " + 571 "allowed between ToCIDR and ToCIDRSet.\n\nExample: Any endpoint with the " + 572 "label \"app=database-proxy\" is allowed to initiate connections to " + 573 "10.2.3.0/24", 574 Type: "array", 575 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 576 Schema: &CIDR, 577 }, 578 }, 579 "toCIDRSet": { 580 Description: "ToCIDRSet is a list of IP blocks which the endpoint subject to " + 581 "the rule is allowed to initiate connections to in addition to connections " + 582 "which are allowed via FromEndpoints, along with a list of subnets " + 583 "contained within their corresponding IP block to which traffic should not " + 584 "be allowed. This will match on the destination IP address of outgoing " + 585 "connections. Adding a prefix into ToCIDR or into ToCIDRSet with no " + 586 "ExcludeCIDRs is equivalent. Overlaps are allowed between ToCIDR and " + 587 "ToCIDRSet.\n\nExample: Any endpoint with the label \"app=database-proxy\" " + 588 "is allowed to initiate connections to 10.2.3.0/24 except from IPs in " + 589 "subnet 10.2.3.0/28.", 590 Type: "array", 591 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 592 Schema: &CIDRRule, 593 }, 594 }, 595 "toEntities": { 596 Description: "ToEntities is a list of special entities to which the endpoint " + 597 "subject to the rule is allowed to initiate connections. Supported " + 598 "entities are `world`, `cluster` and `host`", 599 Type: "array", 600 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 601 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 602 Type: "string", 603 }, 604 }, 605 }, 606 "toPorts": { 607 Description: "ToPorts is a list of destination ports identified by port number " + 608 "and protocol which the endpoint subject to the rule is allowed to connect " + 609 "to.\n\nExample: Any endpoint with the label \"role=frontend\" is allowed " + 610 "to initiate connections to destination port 8080/tcp", 611 Type: "array", 612 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 613 Schema: &PortRule, 614 }, 615 }, 616 "toServices": { 617 Description: "ToServices is a list of services to which the endpoint subject " + 618 "to the rule is allowed to initiate connections.\n\nExample: Any endpoint " + 619 "with the label \"app=backend-app\" is allowed to initiate connections to " + 620 "all cidrs backing the \"external-service\" service", 621 Type: "array", 622 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 623 Schema: &Service, 624 }, 625 }, 626 "toEndpoints": { 627 Description: "ToEndpoints is a list of endpoints identified by an " + 628 "EndpointSelector to which the endpoint subject to the rule" + 629 "is allowed to communicate.\n\nExample: Any endpoint with the label " + 630 "\"role=frontend\" can be consumed by any endpoint carrying the label " + 631 "\"role=backend\".", 632 Type: "array", 633 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 634 Schema: &EndpointSelector, 635 }, 636 }, 637 "toRequires": { 638 Description: "ToRequires is a list of additional constraints which must be " + 639 "met in order for the selected endpoints to be able to reach other " + 640 "endpoints. These additional constraints do not by themselves grant access " + 641 "privileges and must always be accompanied with at least one matching " + 642 "FromEndpoints.\n\nExample: Any Endpoint with the label \"team=A\" " + 643 "requires any endpoint to which it communicates to also carry the label " + 644 "\"team=A\".", 645 Type: "array", 646 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 647 Schema: &EndpointSelector, 648 }, 649 }, 650 "toGroups": { 651 Type: "array", 652 Description: `ToGroups is a list of constraints that will 653 gather data from third-party providers and create a new 654 derived policy.`, 655 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 656 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 657 Type: "object", 658 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 659 "aws": AWSGroup, 660 }, 661 }, 662 }, 663 }, 664 "toFQDNs": { 665 Description: `ToFQDNs is a list of rules matching fqdns that endpoint 666 is allowed to communicate with`, 667 Type: "array", 668 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 669 Schema: &FQDNRule, 670 }, 671 }, 672 }, 673 } 674 675 FQDNRule = apiextensionsv1beta1.JSONSchemaProps{ 676 Type: "object", 677 Description: `FQDNRule is a rule that specifies an fully qualified domain name to which outside communication is allowed`, 678 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 679 "matchName": MatchFQDNName, 680 "matchPattern": MatchFQDNPattern, 681 }, 682 } 683 684 MatchFQDNName = apiextensionsv1beta1.JSONSchemaProps{ 685 Description: `MatchName matches fqdn name`, 686 Type: "string", 687 Pattern: fqdnNameRegex, 688 } 689 690 MatchFQDNPattern = apiextensionsv1beta1.JSONSchemaProps{ 691 Description: `MatchPattern matches fqdn by pattern`, 692 Type: "string", 693 Pattern: fqdnPatternRegex, 694 } 695 696 AWSGroup = apiextensionsv1beta1.JSONSchemaProps{ 697 Type: "object", 698 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 699 "securityGroupsIds": { 700 Description: `SecurityGroupsIds is the list of AWS security 701 group IDs that will filter the instances IPs from the AWS API`, 702 Type: "array", 703 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 704 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 705 Type: "string", 706 }, 707 }, 708 }, 709 "securityGroupsNames": { 710 Description: `SecurityGroupsNames is the list of AWS security 711 group names that will filter the instances IPs from the AWS API`, 712 Type: "array", 713 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 714 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 715 Type: "string", 716 }, 717 }, 718 }, 719 "region": { 720 Description: `Region is the key that will filter the AWS EC2 721 instances in the given region`, 722 Type: "string", 723 }, 724 }, 725 } 726 EndpointSelector = initEndpointSelector() 727 728 IngressRule = apiextensionsv1beta1.JSONSchemaProps{ 729 Type: "object", 730 Description: "IngressRule contains all rule types which can be applied at ingress, " + 731 "i.e. network traffic that originates outside of the endpoint and is entering " + 732 "the endpoint selected by the endpointSelector.\n\n- All members of this structure " + 733 "are optional. If omitted or empty, the\n member will have no effect on the rule." + 734 "\n\n- If multiple members are set, all of them need to match in order for\n " + 735 "the rule to take effect. The exception to this rule is FromRequires field;\n " + 736 "the effects of any Requires field in any rule will apply to all other\n rules " + 737 "as well.\n\n- For now, combining ToPorts, FromCIDR, and FromEndpoints in the same " + 738 "rule\n is not supported and any such rules will be rejected. In the future, " + 739 "this\n will be supported and if multiple members of this structure are specified," + 740 "\n then all members must match in order for the rule to take effect. The\n " + 741 "exception to this rule is the Requires field, the effects of any Requires\n " + 742 "field in any rule will apply to all other rules as well.", 743 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 744 "fromCIDR": { 745 Description: "FromCIDR is a list of IP blocks which the endpoint subject to " + 746 "the rule is allowed to receive connections from. This will match on the " + 747 "source IP address of incoming connections. Adding a prefix into FromCIDR " + 748 "or into FromCIDRSet with no ExcludeCIDRs is equivalent. Overlaps are " + 749 "allowed between FromCIDR and FromCIDRSet.\n\nExample: Any endpoint with " + 750 "the label \"app=my-legacy-pet\" is allowed to receive connections from " + 751 "10.3.9.1", 752 Type: "array", 753 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 754 Schema: &CIDR, 755 }, 756 }, 757 "fromCIDRSet": { 758 Description: "FromCIDRSet is a list of IP blocks which the endpoint subject to " + 759 "the rule is allowed to receive connections from in addition to " + 760 "FromEndpoints, along with a list of subnets contained within their " + 761 "corresponding IP block from which traffic should not be allowed. This " + 762 "will match on the source IP address of incoming connections. Adding a " + 763 "prefix into FromCIDR or into FromCIDRSet with no ExcludeCIDRs is " + 764 "equivalent. Overlaps are allowed between FromCIDR and FromCIDRSet." + 765 "\n\nExample: Any endpoint with the label \"app=my-legacy-pet\" is allowed " + 766 "to receive connections from 10.0.0.0/8 except from IPs in subnet " + 767 "10.96.0.0/12.", 768 Type: "array", 769 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 770 Schema: &CIDRRule, 771 }, 772 }, 773 "fromEndpoints": { 774 Description: "FromEndpoints is a list of endpoints identified by an " + 775 "EndpointSelector which are allowed to communicate with the endpoint " + 776 "subject to the rule.\n\nExample: Any endpoint with the label " + 777 "\"role=backend\" can be consumed by any endpoint carrying the label " + 778 "\"role=frontend\".", 779 Type: "array", 780 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 781 Schema: &EndpointSelector, 782 }, 783 }, 784 "fromEntities": { 785 Description: "FromEntities is a list of special entities which the endpoint " + 786 "subject to the rule is allowed to receive connections from. Supported " + 787 "entities are `world`, `cluster`, `host`, and `init`", 788 Type: "array", 789 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 790 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 791 Type: "string", 792 }, 793 }, 794 }, 795 "fromRequires": { 796 Description: "FromRequires is a list of additional constraints which must be " + 797 "met in order for the selected endpoints to be reachable. These additional " + 798 "constraints do no by itself grant access privileges and must always be " + 799 "accompanied with at least one matching FromEndpoints.\n\nExample: Any " + 800 "Endpoint with the label \"team=A\" requires consuming endpoint to also " + 801 "carry the label \"team=A\".", 802 Type: "array", 803 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 804 Schema: &EndpointSelector, 805 }, 806 }, 807 "toPorts": { 808 Description: "ToPorts is a list of destination ports identified by port number " + 809 "and protocol which the endpoint subject to the rule is allowed to receive " + 810 "connections on.\n\nExample: Any endpoint with the label \"app=httpd\" can " + 811 "only accept incoming connections on port 80/tcp.", 812 Type: "array", 813 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 814 Schema: &PortRule, 815 }, 816 }, 817 }, 818 } 819 820 K8sServiceNamespace = apiextensionsv1beta1.JSONSchemaProps{ 821 Type: "object", 822 Description: "K8sServiceNamespace is an abstraction for the k8s service + namespace " + 823 "types.", 824 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 825 "namespace": { 826 Type: "string", 827 }, 828 "serviceName": { 829 Type: "string", 830 }, 831 }, 832 } 833 834 L7Rules = apiextensionsv1beta1.JSONSchemaProps{ 835 Type: "object", 836 Description: "L7Rules is a union of port level rule types. Mixing of different port " + 837 "level rule types is disallowed, so exactly one of the following must be set. If " + 838 "none are specified, then no additional port level rules are applied.", 839 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 840 "http": { 841 Description: "HTTP specific rules.", 842 Type: "array", 843 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 844 Schema: &PortRuleHTTP, 845 }, 846 }, 847 "kafka": { 848 Description: "Kafka-specific rules.", 849 Type: "array", 850 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 851 Schema: &PortRuleKafka, 852 }, 853 }, 854 "l7proto": { 855 Description: "Parser type name that uses Key-Value pair rules.", 856 Type: "string", 857 }, 858 "l7": { 859 Description: "Generic Key-Value pair rules.", 860 Type: "array", 861 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 862 Schema: &PortRuleL7, 863 }, 864 }, 865 "dns": { 866 Description: "DNS specific rules", 867 Type: "array", 868 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 869 Schema: &PortRuleDNS, 870 }, 871 }, 872 }, 873 } 874 875 PortRuleDNS = apiextensionsv1beta1.JSONSchemaProps{ 876 Type: "object", 877 Description: `FQDNRule is a rule that specifies an fully qualified domain name to which outside communication is allowed`, 878 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 879 "matchName": MatchFQDNName, 880 "matchPattern": MatchFQDNPattern, 881 }, 882 } 883 884 Label = apiextensionsv1beta1.JSONSchemaProps{ 885 Type: "object", 886 Description: "Label is the cilium's representation of a container label.", 887 Required: []string{ 888 "key", 889 }, 890 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 891 "key": { 892 Type: "string", 893 }, 894 "source": { 895 Description: "Source can be one of the values present in const.go " + 896 "(e.g.: LabelSourceContainer)", 897 Type: "string", 898 }, 899 "value": { 900 Type: "string", 901 }, 902 }, 903 } 904 905 LabelSelector = apiextensionsv1beta1.JSONSchemaProps{ 906 Type: "object", 907 Description: "A label selector is a label query over a set of resources. The result " + 908 "of matchLabels and matchExpressions are ANDed. An empty label selector matches " + 909 "all objects. A null label selector matches no objects.", 910 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 911 "matchLabels": { 912 Description: "matchLabels is a map of {key,value} pairs. A single {key,value} " + 913 "in the matchLabels map is equivalent to an element of matchExpressions, " + 914 "whose key field is \"key\", the operator is \"In\", and the values array " + 915 "contains only \"value\". The requirements are ANDed.", 916 Type: "object", 917 }, 918 "matchExpressions": { 919 Description: "matchExpressions is a list of label selector requirements. " + 920 "The requirements are ANDed.", 921 Type: "array", 922 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 923 Schema: &LabelSelectorRequirement, 924 }, 925 }, 926 }, 927 } 928 929 LabelSelectorRequirement = apiextensionsv1beta1.JSONSchemaProps{ 930 Type: "object", 931 Description: "A label selector requirement is a selector that contains values, a key, " + 932 "and an operator that relates the key and values.", 933 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 934 "key": { 935 Description: "key is the label key that the selector applies to.", 936 Type: "string", 937 }, 938 "operator": { 939 Description: "operator represents a key's relationship to a set of values. " + 940 "Valid operators are In, NotIn, Exists and DoesNotExist.", 941 Type: "string", 942 Enum: []apiextensionsv1beta1.JSON{ 943 { 944 Raw: []byte(`"In"`), 945 }, 946 { 947 Raw: []byte(`"NotIn"`), 948 }, 949 { 950 Raw: []byte(`"Exists"`), 951 }, 952 { 953 Raw: []byte(`"DoesNotExist"`), 954 }, 955 }, 956 }, 957 "values": { 958 Description: "values is an array of string values. If the operator is In or " + 959 "NotIn, the values array must be non-empty. If the operator is Exists or " + 960 "DoesNotExist, the values array must be empty. This array is replaced " + 961 "during a strategic merge patch.", 962 Type: "array", 963 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 964 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 965 Type: "string", 966 }, 967 }, 968 }, 969 }, 970 Required: []string{"key", "operator"}, 971 } 972 973 PortProtocol = apiextensionsv1beta1.JSONSchemaProps{ 974 Type: "object", 975 Description: "PortProtocol specifies an L4 port with an optional transport protocol", 976 Required: []string{ 977 "port", 978 }, 979 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 980 "port": { 981 Description: "Port is an L4 port number. For now the string will be strictly " + 982 "parsed as a single uint16. In the future, this field may support ranges " + 983 "in the form \"1024-2048", 984 Type: "string", 985 // uint16 string regex 986 Pattern: `^(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|` + 987 `[1-5][0-9]{4}|[0-9]{1,4})$`, 988 }, 989 "protocol": { 990 Description: `Protocol is the L4 protocol. If omitted or empty, any protocol ` + 991 `matches. Accepted values: "TCP", "UDP", ""/"ANY"\n\nMatching on ` + 992 `ICMP is not supported.`, 993 Type: "string", 994 Enum: []apiextensionsv1beta1.JSON{ 995 { 996 Raw: []byte(`"TCP"`), 997 }, 998 { 999 Raw: []byte(`"UDP"`), 1000 }, 1001 { 1002 Raw: []byte(`"ANY"`), 1003 }, 1004 }, 1005 }, 1006 }, 1007 } 1008 1009 PortRule = apiextensionsv1beta1.JSONSchemaProps{ 1010 Type: "object", 1011 Description: "PortRule is a list of ports/protocol combinations with optional Layer 7 " + 1012 "rules which must be met.", 1013 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1014 "ports": { 1015 Description: "Ports is a list of L4 port/protocol\n\nIf omitted or empty but " + 1016 "RedirectPort is set, then all ports of the endpoint subject to either the " + 1017 "ingress or egress rule are being redirected.", 1018 Type: "array", 1019 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1020 Schema: &PortProtocol, 1021 }, 1022 }, 1023 "redirectPort": { 1024 Description: "RedirectPort is the L4 port which, if set, all traffic matching " + 1025 "the Ports is being redirected to. Whatever listener behind that port " + 1026 "becomes responsible to enforce the port rules and is also responsible to " + 1027 "reinject all traffic back and ensure it reaches its original destination.", 1028 Type: "integer", 1029 Format: "uint16", 1030 }, 1031 "rules": initPortRule(), 1032 }, 1033 } 1034 1035 PortRuleHTTP = apiextensionsv1beta1.JSONSchemaProps{ 1036 Type: "object", 1037 Description: "PortRuleHTTP is a list of HTTP protocol constraints. All fields are " + 1038 "optional, if all fields are empty or missing, the rule does not have any effect." + 1039 "\n\nAll fields of this type are extended POSIX regex as defined by " + 1040 "IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) " + 1041 "matched against the path of an incoming request. Currently it can contain " + 1042 "characters disallowed from the conventional \"path\" part of a URL as defined by " + 1043 "RFC 3986.", 1044 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1045 "headers": { 1046 Description: "Headers is a list of HTTP headers which must be present in the " + 1047 "request. If omitted or empty, requests are allowed regardless of headers " + 1048 "present.", 1049 Type: "array", 1050 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1051 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 1052 Type: "string", 1053 }, 1054 }, 1055 }, 1056 "host": { 1057 Description: "Host is an extended POSIX regex matched against the host header " + 1058 "of a request, e.g. \"foo.com\"\n\nIf omitted or empty, the value of the " + 1059 "host header is ignored.", 1060 Type: "string", 1061 Format: "idn-hostname", 1062 }, 1063 "method": { 1064 Description: "Method is an extended POSIX regex matched against the method of " + 1065 "a request, e.g. \"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", ...\n\n" + 1066 "If omitted or empty, all methods are allowed.", 1067 Type: "string", 1068 }, 1069 "path": { 1070 Description: "Path is an extended POSIX regex matched against the path of a " + 1071 "request. Currently it can contain characters disallowed from the " + 1072 "conventional \"path\" part of a URL as defined by RFC 3986.\n\n" + 1073 "If omitted or empty, all paths are all allowed.", 1074 Type: "string", 1075 }, 1076 }, 1077 } 1078 1079 PortRuleKafka = apiextensionsv1beta1.JSONSchemaProps{ 1080 Type: "object", 1081 Description: "PortRuleKafka is a list of Kafka protocol constraints. All fields are " + 1082 "optional, if all fields are empty or missing, the rule will match all Kafka " + 1083 "messages.", 1084 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1085 "role": { 1086 Description: "Role is a case-insensitive string and describes a group of API keys" + 1087 "necessary to perform certain higher level Kafka operations such as" + 1088 "\"produce\" or \"consume\". An APIGroup automatically expands into all APIKeys" + 1089 "required to perform the specified higher level operation." + 1090 "The following values are supported:" + 1091 "- \"produce\": Allow producing to the topics specified in the rule" + 1092 "- \"consume\": Allow consuming from the topics specified in the rule" + 1093 "This field is incompatible with the APIKey field, either APIKey or Role" + 1094 "may be specified. If omitted or empty, the field has no effect and the " + 1095 "logic of the APIKey field applies.", 1096 Type: "string", 1097 Enum: []apiextensionsv1beta1.JSON{ 1098 { 1099 Raw: []byte(`"produce"`), 1100 }, 1101 { 1102 Raw: []byte(`"consume"`), 1103 }, 1104 }, 1105 }, 1106 "apiKey": { 1107 Description: "APIKey is a case-insensitive string matched against the key of " + 1108 "a request, e.g. \"produce\", \"fetch\", \"createtopic\", \"deletetopic\", " + 1109 "et al Reference: https://kafka.apache.org/protocol#protocol_api_keys\n\n" + 1110 "If omitted or empty, all keys are allowed.", 1111 Type: "string", 1112 }, 1113 "apiVersion": { 1114 Description: "APIVersion is the version matched against the api version of the " + 1115 "Kafka message. If set, it has to be a string representing a positive " + 1116 "integer.\n\nIf omitted or empty, all versions are allowed.", 1117 Type: "string", 1118 }, 1119 "clientID": { 1120 Description: "ClientID is the client identifier as provided in the request.\n\n" + 1121 "From Kafka protocol documentation: This is a user supplied identifier for " + 1122 "the client application. The user can use any identifier they like and it " + 1123 "will be used when logging errors, monitoring aggregates, etc. For " + 1124 "example, one might want to monitor not just the requests per second " + 1125 "overall, but the number coming from each client application (each of " + 1126 "which could reside on multiple servers). This id acts as a logical " + 1127 "grouping across all requests from a particular client.\n\nIf omitted or " + 1128 "empty, all client identifiers are allowed.", 1129 Type: "string", 1130 }, 1131 "topic": { 1132 Description: "Topic is the topic name contained in the message. If a Kafka " + 1133 "request contains multiple topics, then all topics must be allowed or the " + 1134 "message will be rejected.\n\nThis constraint is ignored if the matched " + 1135 "request message type doesn't contain any topic. Maximum size of Topic can " + 1136 "be 249 characters as per recent Kafka spec and allowed characters are " + 1137 "a-z, A-Z, 0-9, -, . and _ Older Kafka versions had longer topic lengths " + 1138 "of 255, but in Kafka 0.10 version the length was changed from 255 to 249. " + 1139 "For compatibility reasons we are using 255\n\nIf omitted or empty, all " + 1140 "topics are allowed.", 1141 Type: "string", 1142 MaxLength: getInt64(255), 1143 }, 1144 }, 1145 } 1146 1147 PortRuleL7 = apiextensionsv1beta1.JSONSchemaProps{ 1148 Type: "object", 1149 Description: "PortRuleL7 is a map of {key,value} pairs which is passed to the " + 1150 "parser referenced in l7proto. It is up to the parser to define what to " + 1151 "do with the map data. If omitted or empty, all requests are allowed. " + 1152 "Both keys and values must be strings.", 1153 // 1154 // AdditionalProperties is supported by k8s 1.11 and later only 1155 // Without it non-string value types are accepted which may cause policy translation 1156 // in cilium-agent to fail. 1157 // 1158 // Keep this here so that we can re-introduce this when th minimum suppoerted k8s version 1159 // is 1.11. 1160 // 1161 //AdditionalProperties: &apiextensionsv1beta1.JSONSchemaPropsOrBool{ 1162 // Schema: &apiextensionsv1beta1.JSONSchemaProps{ 1163 // Type: "string", 1164 // }, 1165 //}, 1166 } 1167 1168 Rule = apiextensionsv1beta1.JSONSchemaProps{ 1169 Type: "object", 1170 Description: "Rule is a policy rule which must be applied to all endpoints which match " + 1171 "the labels contained in the endpointSelector\n\nEach rule is split into an " + 1172 "ingress section which contains all rules applicable at ingress, and an egress " + 1173 "section applicable at egress. For rule types such as `L4Rule` and `CIDR` which " + 1174 "can be applied at both ingress and egress, both ingress and egress side have to " + 1175 "either specifically allow the connection or one side has to be omitted.\n\n" + 1176 "Either ingress, egress, or both can be provided. If both ingress and egress are " + 1177 "omitted, the rule has no effect.", 1178 Required: []string{ 1179 "endpointSelector", 1180 }, 1181 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1182 "Description": { 1183 Description: "Description is a free form string, it can be used by the creator " + 1184 "of the rule to store human readable explanation of the purpose of this " + 1185 "rule. Rules cannot be identified by comment.", 1186 Type: "string", 1187 }, 1188 "egress": { 1189 Description: "Egress is a list of EgressRule which are enforced at egress. If " + 1190 "omitted or empty, this rule does not apply at egress.", 1191 Type: "array", 1192 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1193 Schema: &EgressRule, 1194 }, 1195 }, 1196 "endpointSelector": initRuleEndpointSelector(), 1197 "ingress": { 1198 Description: "Ingress is a list of IngressRule which are enforced at ingress. " + 1199 "If omitted or empty, this rule does not apply at ingress.", 1200 Type: "array", 1201 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1202 Schema: &IngressRule, 1203 }, 1204 }, 1205 "labels": { 1206 Description: "Labels is a list of optional strings which can be used to " + 1207 "re-identify the rule or to store metadata. It is possible to lookup or " + 1208 "delete strings based on labels. Labels are not required to be unique, " + 1209 "multiple rules can have overlapping or identical labels.", 1210 Type: "array", 1211 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1212 Schema: &Label, 1213 }, 1214 }, 1215 }, 1216 } 1217 1218 Service = apiextensionsv1beta1.JSONSchemaProps{ 1219 Type: "object", 1220 Description: "Service wraps around selectors for services", 1221 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1222 "k8sService": K8sServiceNamespace, 1223 "k8sServiceSelector": initK8sServiceSelector(), 1224 }, 1225 } 1226 1227 ServiceSelector = apiextensionsv1beta1.JSONSchemaProps{ 1228 Type: "object", 1229 Description: "ServiceSelector is a label selector for k8s services", 1230 Required: []string{ 1231 "selector", 1232 }, 1233 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1234 "selector": EndpointSelector, 1235 "namespace": { 1236 Type: "string", 1237 }, 1238 }, 1239 } 1240 1241 spec = initSpec() 1242 1243 specs = apiextensionsv1beta1.JSONSchemaProps{ 1244 Description: "Specs is a list of desired Cilium specific rule specification.", 1245 Type: "array", 1246 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1247 Schema: &spec, 1248 }, 1249 } 1250 ) 1251 1252 func initEndpointSelector() apiextensionsv1beta1.JSONSchemaProps { 1253 es := LabelSelector.DeepCopy() 1254 es.Description = "EndpointSelector is a wrapper for k8s LabelSelector." 1255 return *es 1256 } 1257 1258 func initPortRule() apiextensionsv1beta1.JSONSchemaProps { 1259 portRuleProps := L7Rules.DeepCopy() 1260 portRuleProps.Description = "Rules is a list of additional port level rules which must be " + 1261 "met in order for the PortRule to allow the traffic. If omitted or empty, " + 1262 "no layer 7 rules are enforced." 1263 return *portRuleProps 1264 } 1265 1266 func initRuleEndpointSelector() apiextensionsv1beta1.JSONSchemaProps { 1267 ruleProps := EndpointSelector.DeepCopy() 1268 ruleProps.Description = "EndpointSelector selects all endpoints which should be subject " + 1269 "to this rule. Cannot be empty if nodeSelector is empty." 1270 return *ruleProps 1271 } 1272 1273 func initK8sServiceSelector() apiextensionsv1beta1.JSONSchemaProps { 1274 serviceProps := ServiceSelector.DeepCopy() 1275 serviceProps.Description = "K8sServiceSelector selects services by k8s labels. " + 1276 "Not supported yet" 1277 return *serviceProps 1278 } 1279 1280 func initSpec() apiextensionsv1beta1.JSONSchemaProps { 1281 spec := Rule.DeepCopy() 1282 spec.Description = "Spec is the desired Cilium specific rule specification." 1283 spec.Type = "object" 1284 return *spec 1285 }