diff --git a/projectcalico.org/adminnetworkpolicy_v3alpha1.json b/projectcalico.org/adminnetworkpolicy_v3alpha1.json new file mode 100644 index 0000000..c2e9a7b --- /dev/null +++ b/projectcalico.org/adminnetworkpolicy_v3alpha1.json @@ -0,0 +1,856 @@ +{ + "description": "AdminNetworkPolicy is a cluster level resource that is part of the\nAdminNetworkPolicy API.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "type": "object" + }, + "spec": { + "description": "Specification of the desired behavior of AdminNetworkPolicy.", + "properties": { + "egress": { + "description": "Egress is the list of Egress rules to be applied to the selected pods.\nA total of 100 rules will be allowed in each ANP instance.\nThe relative precedence of egress rules within a single ANP object (all of\nwhich share the priority) will be determined by the order in which the rule\nis written. Thus, a rule that appears at the top of the egress rules\nwould take the highest precedence.\nANPs with no egress rules do not affect egress traffic.\n\n\nSupport: Core", + "items": { + "description": "AdminNetworkPolicyEgressRule describes an action to take on a particular\nset of traffic originating from pods selected by a AdminNetworkPolicy's\nSubject field.\n", + "properties": { + "action": { + "description": "Action specifies the effect this rule will have on matching traffic.\nCurrently the following actions are supported:\nAllow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy)\nDeny: denies the selected traffic\nPass: instructs the selected traffic to skip any remaining ANP rules, and\nthen pass execution to any NetworkPolicies that select the pod.\nIf the pod is not selected by any NetworkPolicies then execution\nis passed to any BaselineAdminNetworkPolicies that select the pod.\n\n\nSupport: Core", + "enum": [ + "Allow", + "Deny", + "Pass" + ], + "type": "string" + }, + "name": { + "description": "Name is an identifier for this rule, that may be no more than 100 characters\nin length. This field should be used by the implementation to help\nimprove observability, readability and error-reporting for any applied\nAdminNetworkPolicies.\n\n\nSupport: Core", + "maxLength": 100, + "type": "string" + }, + "ports": { + "description": "Ports allows for matching traffic based on port and protocols.\nThis field is a list of destination ports for the outgoing egress traffic.\nIf Ports is not set then the rule does not filter traffic via port.\n\n\nSupport: Core", + "items": { + "description": "AdminNetworkPolicyPort describes how to select network ports on pod(s).\nExactly one field must be set.", + "maxProperties": 1, + "minProperties": 1, + "properties": { + "namedPort": { + "description": "NamedPort selects a port on a pod(s) based on name.\n\n\nSupport: Extended\n\n\n", + "type": "string" + }, + "portNumber": { + "description": "Port selects a port on a pod(s) based on number.\n\n\nSupport: Core", + "properties": { + "port": { + "description": "Number defines a network port value.\n\n\nSupport: Core", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "protocol": { + "default": "TCP", + "description": "Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must\nmatch. If not specified, this field defaults to TCP.\n\n\nSupport: Core", + "type": "string" + } + }, + "required": [ + "port", + "protocol" + ], + "type": "object", + "additionalProperties": false + }, + "portRange": { + "description": "PortRange selects a port range on a pod(s) based on provided start and end\nvalues.\n\n\nSupport: Core", + "properties": { + "end": { + "description": "End defines a network port that is the end of a port range, the End value\nmust be greater than Start.\n\n\nSupport: Core", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "protocol": { + "default": "TCP", + "description": "Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must\nmatch. If not specified, this field defaults to TCP.\n\n\nSupport: Core", + "type": "string" + }, + "start": { + "description": "Start defines a network port that is the start of a port range, the Start\nvalue must be less than End.\n\n\nSupport: Core", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "end", + "start" + ], + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false + }, + "maxItems": 100, + "type": "array" + }, + "to": { + "description": "To is the List of destinations whose traffic this rule applies to.\nIf any AdminNetworkPolicyEgressPeer matches the destination of outgoing\ntraffic then the specified action is applied.\nThis field must be defined and contain at least one item.\n\n\nSupport: Core", + "items": { + "description": "AdminNetworkPolicyEgressPeer defines a peer to allow traffic to.\nExactly one of the selector pointers must be set for a given peer. If a\nconsumer observes none of its fields are set, they must assume an unknown\noption has been specified and fail closed.", + "maxProperties": 1, + "minProperties": 1, + "properties": { + "namespaces": { + "description": "Namespaces defines a way to select all pods within a set of Namespaces.\nNote that host-networked pods are not included in this type of peer.\n\n\nSupport: Core", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + }, + "networks": { + "description": "Networks defines a way to select peers via CIDR blocks.\nThis is intended for representing entities that live outside the cluster,\nwhich can't be selected by pods, namespaces and nodes peers, but note\nthat cluster-internal traffic will be checked against the rule as\nwell. So if you Allow or Deny traffic to `\"0.0.0.0/0\"`, that will allow\nor deny all IPv4 pod-to-pod traffic as well. If you don't want that,\nadd a rule that Passes all pod traffic before the Networks rule.\n\n\nEach item in Networks should be provided in the CIDR format and should be\nIPv4 or IPv6, for example \"10.0.0.0/8\" or \"fd00::/8\".\n\n\nNetworks can have upto 25 CIDRs specified.\n\n\nSupport: Extended\n\n\n", + "items": { + "description": "CIDR is an IP address range in CIDR notation (for example, \"10.0.0.0/8\" or \"fd00::/8\").\nThis string must be validated by implementations using net.ParseCIDR\nTODO: Introduce CEL CIDR validation regex isCIDR() in Kube 1.31 when it is available.", + "maxLength": 43, + "type": "string", + "x-kubernetes-validations": [ + { + "message": "CIDR must be either an IPv4 or IPv6 address. IPv4 address embedded in IPv6 addresses are not supported", + "rule": "self.contains(':') != self.contains('.')" + } + ] + }, + "maxItems": 25, + "minItems": 1, + "type": "array", + "x-kubernetes-list-type": "set" + }, + "nodes": { + "description": "Nodes defines a way to select a set of nodes in\nthe cluster. This field follows standard label selector\nsemantics; if present but empty, it selects all Nodes.\n\n\nSupport: Extended\n\n\n", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + }, + "pods": { + "description": "Pods defines a way to select a set of pods in\na set of namespaces. Note that host-networked pods\nare not included in this type of peer.\n\n\nSupport: Core", + "properties": { + "namespaceSelector": { + "description": "NamespaceSelector follows standard label selector semantics; if empty,\nit selects all Namespaces.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + }, + "podSelector": { + "description": "PodSelector is used to explicitly select pods within a namespace; if empty,\nit selects all Pods.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + } + }, + "required": [ + "namespaceSelector", + "podSelector" + ], + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false + }, + "maxItems": 100, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "action", + "to" + ], + "type": "object", + "x-kubernetes-validations": [ + { + "message": "networks/nodes peer cannot be set with namedPorts since there are no namedPorts for networks/nodes", + "rule": "!(self.to.exists(peer, has(peer.networks) || has(peer.nodes)) && has(self.ports) && self.ports.exists(port, has(port.namedPort)))" + } + ], + "additionalProperties": false + }, + "maxItems": 100, + "type": "array" + }, + "ingress": { + "description": "Ingress is the list of Ingress rules to be applied to the selected pods.\nA total of 100 rules will be allowed in each ANP instance.\nThe relative precedence of ingress rules within a single ANP object (all of\nwhich share the priority) will be determined by the order in which the rule\nis written. Thus, a rule that appears at the top of the ingress rules\nwould take the highest precedence.\nANPs with no ingress rules do not affect ingress traffic.\n\n\nSupport: Core", + "items": { + "description": "AdminNetworkPolicyIngressRule describes an action to take on a particular\nset of traffic destined for pods selected by an AdminNetworkPolicy's\nSubject field.", + "properties": { + "action": { + "description": "Action specifies the effect this rule will have on matching traffic.\nCurrently the following actions are supported:\nAllow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy)\nDeny: denies the selected traffic\nPass: instructs the selected traffic to skip any remaining ANP rules, and\nthen pass execution to any NetworkPolicies that select the pod.\nIf the pod is not selected by any NetworkPolicies then execution\nis passed to any BaselineAdminNetworkPolicies that select the pod.\n\n\nSupport: Core", + "enum": [ + "Allow", + "Deny", + "Pass" + ], + "type": "string" + }, + "from": { + "description": "From is the list of sources whose traffic this rule applies to.\nIf any AdminNetworkPolicyIngressPeer matches the source of incoming\ntraffic then the specified action is applied.\nThis field must be defined and contain at least one item.\n\n\nSupport: Core", + "items": { + "description": "AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from.\nExactly one of the selector pointers must be set for a given peer. If a\nconsumer observes none of its fields are set, they must assume an unknown\noption has been specified and fail closed.", + "maxProperties": 1, + "minProperties": 1, + "properties": { + "namespaces": { + "description": "Namespaces defines a way to select all pods within a set of Namespaces.\nNote that host-networked pods are not included in this type of peer.\n\n\nSupport: Core", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + }, + "pods": { + "description": "Pods defines a way to select a set of pods in\na set of namespaces. Note that host-networked pods\nare not included in this type of peer.\n\n\nSupport: Core", + "properties": { + "namespaceSelector": { + "description": "NamespaceSelector follows standard label selector semantics; if empty,\nit selects all Namespaces.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + }, + "podSelector": { + "description": "PodSelector is used to explicitly select pods within a namespace; if empty,\nit selects all Pods.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + } + }, + "required": [ + "namespaceSelector", + "podSelector" + ], + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false + }, + "maxItems": 100, + "minItems": 1, + "type": "array" + }, + "name": { + "description": "Name is an identifier for this rule, that may be no more than 100 characters\nin length. This field should be used by the implementation to help\nimprove observability, readability and error-reporting for any applied\nAdminNetworkPolicies.\n\n\nSupport: Core", + "maxLength": 100, + "type": "string" + }, + "ports": { + "description": "Ports allows for matching traffic based on port and protocols.\nThis field is a list of ports which should be matched on\nthe pods selected for this policy i.e the subject of the policy.\nSo it matches on the destination port for the ingress traffic.\nIf Ports is not set then the rule does not filter traffic via port.\n\n\nSupport: Core", + "items": { + "description": "AdminNetworkPolicyPort describes how to select network ports on pod(s).\nExactly one field must be set.", + "maxProperties": 1, + "minProperties": 1, + "properties": { + "namedPort": { + "description": "NamedPort selects a port on a pod(s) based on name.\n\n\nSupport: Extended\n\n\n", + "type": "string" + }, + "portNumber": { + "description": "Port selects a port on a pod(s) based on number.\n\n\nSupport: Core", + "properties": { + "port": { + "description": "Number defines a network port value.\n\n\nSupport: Core", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "protocol": { + "default": "TCP", + "description": "Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must\nmatch. If not specified, this field defaults to TCP.\n\n\nSupport: Core", + "type": "string" + } + }, + "required": [ + "port", + "protocol" + ], + "type": "object", + "additionalProperties": false + }, + "portRange": { + "description": "PortRange selects a port range on a pod(s) based on provided start and end\nvalues.\n\n\nSupport: Core", + "properties": { + "end": { + "description": "End defines a network port that is the end of a port range, the End value\nmust be greater than Start.\n\n\nSupport: Core", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "protocol": { + "default": "TCP", + "description": "Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must\nmatch. If not specified, this field defaults to TCP.\n\n\nSupport: Core", + "type": "string" + }, + "start": { + "description": "Start defines a network port that is the start of a port range, the Start\nvalue must be less than End.\n\n\nSupport: Core", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "end", + "start" + ], + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false + }, + "maxItems": 100, + "type": "array" + } + }, + "required": [ + "action", + "from" + ], + "type": "object", + "additionalProperties": false + }, + "maxItems": 100, + "type": "array" + }, + "priority": { + "description": "Priority is a value from 0 to 1000. Rules with lower priority values have\nhigher precedence, and are checked before rules with higher priority values.\nAll AdminNetworkPolicy rules have higher precedence than NetworkPolicy or\nBaselineAdminNetworkPolicy rules\nThe behavior is undefined if two ANP objects have same priority.\n\n\nSupport: Core", + "format": "int32", + "maximum": 1000, + "minimum": 0, + "type": "integer" + }, + "subject": { + "description": "Subject defines the pods to which this AdminNetworkPolicy applies.\nNote that host-networked pods are not included in subject selection.\n\n\nSupport: Core", + "maxProperties": 1, + "minProperties": 1, + "properties": { + "namespaces": { + "description": "Namespaces is used to select pods via namespace selectors.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + }, + "pods": { + "description": "Pods is used to select pods via namespace AND pod selectors.", + "properties": { + "namespaceSelector": { + "description": "NamespaceSelector follows standard label selector semantics; if empty,\nit selects all Namespaces.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + }, + "podSelector": { + "description": "PodSelector is used to explicitly select pods within a namespace; if empty,\nit selects all Pods.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "items": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.", + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "key", + "operator" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object" + } + }, + "type": "object", + "x-kubernetes-map-type": "atomic", + "additionalProperties": false + } + }, + "required": [ + "namespaceSelector", + "podSelector" + ], + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false + } + }, + "required": [ + "priority", + "subject" + ], + "type": "object", + "additionalProperties": false + }, + "status": { + "description": "Status is the status to be reported by the implementation.", + "properties": { + "conditions": { + "items": { + "description": "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis struct is intended for direct use as an array at the field path .status.conditions. For example,\n\n\n\ttype FooStatus struct{\n\t // Represents the observations of a foo's current state.\n\t // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t // other fields\n\t}", + "properties": { + "lastTransitionTime": { + "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.", + "format": "date-time", + "type": "string" + }, + "message": { + "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.", + "maxLength": 32768, + "type": "string" + }, + "observedGeneration": { + "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.", + "format": "int64", + "minimum": 0, + "type": "integer" + }, + "reason": { + "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.", + "maxLength": 1024, + "minLength": 1, + "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$", + "type": "string" + }, + "status": { + "description": "status of the condition, one of True, False, Unknown.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + }, + "type": { + "description": "type of condition in CamelCase or in foo.example.com/CamelCase.\n---\nMany .condition.type values are consistent across resources like Available, but because arbitrary conditions can be\nuseful (see .node.status.conditions), the ability to deconflict is important.\nThe regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)", + "maxLength": 316, + "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$", + "type": "string" + } + }, + "required": [ + "lastTransitionTime", + "message", + "reason", + "status", + "type" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "type" + ], + "x-kubernetes-list-type": "map" + } + }, + "required": [ + "conditions" + ], + "type": "object", + "additionalProperties": false + } + }, + "required": [ + "metadata", + "spec" + ], + "type": "object" +} diff --git a/projectcalico.org/all-anyOf.json b/projectcalico.org/all-anyOf.json index d45489f..5eaec27 100644 --- a/projectcalico.org/all-anyOf.json +++ b/projectcalico.org/all-anyOf.json @@ -1,5 +1,8 @@ { "anyOf": [ + { + "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/adminnetworkpolicy_v3alpha1.json" + }, { "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/bgpconfiguration_v3.json" }, @@ -53,6 +56,9 @@ }, { "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/networkset_v3.json" + }, + { + "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/tier_v3.json" } ] } diff --git a/projectcalico.org/all-oneOf.json b/projectcalico.org/all-oneOf.json index a3a983c..4c48294 100644 --- a/projectcalico.org/all-oneOf.json +++ b/projectcalico.org/all-oneOf.json @@ -1,5 +1,8 @@ { "oneOf": [ + { + "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/adminnetworkpolicy_v3alpha1.json" + }, { "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/bgpconfiguration_v3.json" }, @@ -53,6 +56,9 @@ }, { "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/networkset_v3.json" + }, + { + "$ref": "https://gitea.rknet.org/infra/crds-catalog/raw/branch/catalog/projectcalico.org/tier_v3.json" } ] } diff --git a/projectcalico.org/bgpfilter_v3.json b/projectcalico.org/bgpfilter_v3.json index 791293d..770f66d 100644 --- a/projectcalico.org/bgpfilter_v3.json +++ b/projectcalico.org/bgpfilter_v3.json @@ -31,6 +31,24 @@ "matchOperator": { "type": "string" }, + "prefixLength": { + "properties": { + "max": { + "format": "int32", + "maximum": 32, + "minimum": 0, + "type": "integer" + }, + "min": { + "format": "int32", + "maximum": 32, + "minimum": 0, + "type": "integer" + } + }, + "type": "object", + "additionalProperties": false + }, "source": { "type": "string" } @@ -60,6 +78,24 @@ "matchOperator": { "type": "string" }, + "prefixLength": { + "properties": { + "max": { + "format": "int32", + "maximum": 128, + "minimum": 0, + "type": "integer" + }, + "min": { + "format": "int32", + "maximum": 128, + "minimum": 0, + "type": "integer" + } + }, + "type": "object", + "additionalProperties": false + }, "source": { "type": "string" } @@ -89,6 +125,24 @@ "matchOperator": { "type": "string" }, + "prefixLength": { + "properties": { + "max": { + "format": "int32", + "maximum": 32, + "minimum": 0, + "type": "integer" + }, + "min": { + "format": "int32", + "maximum": 32, + "minimum": 0, + "type": "integer" + } + }, + "type": "object", + "additionalProperties": false + }, "source": { "type": "string" } @@ -118,6 +172,24 @@ "matchOperator": { "type": "string" }, + "prefixLength": { + "properties": { + "max": { + "format": "int32", + "maximum": 128, + "minimum": 0, + "type": "integer" + }, + "min": { + "format": "int32", + "maximum": 128, + "minimum": 0, + "type": "integer" + } + }, + "type": "object", + "additionalProperties": false + }, "source": { "type": "string" } diff --git a/projectcalico.org/felixconfiguration_v3.json b/projectcalico.org/felixconfiguration_v3.json index 20fa1a6..4e46487 100644 --- a/projectcalico.org/felixconfiguration_v3.json +++ b/projectcalico.org/felixconfiguration_v3.json @@ -185,6 +185,10 @@ "description": "BPFPolicyDebugEnabled when true, Felix records detailed information about the BPF policy programs, which can be examined with the calico-bpf command-line tool.", "type": "boolean" }, + "bpfRedirectToPeer": { + "description": "BPFRedirectToPeer controls which whether it is allowed to forward straight to the peer side of the workload devices. It is allowed for any host L2 devices by default (L2Only), but it breaks TCP dump on the host side of workload device as it bypasses it on ingress. Value of Enabled also allows redirection from L3 host devices like IPIP tunnel or Wireguard directly to the peer side of the workload's device. This makes redirection faster, however, it breaks tools like tcpdump on the peer side. Use Enabled with caution. [Default: L2Only]", + "type": "string" + }, "chainInsertMode": { "description": "ChainInsertMode controls whether Felix hooks the kernel's top-level iptables chains by inserting a rule at the top of the chain or by appending a rule at the bottom. insert is the safe default since it prevents Calico's rules from being bypassed. If you switch to append mode, be sure that the other rules in the chains signal acceptance by falling through to the Calico rules, otherwise the Calico policy will be bypassed. [Default: insert]", "pattern": "^(?i)(insert|append)?$", @@ -263,7 +267,7 @@ "type": "array" }, "failsafeInboundHostPorts": { - "description": "FailsafeInboundHostPorts is a list of UDP/TCP ports and CIDRs that Felix will allow incoming traffic to host endpoints on irrespective of the security policy. This is useful to avoid accidentally cutting off a host with incorrect configuration. For back-compatibility, if the protocol is not specified, it defaults to \"tcp\". If a CIDR is not specified, it will allow traffic from all addresses. To disable all inbound host ports, use the value none. The default value allows ssh access and DHCP. [Default: tcp:22, udp:68, tcp:179, tcp:2379, tcp:2380, tcp:6443, tcp:6666, tcp:6667]", + "description": "FailsafeInboundHostPorts is a list of PortProto struct objects including UDP/TCP/SCTP ports and CIDRs that Felix will allow incoming traffic to host endpoints on irrespective of the security policy. This is useful to avoid accidentally cutting off a host with incorrect configuration. For backwards compatibility, if the protocol is not specified, it defaults to \"tcp\". If a CIDR is not specified, it will allow traffic from all addresses. To disable all inbound host ports, use the value \"[]\". The default value allows ssh access, DHCP, BGP, etcd and the Kubernetes API. [Default: tcp:22, udp:68, tcp:179, tcp:2379, tcp:2380, tcp:5473, tcp:6443, tcp:6666, tcp:6667 ]", "items": { "description": "ProtoPort is combination of protocol, port, and CIDR. Protocol and port must be specified.", "properties": { @@ -287,7 +291,7 @@ "type": "array" }, "failsafeOutboundHostPorts": { - "description": "FailsafeOutboundHostPorts is a list of UDP/TCP ports and CIDRs that Felix will allow outgoing traffic from host endpoints to irrespective of the security policy. This is useful to avoid accidentally cutting off a host with incorrect configuration. For back-compatibility, if the protocol is not specified, it defaults to \"tcp\". If a CIDR is not specified, it will allow traffic from all addresses. To disable all outbound host ports, use the value none. The default value opens etcd's standard ports to ensure that Felix does not get cut off from etcd as well as allowing DHCP and DNS. [Default: tcp:179, tcp:2379, tcp:2380, tcp:6443, tcp:6666, tcp:6667, udp:53, udp:67]", + "description": "FailsafeOutboundHostPorts is a list of List of PortProto struct objects including UDP/TCP/SCTP ports and CIDRs that Felix will allow outgoing traffic from host endpoints to irrespective of the security policy. This is useful to avoid accidentally cutting off a host with incorrect configuration. For backwards compatibility, if the protocol is not specified, it defaults to \"tcp\". If a CIDR is not specified, it will allow traffic from all addresses. To disable all outbound host ports, use the value \"[]\". The default value opens etcd's standard ports to ensure that Felix does not get cut off from etcd as well as allowing DHCP, DNS, BGP and the Kubernetes API. [Default: udp:53, udp:67, tcp:179, tcp:2379, tcp:2380, tcp:5473, tcp:6443, tcp:6666, tcp:6667 ]", "items": { "description": "ProtoPort is combination of protocol, port, and CIDR. Protocol and port must be specified.", "properties": { @@ -332,6 +336,18 @@ "description": "GenericXDPEnabled enables Generic XDP so network cards that don't support XDP offload or driver modes can use XDP. This is not recommended since it doesn't provide better performance than iptables. [Default: false]", "type": "boolean" }, + "goGCThreshold": { + "description": "GoGCThreshold Sets the Go runtime's garbage collection threshold. I.e. the percentage that the heap is allowed to grow before garbage collection is triggered. In general, doubling the value halves the CPU time spent doing GC, but it also doubles peak GC memory overhead. A special value of -1 can be used to disable GC entirely; this should only be used in conjunction with the GoMemoryLimitMB setting. \n This setting is overridden by the GOGC environment variable. \n [Default: 40]", + "type": "integer" + }, + "goMaxProcs": { + "description": "GoMaxProcs sets the maximum number of CPUs that the Go runtime will use concurrently. A value of -1 means \"use the system default\"; typically the number of real CPUs on the system. \n this setting is overridden by the GOMAXPROCS environment variable. \n [Default: -1]", + "type": "integer" + }, + "goMemoryLimitMB": { + "description": "GoMemoryLimitMB sets a (soft) memory limit for the Go runtime in MB. The Go runtime will try to keep its memory usage under the limit by triggering GC as needed. To avoid thrashing, it will exceed the limit if GC starts to take more than 50% of the process's CPU time. A value of -1 disables the memory limit. \n Note that the memory limit, if used, must be considerably less than any hard resource limit set at the container or pod level. This is because felix is not the only process that must run in the container or pod. \n This setting is overridden by the GOMEMLIMIT environment variable. \n [Default: -1]", + "type": "integer" + }, "healthEnabled": { "type": "boolean" }, @@ -374,6 +390,14 @@ "pattern": "^([0-9]+(\\\\.[0-9]+)?(ms|s|m|h))*$", "type": "string" }, + "ipForwarding": { + "description": "IPForwarding controls whether Felix sets the host sysctls to enable IP forwarding. IP forwarding is required when using Calico for workload networking. This should only be disabled on hosts where Calico is used for host protection. [Default: Enabled]", + "enum": [ + "Enabled", + "Disabled" + ], + "type": "string" + }, "ipipEnabled": { "description": "IPIPEnabled overrides whether Felix should configure an IPIP interface on the host. Optional as Felix determines this based on the existing IP pools. [Default: nil (unset)]", "type": "boolean" @@ -485,6 +509,7 @@ "type": "string" }, "maxIpsetSize": { + "description": "MaxIpsetSize is the maximum number of IP addresses that can be stored in an IP set. Not applicable if using the nftables backend.", "type": "integer" }, "metadataAddr": { @@ -520,6 +545,32 @@ "pattern": "^([0-9]+(\\\\.[0-9]+)?(ms|s|m|h))*$", "type": "string" }, + "nftablesFilterAllowAction": { + "pattern": "^(?i)(Accept|Return)?$", + "type": "string" + }, + "nftablesFilterDenyAction": { + "description": "FilterDenyAction controls what happens to traffic that is denied by network policy. By default Calico blocks traffic with a \"drop\" action. If you want to use a \"reject\" action instead you can configure it here.", + "pattern": "^(?i)(Drop|Reject)?$", + "type": "string" + }, + "nftablesMangleAllowAction": { + "pattern": "^(?i)(Accept|Return)?$", + "type": "string" + }, + "nftablesMarkMask": { + "description": "MarkMask is the mask that Felix selects its nftables Mark bits from. Should be a 32 bit hexadecimal number with at least 8 bits set, none of which clash with any other mark bits in use on the system. [Default: 0xffff0000]", + "format": "int32", + "type": "integer" + }, + "nftablesMode": { + "description": "NFTablesMode configures nftables support in Felix. [Default: Disabled]", + "type": "string" + }, + "nftablesRefreshInterval": { + "description": "NftablesRefreshInterval controls the interval at which Felix periodically refreshes the nftables rules. [Default: 90s]", + "type": "string" + }, "openstackRegion": { "description": "OpenstackRegion is the name of the region that a particular Felix belongs to. In a multi-region Calico/OpenStack deployment, this must be configured somehow for each Felix (here in the datamodel, or in felix.cfg or the environment on each compute node), and must match the [calico] openstack_region value configured in neutron.conf on each node. [Default: Empty]", "type": "string" diff --git a/projectcalico.org/globalnetworkpolicy_v3.json b/projectcalico.org/globalnetworkpolicy_v3.json index 032da9d..67dec29 100644 --- a/projectcalico.org/globalnetworkpolicy_v3.json +++ b/projectcalico.org/globalnetworkpolicy_v3.json @@ -662,7 +662,7 @@ "type": "string" }, "order": { - "description": "Order is an optional field that specifies the order in which the policy is applied. Policies with higher \"order\" are applied after those with lower order. If the order is omitted, it may be considered to be \"infinite\" - i.e. the policy will be applied last. Policies with identical order will be applied in alphanumerical order based on the Policy \"Name\".", + "description": "Order is an optional field that specifies the order in which the policy is applied. Policies with higher \"order\" are applied after those with lower order within the same tier. If the order is omitted, it may be considered to be \"infinite\" - i.e. the policy will be applied last. Policies with identical order will be applied in alphanumerical order based on the Policy \"Name\" within the tier.", "type": "number" }, "performanceHints": { @@ -684,6 +684,10 @@ "description": "ServiceAccountSelector is an optional field for an expression used to select a pod based on service accounts.", "type": "string" }, + "tier": { + "description": "The name of the tier that this policy belongs to. If this is omitted, the default tier (name is \"default\") is assumed. The specified tier must exist in order to create security policies within the tier, the \"default\" tier is created automatically if it does not exist, this means for deployments requiring only a single Tier, the tier name may be omitted on all policy management requests.", + "type": "string" + }, "types": { "description": "Types indicates whether this policy applies to ingress, or to egress, or to both. When not explicitly specified (and so the value on creation is empty or nil), Calico defaults Types according to what Ingress and Egress rules are present in the policy. The default is: \n - [ PolicyTypeIngress ], if there are no Egress rules (including the case where there are also no Ingress rules) \n - [ PolicyTypeEgress ], if there are Egress rules but no Ingress rules \n - [ PolicyTypeIngress, PolicyTypeEgress ], if there are both Ingress and Egress rules. \n When the policy is read back again, Types will always be one of these values, never empty or nil.", "items": { diff --git a/projectcalico.org/networkpolicy_v3.json b/projectcalico.org/networkpolicy_v3.json index 686180e..c7321a3 100644 --- a/projectcalico.org/networkpolicy_v3.json +++ b/projectcalico.org/networkpolicy_v3.json @@ -650,7 +650,7 @@ "type": "array" }, "order": { - "description": "Order is an optional field that specifies the order in which the policy is applied. Policies with higher \"order\" are applied after those with lower order. If the order is omitted, it may be considered to be \"infinite\" - i.e. the policy will be applied last. Policies with identical order will be applied in alphanumerical order based on the Policy \"Name\".", + "description": "Order is an optional field that specifies the order in which the policy is applied. Policies with higher \"order\" are applied after those with lower order within the same tier. If the order is omitted, it may be considered to be \"infinite\" - i.e. the policy will be applied last. Policies with identical order will be applied in alphanumerical order based on the Policy \"Name\" within the tier.", "type": "number" }, "performanceHints": { @@ -668,6 +668,10 @@ "description": "ServiceAccountSelector is an optional field for an expression used to select a pod based on service accounts.", "type": "string" }, + "tier": { + "description": "The name of the tier that this policy belongs to. If this is omitted, the default tier (name is \"default\") is assumed. The specified tier must exist in order to create security policies within the tier, the \"default\" tier is created automatically if it does not exist, this means for deployments requiring only a single Tier, the tier name may be omitted on all policy management requests.", + "type": "string" + }, "types": { "description": "Types indicates whether this policy applies to ingress, or to egress, or to both. When not explicitly specified (and so the value on creation is empty or nil), Calico defaults Types according to what Ingress and Egress are present in the policy. The default is: \n - [ PolicyTypeIngress ], if there are no Egress rules (including the case where there are also no Ingress rules) \n - [ PolicyTypeEgress ], if there are Egress rules but no Ingress rules \n - [ PolicyTypeIngress, PolicyTypeEgress ], if there are both Ingress and Egress rules. \n When the policy is read back again, Types will always be one of these values, never empty or nil.", "items": { diff --git a/projectcalico.org/tier_v3.json b/projectcalico.org/tier_v3.json new file mode 100644 index 0000000..142ed2d --- /dev/null +++ b/projectcalico.org/tier_v3.json @@ -0,0 +1,35 @@ +{ + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "type": "object" + }, + "spec": { + "description": "TierSpec contains the specification for a security policy tier resource.", + "properties": { + "defaultAction": { + "description": "DefaultAction specifies the action applied to workloads selected by a policy in the tier, but not rule matched the workload's traffic. [Default: Deny]", + "enum": [ + "Pass", + "Deny" + ], + "type": "string" + }, + "order": { + "description": "Order is an optional field that specifies the order in which the tier is applied. Tiers with higher \"order\" are applied after those with lower order. If the order is omitted, it may be considered to be \"infinite\" - i.e. the tier will be applied last. Tiers with identical order will be applied in alphanumerical order based on the Tier \"Name\".", + "type": "number" + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object" +}