github.com/imran-kn/cilium-fork@v1.6.9/pkg/policy/api/ingress.go (about)

     1  // Copyright 2016-2019 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 api
    16  
    17  import (
    18  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    19  )
    20  
    21  // IngressRule contains all rule types which can be applied at ingress,
    22  // i.e. network traffic that originates outside of the endpoint and
    23  // is entering the endpoint selected by the endpointSelector.
    24  //
    25  // - All members of this structure are optional. If omitted or empty, the
    26  //   member will have no effect on the rule.
    27  //
    28  // - If multiple members are set, all of them need to match in order for
    29  //   the rule to take effect. The exception to this rule is FromRequires field;
    30  //   the effects of any Requires field in any rule will apply to all other
    31  //   rules as well.
    32  //
    33  // - For now, combining ToPorts, FromCIDR, and FromEndpoints in the same rule
    34  //   is not supported and any such rules will be rejected. In the future, this
    35  //   will be supported and if multiple members of this structure are specified,
    36  //   then all members must match in order for the rule to take effect. The
    37  //   exception to this rule is the Requires field, the effects of any Requires
    38  //   field in any rule will apply to all other rules as well.
    39  type IngressRule struct {
    40  	// FromEndpoints is a list of endpoints identified by an
    41  	// EndpointSelector which are allowed to communicate with the endpoint
    42  	// subject to the rule.
    43  	//
    44  	// Example:
    45  	// Any endpoint with the label "role=backend" can be consumed by any
    46  	// endpoint carrying the label "role=frontend".
    47  	//
    48  	// +optional
    49  	FromEndpoints []EndpointSelector `json:"fromEndpoints,omitempty"`
    50  
    51  	// FromRequires is a list of additional constraints which must be met
    52  	// in order for the selected endpoints to be reachable. These
    53  	// additional constraints do no by itself grant access privileges and
    54  	// must always be accompanied with at least one matching FromEndpoints.
    55  	//
    56  	// Example:
    57  	// Any Endpoint with the label "team=A" requires consuming endpoint
    58  	// to also carry the label "team=A".
    59  	//
    60  	// +optional
    61  	FromRequires []EndpointSelector `json:"fromRequires,omitempty"`
    62  
    63  	// ToPorts is a list of destination ports identified by port number and
    64  	// protocol which the endpoint subject to the rule is allowed to
    65  	// receive connections on.
    66  	//
    67  	// Example:
    68  	// Any endpoint with the label "app=httpd" can only accept incoming
    69  	// connections on port 80/tcp.
    70  	//
    71  	// +optional
    72  	ToPorts []PortRule `json:"toPorts,omitempty"`
    73  
    74  	// FromCIDR is a list of IP blocks which the endpoint subject to the
    75  	// rule is allowed to receive connections from. Only connections which
    76  	// do *not* originate from the cluster or from the local host are subject
    77  	// to CIDR rules. In order to allow in-cluster connectivity, use the
    78  	// FromEndpoints field.  This will match on the source IP address of
    79  	// incoming connections. Adding  a prefix into FromCIDR or into
    80  	// FromCIDRSet with no ExcludeCIDRs is  equivalent.  Overlaps are
    81  	// allowed between FromCIDR and FromCIDRSet.
    82  	//
    83  	// Example:
    84  	// Any endpoint with the label "app=my-legacy-pet" is allowed to receive
    85  	// connections from 10.3.9.1
    86  	//
    87  	// +optional
    88  	FromCIDR CIDRSlice `json:"fromCIDR,omitempty"`
    89  
    90  	// FromCIDRSet is a list of IP blocks which the endpoint subject to the
    91  	// rule is allowed to receive connections from in addition to FromEndpoints,
    92  	// along with a list of subnets contained within their corresponding IP block
    93  	// from which traffic should not be allowed.
    94  	// This will match on the source IP address of incoming connections. Adding
    95  	// a prefix into FromCIDR or into FromCIDRSet with no ExcludeCIDRs is
    96  	// equivalent. Overlaps are allowed between FromCIDR and FromCIDRSet.
    97  	//
    98  	// Example:
    99  	// Any endpoint with the label "app=my-legacy-pet" is allowed to receive
   100  	// connections from 10.0.0.0/8 except from IPs in subnet 10.96.0.0/12.
   101  	//
   102  	// +optional
   103  	FromCIDRSet CIDRRuleSlice `json:"fromCIDRSet,omitempty"`
   104  
   105  	// FromEntities is a list of special entities which the endpoint subject
   106  	// to the rule is allowed to receive connections from. Supported entities are
   107  	// `world`, `cluster` and `host`
   108  	//
   109  	// +optional
   110  	FromEntities EntitySlice `json:"fromEntities,omitempty"`
   111  
   112  	// TODO: Move this to the policy package (https://github.com/cilium/cilium/issues/8353)
   113  	aggregatedSelectors EndpointSelectorSlice
   114  }
   115  
   116  // SetAggregatedSelectors creates a single slice containing all of the following
   117  // fields within the IngressRule, converted to EndpointSelector, to be stored
   118  // within the IngressRule for easy lookup while performing policy evaluation
   119  // for the rule:
   120  // * FromEntities
   121  // * FromCIDR
   122  // * FromCIDRSet
   123  //
   124  // FromEndpoints is not aggregated due to requirement folding in
   125  // GetSourceEndpointSelectorsWithRequirements()
   126  func (i *IngressRule) SetAggregatedSelectors() {
   127  	res := make(EndpointSelectorSlice, 0, len(i.FromEntities)+len(i.FromCIDR)+len(i.FromCIDRSet))
   128  	res = append(res, i.FromEntities.GetAsEndpointSelectors()...)
   129  	res = append(res, i.FromCIDR.GetAsEndpointSelectors()...)
   130  	res = append(res, i.FromCIDRSet.GetAsEndpointSelectors()...)
   131  	// Goroutines can race setting this, but they will all compute
   132  	// the same result, so it does not matter.
   133  	i.aggregatedSelectors = res
   134  }
   135  
   136  // GetSourceEndpointSelectorsWithRequirements returns a slice of endpoints selectors covering
   137  // all L3 source selectors of the ingress rule
   138  func (i *IngressRule) GetSourceEndpointSelectorsWithRequirements(requirements []metav1.LabelSelectorRequirement) EndpointSelectorSlice {
   139  	if i.aggregatedSelectors == nil {
   140  		i.SetAggregatedSelectors()
   141  	}
   142  	res := make(EndpointSelectorSlice, 0, len(i.FromEndpoints)+len(i.aggregatedSelectors))
   143  	if len(requirements) > 0 && len(i.FromEndpoints) > 0 {
   144  		for idx := range i.FromEndpoints {
   145  			sel := *i.FromEndpoints[idx].DeepCopy()
   146  			sel.MatchExpressions = append(sel.MatchExpressions, requirements...)
   147  			sel.SyncRequirementsWithLabelSelector()
   148  			// Even though this string is deep copied, we need to override it
   149  			// because we are updating the contents of the MatchExpressions.
   150  			sel.cachedLabelSelectorString = sel.LabelSelector.String()
   151  			res = append(res, sel)
   152  		}
   153  	} else {
   154  		res = append(res, i.FromEndpoints...)
   155  	}
   156  
   157  	return append(res, i.aggregatedSelectors...)
   158  }
   159  
   160  // IsLabelBased returns true whether the L3 source endpoints are selected based
   161  // on labels, i.e. either by setting FromEndpoints or FromEntities, or not
   162  // setting any From field.
   163  func (i *IngressRule) IsLabelBased() bool {
   164  	return len(i.FromRequires) == 0
   165  }