diff options
Diffstat (limited to 'controller-api/src/main/java/com')
33 files changed, 758 insertions, 68 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/DeploymentId.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/DeploymentId.java index 80fe98a4489..c0bebf54803 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/DeploymentId.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/DeploymentId.java @@ -1,7 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.api.identifiers; -import com.yahoo.config.provision.Zone; +import com.yahoo.config.provision.ZoneId; /** * Application + zone. @@ -12,9 +12,9 @@ import com.yahoo.config.provision.Zone; public class DeploymentId { private final com.yahoo.config.provision.ApplicationId application; - private final Zone zone; + private final ZoneId zone; - public DeploymentId(com.yahoo.config.provision.ApplicationId application, Zone zone) { + public DeploymentId(com.yahoo.config.provision.ApplicationId application, ZoneId zone) { this.application = application; this.zone = zone; } @@ -22,7 +22,7 @@ public class DeploymentId { public com.yahoo.config.provision.ApplicationId applicationId() { return application; } - public Zone zone() { return zone; } + public ZoneId zone() { return zone; } public String dottedString() { diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/RotationId.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/RotationId.java index aab18595d20..2eeb0f60748 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/RotationId.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/RotationId.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.controller.api.identifiers; /** * @author smorgrav */ +// TODO: Used in serialization (ConfigServerClient). Remove when no longer used by ControllerDb and ConfigServerClient public class RotationId extends Identifier { public RotationId(String id) { diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/ZoneId.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/ZoneId.java deleted file mode 100644 index 79210143d19..00000000000 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/identifiers/ZoneId.java +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.api.identifiers; - -/** - * @author smorgrav - */ -public class ZoneId extends Identifier { - - public ZoneId(EnvironmentId envId, RegionId regionId) { - super(envId.id() + ":" + regionId.id()); - } - -} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MetricsService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MetricsService.java index 1ceb064ad44..d3e1b881bbd 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MetricsService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MetricsService.java @@ -2,7 +2,7 @@ package com.yahoo.vespa.hosted.controller.api.integration; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Zone; +import com.yahoo.config.provision.ZoneId; import java.util.Map; @@ -15,9 +15,9 @@ public interface MetricsService { ApplicationMetrics getApplicationMetrics(ApplicationId application); - DeploymentMetrics getDeploymentMetrics(ApplicationId application, Zone zone); + DeploymentMetrics getDeploymentMetrics(ApplicationId application, ZoneId zone); - Map<String, SystemMetrics> getSystemMetrics(ApplicationId application, Zone zone); + Map<String, SystemMetrics> getSystemMetrics(ApplicationId application, ZoneId zone); class DeploymentMetrics { diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ApplicationAction.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ApplicationAction.java new file mode 100644 index 00000000000..3323cda89b3 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ApplicationAction.java @@ -0,0 +1,17 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +/** + * @author bjorncs + */ +public enum ApplicationAction { + deploy("deployer"), + read("reader"), + write("writer"); + + public final String roleName; + + ApplicationAction(String roleName) { + this.roleName = roleName; + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzClientFactory.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzClientFactory.java new file mode 100644 index 00000000000..a2a16d10cdb --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzClientFactory.java @@ -0,0 +1,15 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +/** + * @author bjorncs + */ +public interface AthenzClientFactory { + + ZmsClient createZmsClientWithServicePrincipal(); + + ZtsClient createZtsClientWithServicePrincipal(); + + ZmsClient createZmsClientWithAuthorizedServiceToken(NToken authorizedServiceToken); + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzIdentity.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzIdentity.java new file mode 100644 index 00000000000..ef63ef2581f --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzIdentity.java @@ -0,0 +1,16 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + + +import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; + +/** + * @author bjorncs + */ +public interface AthenzIdentity { + AthenzDomain getDomain(); + String getName(); + default String getFullName() { + return getDomain().id() + "." + getName(); + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzIdentityCertificate.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzIdentityCertificate.java new file mode 100644 index 00000000000..d53817c09e4 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzIdentityCertificate.java @@ -0,0 +1,27 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +/** + * @author bjorncs + */ +public class AthenzIdentityCertificate { + + private final X509Certificate certificate; + private final PrivateKey privateKey; + + public AthenzIdentityCertificate(X509Certificate certificate, PrivateKey privateKey) { + this.certificate = certificate; + this.privateKey = privateKey; + } + + public X509Certificate getCertificate() { + return certificate; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzPrincipal.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzPrincipal.java new file mode 100644 index 00000000000..8279edcd8e6 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzPrincipal.java @@ -0,0 +1,59 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; + +import java.security.Principal; +import java.util.Objects; + +/** + * @author bjorncs + */ +public class AthenzPrincipal implements Principal { + + private final AthenzIdentity athenzIdentity; + private final NToken nToken; + + public AthenzPrincipal(AthenzIdentity athenzIdentity, + NToken nToken) { + this.athenzIdentity = athenzIdentity; + this.nToken = nToken; + } + + public AthenzIdentity getIdentity() { + return athenzIdentity; + } + + @Override + public String getName() { + return athenzIdentity.getFullName(); + } + + public AthenzDomain getDomain() { + return athenzIdentity.getDomain(); + } + + public NToken getNToken() { + return nToken; + } + + @Override + public String toString() { + return "AthenzPrincipal{" + + "athenzIdentity=" + athenzIdentity + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AthenzPrincipal principal = (AthenzPrincipal) o; + return Objects.equals(athenzIdentity, principal.athenzIdentity); + } + + @Override + public int hashCode() { + return Objects.hash(athenzIdentity); + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzPublicKey.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzPublicKey.java new file mode 100644 index 00000000000..c7f370dd4e3 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzPublicKey.java @@ -0,0 +1,49 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import java.security.PublicKey; +import java.util.Objects; + +/** + * @author bjorncs + */ +public class AthenzPublicKey { + + private final PublicKey publicKey; + private final String keyId; + + public AthenzPublicKey(PublicKey publicKey, String keyId) { + this.publicKey = publicKey; + this.keyId = keyId; + } + + public PublicKey getPublicKey() { + return publicKey; + } + + public String getKeyId() { + return keyId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AthenzPublicKey that = (AthenzPublicKey) o; + return Objects.equals(publicKey, that.publicKey) && + Objects.equals(keyId, that.keyId); + } + + @Override + public int hashCode() { + return Objects.hash(publicKey, keyId); + } + + @Override + public String toString() { + return "AthenzPublicKey{" + + "publicKey=" + publicKey + + ", keyId='" + keyId + '\'' + + '}'; + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzRoleCertificate.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzRoleCertificate.java new file mode 100644 index 00000000000..80548cccd89 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzRoleCertificate.java @@ -0,0 +1,27 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +/** + * @author bjorncs + */ +public class AthenzRoleCertificate { + + private final X509Certificate certificate; + private final PrivateKey privateKey; + + public AthenzRoleCertificate(X509Certificate certificate, PrivateKey privateKey) { + this.certificate = certificate; + this.privateKey = privateKey; + } + + public X509Certificate getCertificate() { + return certificate; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzService.java new file mode 100644 index 00000000000..24cd7671d96 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzService.java @@ -0,0 +1,58 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; +import com.yahoo.vespa.hosted.controller.api.identifiers.ScrewdriverId; + +import java.util.Objects; + +/** + * @author bjorncs + */ +public class AthenzService implements AthenzIdentity { + + private final AthenzDomain domain; + private final String serviceName; + + public AthenzService(AthenzDomain domain, String serviceName) { + this.domain = domain; + this.serviceName = serviceName; + } + + public AthenzService(String domain, String serviceName) { + this(new AthenzDomain(domain), serviceName); + } + + public static AthenzService fromScrewdriverId(ScrewdriverId screwdriverId) { + return new AthenzService(AthenzUtils.SCREWDRIVER_DOMAIN, "sd" + screwdriverId.id()); + } + + @Override + public AthenzDomain getDomain() { + return domain; + } + + @Override + public String getName() { + return serviceName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AthenzService that = (AthenzService) o; + return Objects.equals(domain, that.domain) && + Objects.equals(serviceName, that.serviceName); + } + + @Override + public int hashCode() { + return Objects.hash(domain, serviceName); + } + + @Override + public String toString() { + return String.format("AthenzService(%s)", getFullName()); + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzSslContextProvider.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzSslContextProvider.java new file mode 100644 index 00000000000..480105a2d86 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzSslContextProvider.java @@ -0,0 +1,14 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.google.inject.Provider; + +import javax.net.ssl.SSLContext; + +/** + * Provides a {@link SSLContext} for use in controller clients communicating with Athenz TLS secured services. + * It is configured with a keystore containing the Athenz service certificate and a trust store with the Athenz CA certificates. + * + * @author bjorncs + */ +public interface AthenzSslContextProvider extends Provider<SSLContext> {} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzUser.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzUser.java new file mode 100644 index 00000000000..782876f21f1 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzUser.java @@ -0,0 +1,56 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; +import com.yahoo.vespa.hosted.controller.api.identifiers.UserId; + +import java.util.Objects; + +/** + * @author bjorncs + */ +public class AthenzUser implements AthenzIdentity { + private final UserId userId; + + public AthenzUser(UserId userId) { + this.userId = userId; + } + + public static AthenzUser fromUserId(UserId userId) { + return new AthenzUser(userId); + } + + @Override + public AthenzDomain getDomain() { + return AthenzUtils.USER_PRINCIPAL_DOMAIN; + } + + @Override + public String getName() { + return userId.id(); + } + + public UserId getUserId() { + return userId; + } + + @Override + public String toString() { + return "AthenzUser{" + + "userId=" + userId + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AthenzUser that = (AthenzUser) o; + return Objects.equals(userId, that.userId); + } + + @Override + public int hashCode() { + return Objects.hash(userId); + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzUtils.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzUtils.java new file mode 100644 index 00000000000..0ed5d86dd7e --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzUtils.java @@ -0,0 +1,26 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; +import com.yahoo.vespa.hosted.controller.api.identifiers.UserId; + +/** + * @author bjorncs + */ +public class AthenzUtils { + + private AthenzUtils() {} + + public static final AthenzDomain USER_PRINCIPAL_DOMAIN = new AthenzDomain("user"); + public static final AthenzDomain SCREWDRIVER_DOMAIN = new AthenzDomain("cd.screwdriver.project"); + public static final AthenzService ZMS_ATHENZ_SERVICE = new AthenzService("sys.auth", "zms"); + + public static AthenzIdentity createAthenzIdentity(AthenzDomain domain, String identityName) { + if (domain.equals(USER_PRINCIPAL_DOMAIN)) { + return AthenzUser.fromUserId(new UserId(identityName)); + } else { + return new AthenzService(domain, identityName); + } + } + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/InvalidTokenException.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/InvalidTokenException.java new file mode 100644 index 00000000000..1df1746b02e --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/InvalidTokenException.java @@ -0,0 +1,11 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +/** + * @author bjorncs + */ +public class InvalidTokenException extends Exception { + public InvalidTokenException(String message) { + super(message); + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/NToken.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/NToken.java new file mode 100644 index 00000000000..c2796befdc8 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/NToken.java @@ -0,0 +1,36 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import java.util.Objects; + +/** + * Represents an Athenz NToken (principal token) + * + * @author bjorncs + */ +public class NToken { + + private final String rawToken; + + public NToken(String rawToken) { + this.rawToken = rawToken; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NToken nToken = (NToken) o; + return Objects.equals(rawToken, nToken.rawToken); + } + + public String getRawToken() { + return rawToken; + } + + @Override + public int hashCode() { + return Objects.hash(rawToken); + } + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZToken.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZToken.java new file mode 100644 index 00000000000..cfa63b04197 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZToken.java @@ -0,0 +1,36 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import java.util.Objects; + +/** + * Represents an Athenz ZToken (role token) + * + * @author bjorncs + */ +public class ZToken { + + private final String rawToken; + + public ZToken(String rawToken) { + this.rawToken = rawToken; + } + + public String getRawToken() { + return rawToken; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ZToken zToken = (ZToken) o; + return Objects.equals(rawToken, zToken.rawToken); + } + + @Override + public int hashCode() { + return Objects.hash(rawToken); + } + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClient.java new file mode 100644 index 00000000000..d72b8960427 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClient.java @@ -0,0 +1,35 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId; +import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; + +import java.util.List; + +/** + * @author bjorncs + */ +public interface ZmsClient { + + void createTenant(AthenzDomain tenantDomain); + + void deleteTenant(AthenzDomain tenantDomain); + + void addApplication(AthenzDomain tenantDomain, ApplicationId applicationName); + + void deleteApplication(AthenzDomain tenantDomain, ApplicationId applicationName); + + boolean hasApplicationAccess(AthenzIdentity athenzIdentity, ApplicationAction action, AthenzDomain tenantDomain, ApplicationId applicationName); + + boolean hasTenantAdminAccess(AthenzIdentity athenzIdentity, AthenzDomain tenantDomain); + + // Used before vespa tenancy is established for the domain. + boolean isDomainAdmin(AthenzIdentity athenzIdentity, AthenzDomain domain); + + List<AthenzDomain> getDomainList(String prefix); + + AthenzPublicKey getPublicKey(AthenzService service, String keyId); + + List<AthenzPublicKey> getPublicKeys(AthenzService service); + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsException.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsException.java new file mode 100644 index 00000000000..31e9e549c08 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsException.java @@ -0,0 +1,24 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +/** + * @author bjorncs + */ +public class ZmsException extends RuntimeException { + + private final int code; + + public ZmsException(int code, Throwable cause) { + super(cause.getMessage(), cause); + this.code = code; + } + + public ZmsException(int code, String message) { + super(message); + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsKeystore.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsKeystore.java new file mode 100644 index 00000000000..e2cb38a8466 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsKeystore.java @@ -0,0 +1,16 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import java.security.PublicKey; +import java.util.Optional; + +/** + * @author bjorncs + */ +public interface ZmsKeystore { + + Optional<PublicKey> getPublicKey(AthenzService service, String keyId); + + default void preloadKeys(AthenzService service) { /* Default implementation is noop */ } + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java new file mode 100644 index 00000000000..f37c1679d1e --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsClient.java @@ -0,0 +1,19 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.yahoo.vespa.hosted.controller.api.identifiers.AthenzDomain; + +import java.util.List; + +/** + * @author bjorncs + */ +public interface ZtsClient { + + List<AthenzDomain> getTenantDomainsForUser(AthenzIdentity principal); + + AthenzIdentityCertificate getIdentityCertificate(); + + AthenzRoleCertificate getRoleCertificate(AthenzDomain roleDomain, String roleName); + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsException.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsException.java new file mode 100644 index 00000000000..2be998e1544 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZtsException.java @@ -0,0 +1,19 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +/** + * @author bjorncs + */ +public class ZtsException extends RuntimeException { + + private final int code; + + public ZtsException(int code, Throwable cause) { + super(cause.getMessage(), cause); + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/package-info.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/package-info.java new file mode 100644 index 00000000000..d66525275bc --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/package-info.java @@ -0,0 +1,8 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +/** + * @author bjorncs + */ +@ExportPackage +package com.yahoo.vespa.hosted.controller.api.integration.athenz; + +import com.yahoo.osgi.annotation.ExportPackage;
\ No newline at end of file diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java index 10f9e18fa41..ec9cf0b3436 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java @@ -2,9 +2,9 @@ package com.yahoo.vespa.hosted.controller.api.integration.dns; -import java.util.ArrayList; import java.util.Collections; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -15,22 +15,41 @@ import java.util.UUID; */ public class MemoryNameService implements NameService { - private final List<Record> records = new ArrayList<>(); + private final Map<RecordId, Record> records = new HashMap<>(); - public List<Record> records() { - return Collections.unmodifiableList(records); + public Map<RecordId, Record> records() { + return Collections.unmodifiableMap(records); } @Override - public RecordId createCname(String alias, String canonicalName) { - records.add(new Record(Record.Type.CNAME.name(), alias, canonicalName)); - return new RecordId(UUID.randomUUID().toString()); + public RecordId createCname(RecordName alias, RecordData canonicalName) { + RecordId id = new RecordId(UUID.randomUUID().toString()); + records.put(id, new Record(id, Record.Type.CNAME, alias, canonicalName)); + return id; } @Override - public Optional<Record> findRecord(Record.Type type, String name) { - return records.stream() + public Optional<Record> findRecord(Record.Type type, RecordName name) { + return records.values().stream() .filter(record -> record.type() == type && record.name().equals(name)) .findFirst(); } + + @Override + public Optional<Record> findRecord(Record.Type type, RecordData data) { + return records.values() + .stream() + .filter(record -> record.type() == type && record.data().equals(data)) + .findFirst(); + } + + @Override + public void updateRecord(RecordId id, RecordData newData) { + records.computeIfPresent(id, (k, record) -> new Record(id, record.type(), record.name(), newData)); + } + + @Override + public void removeRecord(RecordId id) { + records.remove(id); + } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java index 2ccce23b60c..078a7e7cefb 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java @@ -14,11 +14,20 @@ public interface NameService { * Create a new CNAME record * * @param alias The alias to create - * @param canonicalName The canonical name which the alias should point to. This must be a domain. + * @param canonicalName The canonical name which the alias should point to. This must be a FQDN. */ - RecordId createCname(String alias, String canonicalName); + RecordId createCname(RecordName alias, RecordData canonicalName); /** Find record by type and name */ - Optional<Record> findRecord(Record.Type type, String name); + Optional<Record> findRecord(Record.Type type, RecordName name); + + /** Find record by type and data */ + Optional<Record> findRecord(Record.Type type, RecordData data); + + /** Update existing record */ + void updateRecord(RecordId id, RecordData newData); + + /** Remove record by ID */ + void removeRecord(RecordId id); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/Record.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/Record.java index 0782a82da79..b51202e8261 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/Record.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/Record.java @@ -4,35 +4,41 @@ package com.yahoo.vespa.hosted.controller.api.integration.dns; import java.util.Objects; /** - * A basic representation of a DNS resource record, containing only the record type, name and value. + * A basic representation of a DNS resource record, containing the record id, type, name and value. * * @author mpolden */ public class Record { + private final RecordId id; private final Type type; - private final String name; - private final String value; + private final RecordName name; + private final RecordData data; - public Record(Type type, String name, String value) { - this.type = type; - this.name = name; - this.value = value; + public Record(RecordId id, Type type, RecordName name, RecordData data) { + this.id = Objects.requireNonNull(id, "id cannot be null"); + this.type = Objects.requireNonNull(type, "type cannot be null"); + this.name = Objects.requireNonNull(name, "name cannot be null"); + this.data = Objects.requireNonNull(data, "data cannot be null"); } - public Record(String type, String name, String value) { - this(Type.valueOf(type), name, value); + /** Unique identifier for this */ + public RecordId id() { + return id; } + /** DNS type of this */ public Type type() { return type; } - public String value() { - return value; + /** Data in this, e.g. IP address for "A" record */ + public RecordData data() { + return data; } - public String name() { + /** Name of this, e.g. a FQDN for "A" record */ + public RecordName name() { return name; } @@ -51,24 +57,26 @@ public class Record { @Override public String toString() { return "Record{" + - "type=" + type + - ", name='" + name + '\'' + - ", value='" + value + '\'' + - '}'; + "id=" + id + + ", type=" + type + + ", name='" + name + '\'' + + ", data='" + data + '\'' + + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Record)) return false; + if (o == null || getClass() != o.getClass()) return false; Record record = (Record) o; - return type == record.type && - Objects.equals(name, record.name); + return Objects.equals(id, record.id) && + type == record.type && + Objects.equals(name, record.name) && + Objects.equals(data, record.data); } @Override public int hashCode() { - return Objects.hash(type, name); + return Objects.hash(id, type, name, data); } - } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordData.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordData.java new file mode 100644 index 00000000000..e0d19e0fff9 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordData.java @@ -0,0 +1,55 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.dns; + +import java.util.Objects; + +/** + * Represents the data field of a DNS record (RDATA). + * + * E.g. this may be an IP address for A records, or a FQDN for CNAME records. + * + * @author mpolden + */ +public class RecordData { + + private final String data; + + private RecordData(String data) { + this.data = Objects.requireNonNull(data, "data cannot be null"); + } + + public String asString() { + return data; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RecordData that = (RecordData) o; + return Objects.equals(data, that.data); + } + + @Override + public int hashCode() { + return Objects.hash(data); + } + + @Override + public String toString() { + return "RecordValue{" + + "value='" + data + '\'' + + '}'; + } + + /** Create a new record containing the given data */ + public static RecordData from(String data) { + return new RecordData(data); + } + + /** Create a new record and append a trailing dot to given data, if missing */ + public static RecordData fqdn(String data) { + return from(data.endsWith(".") ? data : data + "."); + } + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordId.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordId.java index 9c47be12855..da42c38252a 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordId.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordId.java @@ -14,7 +14,7 @@ public class RecordId { this.id = id; } - public String id() { + public String asString() { return id; } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordName.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordName.java new file mode 100644 index 00000000000..aa239ece588 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/RecordName.java @@ -0,0 +1,47 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.dns; + +import java.util.Objects; + +/** + * Represents the name field of a DNS record (NAME). This is typically a FQDN. + * + * @author mpolden + */ +public class RecordName { + + private final String name; + + private RecordName(String name) { + this.name = Objects.requireNonNull(name, "name cannot be null"); + } + + public String asString() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RecordName that = (RecordName) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + + @Override + public String toString() { + return "RecordName{" + + "name='" + name + '\'' + + '}'; + } + + public static RecordName from(String name) { + return new RecordName(name); + } + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java index df6f023f6af..3318bf783d8 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java @@ -5,7 +5,7 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; -import com.yahoo.config.provision.Zone; +import com.yahoo.config.provision.ZoneId; import java.net.URI; import java.time.Duration; @@ -20,8 +20,8 @@ import java.util.Optional; public interface ZoneRegistry { SystemName system(); - List<Zone> zones(); - Optional<Zone> getZone(Environment environment, RegionName region); + List<ZoneId> zones(); + Optional<ZoneId> getZone(Environment environment, RegionName region); List<URI> getConfigServerUris(Environment environment, RegionName region); Optional<URI> getLogServerUri(Environment environment, RegionName region); Optional<Duration> getDeploymentTimeToLive(Environment environment, RegionName region); diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/rotation/Rotation.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/rotation/Rotation.java index ed3e69bcac7..a1f78302e4b 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/rotation/Rotation.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/rotation/Rotation.java @@ -10,6 +10,8 @@ import java.util.Objects; * * @author Oyvind Gronnesby */ +// TODO: Used in serialization (ConfigServerClient). This should be removed and config server client should use a +// Set<String> instead, like it does for CNAMEs. public class Rotation { /** The ID of the allocated rotation. This value is generated by global routing system. */ diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java index 97d99e262b5..1f1350ca001 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/zone/v2/ZoneApiV2.java @@ -8,7 +8,6 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.InstanceId; import com.yahoo.vespa.hosted.controller.api.identifiers.RegionId; import com.yahoo.vespa.hosted.controller.api.identifiers.TenantId; -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -18,7 +17,6 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -44,32 +42,28 @@ public interface ZoneApiV2 { Response proxyGet( @PathParam("environment") String env, @PathParam("region") String region, - @PathParam("proxy_request") String proxyRequest, - @Context HttpServletRequest request); + @PathParam("proxy_request") String proxyRequest); @POST @Path("/{environment}/{region}/{proxy_request: .+}") Response proxyPost( @PathParam("environment") String env, @PathParam("region") String region, - @PathParam("proxy_request") String proxyRequest, - @Context HttpServletRequest request); + @PathParam("proxy_request") String proxyRequest); @PUT @Path("/{environment}/{region}/{proxy_request: .+}") Response proxyPut( @PathParam("environment") String env, @PathParam("region") String region, - @PathParam("proxy_request") String proxyRequest, - @Context HttpServletRequest request); + @PathParam("proxy_request") String proxyRequest); @DELETE @Path("/{environment}/{region}/{proxy_request: .+}") Response proxyDelete( @PathParam("environment") String env, @PathParam("region") String region, - @PathParam("proxy_request") String proxyRequest, - @Context HttpServletRequest request); + @PathParam("proxy_request") String proxyRequest); // Explicit mappings of some proxy requests (to enable creation of proxy clients with javax.ws.rs) |