github.com/cilium/cilium@v1.16.2/pkg/policy/api/rule.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package api 5 6 import ( 7 "context" 8 "encoding/json" 9 10 "github.com/cilium/cilium/pkg/labels" 11 ) 12 13 // AuthenticationMode is a string identifying a supported authentication type 14 type AuthenticationMode string 15 16 const ( 17 AuthenticationModeDisabled AuthenticationMode = "disabled" // Always succeeds 18 AuthenticationModeRequired AuthenticationMode = "required" // Mutual TLS with SPIFFE as certificate provider by default 19 AuthenticationModeAlwaysFail AuthenticationMode = "test-always-fail" 20 ) 21 22 // Authentication specifies the kind of cryptographic authentication required for the traffic to 23 // be allowed. 24 type Authentication struct { 25 // Mode is the required authentication mode for the allowed traffic, if any. 26 // 27 // +kubebuilder:validation:Enum=disabled;required;test-always-fail 28 // +kubebuilder:validation:Required 29 Mode AuthenticationMode `json:"mode"` 30 } 31 32 // DefaultDenyConfig expresses a policy's desired default mode for the subject 33 // endpoints. 34 type DefaultDenyConfig struct { 35 // Whether or not the endpoint should have a default-deny rule applied 36 // to ingress traffic. 37 // 38 // +kubebuilder:validation:Optional 39 Ingress *bool `json:"ingress,omitempty"` 40 41 // Whether or not the endpoint should have a default-deny rule applied 42 // to egress traffic. 43 // 44 // +kubebuilder:validation:Optional 45 Egress *bool `json:"egress,omitempty"` 46 } 47 48 // Rule is a policy rule which must be applied to all endpoints which match the 49 // labels contained in the endpointSelector 50 // 51 // Each rule is split into an ingress section which contains all rules 52 // applicable at ingress, and an egress section applicable at egress. For rule 53 // types such as `L4Rule` and `CIDR` which can be applied at both ingress and 54 // egress, both ingress and egress side have to either specifically allow the 55 // connection or one side has to be omitted. 56 // 57 // Either ingress, egress, or both can be provided. If both ingress and egress 58 // are omitted, the rule has no effect. 59 // 60 // +deepequal-gen:private-method=true 61 type Rule struct { 62 // EndpointSelector selects all endpoints which should be subject to 63 // this rule. EndpointSelector and NodeSelector cannot be both empty and 64 // are mutually exclusive. 65 // 66 // +kubebuilder:validation:OneOf 67 EndpointSelector EndpointSelector `json:"endpointSelector,omitempty"` 68 69 // NodeSelector selects all nodes which should be subject to this rule. 70 // EndpointSelector and NodeSelector cannot be both empty and are mutually 71 // exclusive. Can only be used in CiliumClusterwideNetworkPolicies. 72 // 73 // +kubebuilder:validation:OneOf 74 NodeSelector EndpointSelector `json:"nodeSelector,omitempty"` 75 76 // Ingress is a list of IngressRule which are enforced at ingress. 77 // If omitted or empty, this rule does not apply at ingress. 78 // 79 // +kubebuilder:validation:Optional 80 Ingress []IngressRule `json:"ingress,omitempty"` 81 82 // IngressDeny is a list of IngressDenyRule which are enforced at ingress. 83 // Any rule inserted here will be denied regardless of the allowed ingress 84 // rules in the 'ingress' field. 85 // If omitted or empty, this rule does not apply at ingress. 86 // 87 // +kubebuilder:validation:Optional 88 IngressDeny []IngressDenyRule `json:"ingressDeny,omitempty"` 89 90 // Egress is a list of EgressRule which are enforced at egress. 91 // If omitted or empty, this rule does not apply at egress. 92 // 93 // +kubebuilder:validation:Optional 94 Egress []EgressRule `json:"egress,omitempty"` 95 96 // EgressDeny is a list of EgressDenyRule which are enforced at egress. 97 // Any rule inserted here will be denied regardless of the allowed egress 98 // rules in the 'egress' field. 99 // If omitted or empty, this rule does not apply at egress. 100 // 101 // +kubebuilder:validation:Optional 102 EgressDeny []EgressDenyRule `json:"egressDeny,omitempty"` 103 104 // Labels is a list of optional strings which can be used to 105 // re-identify the rule or to store metadata. It is possible to lookup 106 // or delete strings based on labels. Labels are not required to be 107 // unique, multiple rules can have overlapping or identical labels. 108 // 109 // +kubebuilder:validation:Optional 110 Labels labels.LabelArray `json:"labels,omitempty"` 111 112 // EnableDefaultDeny determines whether this policy configures the 113 // subject endpoint(s) to have a default deny mode. If enabled, 114 // this causes all traffic not explicitly allowed by a network policy 115 // to be dropped. 116 // 117 // If not specified, the default is true for each traffic direction 118 // that has rules, and false otherwise. For example, if a policy 119 // only has Ingress or IngressDeny rules, then the default for 120 // ingress is true and egress is false. 121 // 122 // If multiple policies apply to an endpoint, that endpoint's default deny 123 // will be enabled if any policy requests it. 124 // 125 // This is useful for creating broad-based network policies that will not 126 // cause endpoints to enter default-deny mode. 127 // 128 // +kubebuilder:validation:Optional 129 EnableDefaultDeny DefaultDenyConfig `json:"enableDefaultDeny,omitempty"` 130 131 // Description is a free form string, it can be used by the creator of 132 // the rule to store human readable explanation of the purpose of this 133 // rule. Rules cannot be identified by comment. 134 // 135 // +kubebuilder:validation:Optional 136 Description string `json:"description,omitempty"` 137 } 138 139 // MarshalJSON returns the JSON encoding of Rule r. We need to overwrite it to 140 // enforce omitempty on the EndpointSelector nested structures. 141 func (r *Rule) MarshalJSON() ([]byte, error) { 142 type common struct { 143 Ingress []IngressRule `json:"ingress,omitempty"` 144 IngressDeny []IngressDenyRule `json:"ingressDeny,omitempty"` 145 Egress []EgressRule `json:"egress,omitempty"` 146 EgressDeny []EgressDenyRule `json:"egressDeny,omitempty"` 147 Labels labels.LabelArray `json:"labels,omitempty"` 148 EnableDefaultDeny DefaultDenyConfig `json:"enableDefaultDeny,omitempty"` 149 Description string `json:"description,omitempty"` 150 } 151 152 var a interface{} 153 ruleCommon := common{ 154 Ingress: r.Ingress, 155 IngressDeny: r.IngressDeny, 156 Egress: r.Egress, 157 EgressDeny: r.EgressDeny, 158 Labels: r.Labels, 159 EnableDefaultDeny: r.EnableDefaultDeny, 160 Description: r.Description, 161 } 162 163 // Only one of endpointSelector or nodeSelector is permitted. 164 switch { 165 case r.EndpointSelector.LabelSelector != nil: 166 a = struct { 167 EndpointSelector EndpointSelector `json:"endpointSelector,omitempty"` 168 common 169 }{ 170 EndpointSelector: r.EndpointSelector, 171 common: ruleCommon, 172 } 173 case r.NodeSelector.LabelSelector != nil: 174 a = struct { 175 NodeSelector EndpointSelector `json:"nodeSelector,omitempty"` 176 common 177 }{ 178 NodeSelector: r.NodeSelector, 179 common: ruleCommon, 180 } 181 } 182 183 return json.Marshal(a) 184 } 185 186 func (r *Rule) DeepEqual(o *Rule) bool { 187 switch { 188 case (r == nil) != (o == nil): 189 return false 190 case (r == nil) && (o == nil): 191 return true 192 } 193 return r.deepEqual(o) 194 } 195 196 // NewRule builds a new rule with no selector and no policy. 197 func NewRule() *Rule { 198 return &Rule{} 199 } 200 201 // WithEndpointSelector configures the Rule with the specified selector. 202 func (r *Rule) WithEndpointSelector(es EndpointSelector) *Rule { 203 r.EndpointSelector = es 204 return r 205 } 206 207 // WithIngressRules configures the Rule with the specified rules. 208 func (r *Rule) WithIngressRules(rules []IngressRule) *Rule { 209 r.Ingress = rules 210 return r 211 } 212 213 // WithIngressDenyRules configures the Rule with the specified rules. 214 func (r *Rule) WithIngressDenyRules(rules []IngressDenyRule) *Rule { 215 r.IngressDeny = rules 216 return r 217 } 218 219 // WithEgressRules configures the Rule with the specified rules. 220 func (r *Rule) WithEgressRules(rules []EgressRule) *Rule { 221 r.Egress = rules 222 return r 223 } 224 225 // WithEgressDenyRules configures the Rule with the specified rules. 226 func (r *Rule) WithEgressDenyRules(rules []EgressDenyRule) *Rule { 227 r.EgressDeny = rules 228 return r 229 } 230 231 // WithLabels configures the Rule with the specified labels metadata. 232 func (r *Rule) WithLabels(labels labels.LabelArray) *Rule { 233 r.Labels = labels 234 return r 235 } 236 237 // WithDescription configures the Rule with the specified description metadata. 238 func (r *Rule) WithDescription(desc string) *Rule { 239 r.Description = desc 240 return r 241 } 242 243 // RequiresDerivative it return true if the rule has a derivative rule. 244 func (r *Rule) RequiresDerivative() bool { 245 for _, rule := range r.Egress { 246 if rule.RequiresDerivative() { 247 return true 248 } 249 } 250 for _, rule := range r.EgressDeny { 251 if rule.RequiresDerivative() { 252 return true 253 } 254 } 255 for _, rule := range r.Ingress { 256 if rule.RequiresDerivative() { 257 return true 258 } 259 } 260 for _, rule := range r.IngressDeny { 261 if rule.RequiresDerivative() { 262 return true 263 } 264 } 265 return false 266 } 267 268 // CreateDerivative will return a new Rule with the new data based gather 269 // by the rules that autogenerated new Rule 270 func (r *Rule) CreateDerivative(ctx context.Context) (*Rule, error) { 271 newRule := r.DeepCopy() 272 newRule.Egress = []EgressRule{} 273 newRule.EgressDeny = []EgressDenyRule{} 274 newRule.Ingress = []IngressRule{} 275 newRule.IngressDeny = []IngressDenyRule{} 276 277 for _, egressRule := range r.Egress { 278 derivativeEgressRule, err := egressRule.CreateDerivative(ctx) 279 if err != nil { 280 return newRule, err 281 } 282 newRule.Egress = append(newRule.Egress, *derivativeEgressRule) 283 } 284 285 for _, egressDenyRule := range r.EgressDeny { 286 derivativeEgressDenyRule, err := egressDenyRule.CreateDerivative(ctx) 287 if err != nil { 288 return newRule, err 289 } 290 newRule.EgressDeny = append(newRule.EgressDeny, *derivativeEgressDenyRule) 291 } 292 293 for _, ingressRule := range r.Ingress { 294 derivativeIngressRule, err := ingressRule.CreateDerivative(ctx) 295 if err != nil { 296 return newRule, err 297 } 298 newRule.Ingress = append(newRule.Ingress, *derivativeIngressRule) 299 } 300 301 for _, ingressDenyRule := range r.IngressDeny { 302 derivativeDenyIngressRule, err := ingressDenyRule.CreateDerivative(ctx) 303 if err != nil { 304 return newRule, err 305 } 306 newRule.IngressDeny = append(newRule.IngressDeny, *derivativeDenyIngressRule) 307 } 308 return newRule, nil 309 }