blob: ce31f0449deea0dbd7a36051dd62afc05b50daa0 [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 Li73d3b6a2019-07-08 18:07:53 +0900262 } else if (d.equalsIgnoreCase(DIRECTION_EGRESS)) {
263 sBuilder.matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(k), HOST_PREFIX));
Jian Li0f459612019-07-11 10:38:02 +0900264 tBuilder.transition(ACL_EGRESS_WHITE_TABLE);
Jian Li73d3b6a2019-07-08 18:07:53 +0900265 }
266
Jian Lie1a5b8f2019-07-23 17:13:19 +0900267 setPolicyRulesBase(sBuilder, tBuilder, ACL_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900268 });
269 });
270 }
271
Jian Lie1a5b8f2019-07-23 17:13:19 +0900272 private void setDefaultAllowNamespaceRules(Namespace namespace, boolean install) {
273
274 String ns = namespace.getMetadata().getName();
275 if (KUBE_SYSTEM.equalsIgnoreCase(ns)) {
276 setAllowNamespaceRulesBase(0, namespace.hashCode(),
277 DIRECTION_INGRESS, install);
278 }
279 }
280
281 private void setDefaultAllowServiceRules(boolean install) {
282 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
283 .matchEthType(TYPE_IPV4)
284 .matchIPSrc(IpPrefix.valueOf(SERVICE_IP_CIDR_DEFAULT));
285 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
286 .setTunnelId(DEFAULT_SEGMENT_ID)
287 .transition(ROUTING_TABLE);
288
289 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
290 }
291
292 private void setAllowNamespaceRulesBase(int tunnelId, int metadata,
293 String direction, boolean install) {
294 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
295
296 if (tunnelId != 0) {
297 sBuilder.matchTunnelId(tunnelId);
298 }
299
300 sBuilder.matchMetadata(metadata);
301 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
302 .setTunnelId(DEFAULT_SEGMENT_ID)
303 .transition(ROUTING_TABLE);
304
305 int table = 0;
306 if (DIRECTION_INGRESS.equals(direction)) {
307 table = ACL_INGRESS_WHITE_TABLE;
308 }
309
310 setPolicyRulesBase(sBuilder, tBuilder, table, install);
311 }
312
Jian Li73d3b6a2019-07-08 18:07:53 +0900313 private void setAllowRulesByPolicy(NetworkPolicy policy, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900314 Map<String, Map<String, List<NetworkPolicyPort>>>
315 white = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900316
Jian Lie1a5b8f2019-07-23 17:13:19 +0900317 int nsHash = namespaceHashByNamespace(k8sNamespaceService,
318 policy.getMetadata().getNamespace());
319
Jian Lib7dfb5b2019-07-15 17:37:12 +0900320 List<NetworkPolicyIngressRule> ingress = policy.getSpec().getIngress();
321 if (ingress != null && ingress.size() == 1) {
322 NetworkPolicyIngressRule rule = ingress.get(0);
323 if (rule.getFrom().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900324 setAllowAllRule(nsHash, DIRECTION_INGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900325 }
326 }
327
Jian Li73d3b6a2019-07-08 18:07:53 +0900328 policy.getSpec().getIngress().forEach(i -> {
329 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
330 direction.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900331 i.getFrom().forEach(peer -> {
332
333 // IP block
334 if (peer.getIpBlock() != null) {
335 if (peer.getIpBlock().getExcept() != null &&
336 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900337 Map<String, List<NetworkPolicyPort>>
338 blkDirection = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900339
Jian Li0f459612019-07-11 10:38:02 +0900340 blkDirection.put(DIRECTION_INGRESS, i.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900341 white.compute(peer.getIpBlock().getCidr(), (k, v) -> blkDirection);
Jian Li73d3b6a2019-07-08 18:07:53 +0900342
Jian Lie1a5b8f2019-07-23 17:13:19 +0900343 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_INGRESS,
344 peer.getIpBlock().getExcept(), install);
Jian Li0f459612019-07-11 10:38:02 +0900345 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900346 white.compute(peer.getIpBlock().getCidr(), (k, v) -> direction);
Jian Li0f459612019-07-11 10:38:02 +0900347 }
348 }
349
Jian Lie1a5b8f2019-07-23 17:13:19 +0900350 // POD selector
Jian Li0f459612019-07-11 10:38:02 +0900351 Set<Pod> pods = Sets.newConcurrentHashSet();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900352 if (peer.getPodSelector() != null) {
353 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
354 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li0f459612019-07-11 10:38:02 +0900355
Jian Lie1a5b8f2019-07-23 17:13:19 +0900356 if (podLabels == null && matchExps.size() == 0) {
357 k8sPodService.pods().stream()
358 .filter(pod -> pod.getMetadata().getNamespace().equals(
359 policy.getMetadata().getNamespace()))
360 .forEach(pods::add);
Jian Li0f459612019-07-11 10:38:02 +0900361 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900362 k8sPodService.pods().stream()
363 .filter(pod -> pod.getMetadata().getNamespace().equals(
364 policy.getMetadata().getNamespace()))
365 .forEach(pod -> {
366 pod.getMetadata().getLabels().forEach((k, v) -> {
367 if (podLabels != null && podLabels.get(k) != null &&
368 podLabels.get(k).equals(v)) {
369 pods.add(pod);
370 }
371 });
372 });
Jian Li0f459612019-07-11 10:38:02 +0900373 }
374 }
375
376 pods.forEach(pod -> {
377 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
378 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> direction);
379 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX, (m, n) -> direction);
Jian Li73d3b6a2019-07-08 18:07:53 +0900380 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900381
382 // Namespace selector
383 setAllowNamespaceRules(nsHash,
384 namespacesByPolicyPeer(peer), DIRECTION_INGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900385 });
386 });
387
Jian Lib7dfb5b2019-07-15 17:37:12 +0900388 List<NetworkPolicyEgressRule> egress = policy.getSpec().getEgress();
389 if (egress != null && egress.size() == 1) {
390 NetworkPolicyEgressRule rule = egress.get(0);
391 if (rule.getTo().size() == 0 && rule.getPorts().size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900392 setAllowAllRule(nsHash, DIRECTION_EGRESS, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900393 }
394 }
395
Jian Li73d3b6a2019-07-08 18:07:53 +0900396 policy.getSpec().getEgress().forEach(e -> {
397 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
398 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900399 e.getTo().forEach(peer -> {
400
401 // IP block
402 if (peer.getIpBlock() != null) {
403 if (peer.getIpBlock().getExcept() != null &&
404 peer.getIpBlock().getExcept().size() > 0) {
Jian Li0f459612019-07-11 10:38:02 +0900405
406 Map<String, List<NetworkPolicyPort>>
407 blkDirection = Maps.newConcurrentMap();
408 blkDirection.put(DIRECTION_EGRESS, e.getPorts());
Jian Lie1a5b8f2019-07-23 17:13:19 +0900409 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900410 if (v != null) {
411 v.put(DIRECTION_EGRESS, e.getPorts());
412 return v;
413 } else {
414 return blkDirection;
415 }
416 });
417
Jian Lie1a5b8f2019-07-23 17:13:19 +0900418 setBlackRules(peer.getIpBlock().getCidr(), DIRECTION_EGRESS,
419 peer.getIpBlock().getExcept(), install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900420 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900421 white.compute(peer.getIpBlock().getCidr(), (k, v) -> {
Jian Li0f459612019-07-11 10:38:02 +0900422 if (v != null) {
423 v.put(DIRECTION_EGRESS, e.getPorts());
424 return v;
425 } else {
426 return direction;
427 }
428 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900429 }
Jian Li0f459612019-07-11 10:38:02 +0900430 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900431
Jian Li0f459612019-07-11 10:38:02 +0900432 Set<Pod> pods = Sets.newConcurrentHashSet();
Jian Li73d3b6a2019-07-08 18:07:53 +0900433
Jian Lie1a5b8f2019-07-23 17:13:19 +0900434 // POD selector
435 if (peer.getPodSelector() != null) {
436 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Li0f459612019-07-11 10:38:02 +0900437
Jian Lie1a5b8f2019-07-23 17:13:19 +0900438 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
439
440 if (podLabels == null && matchExps.size() == 0) {
441 k8sPodService.pods().stream()
442 .filter(pod -> pod.getMetadata().getNamespace().equals(
443 policy.getMetadata().getNamespace()))
444 .forEach(pods::add);
Jian Li0f459612019-07-11 10:38:02 +0900445 } else {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900446 k8sPodService.pods().stream()
447 .filter(pod -> pod.getMetadata().getNamespace().equals(
448 policy.getMetadata().getNamespace()))
449 .forEach(pod -> {
450 pod.getMetadata().getLabels().forEach((k, v) -> {
451 if (podLabels != null && podLabels.get(k) != null &&
452 podLabels.get(k).equals(v)) {
453 pods.add(pod);
454 }
455 });
456 });
Jian Li0f459612019-07-11 10:38:02 +0900457 }
458 }
459
460 pods.forEach(pod -> {
461 white.compute(shiftIpDomain(pod.getStatus().getPodIP(),
462 SHIFTED_IP_PREFIX) + "/" + HOST_PREFIX, (m, n) -> {
463 if (n != null) {
464 n.put(DIRECTION_EGRESS, e.getPorts());
465 return n;
466 } else {
467 return direction;
468 }
469 });
470
471 white.compute(pod.getStatus().getPodIP() + "/" + HOST_PREFIX,
472 (m, n) -> {
473 if (n != null) {
474 n.put(DIRECTION_EGRESS, e.getPorts());
475 return n;
476 } else {
477 return direction;
Jian Li73d3b6a2019-07-08 18:07:53 +0900478 }
479 });
480 });
Jian Lie1a5b8f2019-07-23 17:13:19 +0900481
482 // Namespace selector
483 setAllowNamespaceRules(nsHash,
484 namespacesByPolicyPeer(peer), DIRECTION_EGRESS, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900485 });
486 });
487
Jian Lie1a5b8f2019-07-23 17:13:19 +0900488 setAllowRules(namespaceHashByNamespace(k8sNamespaceService,
489 policy.getMetadata().getNamespace()), white, install);
Jian Li0f459612019-07-11 10:38:02 +0900490 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900491 }
492
493 private void setAllowRulesByPod(Pod pod, boolean install) {
Jian Li0f459612019-07-11 10:38:02 +0900494 Map<String, Map<String, List<NetworkPolicyPort>>>
495 white = Maps.newConcurrentMap();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900496 AtomicReference<NetworkPolicy> selectedPolicy = new AtomicReference<>();
497 k8sNetworkPolicyService.networkPolicies().stream()
498 .filter(policy -> policy.getMetadata().getNamespace().equals(
499 pod.getMetadata().getNamespace()))
500 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900501 String podIp = pod.getStatus().getPodIP();
502
Jian Li73d3b6a2019-07-08 18:07:53 +0900503 policy.getSpec().getIngress().forEach(i -> {
Jian Li0f459612019-07-11 10:38:02 +0900504 Map<String, List<NetworkPolicyPort>>
505 direction = Maps.newConcurrentMap();
Jian Li73d3b6a2019-07-08 18:07:53 +0900506 direction.put(DIRECTION_INGRESS, i.getPorts());
507 i.getFrom().forEach(peer -> {
Jian Li0f459612019-07-11 10:38:02 +0900508 if (peer.getPodSelector() != null) {
509 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900510 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900511
Jian Lie1a5b8f2019-07-23 17:13:19 +0900512 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
513 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
514 "/" + HOST_PREFIX, (m, n) -> direction);
515 white.compute(podIp + "/" +
516 HOST_PREFIX, (m, n) -> direction);
517
518 selectedPolicy.set(policy);
519 } else {
520 pod.getMetadata().getLabels().forEach((k, v) -> {
521 if (podLabels != null && podLabels.get(k) != null &&
522 podLabels.get(k).equals(v) && podIp != null) {
523 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
524 "/" + HOST_PREFIX, (m, n) -> direction);
525 white.compute(podIp + "/" +
526 HOST_PREFIX, (m, n) -> direction);
527
528 selectedPolicy.set(policy);
529 }
530 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900531 }
Jian Li0f459612019-07-11 10:38:02 +0900532 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900533 });
534 });
535 });
536
Jian Lie1a5b8f2019-07-23 17:13:19 +0900537 k8sNetworkPolicyService.networkPolicies().stream()
538 .filter(policy -> policy.getMetadata().getNamespace().equals(
539 pod.getMetadata().getNamespace()))
540 .forEach(policy -> {
Jian Lib7dfb5b2019-07-15 17:37:12 +0900541 String podIp = pod.getStatus().getPodIP();
542
Jian Li73d3b6a2019-07-08 18:07:53 +0900543 policy.getSpec().getEgress().forEach(e -> {
544 Map<String, List<NetworkPolicyPort>> direction = Maps.newConcurrentMap();
545 direction.put(DIRECTION_EGRESS, e.getPorts());
Jian Li0f459612019-07-11 10:38:02 +0900546 e.getTo().forEach(peer -> {
547 if (peer.getPodSelector() != null) {
548 Map<String, String> podLabels = peer.getPodSelector().getMatchLabels();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900549 List<LabelSelectorRequirement> matchExps = peer.getPodSelector().getMatchExpressions();
Jian Li73d3b6a2019-07-08 18:07:53 +0900550
Jian Lie1a5b8f2019-07-23 17:13:19 +0900551 if (podLabels == null && matchExps.size() == 0 && podIp != null) {
552 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
553 "/" + HOST_PREFIX, (m, n) -> {
554 if (n != null) {
555 n.put(DIRECTION_EGRESS, e.getPorts());
556 return n;
557 } else {
558 return direction;
559 }
560 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900561
Jian Lie1a5b8f2019-07-23 17:13:19 +0900562 white.compute(podIp + "/" +
563 HOST_PREFIX, (m, n) -> {
564 if (n != null) {
565 n.put(DIRECTION_EGRESS, e.getPorts());
566 return n;
567 } else {
568 return direction;
569 }
570 });
Jian Li0f459612019-07-11 10:38:02 +0900571
Jian Lie1a5b8f2019-07-23 17:13:19 +0900572 selectedPolicy.set(policy);
573 } else {
574 pod.getMetadata().getLabels().forEach((k, v) -> {
575 if (podLabels != null && podLabels.get(k) != null &&
576 podLabels.get(k).equals(v) && podIp != null) {
577 white.compute(shiftIpDomain(podIp, SHIFTED_IP_PREFIX) +
578 "/" + HOST_PREFIX, (m, n) -> {
579 if (n != null) {
580 n.put(DIRECTION_EGRESS, e.getPorts());
581 return n;
582 } else {
583 return direction;
584 }
585 });
586
587 white.compute(podIp + "/" +
588 HOST_PREFIX, (m, n) -> {
589 if (n != null) {
590 n.put(DIRECTION_EGRESS, e.getPorts());
591 return n;
592 } else {
593 return direction;
594 }
595 });
596
597 selectedPolicy.set(policy);
598 }
599 });
Jian Li73d3b6a2019-07-08 18:07:53 +0900600 }
Jian Li0f459612019-07-11 10:38:02 +0900601 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900602 });
603 });
604 });
605
Jian Lie1a5b8f2019-07-23 17:13:19 +0900606 int nsHash = selectedPolicy.get() != null ? namespaceHashByNamespace(k8sNamespaceService,
607 selectedPolicy.get().getMetadata().getNamespace()) : DEFAULT_NAMESPACE_HASH;
608
609 setAllowRules(nsHash, white, install);
Jian Li0f459612019-07-11 10:38:02 +0900610 setBlackToRouteRules(true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900611 }
612
Jian Lie1a5b8f2019-07-23 17:13:19 +0900613 private Set<Namespace> namespacesByLabels(Map<String, String> labels) {
614 Set<Namespace> nsSet = Sets.newConcurrentHashSet();
Jian Li0f459612019-07-11 10:38:02 +0900615 k8sNamespaceService.namespaces().forEach(ns -> {
616 if (ns != null && ns.getMetadata() != null &&
Jian Lie1a5b8f2019-07-23 17:13:19 +0900617 ns.getMetadata().getLabels() != null && labels != null) {
Jian Li0f459612019-07-11 10:38:02 +0900618 ns.getMetadata().getLabels().forEach((k, v) -> {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900619 if (labels.get(k) != null && labels.get(k).equals(v)) {
620 nsSet.add(ns);
Jian Li0f459612019-07-11 10:38:02 +0900621 }
622 });
623 }
624 });
625
Jian Lie1a5b8f2019-07-23 17:13:19 +0900626 return nsSet;
Jian Li0f459612019-07-11 10:38:02 +0900627 }
628
Jian Lie1a5b8f2019-07-23 17:13:19 +0900629 private Set<Namespace> namespacesByPolicyPeer(NetworkPolicyPeer peer) {
630 if (peer.getNamespaceSelector() != null) {
631 Map<String, String> labels = peer.getNamespaceSelector().getMatchLabels();
632 if (labels == null || labels.size() == 0) {
633 // if none of match labels are specified, it means the
634 // target PODs are from any namespaces
635 return k8sNamespaceService.namespaces();
636 } else {
637 return namespacesByLabels(labels);
638 }
639 }
640
641 return Sets.newConcurrentHashSet();
642 }
643
644 private void setAllowNamespaceRules(int tunnelId, Set<Namespace> nsSet,
645 String direction, boolean install) {
646
647 nsSet.forEach(ns -> {
648 setAllowNamespaceRulesBase(tunnelId, ns.hashCode(), direction, install);
649 });
650
651 }
652
653 private void setAllowAllRule(int nsHash, String direction, boolean install) {
654 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
655 .matchTunnelId(nsHash);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900656 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900657 .setTunnelId(DEFAULT_SEGMENT_ID)
Jian Lib7dfb5b2019-07-15 17:37:12 +0900658 .transition(ROUTING_TABLE);
659
660 int table = 0;
661
662 if (DIRECTION_INGRESS.equalsIgnoreCase(direction)) {
663 table = ACL_INGRESS_WHITE_TABLE;
Jian Lib7dfb5b2019-07-15 17:37:12 +0900664 }
665
Jian Lie1a5b8f2019-07-23 17:13:19 +0900666 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900667 }
668
Jian Lie1a5b8f2019-07-23 17:13:19 +0900669 private void setAllowRules(int namespaceHash,
670 Map<String, Map<String, List<NetworkPolicyPort>>> white,
Jian Li0f459612019-07-11 10:38:02 +0900671 boolean install) {
Jian Li73d3b6a2019-07-08 18:07:53 +0900672 white.forEach((k, v) -> {
673 v.forEach((pk, pv) -> {
674 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900675 .matchTunnelId(namespaceHash)
676 .matchEthType(TYPE_IPV4);
Jian Li73d3b6a2019-07-08 18:07:53 +0900677 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
Jian Lie1a5b8f2019-07-23 17:13:19 +0900678 tBuilder.setTunnelId(DEFAULT_SEGMENT_ID);
679
Jian Li73d3b6a2019-07-08 18:07:53 +0900680 if (pk.equalsIgnoreCase(DIRECTION_INGRESS)) {
Jian Li0f459612019-07-11 10:38:02 +0900681 sBuilder.matchIPSrc(IpPrefix.valueOf(k));
682 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
683 .transition(ACL_INGRESS_BLACK_TABLE);
Jian Li73d3b6a2019-07-08 18:07:53 +0900684
685 if (pv.size() == 0) {
Jian Lie1a5b8f2019-07-23 17:13:19 +0900686 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900687 } else {
688 pv.forEach(p -> {
689 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
690 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900691
692 if (p.getPort() != null &&
693 p.getPort().getIntVal() != null) {
694 sBuilder.matchTcpDst(TpPort.tpPort(p.getPort().getIntVal()));
695 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900696 }
697 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
698 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
Jian Lib7dfb5b2019-07-15 17:37:12 +0900699
700 if (p.getPort() != null &&
701 p.getPort().getIntVal() != null) {
702 sBuilder.matchUdpDst(TpPort.tpPort(p.getPort().getIntVal()));
703 }
Jian Li73d3b6a2019-07-08 18:07:53 +0900704 }
705
Jian Lie1a5b8f2019-07-23 17:13:19 +0900706 setPolicyRulesBase(sBuilder, tBuilder, ACL_INGRESS_WHITE_TABLE, install);
707 });
708 }
709 } else if (pk.equalsIgnoreCase(DIRECTION_EGRESS)) {
710 sBuilder.matchIPDst(IpPrefix.valueOf(k));
711 tBuilder.writeMetadata(k.hashCode(), DEFAULT_METADATA_MASK)
712 .transition(ACL_EGRESS_BLACK_TABLE);
713
714 if (pv.size() == 0) {
715 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
716 } else {
717 pv.forEach(p -> {
718 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_TCP)) {
719 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
720
721 if (p.getPort() != null &&
722 p.getPort().getIntVal() != null) {
723 sBuilder.matchTcpSrc(TpPort.tpPort(p.getPort().getIntVal()));
724 }
725 }
726 if (p.getProtocol().equalsIgnoreCase(PROTOCOL_UDP)) {
727 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
728
729 if (p.getPort() != null &&
730 p.getPort().getIntVal() != null) {
731 sBuilder.matchUdpSrc(TpPort.tpPort(p.getPort().getIntVal()));
732 }
733 }
734 setPolicyRulesBase(sBuilder, tBuilder, ACL_EGRESS_WHITE_TABLE, install);
Jian Li73d3b6a2019-07-08 18:07:53 +0900735 });
736 }
737
738 } else {
739 log.error("In correct direction has been specified at network policy.");
740 }
741 });
742 });
743 }
744
Jian Lie1a5b8f2019-07-23 17:13:19 +0900745 private void setPolicyRulesBase(TrafficSelector.Builder sBuilder,
746 TrafficTreatment.Builder tBuilder,
747 int table,
748 boolean install) {
749 k8sNodeService.completeNodes().forEach(n -> {
750 k8sFlowRuleService.setRule(
751 appId,
752 n.intgBridge(),
753 sBuilder.build(),
754 tBuilder.build(),
755 PRIORITY_CIDR_RULE,
756 table,
757 install
758 );
759 });
760 }
761
Jian Li0f459612019-07-11 10:38:02 +0900762 private void setBlackRules(String whiteIpCidr, String direction,
763 List<String> except, boolean install) {
764 k8sNodeService.completeNodes().forEach(n -> {
765 except.forEach(blkIp -> {
766 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Jian Lie1a5b8f2019-07-23 17:13:19 +0900767 .matchEthType(TYPE_IPV4)
Jian Li0f459612019-07-11 10:38:02 +0900768 .matchMetadata(whiteIpCidr.hashCode());
769 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
770 .drop();
771 int table = 0;
772 if (direction.equalsIgnoreCase(DIRECTION_INGRESS)) {
773 sBuilder.matchIPSrc(IpPrefix.valueOf(blkIp));
774 table = ACL_INGRESS_BLACK_TABLE;
775 }
776 if (direction.equalsIgnoreCase(DIRECTION_EGRESS)) {
777 sBuilder.matchIPDst(IpPrefix.valueOf(blkIp));
778 table = ACL_EGRESS_BLACK_TABLE;
779 }
780
Jian Lie1a5b8f2019-07-23 17:13:19 +0900781 setPolicyRulesBase(sBuilder, tBuilder, table, install);
Jian Li0f459612019-07-11 10:38:02 +0900782 });
783 });
784 }
785
786 private void setBlackToRouteRules(boolean install) {
787
788 k8sNodeService.completeNodes().forEach(n -> {
789 ImmutableSet.of(ACL_INGRESS_BLACK_TABLE, ACL_EGRESS_BLACK_TABLE).forEach(t -> {
790 k8sFlowRuleService.setRule(
791 appId,
792 n.intgBridge(),
793 DefaultTrafficSelector.builder().build(),
Jian Lie1a5b8f2019-07-23 17:13:19 +0900794 DefaultTrafficTreatment.builder()
795 .transition(ROUTING_TABLE).build(),
Jian Li0f459612019-07-11 10:38:02 +0900796 0,
797 t,
798 install
799 );
800 });
801 });
802 }
803
Jian Lie1a5b8f2019-07-23 17:13:19 +0900804 private void setNamespaceRulesByPod(Pod pod, boolean install) {
805 String podIp = pod.getStatus().getPodIP();
806
807 if (podIp == null) {
808 return;
809 }
810
811 Integer nsHash = namespaceHashByPodIp(k8sPodService, k8sNamespaceService, podIp);
812
813 if (nsHash == null) {
814 return;
815 }
816
817 setNamespaceRulesBase(podIp, nsHash, install);
818 }
819
820 private void setNamespaceRulesByService(Service service, boolean install) {
821 String clusterIp = service.getSpec().getClusterIP();
822
823 if (clusterIp == null) {
824 return;
825 }
826
827 setNamespaceRulesBase(clusterIp, namespaceHashByServiceIp(k8sServiceService,
828 k8sNamespaceService, clusterIp), install);
829 }
830
831 private void setNamespaceRulesBase(String ip, Integer nsHash, boolean install) {
832
833 k8sNodeService.completeNodes().forEach(n -> {
834 TrafficSelector.Builder origBuilder = DefaultTrafficSelector.builder()
835 .matchEthType(TYPE_IPV4)
836 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(ip), HOST_PREFIX));
837 TrafficSelector.Builder convBuilder = DefaultTrafficSelector.builder()
838 .matchEthType(TYPE_IPV4)
839 .matchIPSrc(IpPrefix.valueOf(IpAddress.valueOf(
840 shiftIpDomain(ip, SHIFTED_IP_PREFIX)), HOST_PREFIX));
841 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
842 .writeMetadata(nsHash, DEFAULT_METADATA_MASK)
843 .transition(GROUPING_TABLE);
844
845 k8sFlowRuleService.setRule(
846 appId,
847 n.intgBridge(),
848 origBuilder.build(),
849 tBuilder.build(),
850 PRIORITY_NAMESPACE_RULE,
851 NAMESPACE_TABLE,
852 install
853 );
854
855 k8sFlowRuleService.setRule(
856 appId,
857 n.intgBridge(),
858 convBuilder.build(),
859 tBuilder.build(),
860 PRIORITY_NAMESPACE_RULE,
861 NAMESPACE_TABLE,
862 install
863 );
864 });
865 }
866
867 private class InternalServiceListener implements K8sServiceListener {
868
869 private boolean isRelevantHelper() {
870 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
871 }
872
873 @Override
874 public void event(K8sServiceEvent event) {
875 Service service = event.subject();
876 switch (event.type()) {
877 case K8S_SERVICE_CREATED:
878 case K8S_SERVICE_UPDATED:
879 eventExecutor.execute(() -> processServiceCreation(service));
880 break;
881 case K8S_SERVICE_REMOVED:
882 eventExecutor.execute(() -> processServiceRemoval(service));
883 break;
884 default:
885 break;
886 }
887 }
888
889 private void processServiceCreation(Service service) {
890 if (!isRelevantHelper()) {
891 return;
892 }
893
894 setNamespaceRulesByService(service, true);
895 }
896
897 private void processServiceRemoval(Service service) {
898 if (!isRelevantHelper()) {
899 return;
900 }
901
902 setNamespaceRulesByService(service, false);
903 }
904 }
905
Jian Li73d3b6a2019-07-08 18:07:53 +0900906 private class InternalPodListener implements K8sPodListener {
907
908 private boolean isRelevantHelper() {
909 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
910 }
911
912 @Override
913 public void event(K8sPodEvent event) {
914 Pod pod = event.subject();
915 switch (event.type()) {
916 case K8S_POD_CREATED:
917 case K8S_POD_UPDATED:
918 eventExecutor.execute(() -> processPodCreation(pod));
919 break;
920 case K8S_POD_REMOVED:
921 eventExecutor.execute(() -> processPodRemoval(pod));
922 break;
923 default:
924 break;
925 }
926 }
927
928 private void processPodCreation(Pod pod) {
929 if (!isRelevantHelper()) {
930 return;
931 }
932
933 setBlockRulesByPod(pod, true);
934 setAllowRulesByPod(pod, true);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900935 setNamespaceRulesByPod(pod, true);
Jian Li73d3b6a2019-07-08 18:07:53 +0900936 }
937
938 private void processPodRemoval(Pod pod) {
939 if (!isRelevantHelper()) {
940 return;
941 }
942
943 setBlockRulesByPod(pod, false);
944 setAllowRulesByPod(pod, false);
Jian Lie1a5b8f2019-07-23 17:13:19 +0900945 setNamespaceRulesByPod(pod, false);
Jian Li73d3b6a2019-07-08 18:07:53 +0900946 }
947 }
948
949 private class InternalNetworkPolicyListener implements K8sNetworkPolicyListener {
950
951 private boolean isRelevantHelper() {
952 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
953 }
954
955 @Override
956 public void event(K8sNetworkPolicyEvent event) {
957 NetworkPolicy policy = event.subject();
958 switch (event.type()) {
959 case K8S_NETWORK_POLICY_CREATED:
960 case K8S_NETWORK_POLICY_UPDATED:
961 eventExecutor.execute(() -> processNetworkPolicyCreation(policy));
962 break;
963 case K8S_NETWORK_POLICY_REMOVED:
964 eventExecutor.execute(() -> processNetworkPolicyRemoval(policy));
965 break;
966 default:
967 break;
968 }
969 }
970
971 private void processNetworkPolicyCreation(NetworkPolicy policy) {
972 if (!isRelevantHelper()) {
973 return;
974 }
975
976 setBlockRulesByPolicy(policy, true);
977 setAllowRulesByPolicy(policy, true);
978 }
979
980 private void processNetworkPolicyRemoval(NetworkPolicy policy) {
981 if (!isRelevantHelper()) {
982 return;
983 }
984
985 setBlockRulesByPolicy(policy, false);
986 setAllowRulesByPolicy(policy, false);
987 }
988 }
Jian Lie1a5b8f2019-07-23 17:13:19 +0900989
990 private class InternalNamespaceListener implements K8sNamespaceListener {
991
992 private boolean isRelevantHelper() {
993 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
994 }
995
996 @Override
997 public void event(K8sNamespaceEvent event) {
998 Namespace ns = event.subject();
999 switch (event.type()) {
1000 case K8S_NAMESPACE_CREATED:
1001 case K8S_NAMESPACE_UPDATED:
1002 eventExecutor.execute(() -> processNamespaceCreation(ns));
1003 break;
1004 case K8S_NAMESPACE_REMOVED:
1005 eventExecutor.execute(() -> processNamespaceRemoval(ns));
1006 break;
1007 default:
1008 break;
1009 }
1010 }
1011
1012 private void processNamespaceCreation(Namespace namespace) {
1013 if (!isRelevantHelper()) {
1014 return;
1015 }
1016
1017 setDefaultAllowNamespaceRules(namespace, true);
1018 setDefaultAllowServiceRules(true);
1019 }
1020
1021 private void processNamespaceRemoval(Namespace namespace) {
1022 if (!isRelevantHelper()) {
1023 return;
1024 }
1025
1026 // do nothing for now
1027 }
1028 }
Jian Li73d3b6a2019-07-08 18:07:53 +09001029}