diff options
Diffstat (limited to 'node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/NodeAcl.java')
-rw-r--r-- | node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/NodeAcl.java | 89 |
1 files changed, 88 insertions, 1 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/NodeAcl.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/NodeAcl.java index b24fba83b12..4116d58f2d1 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/NodeAcl.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/NodeAcl.java @@ -2,10 +2,18 @@ package com.yahoo.vespa.hosted.provision.node; import com.google.common.collect.ImmutableSet; +import com.yahoo.config.provision.NodeType; import com.yahoo.vespa.hosted.provision.Node; +import com.yahoo.vespa.hosted.provision.NodeList; +import com.yahoo.vespa.hosted.provision.lb.LoadBalancer; +import com.yahoo.vespa.hosted.provision.lb.LoadBalancerInstance; +import com.yahoo.vespa.hosted.provision.lb.LoadBalancers; +import java.util.Comparator; +import java.util.LinkedHashSet; import java.util.Objects; import java.util.Set; +import java.util.TreeSet; /** * A node ACL. The ACL contains the node which the ACL is valid for, @@ -20,7 +28,7 @@ public class NodeAcl { private final Set<String> trustedNetworks; private final Set<Integer> trustedPorts; - public NodeAcl(Node node, Set<Node> trustedNodes, Set<String> trustedNetworks, Set<Integer> trustedPorts) { + private NodeAcl(Node node, Set<Node> trustedNodes, Set<String> trustedNetworks, Set<Integer> trustedPorts) { this.node = Objects.requireNonNull(node, "node must be non-null"); this.trustedNodes = ImmutableSet.copyOf(Objects.requireNonNull(trustedNodes, "trustedNodes must be non-null")); this.trustedNetworks = ImmutableSet.copyOf(Objects.requireNonNull(trustedNetworks, "trustedNetworks must be non-null")); @@ -43,4 +51,83 @@ public class NodeAcl { return trustedPorts; } + public static NodeAcl from(Node node, NodeList allNodes, LoadBalancers loadBalancers) { + Set<Node> trustedNodes = new TreeSet<>(Comparator.comparing(Node::hostname)); + Set<Integer> trustedPorts = new LinkedHashSet<>(); + Set<String> trustedNetworks = new LinkedHashSet<>(); + + // For all cases below, trust: + // - SSH: If the Docker host has one container, and it is using the Docker host's network namespace, + // opening up SSH to the Docker host is done here as a trusted port. For simplicity all nodes have + // SSH opened (which is safe for 2 reasons: SSH daemon is not run inside containers, and NPT networks + // will (should) not forward port 22 traffic to container). + // - parent host (for health checks and metrics) + // - nodes in same application + // - load balancers allocated to application + trustedPorts.add(22); + allNodes.parentOf(node).ifPresent(trustedNodes::add); + node.allocation().ifPresent(allocation -> { + trustedNodes.addAll(allNodes.owner(allocation.owner()).asList()); + loadBalancers.list(allocation.owner()).asList() + .stream() + .map(LoadBalancer::instance) + .map(LoadBalancerInstance::networks) + .forEach(trustedNetworks::addAll); + }); + + switch (node.type()) { + case tenant: + // Tenant nodes in other states than ready, trust: + // - config servers + // - proxy nodes + // - parents of the nodes in the same application: If some of the nodes are on a different IP versions + // or only a subset of them are dual-stacked, the communication between the nodes may be NATed + // with via parent's IP address. + trustedNodes.addAll(allNodes.nodeType(NodeType.config).asList()); + trustedNodes.addAll(allNodes.nodeType(NodeType.proxy).asList()); + node.allocation().ifPresent(allocation -> + trustedNodes.addAll(allNodes.parentsOf(allNodes.owner(allocation.owner())).asList())); + + if (node.state() == Node.State.ready) { + // Tenant nodes in state ready, trust: + // - All tenant nodes in zone. When a ready node is allocated to a an application there's a brief + // window where current ACLs have not yet been applied on the node. To avoid service disruption + // during this window, ready tenant nodes trust all other tenant nodes. + trustedNodes.addAll(allNodes.nodeType(NodeType.tenant).asList()); + } + break; + + case config: + // Config servers trust: + // - all nodes + // - port 4443 from the world + trustedNodes.addAll(allNodes.asList()); + trustedPorts.add(4443); + break; + + case proxy: + // Proxy nodes trust: + // - config servers + // - all connections from the world on 4080 (insecure tb removed), and 4443 + trustedNodes.addAll(allNodes.nodeType(NodeType.config).asList()); + trustedPorts.add(443); + trustedPorts.add(4080); + trustedPorts.add(4443); + break; + + case controller: + // Controllers: + // - port 4443 (HTTPS + Athenz) from the world + // - port 443 (HTTPS + Okta) from the world + trustedPorts.add(4443); + trustedPorts.add(443); + break; + + default: + throw new IllegalArgumentException("Don't know how to create ACL for " + node + + " of type " + node.type()); + } + return new NodeAcl(node, trustedNodes, trustedNetworks, trustedPorts); + } + } |