github.com/imran-kn/cilium-fork@v1.6.9/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" 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: "object", 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 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 656 "aws": AWSGroup, 657 }, 658 }, 659 "toFQDNs": { 660 Description: `ToFQDNs is a list of rules matching fqdns that endpoint 661 is allowed to communicate with`, 662 Type: "array", 663 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 664 Schema: &FQDNRule, 665 }, 666 }, 667 }, 668 } 669 670 FQDNRule = apiextensionsv1beta1.JSONSchemaProps{ 671 Type: "object", 672 Description: `FQDNRule is a rule that specifies an fully qualified domain name to which outside communication is allowed`, 673 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 674 "matchName": MatchFQDNName, 675 "matchPattern": MatchFQDNPattern, 676 }, 677 } 678 679 MatchFQDNName = apiextensionsv1beta1.JSONSchemaProps{ 680 Description: `MatchName matches fqdn name`, 681 Type: "string", 682 Pattern: fqdnNameRegex, 683 } 684 685 MatchFQDNPattern = apiextensionsv1beta1.JSONSchemaProps{ 686 Description: `MatchPattern matches fqdn by pattern`, 687 Type: "string", 688 Pattern: fqdnPatternRegex, 689 } 690 691 AWSGroup = apiextensionsv1beta1.JSONSchemaProps{ 692 Type: "object", 693 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 694 "securityGroupsIds": { 695 Description: `SecurityGroupsIds is the list of AWS security 696 group IDs that will filter the instances IPs from the AWS API`, 697 Type: "array", 698 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 699 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 700 Type: "string", 701 }, 702 }, 703 }, 704 "securityGroupsNames": { 705 Description: `SecurityGroupsNames is the list of AWS security 706 group names that will filter the instances IPs from the AWS API`, 707 Type: "array", 708 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 709 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 710 Type: "string", 711 }, 712 }, 713 }, 714 "region": { 715 Description: `Region is the key that will filter the AWS EC2 716 instances in the given region`, 717 Type: "string", 718 }, 719 }, 720 } 721 EndpointSelector = *LabelSelector.DeepCopy() 722 723 IngressRule = apiextensionsv1beta1.JSONSchemaProps{ 724 Type: "object", 725 Description: "IngressRule contains all rule types which can be applied at ingress, " + 726 "i.e. network traffic that originates outside of the endpoint and is entering " + 727 "the endpoint selected by the endpointSelector.\n\n- All members of this structure " + 728 "are optional. If omitted or empty, the\n member will have no effect on the rule." + 729 "\n\n- If multiple members are set, all of them need to match in order for\n " + 730 "the rule to take effect. The exception to this rule is FromRequires field;\n " + 731 "the effects of any Requires field in any rule will apply to all other\n rules " + 732 "as well.\n\n- For now, combining ToPorts, FromCIDR, and FromEndpoints in the same " + 733 "rule\n is not supported and any such rules will be rejected. In the future, " + 734 "this\n will be supported and if multiple members of this structure are specified," + 735 "\n then all members must match in order for the rule to take effect. The\n " + 736 "exception to this rule is the Requires field, the effects of any Requires\n " + 737 "field in any rule will apply to all other rules as well.", 738 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 739 "fromCIDR": { 740 Description: "FromCIDR is a list of IP blocks which the endpoint subject to " + 741 "the rule is allowed to receive connections from. This will match on the " + 742 "source IP address of incoming connections. Adding a prefix into FromCIDR " + 743 "or into FromCIDRSet with no ExcludeCIDRs is equivalent. Overlaps are " + 744 "allowed between FromCIDR and FromCIDRSet.\n\nExample: Any endpoint with " + 745 "the label \"app=my-legacy-pet\" is allowed to receive connections from " + 746 "10.3.9.1", 747 Type: "array", 748 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 749 Schema: &CIDR, 750 }, 751 }, 752 "fromCIDRSet": { 753 Description: "FromCIDRSet is a list of IP blocks which the endpoint subject to " + 754 "the rule is allowed to receive connections from in addition to " + 755 "FromEndpoints, along with a list of subnets contained within their " + 756 "corresponding IP block from which traffic should not be allowed. This " + 757 "will match on the source IP address of incoming connections. Adding a " + 758 "prefix into FromCIDR or into FromCIDRSet with no ExcludeCIDRs is " + 759 "equivalent. Overlaps are allowed between FromCIDR and FromCIDRSet." + 760 "\n\nExample: Any endpoint with the label \"app=my-legacy-pet\" is allowed " + 761 "to receive connections from 10.0.0.0/8 except from IPs in subnet " + 762 "10.96.0.0/12.", 763 Type: "array", 764 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 765 Schema: &CIDRRule, 766 }, 767 }, 768 "fromEndpoints": { 769 Description: "FromEndpoints is a list of endpoints identified by an " + 770 "EndpointSelector which are allowed to communicate with the endpoint " + 771 "subject to the rule.\n\nExample: Any endpoint with the label " + 772 "\"role=backend\" can be consumed by any endpoint carrying the label " + 773 "\"role=frontend\".", 774 Type: "array", 775 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 776 Schema: &EndpointSelector, 777 }, 778 }, 779 "fromEntities": { 780 Description: "FromEntities is a list of special entities which the endpoint " + 781 "subject to the rule is allowed to receive connections from. Supported " + 782 "entities are `world`, `cluster`, `host`, and `init`", 783 Type: "array", 784 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 785 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 786 Type: "string", 787 }, 788 }, 789 }, 790 "fromRequires": { 791 Description: "FromRequires is a list of additional constraints which must be " + 792 "met in order for the selected endpoints to be reachable. These additional " + 793 "constraints do no by itself grant access privileges and must always be " + 794 "accompanied with at least one matching FromEndpoints.\n\nExample: Any " + 795 "Endpoint with the label \"team=A\" requires consuming endpoint to also " + 796 "carry the label \"team=A\".", 797 Type: "array", 798 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 799 Schema: &EndpointSelector, 800 }, 801 }, 802 "toPorts": { 803 Description: "ToPorts is a list of destination ports identified by port number " + 804 "and protocol which the endpoint subject to the rule is allowed to receive " + 805 "connections on.\n\nExample: Any endpoint with the label \"app=httpd\" can " + 806 "only accept incoming connections on port 80/tcp.", 807 Type: "array", 808 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 809 Schema: &PortRule, 810 }, 811 }, 812 }, 813 } 814 815 K8sServiceNamespace = apiextensionsv1beta1.JSONSchemaProps{ 816 Type: "object", 817 Description: "K8sServiceNamespace is an abstraction for the k8s service + namespace " + 818 "types.", 819 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 820 "namespace": { 821 Type: "string", 822 }, 823 "serviceName": { 824 Type: "string", 825 }, 826 }, 827 } 828 829 L7Rules = apiextensionsv1beta1.JSONSchemaProps{ 830 Type: "object", 831 Description: "L7Rules is a union of port level rule types. Mixing of different port " + 832 "level rule types is disallowed, so exactly one of the following must be set. If " + 833 "none are specified, then no additional port level rules are applied.", 834 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 835 "http": { 836 Description: "HTTP specific rules.", 837 Type: "array", 838 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 839 Schema: &PortRuleHTTP, 840 }, 841 }, 842 "kafka": { 843 Description: "Kafka-specific rules.", 844 Type: "array", 845 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 846 Schema: &PortRuleKafka, 847 }, 848 }, 849 "l7proto": { 850 Description: "Parser type name that uses Key-Value pair rules.", 851 Type: "string", 852 }, 853 "l7": { 854 Description: "Generic Key-Value pair rules.", 855 Type: "array", 856 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 857 Schema: &PortRuleL7, 858 }, 859 }, 860 "dns": { 861 Description: "DNS specific rules", 862 Type: "array", 863 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 864 Schema: &PortRuleDNS, 865 }, 866 }, 867 }, 868 } 869 870 PortRuleDNS = apiextensionsv1beta1.JSONSchemaProps{ 871 Type: "object", 872 Description: `FQDNRule is a rule that specifies an fully qualified domain name to which outside communication is allowed`, 873 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 874 "matchName": MatchFQDNName, 875 "matchPattern": MatchFQDNPattern, 876 }, 877 } 878 879 Label = apiextensionsv1beta1.JSONSchemaProps{ 880 Type: "object", 881 Description: "Label is the cilium's representation of a container label.", 882 Required: []string{ 883 "key", 884 }, 885 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 886 "key": { 887 Type: "string", 888 }, 889 "source": { 890 Description: "Source can be one of the values present in const.go " + 891 "(e.g.: LabelSourceContainer)", 892 Type: "string", 893 }, 894 "value": { 895 Type: "string", 896 }, 897 }, 898 } 899 900 LabelSelector = apiextensionsv1beta1.JSONSchemaProps{ 901 Type: "object", 902 Description: "A label selector is a label query over a set of resources. The result " + 903 "of matchLabels and matchExpressions are ANDed. An empty label selector matches " + 904 "all objects. A null label selector matches no objects.", 905 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 906 "matchLabels": { 907 Description: "matchLabels is a map of {key,value} pairs. A single {key,value} " + 908 "in the matchLabels map is equivalent to an element of matchExpressions, " + 909 "whose key field is \"key\", the operator is \"In\", and the values array " + 910 "contains only \"value\". The requirements are ANDed.", 911 Type: "object", 912 }, 913 "matchExpressions": { 914 Description: "matchExpressions is a list of label selector requirements. " + 915 "The requirements are ANDed.", 916 Type: "array", 917 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 918 Schema: &LabelSelectorRequirement, 919 }, 920 }, 921 }, 922 } 923 924 LabelSelectorRequirement = apiextensionsv1beta1.JSONSchemaProps{ 925 Type: "object", 926 Description: "A label selector requirement is a selector that contains values, a key, " + 927 "and an operator that relates the key and values.", 928 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 929 "key": { 930 Description: "key is the label key that the selector applies to.", 931 Type: "string", 932 }, 933 "operator": { 934 Description: "operator represents a key's relationship to a set of values. " + 935 "Valid operators are In, NotIn, Exists and DoesNotExist.", 936 Type: "string", 937 Enum: []apiextensionsv1beta1.JSON{ 938 { 939 Raw: []byte(`"In"`), 940 }, 941 { 942 Raw: []byte(`"NotIn"`), 943 }, 944 { 945 Raw: []byte(`"Exists"`), 946 }, 947 { 948 Raw: []byte(`"DoesNotExist"`), 949 }, 950 }, 951 }, 952 "values": { 953 Description: "values is an array of string values. If the operator is In or " + 954 "NotIn, the values array must be non-empty. If the operator is Exists or " + 955 "DoesNotExist, the values array must be empty. This array is replaced " + 956 "during a strategic merge patch.", 957 Type: "array", 958 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 959 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 960 Type: "string", 961 }, 962 }, 963 }, 964 }, 965 Required: []string{"key", "operator"}, 966 } 967 968 PortProtocol = apiextensionsv1beta1.JSONSchemaProps{ 969 Type: "object", 970 Description: "PortProtocol specifies an L4 port with an optional transport protocol", 971 Required: []string{ 972 "port", 973 }, 974 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 975 "port": { 976 Description: "Port is an L4 port number. For now the string will be strictly " + 977 "parsed as a single uint16. In the future, this field may support ranges " + 978 "in the form \"1024-2048", 979 Type: "string", 980 // uint16 string regex 981 Pattern: `^(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|` + 982 `[1-5][0-9]{4}|[0-9]{1,4})$`, 983 }, 984 "protocol": { 985 Description: `Protocol is the L4 protocol. If omitted or empty, any protocol ` + 986 `matches. Accepted values: "TCP", "UDP", ""/"ANY"\n\nMatching on ` + 987 `ICMP is not supported.`, 988 Type: "string", 989 Enum: []apiextensionsv1beta1.JSON{ 990 { 991 Raw: []byte(`"TCP"`), 992 }, 993 { 994 Raw: []byte(`"UDP"`), 995 }, 996 { 997 Raw: []byte(`"ANY"`), 998 }, 999 }, 1000 }, 1001 }, 1002 } 1003 1004 PortRule = apiextensionsv1beta1.JSONSchemaProps{ 1005 Type: "object", 1006 Description: "PortRule is a list of ports/protocol combinations with optional Layer 7 " + 1007 "rules which must be met.", 1008 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1009 "ports": { 1010 Description: "Ports is a list of L4 port/protocol\n\nIf omitted or empty but " + 1011 "RedirectPort is set, then all ports of the endpoint subject to either the " + 1012 "ingress or egress rule are being redirected.", 1013 Type: "array", 1014 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1015 Schema: &PortProtocol, 1016 }, 1017 }, 1018 "redirectPort": { 1019 Description: "RedirectPort is the L4 port which, if set, all traffic matching " + 1020 "the Ports is being redirected to. Whatever listener behind that port " + 1021 "becomes responsible to enforce the port rules and is also responsible to " + 1022 "reinject all traffic back and ensure it reaches its original destination.", 1023 Type: "integer", 1024 Format: "uint16", 1025 }, 1026 "rules": L7Rules, 1027 }, 1028 } 1029 1030 PortRuleHTTP = apiextensionsv1beta1.JSONSchemaProps{ 1031 Type: "object", 1032 Description: "PortRuleHTTP is a list of HTTP protocol constraints. All fields are " + 1033 "optional, if all fields are empty or missing, the rule does not have any effect." + 1034 "\n\nAll fields of this type are extended POSIX regex as defined by " + 1035 "IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) " + 1036 "matched against the path of an incoming request. Currently it can contain " + 1037 "characters disallowed from the conventional \"path\" part of a URL as defined by " + 1038 "RFC 3986.", 1039 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1040 "headers": { 1041 Description: "Headers is a list of HTTP headers which must be present in the " + 1042 "request. If omitted or empty, requests are allowed regardless of headers " + 1043 "present.", 1044 Type: "array", 1045 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1046 Schema: &apiextensionsv1beta1.JSONSchemaProps{ 1047 Type: "string", 1048 }, 1049 }, 1050 }, 1051 "host": { 1052 Description: "Host is an extended POSIX regex matched against the host header " + 1053 "of a request, e.g. \"foo.com\"\n\nIf omitted or empty, the value of the " + 1054 "host header is ignored.", 1055 Type: "string", 1056 Format: "idn-hostname", 1057 }, 1058 "method": { 1059 Description: "Method is an extended POSIX regex matched against the method of " + 1060 "a request, e.g. \"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", ...\n\n" + 1061 "If omitted or empty, all methods are allowed.", 1062 Type: "string", 1063 }, 1064 "path": { 1065 Description: "Path is an extended POSIX regex matched against the path of a " + 1066 "request. Currently it can contain characters disallowed from the " + 1067 "conventional \"path\" part of a URL as defined by RFC 3986.\n\n" + 1068 "If omitted or empty, all paths are all allowed.", 1069 Type: "string", 1070 }, 1071 }, 1072 } 1073 1074 PortRuleKafka = apiextensionsv1beta1.JSONSchemaProps{ 1075 Type: "object", 1076 Description: "PortRuleKafka is a list of Kafka protocol constraints. All fields are " + 1077 "optional, if all fields are empty or missing, the rule will match all Kafka " + 1078 "messages.", 1079 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1080 "role": { 1081 Description: "Role is a case-insensitive string and describes a group of API keys" + 1082 "necessary to perform certain higher level Kafka operations such as" + 1083 "\"produce\" or \"consume\". An APIGroup automatically expands into all APIKeys" + 1084 "required to perform the specified higher level operation." + 1085 "The following values are supported:" + 1086 "- \"produce\": Allow producing to the topics specified in the rule" + 1087 "- \"consume\": Allow consuming from the topics specified in the rule" + 1088 "This field is incompatible with the APIKey field, either APIKey or Role" + 1089 "may be specified. If omitted or empty, the field has no effect and the " + 1090 "logic of the APIKey field applies.", 1091 Type: "string", 1092 Enum: []apiextensionsv1beta1.JSON{ 1093 { 1094 Raw: []byte(`"produce"`), 1095 }, 1096 { 1097 Raw: []byte(`"consume"`), 1098 }, 1099 }, 1100 }, 1101 "apiKey": { 1102 Description: "APIKey is a case-insensitive string matched against the key of " + 1103 "a request, e.g. \"produce\", \"fetch\", \"createtopic\", \"deletetopic\", " + 1104 "et al Reference: https://kafka.apache.org/protocol#protocol_api_keys\n\n" + 1105 "If omitted or empty, all keys are allowed.", 1106 Type: "string", 1107 }, 1108 "apiVersion": { 1109 Description: "APIVersion is the version matched against the api version of the " + 1110 "Kafka message. If set, it has to be a string representing a positive " + 1111 "integer.\n\nIf omitted or empty, all versions are allowed.", 1112 Type: "string", 1113 }, 1114 "clientID": { 1115 Description: "ClientID is the client identifier as provided in the request.\n\n" + 1116 "From Kafka protocol documentation: This is a user supplied identifier for " + 1117 "the client application. The user can use any identifier they like and it " + 1118 "will be used when logging errors, monitoring aggregates, etc. For " + 1119 "example, one might want to monitor not just the requests per second " + 1120 "overall, but the number coming from each client application (each of " + 1121 "which could reside on multiple servers). This id acts as a logical " + 1122 "grouping across all requests from a particular client.\n\nIf omitted or " + 1123 "empty, all client identifiers are allowed.", 1124 Type: "string", 1125 }, 1126 "topic": { 1127 Description: "Topic is the topic name contained in the message. If a Kafka " + 1128 "request contains multiple topics, then all topics must be allowed or the " + 1129 "message will be rejected.\n\nThis constraint is ignored if the matched " + 1130 "request message type doesn't contain any topic. Maximum size of Topic can " + 1131 "be 249 characters as per recent Kafka spec and allowed characters are " + 1132 "a-z, A-Z, 0-9, -, . and _ Older Kafka versions had longer topic lengths " + 1133 "of 255, but in Kafka 0.10 version the length was changed from 255 to 249. " + 1134 "For compatibility reasons we are using 255\n\nIf omitted or empty, all " + 1135 "topics are allowed.", 1136 Type: "string", 1137 MaxLength: getInt64(255), 1138 }, 1139 }, 1140 } 1141 1142 PortRuleL7 = apiextensionsv1beta1.JSONSchemaProps{ 1143 Type: "object", 1144 Description: "PortRuleL7 is a map of {key,value} pairs which is passed to the " + 1145 "parser referenced in l7proto. It is up to the parser to define what to " + 1146 "do with the map data. If omitted or empty, all requests are allowed. " + 1147 "Both keys and values must be strings.", 1148 // 1149 // AdditionalProperties is supported by k8s 1.11 and later only 1150 // Without it non-string value types are accepted which may cause policy translation 1151 // in cilium-agent to fail. 1152 // 1153 // Keep this here so that we can re-introduce this when th minimum suppoerted k8s version 1154 // is 1.11. 1155 // 1156 //AdditionalProperties: &apiextensionsv1beta1.JSONSchemaPropsOrBool{ 1157 // Schema: &apiextensionsv1beta1.JSONSchemaProps{ 1158 // Type: "string", 1159 // }, 1160 //}, 1161 } 1162 1163 Rule = apiextensionsv1beta1.JSONSchemaProps{ 1164 Type: "object", 1165 Description: "Rule is a policy rule which must be applied to all endpoints which match " + 1166 "the labels contained in the endpointSelector\n\nEach rule is split into an " + 1167 "ingress section which contains all rules applicable at ingress, and an egress " + 1168 "section applicable at egress. For rule types such as `L4Rule` and `CIDR` which " + 1169 "can be applied at both ingress and egress, both ingress and egress side have to " + 1170 "either specifically allow the connection or one side has to be omitted.\n\n" + 1171 "Either ingress, egress, or both can be provided. If both ingress and egress are " + 1172 "omitted, the rule has no effect.", 1173 Required: []string{ 1174 "endpointSelector", 1175 }, 1176 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1177 "Description": { 1178 Description: "Description is a free form string, it can be used by the creator " + 1179 "of the rule to store human readable explanation of the purpose of this " + 1180 "rule. Rules cannot be identified by comment.", 1181 Type: "string", 1182 }, 1183 "egress": { 1184 Description: "Egress is a list of EgressRule which are enforced at egress. If " + 1185 "omitted or empty, this rule does not apply at egress.", 1186 Type: "array", 1187 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1188 Schema: &EgressRule, 1189 }, 1190 }, 1191 "endpointSelector": EndpointSelector, 1192 "ingress": { 1193 Description: "Ingress is a list of IngressRule which are enforced at ingress. " + 1194 "If omitted or empty, this rule does not apply at ingress.", 1195 Type: "array", 1196 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1197 Schema: &IngressRule, 1198 }, 1199 }, 1200 "labels": { 1201 Description: "Labels is a list of optional strings which can be used to " + 1202 "re-identify the rule or to store metadata. It is possible to lookup or " + 1203 "delete strings based on labels. Labels are not required to be unique, " + 1204 "multiple rules can have overlapping or identical labels.", 1205 Type: "array", 1206 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1207 Schema: &Label, 1208 }, 1209 }, 1210 }, 1211 } 1212 1213 Service = apiextensionsv1beta1.JSONSchemaProps{ 1214 Type: "object", 1215 Description: "Service wraps around selectors for services", 1216 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1217 "k8sService": K8sServiceNamespace, 1218 "k8sServiceSelector": ServiceSelector, 1219 }, 1220 } 1221 1222 ServiceSelector = apiextensionsv1beta1.JSONSchemaProps{ 1223 Type: "object", 1224 Description: "ServiceSelector is a label selector for k8s services", 1225 Required: []string{ 1226 "selector", 1227 }, 1228 Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ 1229 "selector": EndpointSelector, 1230 "namespace": { 1231 Type: "string", 1232 }, 1233 }, 1234 } 1235 1236 spec = *Rule.DeepCopy() 1237 1238 specs = apiextensionsv1beta1.JSONSchemaProps{ 1239 Description: "Specs is a list of desired Cilium specific rule specification.", 1240 Type: "array", 1241 Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{ 1242 Schema: &spec, 1243 }, 1244 } 1245 ) 1246 1247 func init() { 1248 EndpointSelector.Description = "EndpointSelector is a wrapper for k8s LabelSelector." 1249 1250 portRuleProps := PortRule.Properties["rules"] 1251 portRuleProps.Description = "Rules is a list of additional port level rules which must be " + 1252 "met in order for the PortRule to allow the traffic. If omitted or empty, " + 1253 "no layer 7 rules are enforced." 1254 PortRule.Properties["rules"] = portRuleProps 1255 1256 ruleProps := Rule.Properties["endpointSelector"] 1257 ruleProps.Description = "EndpointSelector selects all endpoints which should be subject " + 1258 "to this rule. Cannot be empty." 1259 Rule.Properties["endpointSelector"] = ruleProps 1260 1261 serviceProps := Service.Properties["k8sServiceSelector"] 1262 serviceProps.Description = "K8sServiceSelector selects services by k8s labels. " + 1263 "Not supported yet" 1264 Service.Properties["k8sServiceSelector"] = serviceProps 1265 1266 spec.Description = "Spec is the desired Cilium specific rule specification." 1267 spec.Type = "object" 1268 1269 }