github.com/imran-kn/cilium-fork@v1.6.9/pkg/policy/resolve.go (about) 1 // Copyright 2018-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 policy 16 17 import ( 18 "github.com/cilium/cilium/pkg/identity" 19 "github.com/cilium/cilium/pkg/policy/trafficdirection" 20 ) 21 22 // selectorPolicy is a structure which contains the resolved policy for a 23 // particular Identity across all layers (L3, L4, and L7), with the policy 24 // still determined in terms of EndpointSelectors. 25 type selectorPolicy struct { 26 // Revision is the revision of the policy repository used to generate 27 // this selectorPolicy. 28 Revision uint64 29 30 // SelectorCache managing selectors in L4Policy 31 SelectorCache *SelectorCache 32 33 // L4Policy contains the computed L4 and L7 policy. 34 L4Policy *L4Policy 35 36 // CIDRPolicy contains the L3 (not L4) CIDR-based policy. 37 CIDRPolicy *CIDRPolicy 38 39 // IngressPolicyEnabled specifies whether this policy contains any policy 40 // at ingress. 41 IngressPolicyEnabled bool 42 43 // EgressPolicyEnabled specifies whether this policy contains any policy 44 // at egress. 45 EgressPolicyEnabled bool 46 } 47 48 func (p *selectorPolicy) Attach() { 49 if p.L4Policy != nil { 50 p.L4Policy.Attach() 51 } 52 } 53 54 // EndpointPolicy is a structure which contains the resolved policy across all 55 // layers (L3, L4, and L7), distilled against a set of identities. 56 type EndpointPolicy struct { 57 // Note that all Endpoints sharing the same identity will be 58 // referring to a shared selectorPolicy! 59 *selectorPolicy 60 61 // PolicyMapState contains the state of this policy as it relates to the 62 // datapath. In the future, this will be factored out of this object to 63 // decouple the policy as it relates to the datapath vs. its userspace 64 // representation. 65 // It maps each Key to the proxy port if proxy redirection is needed. 66 // Proxy port 0 indicates no proxy redirection. 67 // All fields within the Key and the proxy port must be in host byte-order. 68 PolicyMapState MapState 69 70 // PolicyMapChanges collects pending changes to the PolicyMapState 71 PolicyMapChanges MapChanges 72 73 // PolicyOwner describes any type which consumes this EndpointPolicy object. 74 PolicyOwner PolicyOwner 75 } 76 77 // PolicyOwner is anything which consumes a EndpointPolicy. 78 type PolicyOwner interface { 79 LookupRedirectPort(l4 *L4Filter) uint16 80 GetSecurityIdentity() *identity.Identity 81 } 82 83 // newSelectorPolicy returns an empty selectorPolicy stub. 84 func newSelectorPolicy(revision uint64, selectorCache *SelectorCache) *selectorPolicy { 85 return &selectorPolicy{ 86 Revision: revision, 87 SelectorCache: selectorCache, 88 } 89 } 90 91 // insertUser adds a user to the L4Policy so that incremental 92 // updates of the L4Policy may be fowarded. 93 func (p *selectorPolicy) insertUser(user *EndpointPolicy) { 94 if p.L4Policy != nil { 95 p.L4Policy.insertUser(user) 96 } 97 } 98 99 // Detach releases resources held by a selectorPolicy to enable 100 // successful eventual GC. Note that the selectorPolicy itself if not 101 // modified in any way, so that it can be used concurrently. 102 func (p *selectorPolicy) Detach() { 103 if p.L4Policy != nil { 104 p.L4Policy.Detach(p.SelectorCache) 105 } 106 } 107 108 // DistillPolicy filters down the specified selectorPolicy (which acts 109 // upon selectors) into a set of concrete map entries based on the 110 // SelectorCache. These can subsequently be plumbed into the datapath. 111 // 112 // Must be performed while holding the Repository lock. 113 func (p *selectorPolicy) DistillPolicy(policyOwner PolicyOwner) *EndpointPolicy { 114 calculatedPolicy := &EndpointPolicy{ 115 selectorPolicy: p, 116 PolicyMapState: make(MapState), 117 PolicyOwner: policyOwner, 118 } 119 120 if !p.IngressPolicyEnabled || !p.EgressPolicyEnabled { 121 calculatedPolicy.PolicyMapState.AllowAllIdentities( 122 !p.IngressPolicyEnabled, !p.EgressPolicyEnabled) 123 } 124 125 // Register the new EndpointPolicy as a receiver of delta 126 // updates. Any updates happening after this, but before 127 // computeDesiredL4PolicyMapEntires() call finishes may 128 // already be applied to the PolicyMapState, specifically: 129 // 130 // - PolicyMapChanges may contain an addition of an entry that 131 // is already added to the PolicyMapState 132 // 133 // - PolicyMapChanges may congtain a deletion of an entry that 134 // has already been deleted from PolicyMapState 135 p.insertUser(calculatedPolicy) 136 137 // Must come after the 'insertUser()' above to guarantee 138 // PolicyMapCanges will contain all changes that are applied 139 // after the computation of PolicyMapState has started. 140 calculatedPolicy.computeDesiredL4PolicyMapEntries() 141 calculatedPolicy.PolicyMapState.DetermineAllowLocalhostIngress(p.L4Policy) 142 143 return calculatedPolicy 144 } 145 146 // computeDesiredL4PolicyMapEntries transforms the EndpointPolicy.L4Policy into 147 // the datapath-friendly format inside EndpointPolicy.PolicyMapState. 148 func (p *EndpointPolicy) computeDesiredL4PolicyMapEntries() { 149 150 if p.L4Policy == nil { 151 return 152 } 153 p.computeDirectionL4PolicyMapEntries(p.L4Policy.Ingress, trafficdirection.Ingress) 154 p.computeDirectionL4PolicyMapEntries(p.L4Policy.Egress, trafficdirection.Egress) 155 } 156 157 func (p *EndpointPolicy) computeDirectionL4PolicyMapEntries(l4PolicyMap L4PolicyMap, direction trafficdirection.TrafficDirection) { 158 for _, filter := range l4PolicyMap { 159 keysFromFilter := filter.ToKeys(direction) 160 for _, keyFromFilter := range keysFromFilter { 161 var proxyPort uint16 162 // Preserve the already-allocated proxy ports for redirects that 163 // already exist. 164 if filter.IsRedirect() { 165 proxyPort = p.PolicyOwner.LookupRedirectPort(filter) 166 // If the currently allocated proxy port is 0, this is a new 167 // redirect, for which no port has been allocated yet. Ignore 168 // it for now. This will be configured by 169 // e.addNewRedirectsFromMap once the port has been allocated. 170 if proxyPort == 0 { 171 continue 172 } 173 } 174 p.PolicyMapState[keyFromFilter] = MapStateEntry{ProxyPort: proxyPort} 175 } 176 } 177 } 178 179 // NewEndpointPolicy returns an empty EndpointPolicy stub. 180 func NewEndpointPolicy(repo *Repository) *EndpointPolicy { 181 return &EndpointPolicy{ 182 selectorPolicy: newSelectorPolicy(0, repo.GetSelectorCache()), 183 } 184 }