blob: b67858aed42b8f57477332c0c4d5b4ea6b168fdf [file] [log] [blame]
Jian Li73d3b6a2019-07-08 18:07:53 +09001/*
2 * Copyright 2019-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.k8snetworking.impl;
17
Jian Li0f459612019-07-11 10:38:02 +090018import com.google.common.collect.ImmutableSet;
Jian Li73d3b6a2019-07-08 18:07:53 +090019import com.google.common.collect.Maps;
Jian Li0f459612019-07-11 10:38:02 +090020import com.google.common.collect.Sets;
Jian Lie1a5b8f2019-07-23 17:13:19 +090021import io.fabric8.kubernetes.api.model.LabelSelectorRequirement;
22import io.fabric8.kubernetes.api.model.Namespace;
Jian Li73d3b6a2019-07-08 18:07:53 +090023import io.fabric8.kubernetes.api.model.Pod;
Jian Lie1a5b8f2019-07-23 17:13:19 +090024import io.fabric8.kubernetes.api.model.Service;
Jian Li73d3b6a2019-07-08 18:07:53 +090025import io.fabric8.kubernetes.api.model.networking.NetworkPolicy;
Jian Lib7dfb5b2019-07-15 17:37:12 +090026import io.fabric8.kubernetes.api.model.networking.NetworkPolicyEgressRule;
27import io.fabric8.kubernetes.api.model.networking.NetworkPolicyIngressRule;
Jian Lie1a5b8f2019-07-23 17:13:19 +090028import io.fabric8.kubernetes.api.model.networking.NetworkPolicyPeer;
Jian Li73d3b6a2019-07-08 18:07:53 +090029import io.fabric8.kubernetes.api.model.networking.NetworkPolicyPort;
Jian Li73d3b6a2019-07-08 18:07:53 +090030import org.onlab.packet.IPv4;
31import org.onlab.packet.IpAddress;
32import org.onlab.packet.IpPrefix;
33import org.onlab.packet.TpPort;
34import org.onosproject.cfg.ComponentConfigService;
35import org.onosproject.cluster.ClusterService;
36import org.onosproject.cluster.LeadershipService;
37import org.onosproject.cluster.NodeId;
38import org.onosproject.core.ApplicationId;
39import org.onosproject.core.CoreService;
40import org.onosproject.k8snetworking.api.K8sFlowRuleService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090041import org.onosproject.k8snetworking.api.K8sNamespaceEvent;
42import org.onosproject.k8snetworking.api.K8sNamespaceListener;
Jian Li0f459612019-07-11 10:38:02 +090043import org.onosproject.k8snetworking.api.K8sNamespaceService;
Jian Li73d3b6a2019-07-08 18:07:53 +090044import org.onosproject.k8snetworking.api.K8sNetworkPolicyEvent;
45import org.onosproject.k8snetworking.api.K8sNetworkPolicyListener;
46import org.onosproject.k8snetworking.api.K8sNetworkPolicyService;
47import org.onosproject.k8snetworking.api.K8sNetworkService;
48import org.onosproject.k8snetworking.api.K8sPodEvent;
49import org.onosproject.k8snetworking.api.K8sPodListener;
50import org.onosproject.k8snetworking.api.K8sPodService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090051import org.onosproject.k8snetworking.api.K8sServiceEvent;
52import org.onosproject.k8snetworking.api.K8sServiceListener;
53import org.onosproject.k8snetworking.api.K8sServiceService;
Jian Li73d3b6a2019-07-08 18:07:53 +090054import org.onosproject.k8snode.api.K8sNodeService;
55import org.onosproject.net.device.DeviceService;
56import org.onosproject.net.driver.DriverService;
57import org.onosproject.net.flow.DefaultTrafficSelector;
58import org.onosproject.net.flow.DefaultTrafficTreatment;
59import org.onosproject.net.flow.TrafficSelector;
60import org.onosproject.net.flow.TrafficTreatment;
61import org.onosproject.store.service.StorageService;
62import org.osgi.service.component.annotations.Activate;
63import org.osgi.service.component.annotations.Component;
64import org.osgi.service.component.annotations.Deactivate;
65import org.osgi.service.component.annotations.Reference;
66import org.osgi.service.component.annotations.ReferenceCardinality;
67import org.slf4j.Logger;
68
69import java.util.List;
70import java.util.Map;
71import java.util.Objects;
Jian Li0f459612019-07-11 10:38:02 +090072import java.util.Set;
Jian Li73d3b6a2019-07-08 18:07:53 +090073import java.util.concurrent.ExecutorService;
Jian Lie1a5b8f2019-07-23 17:13:19 +090074import java.util.concurrent.atomic.AtomicReference;
Jian Li73d3b6a2019-07-08 18:07:53 +090075
76import static java.util.concurrent.Executors.newSingleThreadExecutor;
Jian Lie1a5b8f2019-07-23 17:13:19 +090077import static org.onlab.packet.Ethernet.TYPE_IPV4;
Jian Li73d3b6a2019-07-08 18:07:53 +090078import static org.onlab.util.Tools.groupedThreads;
Jian Li0f459612019-07-11 10:38:02 +090079import static org.onosproject.k8snetworking.api.Constants.ACL_EGRESS_BLACK_TABLE;
80import static org.onosproject.k8snetworking.api.Constants.ACL_EGRESS_WHITE_TABLE;
81import static org.onosproject.k8snetworking.api.Constants.ACL_INGRESS_BLACK_TABLE;
82import static org.onosproject.k8snetworking.api.Constants.ACL_INGRESS_WHITE_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090083import static org.onosproject.k8snetworking.api.Constants.ACL_TABLE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090084import static org.onosproject.k8snetworking.api.Constants.DEFAULT_METADATA_MASK;
85import static org.onosproject.k8snetworking.api.Constants.DEFAULT_NAMESPACE_HASH;
86import static org.onosproject.k8snetworking.api.Constants.DEFAULT_SEGMENT_ID;
87import static org.onosproject.k8snetworking.api.Constants.GROUPING_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090088import static org.onosproject.k8snetworking.api.Constants.K8S_NETWORKING_APP_ID;
Jian Lie1a5b8f2019-07-23 17:13:19 +090089import static org.onosproject.k8snetworking.api.Constants.NAMESPACE_TABLE;
Jian Li73d3b6a2019-07-08 18:07:53 +090090import static org.onosproject.k8snetworking.api.Constants.PRIORITY_CIDR_RULE;
Jian Lie1a5b8f2019-07-23 17:13:19 +090091import static org.onosproject.k8snetworking.api.Constants.PRIORITY_NAMESPACE_RULE;
Jian Li73d3b6a2019-07-08 18:07:53 +090092import static org.onosproject.k8snetworking.api.Constants.ROUTING_TABLE;
93import static org.onosproject.k8snetworking.api.Constants.SHIFTED_IP_PREFIX;
Jian Lie1a5b8f2019-07-23 17:13:19 +090094import static org.onosproject.k8snetworking.impl.OsgiPropertyConstants.SERVICE_IP_CIDR_DEFAULT;
95import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByNamespace;
96import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByPodIp;
97import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.namespaceHashByServiceIp;
Jian Li73d3b6a2019-07-08 18:07:53 +090098import static org.onosproject.k8snetworking.util.K8sNetworkingUtil.shiftIpDomain;
99import static org.slf4j.LoggerFactory.getLogger;
100
101/**
102 * Handles the ACL by referring to the network policy defined through kubernetes.
103 */
104@Component(immediate = true)
105public class K8sNetworkPolicyHandler {
106
107 private final Logger log = getLogger(getClass());
108
109 private static final String DIRECTION_INGRESS = "ingress";
110 private static final String DIRECTION_EGRESS = "egress";
111
112 private static final String PROTOCOL_TCP = "tcp";
113 private static final String PROTOCOL_UDP = "udp";
114
Jian Lie1a5b8f2019-07-23 17:13:19 +0900115 private static final String KUBE_SYSTEM = "kube-system";
116
Jian Li73d3b6a2019-07-08 18:07:53 +0900117 private static final int HOST_PREFIX = 32;
118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
120 protected CoreService coreService;
121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
123 protected LeadershipService leadershipService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
126 protected ClusterService clusterService;
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY)
129 protected DriverService driverService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY)
132 protected DeviceService deviceService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY)
135 protected ComponentConfigService configService;
136
137 @Reference(cardinality = ReferenceCardinality.MANDATORY)
138 protected StorageService storageService;
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY)
141 protected K8sNetworkService k8sNetworkService;
142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY)
144 protected K8sFlowRuleService k8sFlowRuleService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY)
147 protected K8sNodeService k8sNodeService;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY)
150 protected K8sPodService k8sPodService;
151
152 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lie1a5b8f2019-07-23 17:13:19 +0900153 protected K8sServiceService k8sServiceService;
154
155 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li73d3b6a2019-07-08 18:07:53 +0900156 protected K8sNetworkPolicyService k8sNetworkPolicyService;
157
Jian Li0f459612019-07-11 10:38:02 +0900158 @Reference(cardinality = ReferenceCardinality.MANDATORY)
159 protected K8sNamespaceService k8sNamespaceService;
160
Jian Li73d3b6a2019-07-08 18:07:53 +0900161 private final ExecutorService eventExecutor = newSingleThreadExecutor(
162 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
163 private final InternalPodListener internalPodListener =
164 new InternalPodListener();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900165 private final InternalServiceListener internalServiceListener =
166 new InternalServiceListener();
Jian Li73d3b6a2019-07-08 18:07:53 +0900167 private final InternalNetworkPolicyListener internalNetworkPolicyListener =
168 new InternalNetworkPolicyListener();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900169 private final InternalNamespaceListener internalNamespaceListener =
170 new InternalNamespaceListener();
Jian Li73d3b6a2019-07-08 18:07:53 +0900171
172 private ApplicationId appId;
173 private NodeId localNodeId;
174
175 @Activate
176 protected void activate() {
177 appId = coreService.registerApplication(K8S_NETWORKING_APP_ID);
178
179 localNodeId = clusterService.getLocalNode().id();
180 leadershipService.runForLeadership(appId.name());
181 k8sPodService.addListener(internalPodListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900182 k8sServiceService.addListener(internalServiceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900183 k8sNetworkPolicyService.addListener(internalNetworkPolicyListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900184 k8sNamespaceService.addListener(internalNamespaceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900185
186 log.info("Started");
187 }
188
189 @Deactivate
190 protected void deactivate() {
191 leadershipService.withdraw(appId.name());
192 k8sPodService.removeListener(internalPodListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900193 k8sServiceService.removeListener(internalServiceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900194 k8sNetworkPolicyService.removeListener(internalNetworkPolicyListener);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900195 k8sNamespaceService.removeListener(internalNamespaceListener);
Jian Li73d3b6a2019-07-08 18:07:53 +0900196 eventExecutor.shutdown();
197
198 log.info("Stopped");
199 }
200
201 private void setBlockRulesByPolicy(NetworkPolicy policy, boolean install) {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900202 final Map<String, List<String>> filter = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900203
Jian Lib7dfb5b2019-07-15 17:37:12 +0900204 k8sPodService.pods().forEach(pod ->
205 filter.putAll(getBlockRuleFilter(pod, policy)));
Jian Li73d3b6a2019-07-08 18:07:53 +0900206
207 setBlockRules(filter, install);
208 }
209
210 private void setBlockRulesByPod(Pod pod, boolean install) {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900211 final Map<String, List<String>> filter = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900212
Jian Lib7dfb5b2019-07-15 17:37:12 +0900213 k8sNetworkPolicyService.networkPolicies().forEach(policy ->
214 filter.putAll(getBlockRuleFilter(pod, policy)));
Jian Li73d3b6a2019-07-08 18:07:53 +0900215
216 setBlockRules(filter, install);
217 }
218
Jian Lib7dfb5b2019-07-15 17:37:12 +0900219 private Map<String, List<String>> getBlockRuleFilter(Pod pod, NetworkPolicy policy) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900220
221 // if the POD is not included in the namespace of the given policy,
222 // we do not block the POD
223 if (!pod.getMetadata().getNamespace().equals(policy.getMetadata().getNamespace())) {
224 return Maps.newConcurrentMap();
225 }
226
Jian Lib7dfb5b2019-07-15 17:37:12 +0900227 Map<String, String> labels = policy.getSpec().getPodSelector().getMatchLabels();
228 Map<String, List<String>> filter = Maps.newConcurrentMap();
229 String podIp = pod.getStatus().getPodIP();
230 List<String> policyTypes = policy.getSpec().getPolicyTypes();
231
232 if (podIp != null && policyTypes != null) {
233 if (labels == null) {
234 filter.put(podIp, policyTypes);
235 } else {
236 pod.getMetadata().getLabels().forEach((k, v) -> {
237 if (labels.get(k) != null && labels.get(k).equals(v)) {
238 filter.put(podIp, policyTypes);
239 }
240 });
241 }
242 }
243
244 return filter;
245 }
246
Jian Li73d3b6a2019-07-08 18:07:53 +0900247 private void setBlockRules(Map<String, List<String>> filter, boolean install) {
248 filter.forEach((k, v) -> {
249 v.forEach(d -> {
250 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900251 .matchEthType(TYPE_IPV4);
Jian Li73d3b6a2019-07-08 18:07:53 +0900252 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900253
254 Integer nsHash = namespaceHashByPodIp(k8sPodService, k8sNamespaceService, k);
255 if (nsHash != null) {
256 tBuilder.setTunnelId(nsHash);
257 }
258
Jian Li73d3b6a2019-07-08 18:07:53 +0900259 if (d.equalsIgnoreCase(DIRECTION_INGRESS)) {
260 sBuilder.matchIPDst(IpPrefix.valueOf(IpAddress.valueOf(k), HOST_PREFIX));
Jian Li0f459612019-07-11 10:38:02 +0900261 tBuilder.transition(ACL_INGRESS_WHITE_TABLE);
Jian Lic9d183c2019-07-30 17:10:39 +0900262 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900263 } else if (d.equalsIgnoreCase(DIRECTION_EGRESS)) {
Jian Lic9d183c2019-07-30 17:10:39 +0900264 // original IP
Jian Li73d3b6a2019-07-08 18:07:53 +0900265 sBuilder.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(k), HOST_PREFIX));
Jian Li0f459612019-07-11 10:38:02 +0900266 tBuilder.transition(ACL_EGRESS_WHITE_TABLE);
Jian Lic9d183c2019-07-30 17:10:39 +0900267 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900268
Jian Lic9d183c2019-07-30 17:10:39 +0900269
270 // shifted IP
271 sBuilder.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(
272 shiftIpDomain(k, SHIFTED_IP_PREFIX)), HOST_PREFIX));
273 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
274 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900275 });
276 });
277 }
278
Jian Lie1a5b8f2019-07-23 17:13:19 +0900279 private void setDefaultAllowNamespaceRules(Namespace namespace, boolean install) {
280
281 String ns = namespace.getMetadata().getName();
282 if (KUBE_SYSTEM.equalsIgnoreCase(ns)) {
283 setAllowNamespaceRulesBase(0, namespace.hashCode(),
284 DIRECTION_INGRESS, install);
285 }
286 }
287
288 private void setDefaultAllowServiceRules(boolean install) {
289 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
290 .matchEthType(TYPE_IPV4)
291 .matchIPSrc(IpPrefix.valueOf(SERVICE_IP_CIDR_DEFAULT));
292 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
293 .setTunnelId(DEFAULT_SEGMENT_ID)
294 .transition(ROUTING_TABLE);
295
296 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
297 }
298
299 private void setAllowNamespaceRulesBase(int tunnelId, int metadata,
300 String direction, boolean install) {
301 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
302
303 if (tunnelId != 0) {
304 sBuilder.matchTunnelId(tunnelId);
305 }
306
307 sBuilder.matchMetadata(metadata);
308 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
309 .setTunnelId(DEFAULT_SEGMENT_ID)
310 .transition(ROUTING_TABLE);
311
Jian Lie1a5b8f2019-07-23 17:13:19 +0900312 if (DIRECTION_INGRESS.equals(direction)) {
Jian Li2744b972019-07-30 19:12:07 +0900313 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900314 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900315 }
316
Jian Li73d3b6a2019-07-08 18:07:53 +0900317 private void setAllowRulesByPolicy(NetworkPolicy policy, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900318 Map<String, Map<String, List<NetworkPolicyPort>>>
319 white = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900320
Jian Lie1a5b8f2019-07-23 17:13:19 +0900321 int nsHash = namespaceHashByNamespace(k8sNamespaceService,
322 policy.getMetadata().getNamespace());
323
Jian Lib7dfb5b2019-07-15 17:37:12 +0900324 List<NetworkPolicyIngressRule> ingress = policy.getSpec().getIngress();
325 if (ingress != null && ingress.size() == 1) {
326 NetworkPolicyIngressRule rule = ingress.get(0);
327 if (rule.getFrom().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900328 setAllowAllRule(nsHash, DIRECTION_INGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900329 }
330 }
331
Jian Li73d3b6a2019-07-08 18:07:53 +0900332 policy.getSpec().getIngress().forEach(i -> {
333 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
334 direction.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900335 i.getFrom().forEach(peer -> {
336
337 // IP block
338 if (peer.getIpBlock() != null) {
339 if (peer.getIpBlock().getExcept() != null &&
340 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900341 Map<String, List<NetworkPolicyPort>>
342 blkDirection = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900343
Jian Li0f459612019-07-11 10:38:02 +0900344 blkDirection.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900345 white.compute(peer.getIpBlock().getCidr(), (k, v) -> blkDirection);
Jian Li73d3b6a2019-07-08 18:07:53 +0900346
Jian Lie1a5b8f2019-07-23 17:13:19 +0900347 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_INGRESS,
348 peer.getIpBlock().getExcept(), install);
Jian Li0f459612019-07-11 10:38:02 +0900349 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900350 white.compute(peer.getIpBlock().getCidr(), (k, v) -> direction);
Jian Li0f459612019-07-11 10:38:02 +0900351 }
352 }
353
Jian Lie1a5b8f2019-07-23 17:13:19 +0900354 // POD selector
Jian Lif3b595b2019-07-28 21:35:49 +0900355 Set<Pod> pods = podsFromPolicyPeer(peer, policy.getMetadata().getNamespace());
Jian Li0f459612019-07-11 10:38:02 +0900356
Jian Li2744b972019-07-30 19:12:07 +0900357 pods.stream()
358 .filter(pod -> pod.getStatus().getPodIP() != null)
359 .forEach(pod -> {
Jian Li0f459612019-07-11 10:38:02 +0900360 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
361 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> direction);
362 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX, (m, n) -> direction);
Jian Li73d3b6a2019-07-08 18:07:53 +0900363 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900364
365 // Namespace selector
366 setAllowNamespaceRules(nsHash,
367 namespacesByPolicyPeer(peer), DIRECTION_INGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900368 });
369 });
370
Jian Lib7dfb5b2019-07-15 17:37:12 +0900371 List<NetworkPolicyEgressRule> egress = policy.getSpec().getEgress();
372 if (egress != null && egress.size() == 1) {
373 NetworkPolicyEgressRule rule = egress.get(0);
374 if (rule.getTo().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900375 setAllowAllRule(nsHash, DIRECTION_EGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900376 }
377 }
378
Jian Li73d3b6a2019-07-08 18:07:53 +0900379 policy.getSpec().getEgress().forEach(e -> {
380 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
381 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900382 e.getTo().forEach(peer -> {
383
384 // IP block
385 if (peer.getIpBlock() != null) {
386 if (peer.getIpBlock().getExcept() != null &&
387 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900388
389 Map<String, List<NetworkPolicyPort>>
390 blkDirection = Maps.newConcurrentMap();
391 blkDirection.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900392 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900393 if (v != null) {
394 v.put(DIRECTION_EGRESS, e.getPorts());
395 return v;
396 } else {
397 return blkDirection;
398 }
399 });
400
Jian Lie1a5b8f2019-07-23 17:13:19 +0900401 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_EGRESS,
402 peer.getIpBlock().getExcept(), install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900403 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900404 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900405 if (v != null) {
406 v.put(DIRECTION_EGRESS, e.getPorts());
407 return v;
408 } else {
409 return direction;
410 }
411 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900412 }
Jian Li0f459612019-07-11 10:38:02 +0900413 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900414
Jian Lie1a5b8f2019-07-23 17:13:19 +0900415 // POD selector
Jian Lif3b595b2019-07-28 21:35:49 +0900416 Set<Pod> pods = podsFromPolicyPeer(peer, policy.getMetadata().getNamespace());
Jian Li0f459612019-07-11 10:38:02 +0900417
Jian Li2744b972019-07-30 19:12:07 +0900418 pods.stream()
419 .filter(pod -> pod.getStatus().getPodIP() != null)
420 .forEach(pod -> {
Jian Li0f459612019-07-11 10:38:02 +0900421 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
422 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> {
423 if (n != null) {
424 n.put(DIRECTION_EGRESS, e.getPorts());
425 return n;
426 } else {
427 return direction;
428 }
429 });
430
431 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX,
432 (m, n) -> {
433 if (n != null) {
434 n.put(DIRECTION_EGRESS, e.getPorts());
435 return n;
436 } else {
437 return direction;
Jian Li73d3b6a2019-07-08 18:07:53 +0900438 }
439 });
440 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900441
442 // Namespace selector
443 setAllowNamespaceRules(nsHash,
444 namespacesByPolicyPeer(peer), DIRECTION_EGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900445 });
446 });
447
Jian Lie1a5b8f2019-07-23 17:13:19 +0900448 setAllowRules(namespaceHashByNamespace(k8sNamespaceService,
449 policy.getMetadata().getNamespace()), white, install);
Jian Li0f459612019-07-11 10:38:02 +0900450 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900451 }
452
Jian Lif3b595b2019-07-28 21:35:49 +0900453 private Set<Pod> podsFromPolicyPeer(NetworkPolicyPeer peer, String namespace) {
454 Set<Pod> pods = Sets.newConcurrentHashSet();
455 if (peer.getPodSelector() != null) {
456 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
457 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
458
459 if (podLabels == null && matchExps.size() == 0) {
460 k8sPodService.pods().stream()
461 .filter(pod -> pod.getMetadata().getNamespace().equals(
462 namespace))
463 .forEach(pods::add);
464 } else {
465 k8sPodService.pods().stream()
466 .filter(pod -> pod.getMetadata().getNamespace().equals(
467 namespace))
468 .forEach(pod -> {
469 pod.getMetadata().getLabels().forEach((k, v) -> {
470 if (podLabels != null && podLabels.get(k) != null &&
471 podLabels.get(k).equals(v)) {
472 pods.add(pod);
473 }
474 });
475 });
476 }
477 }
478 return pods;
479 }
480
Jian Li73d3b6a2019-07-08 18:07:53 +0900481 private void setAllowRulesByPod(Pod pod, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900482 Map<String, Map<String, List<NetworkPolicyPort>>>
483 white = Maps.newConcurrentMap();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900484 AtomicReference<NetworkPolicy> selectedPolicy = new AtomicReference<>();
485 k8sNetworkPolicyService.networkPolicies().stream()
486 .filter(policy -> policy.getMetadata().getNamespace().equals(
487 pod.getMetadata().getNamespace()))
488 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900489 String podIp = pod.getStatus().getPodIP();
490
Jian Li73d3b6a2019-07-08 18:07:53 +0900491 policy.getSpec().getIngress().forEach(i -> {
Jian Li0f459612019-07-11 10:38:02 +0900492 Map<String, List<NetworkPolicyPort>>
493 direction = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900494 direction.put(DIRECTION_INGRESS, i.getPorts());
495 i.getFrom().forEach(peer -> {
Jian Li0f459612019-07-11 10:38:02 +0900496 if (peer.getPodSelector() != null) {
497 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900498 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900499
Jian Lie1a5b8f2019-07-23 17:13:19 +0900500 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
501 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
502 "/" + HOST_PREFIX, (m, n) -> direction);
503 white.compute(podIp + "/" +
504 HOST_PREFIX, (m, n) -> direction);
505
506 selectedPolicy.set(policy);
507 } else {
508 pod.getMetadata().getLabels().forEach((k, v) -> {
509 if (podLabels != null && podLabels.get(k) != null &&
510 podLabels.get(k).equals(v) && podIp != null) {
511 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
512 "/" + HOST_PREFIX, (m, n) -> direction);
513 white.compute(podIp + "/" +
514 HOST_PREFIX, (m, n) -> direction);
515
516 selectedPolicy.set(policy);
517 }
518 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900519 }
Jian Li0f459612019-07-11 10:38:02 +0900520 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900521 });
522 });
523 });
524
Jian Lie1a5b8f2019-07-23 17:13:19 +0900525 k8sNetworkPolicyService.networkPolicies().stream()
526 .filter(policy -> policy.getMetadata().getNamespace().equals(
527 pod.getMetadata().getNamespace()))
528 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900529 String podIp = pod.getStatus().getPodIP();
530
Jian Li73d3b6a2019-07-08 18:07:53 +0900531 policy.getSpec().getEgress().forEach(e -> {
532 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
533 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Li0f459612019-07-11 10:38:02 +0900534 e.getTo().forEach(peer -> {
535 if (peer.getPodSelector() != null) {
536 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900537 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900538
Jian Lie1a5b8f2019-07-23 17:13:19 +0900539 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
540 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
541 "/" + HOST_PREFIX, (m, n) -> {
542 if (n != null) {
543 n.put(DIRECTION_EGRESS, e.getPorts());
544 return n;
545 } else {
546 return direction;
547 }
548 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900549
Jian Lie1a5b8f2019-07-23 17:13:19 +0900550 white.compute(podIp + "/" +
551 HOST_PREFIX, (m, n) -> {
552 if (n != null) {
553 n.put(DIRECTION_EGRESS, e.getPorts());
554 return n;
555 } else {
556 return direction;
557 }
558 });
Jian Li0f459612019-07-11 10:38:02 +0900559
Jian Lie1a5b8f2019-07-23 17:13:19 +0900560 selectedPolicy.set(policy);
561 } else {
562 pod.getMetadata().getLabels().forEach((k, v) -> {
563 if (podLabels != null && podLabels.get(k) != null &&
564 podLabels.get(k).equals(v) && podIp != null) {
565 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
566 "/" + HOST_PREFIX, (m, n) -> {
567 if (n != null) {
568 n.put(DIRECTION_EGRESS, e.getPorts());
569 return n;
570 } else {
571 return direction;
572 }
573 });
574
575 white.compute(podIp + "/" +
576 HOST_PREFIX, (m, n) -> {
577 if (n != null) {
578 n.put(DIRECTION_EGRESS, e.getPorts());
579 return n;
580 } else {
581 return direction;
582 }
583 });
584
585 selectedPolicy.set(policy);
586 }
587 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900588 }
Jian Li0f459612019-07-11 10:38:02 +0900589 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900590 });
591 });
592 });
593
Jian Lie1a5b8f2019-07-23 17:13:19 +0900594 int nsHash = selectedPolicy.get() != null ? namespaceHashByNamespace(k8sNamespaceService,
595 selectedPolicy.get().getMetadata().getNamespace()) : DEFAULT_NAMESPACE_HASH;
596
597 setAllowRules(nsHash, white, install);
Jian Li0f459612019-07-11 10:38:02 +0900598 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900599 }
600
Jian Lie1a5b8f2019-07-23 17:13:19 +0900601 private Set<Namespace> namespacesByLabels(Map<String, String> labels) {
602 Set<Namespace> nsSet = Sets.newConcurrentHashSet();
Jian Li0f459612019-07-11 10:38:02 +0900603 k8sNamespaceService.namespaces().forEach(ns -> {
604 if (ns != null && ns.getMetadata() != null &&
Jian Lie1a5b8f2019-07-23 17:13:19 +0900605 ns.getMetadata().getLabels() != null && labels != null) {
Jian Li0f459612019-07-11 10:38:02 +0900606 ns.getMetadata().getLabels().forEach((k, v) -> {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900607 if (labels.get(k) != null && labels.get(k).equals(v)) {
608 nsSet.add(ns);
Jian Li0f459612019-07-11 10:38:02 +0900609 }
610 });
611 }
612 });
613
Jian Lie1a5b8f2019-07-23 17:13:19 +0900614 return nsSet;
Jian Li0f459612019-07-11 10:38:02 +0900615 }
616
Jian Lie1a5b8f2019-07-23 17:13:19 +0900617 private Set<Namespace> namespacesByPolicyPeer(NetworkPolicyPeer peer) {
618 if (peer.getNamespaceSelector() != null) {
619 Map<String, String> labels = peer.getNamespaceSelector().getMatchLabels();
620 if (labels == null || labels.size() == 0) {
621 // if none of match labels are specified, it means the
622 // target PODs are from any namespaces
623 return k8sNamespaceService.namespaces();
624 } else {
625 return namespacesByLabels(labels);
626 }
627 }
628
629 return Sets.newConcurrentHashSet();
630 }
631
632 private void setAllowNamespaceRules(int tunnelId, Set<Namespace> nsSet,
633 String direction, boolean install) {
634
635 nsSet.forEach(ns -> {
636 setAllowNamespaceRulesBase(tunnelId, ns.hashCode(), direction, install);
637 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900638 }
639
640 private void setAllowAllRule(int nsHash, String direction, boolean install) {
641 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
642 .matchTunnelId(nsHash);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900643 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900644 .setTunnelId(DEFAULT_SEGMENT_ID)
Jian Lib7dfb5b2019-07-15 17:37:12 +0900645 .transition(ROUTING_TABLE);
646
647 int table = 0;
648
649 if (DIRECTION_INGRESS.equalsIgnoreCase(direction)) {
650 table = ACL_INGRESS_WHITE_TABLE;
Jian Lib7dfb5b2019-07-15 17:37:12 +0900651 }
652
Jian Lie1a5b8f2019-07-23 17:13:19 +0900653 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900654 }
655
Jian Lie1a5b8f2019-07-23 17:13:19 +0900656 private void setAllowRules(int namespaceHash,
657 Map<String, Map<String, List<NetworkPolicyPort>>> white,
Jian Li0f459612019-07-11 10:38:02 +0900658 boolean install) {
Jian Li73d3b6a2019-07-08 18:07:53 +0900659 white.forEach((k, v) -> {
660 v.forEach((pk, pv) -> {
661 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900662 .matchTunnelId(namespaceHash)
663 .matchEthType(TYPE_IPV4);
Jian Li73d3b6a2019-07-08 18:07:53 +0900664 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900665 tBuilder.setTunnelId(DEFAULT_SEGMENT_ID);
666
Jian Li73d3b6a2019-07-08 18:07:53 +0900667 if (pk.equalsIgnoreCase(DIRECTION_INGRESS)) {
Jian Li0f459612019-07-11 10:38:02 +0900668 sBuilder.matchIPSrc(IpPrefix.valueOf(k));
669 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
670 .transition(ACL_INGRESS_BLACK_TABLE);
Jian Li73d3b6a2019-07-08 18:07:53 +0900671
672 if (pv.size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900673 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900674 } else {
675 pv.forEach(p -> {
676 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
677 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900678
679 if (p.getPort() != null &&
680 p.getPort().getIntVal() != null) {
681 sBuilder.matchTcpDst(TpPort.tpPort(p.getPort().getIntVal()));
682 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900683 }
684 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
685 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900686
687 if (p.getPort() != null &&
688 p.getPort().getIntVal() != null) {
689 sBuilder.matchUdpDst(TpPort.tpPort(p.getPort().getIntVal()));
690 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900691 }
692
Jian Lie1a5b8f2019-07-23 17:13:19 +0900693 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
694 });
695 }
696 } else if (pk.equalsIgnoreCase(DIRECTION_EGRESS)) {
697 sBuilder.matchIPDst(IpPrefix.valueOf(k));
698 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
699 .transition(ACL_EGRESS_BLACK_TABLE);
700
701 if (pv.size() == 0) {
702 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
703 } else {
704 pv.forEach(p -> {
705 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
706 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
707
708 if (p.getPort() != null &&
709 p.getPort().getIntVal() != null) {
710 sBuilder.matchTcpSrc(TpPort.tpPort(p.getPort().getIntVal()));
711 }
712 }
713 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
714 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
715
716 if (p.getPort() != null &&
717 p.getPort().getIntVal() != null) {
718 sBuilder.matchUdpSrc(TpPort.tpPort(p.getPort().getIntVal()));
719 }
720 }
721 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900722 });
723 }
724
725 } else {
726 log.error("In correct direction has been specified at network policy.");
727 }
728 });
729 });
730 }
731
Jian Lie1a5b8f2019-07-23 17:13:19 +0900732 private void setPolicyRulesBase(TrafficSelector.Builder sBuilder,
733 TrafficTreatment.Builder tBuilder,
734 int table,
735 boolean install) {
736 k8sNodeService.completeNodes().forEach(n -> {
737 k8sFlowRuleService.setRule(
738 appId,
739 n.intgBridge(),
740 sBuilder.build(),
741 tBuilder.build(),
742 PRIORITY_CIDR_RULE,
743 table,
744 install
745 );
746 });
747 }
748
Jian Li0f459612019-07-11 10:38:02 +0900749 private void setBlackRules(String whiteIpCidr, String direction,
750 List<String> except, boolean install) {
751 k8sNodeService.completeNodes().forEach(n -> {
752 except.forEach(blkIp -> {
753 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900754 .matchEthType(TYPE_IPV4)
Jian Li0f459612019-07-11 10:38:02 +0900755 .matchMetadata(whiteIpCidr.hashCode());
756 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
757 .drop();
758 int table = 0;
759 if (direction.equalsIgnoreCase(DIRECTION_INGRESS)) {
760 sBuilder.matchIPSrc(IpPrefix.valueOf(blkIp));
761 table = ACL_INGRESS_BLACK_TABLE;
762 }
763 if (direction.equalsIgnoreCase(DIRECTION_EGRESS)) {
764 sBuilder.matchIPDst(IpPrefix.valueOf(blkIp));
765 table = ACL_EGRESS_BLACK_TABLE;
766 }
767
Jian Lie1a5b8f2019-07-23 17:13:19 +0900768 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Li0f459612019-07-11 10:38:02 +0900769 });
770 });
771 }
772
773 private void setBlackToRouteRules(boolean install) {
774
775 k8sNodeService.completeNodes().forEach(n -> {
776 ImmutableSet.of(ACL_INGRESS_BLACK_TABLE, ACL_EGRESS_BLACK_TABLE).forEach(t -> {
777 k8sFlowRuleService.setRule(
778 appId,
779 n.intgBridge(),
780 DefaultTrafficSelector.builder().build(),
Jian Lie1a5b8f2019-07-23 17:13:19 +0900781 DefaultTrafficTreatment.builder()
782 .transition(ROUTING_TABLE).build(),
Jian Li0f459612019-07-11 10:38:02 +0900783 0,
784 t,
785 install
786 );
787 });
788 });
789 }
790
Jian Lie1a5b8f2019-07-23 17:13:19 +0900791 private void setNamespaceRulesByPod(Pod pod, boolean install) {
792 String podIp = pod.getStatus().getPodIP();
793
794 if (podIp == null) {
795 return;
796 }
797
798 Integer nsHash = namespaceHashByPodIp(k8sPodService, k8sNamespaceService, podIp);
799
Jian Li2744b972019-07-30 19:12:07 +0900800 // in uninstall case, we will have null nsHash value
801 if (install && nsHash == null) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900802 return;
803 }
804
805 setNamespaceRulesBase(podIp, nsHash, install);
806 }
807
808 private void setNamespaceRulesByService(Service service, boolean install) {
809 String clusterIp = service.getSpec().getClusterIP();
810
811 if (clusterIp == null) {
812 return;
813 }
814
815 setNamespaceRulesBase(clusterIp, namespaceHashByServiceIp(k8sServiceService,
816 k8sNamespaceService, clusterIp), install);
817 }
818
819 private void setNamespaceRulesBase(String ip, Integer nsHash, boolean install) {
820
821 k8sNodeService.completeNodes().forEach(n -> {
822 TrafficSelector.Builder origBuilder = DefaultTrafficSelector.builder()
823 .matchEthType(TYPE_IPV4)
824 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(ip), HOST_PREFIX));
825 TrafficSelector.Builder convBuilder = DefaultTrafficSelector.builder()
826 .matchEthType(TYPE_IPV4)
827 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(
828 shiftIpDomain(ip, SHIFTED_IP_PREFIX)), HOST_PREFIX));
Jian Li2744b972019-07-30 19:12:07 +0900829 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
830
831 if (install) {
832 tBuilder.writeMetadata(nsHash, DEFAULT_METADATA_MASK)
833 .transition(GROUPING_TABLE);
834 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900835
836 k8sFlowRuleService.setRule(
837 appId,
838 n.intgBridge(),
839 origBuilder.build(),
840 tBuilder.build(),
841 PRIORITY_NAMESPACE_RULE,
842 NAMESPACE_TABLE,
843 install
844 );
845
846 k8sFlowRuleService.setRule(
847 appId,
848 n.intgBridge(),
849 convBuilder.build(),
850 tBuilder.build(),
851 PRIORITY_NAMESPACE_RULE,
852 NAMESPACE_TABLE,
853 install
854 );
855 });
856 }
857
858 private class InternalServiceListener implements K8sServiceListener {
859
860 private boolean isRelevantHelper() {
861 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
862 }
863
864 @Override
865 public void event(K8sServiceEvent event) {
866 Service service = event.subject();
867 switch (event.type()) {
868 case K8S_SERVICE_CREATED:
869 case K8S_SERVICE_UPDATED:
870 eventExecutor.execute(() -> processServiceCreation(service));
871 break;
872 case K8S_SERVICE_REMOVED:
873 eventExecutor.execute(() -> processServiceRemoval(service));
874 break;
875 default:
876 break;
877 }
878 }
879
880 private void processServiceCreation(Service service) {
881 if (!isRelevantHelper()) {
882 return;
883 }
884
885 setNamespaceRulesByService(service, true);
886 }
887
888 private void processServiceRemoval(Service service) {
889 if (!isRelevantHelper()) {
890 return;
891 }
892
893 setNamespaceRulesByService(service, false);
894 }
895 }
896
Jian Li73d3b6a2019-07-08 18:07:53 +0900897 private class InternalPodListener implements K8sPodListener {
898
899 private boolean isRelevantHelper() {
900 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
901 }
902
903 @Override
904 public void event(K8sPodEvent event) {
905 Pod pod = event.subject();
906 switch (event.type()) {
907 case K8S_POD_CREATED:
908 case K8S_POD_UPDATED:
909 eventExecutor.execute(() -> processPodCreation(pod));
910 break;
911 case K8S_POD_REMOVED:
912 eventExecutor.execute(() -> processPodRemoval(pod));
913 break;
914 default:
915 break;
916 }
917 }
918
919 private void processPodCreation(Pod pod) {
920 if (!isRelevantHelper()) {
921 return;
922 }
923
924 setBlockRulesByPod(pod, true);
925 setAllowRulesByPod(pod, true);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900926 setNamespaceRulesByPod(pod, true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900927 }
928
929 private void processPodRemoval(Pod pod) {
930 if (!isRelevantHelper()) {
931 return;
932 }
933
934 setBlockRulesByPod(pod, false);
935 setAllowRulesByPod(pod, false);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900936 setNamespaceRulesByPod(pod, false);
Jian Li73d3b6a2019-07-08 18:07:53 +0900937 }
938 }
939
940 private class InternalNetworkPolicyListener implements K8sNetworkPolicyListener {
941
942 private boolean isRelevantHelper() {
943 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
944 }
945
946 @Override
947 public void event(K8sNetworkPolicyEvent event) {
948 NetworkPolicy policy = event.subject();
949 switch (event.type()) {
950 case K8S_NETWORK_POLICY_CREATED:
951 case K8S_NETWORK_POLICY_UPDATED:
952 eventExecutor.execute(() -> processNetworkPolicyCreation(policy));
953 break;
954 case K8S_NETWORK_POLICY_REMOVED:
955 eventExecutor.execute(() -> processNetworkPolicyRemoval(policy));
956 break;
957 default:
958 break;
959 }
960 }
961
962 private void processNetworkPolicyCreation(NetworkPolicy policy) {
963 if (!isRelevantHelper()) {
964 return;
965 }
966
967 setBlockRulesByPolicy(policy, true);
968 setAllowRulesByPolicy(policy, true);
969 }
970
971 private void processNetworkPolicyRemoval(NetworkPolicy policy) {
972 if (!isRelevantHelper()) {
973 return;
974 }
975
976 setBlockRulesByPolicy(policy, false);
977 setAllowRulesByPolicy(policy, false);
978 }
979 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900980
981 private class InternalNamespaceListener implements K8sNamespaceListener {
982
983 private boolean isRelevantHelper() {
984 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
985 }
986
987 @Override
988 public void event(K8sNamespaceEvent event) {
989 Namespace ns = event.subject();
990 switch (event.type()) {
991 case K8S_NAMESPACE_CREATED:
Jian Lie1a5b8f2019-07-23 17:13:19 +0900992 eventExecutor.execute(() -> processNamespaceCreation(ns));
993 break;
994 case K8S_NAMESPACE_REMOVED:
995 eventExecutor.execute(() -> processNamespaceRemoval(ns));
996 break;
997 default:
998 break;
999 }
1000 }
1001
1002 private void processNamespaceCreation(Namespace namespace) {
1003 if (!isRelevantHelper()) {
1004 return;
1005 }
1006
1007 setDefaultAllowNamespaceRules(namespace, true);
1008 setDefaultAllowServiceRules(true);
1009 }
1010
1011 private void processNamespaceRemoval(Namespace namespace) {
1012 if (!isRelevantHelper()) {
1013 return;
1014 }
1015
Jian Li2744b972019-07-30 19:12:07 +09001016 setDefaultAllowNamespaceRules(namespace, false);
Jian Lie1a5b8f2019-07-23 17:13:19 +09001017 }
1018 }
Jian Li73d3b6a2019-07-08 18:07:53 +09001019}