summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorValerij Fredriksen <freva@users.noreply.github.com>2019-04-24 16:34:04 +0200
committerGitHub <noreply@github.com>2019-04-24 16:34:04 +0200
commit3975dbc206434999e1b7f262b7dd58749e29a013 (patch)
tree626d4067c3f7db40c2ccff36e8e144600e91db30
parent0cb54dd44fe85a0ae617b407f730851a2106ec42 (diff)
parent31b16dab69bbc8d594de9001a8d7617b0fa8f2a2 (diff)
Merge pull request #9169 from vespa-engine/freva/do-not-use-filter-config
Use config in NodeIndentifier and Authorizer
-rw-r--r--config-provisioning/src/main/resources/configdefinitions/config-server-security.def9
-rw-r--r--container-disc/src/main/java/com/yahoo/container/FilterConfigProvider.java10
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilter.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/Authorizer.java25
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java46
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierFilter.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilterTest.java17
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizerTest.java21
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierTest.java63
9 files changed, 102 insertions, 105 deletions
diff --git a/config-provisioning/src/main/resources/configdefinitions/config-server-security.def b/config-provisioning/src/main/resources/configdefinitions/config-server-security.def
new file mode 100644
index 00000000000..cfd5c9c04e5
--- /dev/null
+++ b/config-provisioning/src/main/resources/configdefinitions/config-server-security.def
@@ -0,0 +1,9 @@
+# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+namespace=config.provisioning
+
+athenzProviderHostname string
+controllerHostIdentity string
+configServerHostIdentity string
+proxyHostIdentity string
+tenantHostIdentity string
+tenantIdentity string
diff --git a/container-disc/src/main/java/com/yahoo/container/FilterConfigProvider.java b/container-disc/src/main/java/com/yahoo/container/FilterConfigProvider.java
index a127cb03a01..c17b9d445a2 100644
--- a/container-disc/src/main/java/com/yahoo/container/FilterConfigProvider.java
+++ b/container-disc/src/main/java/com/yahoo/container/FilterConfigProvider.java
@@ -57,11 +57,7 @@ public final class FilterConfigProvider implements Provider<FilterConfig> {
private final FilterConfig filterConfig;
public FilterConfigProvider(HttpFilterConfig vespaConfig) {
- this(new MapFilterConfig(toMap(vespaConfig), vespaConfig.filterName(), vespaConfig.filterClass()));
- }
-
- private FilterConfigProvider(FilterConfig filterConfig) {
- this.filterConfig = filterConfig;
+ filterConfig = new MapFilterConfig(toMap(vespaConfig), vespaConfig.filterName(), vespaConfig.filterClass());
}
private static Map<String, String> toMap(HttpFilterConfig vespaConfig) {
@@ -71,10 +67,6 @@ public final class FilterConfigProvider implements Provider<FilterConfig> {
return parameters;
}
- public static FilterConfigProvider from(String filterName, String filterClass, Map<String, String> initParameters) {
- return new FilterConfigProvider(new MapFilterConfig(initParameters, filterName, filterClass));
- }
-
@Override
public FilterConfig get() {
return filterConfig;
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilter.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilter.java
index d15cd288f39..9934c343092 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilter.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilter.java
@@ -2,11 +2,10 @@
package com.yahoo.vespa.hosted.provision.restapi.v2.filter;
import com.google.inject.Inject;
+import com.yahoo.config.provisioning.ConfigServerSecurityConfig;
import com.yahoo.jdisc.handler.ResponseHandler;
import com.yahoo.jdisc.http.filter.DiscFilterRequest;
-import com.yahoo.jdisc.http.filter.FilterConfig;
import com.yahoo.jdisc.http.filter.SecurityRequestFilter;
-import com.yahoo.vespa.athenz.utils.AthenzIdentities;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.restapi.v2.ErrorResponse;
import com.yahoo.yolean.chain.After;
@@ -32,12 +31,8 @@ public class AuthorizationFilter implements SecurityRequestFilter {
private final BiConsumer<ErrorResponse, ResponseHandler> rejectAction;
@Inject
- public AuthorizationFilter(NodeRepository nodeRepository, FilterConfig filterConfig) {
- this.authorizer = new Authorizer(nodeRepository,
- AthenzIdentities.from(filterConfig.getInitParameter("controller.identity")),
- AthenzIdentities.from(filterConfig.getInitParameter("configserver.identity")),
- AthenzIdentities.from(filterConfig.getInitParameter("proxy.identity")),
- AthenzIdentities.from(filterConfig.getInitParameter("tenant-host.identity")));
+ public AuthorizationFilter(NodeRepository nodeRepository, ConfigServerSecurityConfig securityConfig) {
+ this.authorizer = new Authorizer(nodeRepository, securityConfig);
this.rejectAction = AuthorizationFilter::logAndReject;
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/Authorizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/Authorizer.java
index 44636727531..062a9c32afb 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/Authorizer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/Authorizer.java
@@ -2,7 +2,9 @@
package com.yahoo.vespa.hosted.provision.restapi.v2.filter;
import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provisioning.ConfigServerSecurityConfig;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
+import com.yahoo.vespa.athenz.utils.AthenzIdentities;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import org.apache.http.NameValuePair;
@@ -28,16 +30,23 @@ import java.util.stream.Collectors;
*/
public class Authorizer implements BiPredicate<NodePrincipal, URI> {
private final NodeRepository nodeRepository;
- private final AthenzIdentity controllerIdentity;
+ private final String athenzProviderHostname;
+ private final AthenzIdentity controllerHostIdentity;
private final Set<AthenzIdentity> trustedIdentities;
private final Set<AthenzIdentity> hostAdminIdentities;
- Authorizer(NodeRepository nodeRepository, AthenzIdentity controllerIdentity, AthenzIdentity configServerIdentity,
- AthenzIdentity proxyIdentity, AthenzIdentity tenantIdentity) {
+ Authorizer(NodeRepository nodeRepository, ConfigServerSecurityConfig securityConfig) {
+ AthenzIdentity configServerHostIdentity = AthenzIdentities.from(securityConfig.configServerHostIdentity());
+
this.nodeRepository = nodeRepository;
- this.controllerIdentity = controllerIdentity;
- this.trustedIdentities = Set.of(controllerIdentity, configServerIdentity);
- this.hostAdminIdentities = Set.of(controllerIdentity, configServerIdentity, proxyIdentity, tenantIdentity);
+ this.athenzProviderHostname = securityConfig.athenzProviderHostname();
+ this.controllerHostIdentity = AthenzIdentities.from(securityConfig.controllerHostIdentity());
+ this.trustedIdentities = Set.of(controllerHostIdentity, configServerHostIdentity);
+ this.hostAdminIdentities = Set.of(
+ controllerHostIdentity,
+ configServerHostIdentity,
+ AthenzIdentities.from(securityConfig.tenantHostIdentity()),
+ AthenzIdentities.from(securityConfig.proxyHostIdentity()));
}
/** Returns whether principal is authorized to access given URI */
@@ -51,7 +60,7 @@ public class Authorizer implements BiPredicate<NodePrincipal, URI> {
// Only controller can access everything else in flags
if (uri.getPath().startsWith("/flags/v1/")) {
- return principal.getAthenzIdentityName().get().equals(controllerIdentity);
+ return principal.getAthenzIdentityName().get().equals(controllerHostIdentity);
}
// Trusted services can access everything
@@ -63,7 +72,7 @@ public class Authorizer implements BiPredicate<NodePrincipal, URI> {
if (principal.getHostname().isPresent()) {
String hostname = principal.getHostname().get();
if (isAthenzProviderApi(uri)) {
- return hostname.equals(NodeIdentifier.ZTS_AWS_IDENTITY) || hostname.equals(NodeIdentifier.ZTS_ON_PREM_IDENTITY);
+ return athenzProviderHostname.equals(hostname);
}
// Individual nodes can only access their own resources
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java
index a434f021cad..ecc3f84f86c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifier.java
@@ -5,14 +5,16 @@ import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Zone;
-import com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId;
+import com.yahoo.config.provisioning.ConfigServerSecurityConfig;
import com.yahoo.security.SubjectAlternativeName;
import com.yahoo.security.X509CertificateUtils;
+import com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import java.security.cert.X509Certificate;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -25,23 +27,24 @@ import static com.yahoo.security.SubjectAlternativeName.Type.DNS_NAME;
*/
class NodeIdentifier {
- static final String TENANT_DOCKER_HOST_IDENTITY = "vespa.vespa.tenant-host";
- static final String PROXY_HOST_IDENTITY = "vespa.vespa.proxy";
- static final String CONFIGSERVER_HOST_IDENTITY = "vespa.vespa.configserver";
- static final String TENANT_DOCKER_CONTAINER_IDENTITY = "vespa.vespa.tenant";
- static final String ZTS_ON_PREM_IDENTITY = "zts.athens.yahoo.com";
- static final String ZTS_AWS_IDENTITY = "zts.athenz.ouroath.com";
private static final String INSTANCE_ID_DELIMITER = ".instanceid.athenz.";
private final Zone zone;
private final NodeRepository nodeRepository;
-
+ private final String athenzProviderHostname;
+ private final Set<String> configServerLikeIdentities;
+ private final Set<String> tenantAndProxyHostIndentities;
+ private final String tenantIdentity;
private final Supplier<List<Node>> nodeCache;
- NodeIdentifier(Zone zone, NodeRepository nodeRepository) {
+ NodeIdentifier(Zone zone, NodeRepository nodeRepository, ConfigServerSecurityConfig securityConfig) {
this.zone = zone;
this.nodeRepository = nodeRepository;
+ this.athenzProviderHostname = securityConfig.athenzProviderHostname();
+ this.configServerLikeIdentities = Set.of(securityConfig.controllerHostIdentity(), securityConfig.configServerHostIdentity());
+ this.tenantAndProxyHostIndentities = Set.of(securityConfig.tenantHostIdentity(), securityConfig.proxyHostIdentity());
+ this.tenantIdentity = securityConfig.tenantIdentity();
nodeCache = Suppliers.memoizeWithExpiration(nodeRepository::getNodes, 1, TimeUnit.MINUTES);
}
@@ -52,17 +55,17 @@ class NodeIdentifier {
.orElseThrow(() -> new NodeIdentifierException("Certificate subject common name is missing!"));
if (isAthenzIssued(clientCertificate)) {
List<SubjectAlternativeName> sans = X509CertificateUtils.getSubjectAlternativeNames(clientCertificate);
- switch (subjectCommonName) {
- case TENANT_DOCKER_HOST_IDENTITY:
- case PROXY_HOST_IDENTITY:
- return NodePrincipal.withAthenzIdentity(subjectCommonName, getHostFromCalypsoOrAwsCertificate(sans), certificateChain);
- case TENANT_DOCKER_CONTAINER_IDENTITY:
- return NodePrincipal.withAthenzIdentity(subjectCommonName, getHostFromVespaCertificate(sans), certificateChain);
- case CONFIGSERVER_HOST_IDENTITY:
- default:
- return NodePrincipal.withAthenzIdentity(subjectCommonName, certificateChain);
+ if (configServerLikeIdentities.contains(subjectCommonName)) {
+ return NodePrincipal.withAthenzIdentity(subjectCommonName, certificateChain);
+ } else if (tenantAndProxyHostIndentities.contains(subjectCommonName)) {
+ return NodePrincipal.withAthenzIdentity(subjectCommonName, getHostFromCalypsoCertificate(sans), certificateChain);
+ } else if (subjectCommonName.equals(tenantIdentity)) {
+ return NodePrincipal.withAthenzIdentity(subjectCommonName, getHostFromVespaCertificate(sans), certificateChain);
}
- } else if (subjectCommonName.equals(ZTS_ON_PREM_IDENTITY) || subjectCommonName.equals(ZTS_AWS_IDENTITY)) {
+
+ throw new NodeIdentifierException(String.format(
+ "Subject common name (%s) does not match any expected identity", subjectCommonName));
+ } else if (subjectCommonName.contains(athenzProviderHostname)) {
// ZTS treated as a node principal even though its not a Vespa node
return NodePrincipal.withLegacyIdentity(subjectCommonName, certificateChain);
} else {
@@ -79,11 +82,6 @@ class NodeIdentifier {
return issuerCommonName.equals("Yahoo Athenz CA") || issuerCommonName.equals("Athenz AWS CA");
}
- // NOTE: AWS instance id is currently stored as the attribute 'openstack-id' in node repository.
- private String getHostFromCalypsoOrAwsCertificate(List<SubjectAlternativeName> sans) {
- return getHostFromCalypsoCertificate(sans);
- }
-
private String getHostFromCalypsoCertificate(List<SubjectAlternativeName> sans) {
String openStackId = getUniqueInstanceId(sans);
return nodeCache.get().stream()
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierFilter.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierFilter.java
index 1ff8958a993..1c66c17a0bb 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierFilter.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierFilter.java
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.restapi.v2.filter;
import com.google.inject.Inject;
import com.yahoo.config.provision.Zone;
+import com.yahoo.config.provisioning.ConfigServerSecurityConfig;
import com.yahoo.jdisc.Response;
import com.yahoo.jdisc.http.filter.DiscFilterRequest;
import com.yahoo.jdisc.http.filter.security.base.JsonSecurityRequestFilterBase;
@@ -29,8 +30,8 @@ public class NodeIdentifierFilter extends JsonSecurityRequestFilterBase {
private final NodeIdentifier nodeIdentifier;
@Inject
- public NodeIdentifierFilter(Zone zone, NodeRepository nodeRepository) {
- this.nodeIdentifier = new NodeIdentifier(zone, nodeRepository);
+ public NodeIdentifierFilter(Zone zone, NodeRepository nodeRepository, ConfigServerSecurityConfig securityConfig) {
+ this.nodeIdentifier = new NodeIdentifier(zone, nodeRepository, securityConfig);
}
@Override
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilterTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilterTest.java
index 2f1755dd106..3ea1570f770 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilterTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizationFilterTest.java
@@ -2,23 +2,20 @@
package com.yahoo.vespa.hosted.provision.restapi.v2.filter;
import com.yahoo.application.container.handler.Request.Method;
-import com.yahoo.container.FilterConfigProvider;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.hosted.provision.restapi.v2.filter.FilterTester.Request;
import com.yahoo.vespa.hosted.provision.testutils.MockNodeFlavors;
import com.yahoo.vespa.hosted.provision.testutils.MockNodeRepository;
import org.junit.Test;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
/**
* @author mpolden
*/
public class AuthorizationFilterTest {
- private final FilterTester tester = filterTester();
+ private final FilterTester tester = new FilterTester(new AuthorizationFilter(
+ new MockNodeRepository(new MockCurator(), new MockNodeFlavors()),
+ NodeIdentifierTest.SECURITY_CONFIG));
@Test
public void filter() {
@@ -38,12 +35,4 @@ public class AuthorizationFilterTest {
tester.assertSuccess(new Request(Method.GET, "/nodes/v2/node/foo").commonName("foo"));
}
- private static FilterTester filterTester() {
- Map<String, String> params = Stream.of("controller", "configserver", "proxy", "tenant-host")
- .collect(Collectors.toMap(e -> e + ".identity", e -> "vespa." + e));
- return new FilterTester(new AuthorizationFilter(
- new MockNodeRepository(new MockCurator(), new MockNodeFlavors()),
- FilterConfigProvider.from("my-filter", AuthorizationFilter.class.getName(), params).get()));
- }
-
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizerTest.java
index b539420a55a..939de2dff25 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/AuthorizerTest.java
@@ -4,7 +4,6 @@ package com.yahoo.vespa.hosted.provision.restapi.v2.filter;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.vespa.athenz.utils.AthenzIdentities;
import com.yahoo.vespa.curator.mock.MockCurator;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.testutils.MockNodeFlavors;
@@ -17,6 +16,11 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
+import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifierTest.ATHENZ_PROVIDER_HOSTNAME;
+import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifierTest.CONFIG_SERVER_IDENTITY;
+import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifierTest.CONTROLLER_IDENTITY;
+import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifierTest.SECURITY_CONFIG;
+import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifierTest.TENANT_HOST_IDENTITY;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -25,22 +29,13 @@ import static org.junit.Assert.assertTrue;
*/
public class AuthorizerTest {
- private static final String CONTROLLER_IDENTITY = "vespa.controller";
- private static final String CONFIG_SERVER_IDENTITY = "vespa.configserver";
- private static final String PROXY_IDENTITY = "vespa.proxy";
- private static final String TENANT_HOST_IDENTITY = "vespa.tenant-host";
-
private Authorizer authorizer;
@Before
public void before() {
NodeFlavors flavors = new MockNodeFlavors();
MockNodeRepository nodeRepository = new MockNodeRepository(new MockCurator(), flavors);
- authorizer = new Authorizer(nodeRepository,
- AthenzIdentities.from(CONTROLLER_IDENTITY),
- AthenzIdentities.from(CONFIG_SERVER_IDENTITY),
- AthenzIdentities.from(PROXY_IDENTITY),
- AthenzIdentities.from(TENANT_HOST_IDENTITY));
+ authorizer = new Authorizer(nodeRepository, SECURITY_CONFIG);
Set<String> ipAddresses = Set.of("127.0.0.1", "::1");
Flavor flavor = flavors.getFlavorOrThrow("default");
@@ -170,8 +165,8 @@ public class AuthorizerTest {
@Test
public void zts_allowed_for_athenz_provider_api() {
- assertTrue(authorizedLegacyNode(NodeIdentifier.ZTS_AWS_IDENTITY, "/athenz/v1/provider/refresh"));
- assertTrue(authorizedLegacyNode(NodeIdentifier.ZTS_ON_PREM_IDENTITY, "/athenz/v1/provider/instance"));
+ assertTrue(authorizedLegacyNode(ATHENZ_PROVIDER_HOSTNAME, "/athenz/v1/provider/refresh"));
+ assertTrue(authorizedLegacyNode(ATHENZ_PROVIDER_HOSTNAME, "/athenz/v1/provider/instance"));
}
private boolean authorizedTenantNode(String hostname, String path) {
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierTest.java
index cc23be4ddb4..2a9a1c4fa3b 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/filter/NodeIdentifierTest.java
@@ -11,6 +11,7 @@ import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
+import com.yahoo.config.provisioning.ConfigServerSecurityConfig;
import com.yahoo.config.provisioning.FlavorsConfig;
import com.yahoo.security.KeyUtils;
import com.yahoo.security.Pkcs10Csr;
@@ -37,11 +38,6 @@ import java.util.Optional;
import static com.yahoo.security.KeyAlgorithm.EC;
import static com.yahoo.security.SignatureAlgorithm.SHA256_WITH_ECDSA;
import static com.yahoo.vespa.athenz.identityprovider.api.IdentityType.NODE;
-import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifier.CONFIGSERVER_HOST_IDENTITY;
-import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifier.PROXY_HOST_IDENTITY;
-import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifier.TENANT_DOCKER_CONTAINER_IDENTITY;
-import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifier.TENANT_DOCKER_HOST_IDENTITY;
-import static com.yahoo.vespa.hosted.provision.restapi.v2.filter.NodeIdentifier.ZTS_AWS_IDENTITY;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
@@ -57,7 +53,20 @@ public class NodeIdentifierTest {
@Rule
public final ExpectedException expectedException = ExpectedException.none();
- private static final String CONTROLLER_IDENTITY = "vespa.vespa.hosting";
+ static final String ATHENZ_PROVIDER_HOSTNAME = "zts.domain.tld";
+ static final String CONTROLLER_IDENTITY = "vespa.controller";
+ static final String CONFIG_SERVER_IDENTITY = "vespa.configserver";
+ static final String PROXY_HOST_IDENTITY = "vespa.proxy";
+ static final String TENANT_HOST_IDENTITY = "vespa.tenant-host";
+ static final String TENANT_IDENTITY = "vespa.tenant";
+ static final ConfigServerSecurityConfig SECURITY_CONFIG = new ConfigServerSecurityConfig.Builder()
+ .athenzProviderHostname(ATHENZ_PROVIDER_HOSTNAME)
+ .controllerHostIdentity(CONTROLLER_IDENTITY)
+ .configServerHostIdentity(CONFIG_SERVER_IDENTITY)
+ .proxyHostIdentity(PROXY_HOST_IDENTITY)
+ .tenantHostIdentity(TENANT_HOST_IDENTITY)
+ .tenantIdentity(TENANT_IDENTITY)
+ .build();
private static final String HOSTNAME = "myhostname";
private static final String PROXY_HOSTNAME = "myproxyhostname";
@@ -78,7 +87,7 @@ public class NodeIdentifierTest {
.fromKeypair(
KEYPAIR, new X500Principal("CN=" + HOSTNAME), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), SHA256_WITH_ECDSA, BigInteger.ONE)
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
expectedException.expect(NodeIdentifier.NodeIdentifierException.class);
expectedException.expectMessage("(subject=myhostname, issuer=[myhostname])");
identifier.resolveNode(singletonList(certificate));
@@ -90,17 +99,17 @@ public class NodeIdentifierTest {
nodeRepositoryDummy.addNode(OPENSTACK_ID, HOSTNAME, INSTANCE_ID, NodeType.host);
nodeRepositoryDummy.setNodeState(HOSTNAME, Node.State.active);
Pkcs10Csr csr = Pkcs10CsrBuilder
- .fromKeypair(new X500Principal("CN=" + TENANT_DOCKER_HOST_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
+ .fromKeypair(new X500Principal("CN=" + TENANT_HOST_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
.build();
X509Certificate certificate = X509CertificateBuilder
.fromCsr(csr, ATHENZ_YAHOO_CA_CERT.getSubjectX500Principal(), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), KEYPAIR.getPrivate(), SHA256_WITH_ECDSA, BigInteger.ONE)
.addSubjectAlternativeName(OPENSTACK_ID + ".instanceid.athenz.provider-name.ostk.yahoo.cloud")
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
assertTrue(identity.getHostname().isPresent());
assertEquals(HOSTNAME, identity.getHostname().get());
- assertEquals(TENANT_DOCKER_HOST_IDENTITY, identity.getHostIdentityName());
+ assertEquals(TENANT_HOST_IDENTITY, identity.getHostIdentityName());
}
@Test
@@ -109,17 +118,17 @@ public class NodeIdentifierTest {
nodeRepositoryDummy.addNode(AWS_INSTANCE_ID, HOSTNAME, INSTANCE_ID, NodeType.host);
nodeRepositoryDummy.setNodeState(HOSTNAME, Node.State.active);
Pkcs10Csr csr = Pkcs10CsrBuilder
- .fromKeypair(new X500Principal("CN=" + TENANT_DOCKER_HOST_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
+ .fromKeypair(new X500Principal("CN=" + TENANT_HOST_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
.build();
X509Certificate certificate = X509CertificateBuilder
.fromCsr(csr, ATHENZ_AWS_CA_CERT.getSubjectX500Principal(), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), KEYPAIR.getPrivate(), SHA256_WITH_ECDSA, BigInteger.ONE)
.addSubjectAlternativeName(AWS_INSTANCE_ID + ".instanceid.athenz.aws.oath.cloud")
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
assertTrue(identity.getHostname().isPresent());
assertEquals(HOSTNAME, identity.getHostname().get());
- assertEquals(TENANT_DOCKER_HOST_IDENTITY, identity.getHostIdentityName());
+ assertEquals(TENANT_HOST_IDENTITY, identity.getHostIdentityName());
}
@Test
@@ -134,7 +143,7 @@ public class NodeIdentifierTest {
.fromCsr(csr, ATHENZ_AWS_CA_CERT.getSubjectX500Principal(), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), KEYPAIR.getPrivate(), SHA256_WITH_ECDSA, BigInteger.ONE)
.addSubjectAlternativeName(AWS_INSTANCE_ID + ".instanceid.athenz.aws.oath.cloud")
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
assertTrue(identity.getHostname().isPresent());
assertEquals(PROXY_HOSTNAME, identity.getHostname().get());
@@ -145,25 +154,25 @@ public class NodeIdentifierTest {
public void accepts_aws_configserver_host_certificate() {
NodeRepositoryTester nodeRepositoryDummy = new NodeRepositoryTester();
Pkcs10Csr csr = Pkcs10CsrBuilder
- .fromKeypair(new X500Principal("CN=" + CONFIGSERVER_HOST_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
+ .fromKeypair(new X500Principal("CN=" + CONFIG_SERVER_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
.build();
X509Certificate certificate = X509CertificateBuilder
.fromCsr(csr, ATHENZ_AWS_CA_CERT.getSubjectX500Principal(), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), KEYPAIR.getPrivate(), SHA256_WITH_ECDSA, BigInteger.ONE)
.addSubjectAlternativeName(AWS_INSTANCE_ID + ".instanceid.athenz.aws.oath.cloud")
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
- assertEquals(CONFIGSERVER_HOST_IDENTITY, identity.getHostIdentityName());
+ assertEquals(CONFIG_SERVER_IDENTITY, identity.getHostIdentityName());
}
@Test
public void accepts_zts_certificate() {
X509Certificate certificate = X509CertificateBuilder
- .fromKeypair(KEYPAIR, new X500Principal("CN=" + ZTS_AWS_IDENTITY), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), SHA256_WITH_ECDSA, BigInteger.ONE)
+ .fromKeypair(KEYPAIR, new X500Principal("CN=" + ATHENZ_PROVIDER_HOSTNAME), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), SHA256_WITH_ECDSA, BigInteger.ONE)
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, new NodeRepositoryTester().nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, new NodeRepositoryTester().nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
- assertEquals(ZTS_AWS_IDENTITY, identity.getHostIdentityName());
+ assertEquals(ATHENZ_PROVIDER_HOSTNAME, identity.getHostIdentityName());
assertEquals(NodePrincipal.Type.LEGACY, identity.getType());
}
@@ -179,18 +188,18 @@ public class NodeIdentifierTest {
Node node = createNode(clusterId, clusterIndex, tenant, application);
nodeRepositoryDummy.nodeRepository().addDockerNodes(singletonList(node), nodeRepositoryDummy.nodeRepository().lockAllocation());
Pkcs10Csr csr = Pkcs10CsrBuilder
- .fromKeypair(new X500Principal("CN=" + TENANT_DOCKER_CONTAINER_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
+ .fromKeypair(new X500Principal("CN=" + TENANT_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
.build();
VespaUniqueInstanceId vespaUniqueInstanceId = new VespaUniqueInstanceId(clusterIndex, clusterId, INSTANCE_ID, application, tenant, region, environment, NODE);
X509Certificate certificate = X509CertificateBuilder
.fromCsr(csr, ATHENZ_YAHOO_CA_CERT.getSubjectX500Principal(), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), KEYPAIR.getPrivate(), SHA256_WITH_ECDSA, BigInteger.ONE)
.addSubjectAlternativeName(vespaUniqueInstanceId.asDottedString() + ".instanceid.athenz.provider-name.vespa.yahoo.cloud")
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
assertTrue(identity.getHostname().isPresent());
assertEquals(HOSTNAME, identity.getHostname().get());
- assertEquals(TENANT_DOCKER_CONTAINER_IDENTITY, identity.getHostIdentityName());
+ assertEquals(TENANT_IDENTITY, identity.getHostIdentityName());
}
@Test
@@ -202,7 +211,7 @@ public class NodeIdentifierTest {
X509Certificate certificate = X509CertificateBuilder
.fromCsr(csr, ATHENZ_YAHOO_CA_CERT.getSubjectX500Principal(), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), KEYPAIR.getPrivate(), SHA256_WITH_ECDSA, BigInteger.ONE)
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
assertFalse(identity.getHostname().isPresent());
assertEquals(CONTROLLER_IDENTITY, identity.getHostIdentityName());
@@ -214,17 +223,17 @@ public class NodeIdentifierTest {
nodeRepositoryDummy.addNode(OPENSTACK_ID, HOSTNAME, INSTANCE_ID, NodeType.tenant);
nodeRepositoryDummy.setNodeState(HOSTNAME, Node.State.active);
Pkcs10Csr csr = Pkcs10CsrBuilder
- .fromKeypair(new X500Principal("CN=" + TENANT_DOCKER_CONTAINER_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
+ .fromKeypair(new X500Principal("CN=" + TENANT_IDENTITY), KEYPAIR, SHA256_WITH_ECDSA)
.build();
X509Certificate certificate = X509CertificateBuilder
.fromCsr(csr, ATHENZ_YAHOO_CA_CERT.getSubjectX500Principal(), Instant.EPOCH, Instant.EPOCH.plusSeconds(60), KEYPAIR.getPrivate(), SHA256_WITH_ECDSA, BigInteger.ONE)
.addSubjectAlternativeName(OPENSTACK_ID + ".instanceid.athenz.ostk.yahoo.cloud")
.build();
- NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository());
+ NodeIdentifier identifier = new NodeIdentifier(ZONE, nodeRepositoryDummy.nodeRepository(), SECURITY_CONFIG);
NodePrincipal identity = identifier.resolveNode(singletonList(certificate));
assertTrue(identity.getHostname().isPresent());
assertEquals(HOSTNAME, identity.getHostname().get());
- assertEquals(TENANT_DOCKER_CONTAINER_IDENTITY, identity.getHostIdentityName());
+ assertEquals(TENANT_IDENTITY, identity.getHostIdentityName());
}
private static Node createNode(String clusterId, int clusterIndex, String tenant, String application) {