aboutsummaryrefslogtreecommitdiffstats
path: root/vespa-athenz/src
diff options
context:
space:
mode:
authorMorten Tokle <mortent@yahooinc.com>2023-03-06 12:17:47 +0100
committerGitHub <noreply@github.com>2023-03-06 12:17:47 +0100
commit85f059dc265a06d29944d94cf6f3f8368a3d5fd1 (patch)
tree1caf12ecdaf21f3d7ef7b0fc8ceba4de5a344d9e /vespa-athenz/src
parentd96e7c928a1c750a1c0e8657333cd1bb2b8245bf (diff)
Reapply "public athenz provider" (#26311)
* Revert "Revert "Mortent/reapply public athenz provider"" * Add support method
Diffstat (limited to 'vespa-athenz/src')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java6
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java17
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/bindings/SignedIdentityDocumentEntity.java12
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java13
-rw-r--r--vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapperTest.java1
-rw-r--r--vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java39
6 files changed, 70 insertions, 18 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java
index 9b7b666e353..2d77d2ceda1 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java
@@ -4,8 +4,10 @@ package com.yahoo.vespa.athenz.identityprovider.api;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identityprovider.api.bindings.SignedIdentityDocumentEntity;
+import com.yahoo.vespa.athenz.utils.AthenzIdentities;
import java.io.IOException;
import java.io.InputStream;
@@ -58,6 +60,8 @@ public class EntityBindingsMapper {
entity.ipAddresses(),
IdentityType.fromId(entity.identityType()),
Optional.ofNullable(entity.clusterType()).map(ClusterType::from).orElse(null),
+ entity.ztsUrl(),
+ Optional.ofNullable(entity.serviceIdentity()).map(AthenzIdentities::from).orElse(null),
entity.unknownAttributes());
}
@@ -74,6 +78,8 @@ public class EntityBindingsMapper {
model.ipAddresses(),
model.identityType().id(),
Optional.ofNullable(model.clusterType()).map(ClusterType::toConfigValue).orElse(null),
+ model.ztsUrl(),
+ Optional.ofNullable(model.serviceIdentity()).map(AthenzIdentity::getFullName).orElse(null),
model.unknownAttributes());
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java
index 49a39d25e87..de78d81cd1b 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java
@@ -1,8 +1,10 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.athenz.identityprovider.api;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzService;
+import java.net.URL;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
@@ -17,7 +19,8 @@ import java.util.Set;
public record SignedIdentityDocument(String signature, int signingKeyVersion, VespaUniqueInstanceId providerUniqueId,
AthenzService providerService, int documentVersion, String configServerHostname,
String instanceHostname, Instant createdAt, Set<String> ipAddresses,
- IdentityType identityType, ClusterType clusterType, Map<String, Object> unknownAttributes) {
+ IdentityType identityType, ClusterType clusterType, String ztsUrl,
+ AthenzIdentity serviceIdentity, Map<String, Object> unknownAttributes) {
public SignedIdentityDocument {
ipAddresses = Set.copyOf(ipAddresses);
@@ -33,13 +36,19 @@ public record SignedIdentityDocument(String signature, int signingKeyVersion, Ve
public SignedIdentityDocument(String signature, int signingKeyVersion, VespaUniqueInstanceId providerUniqueId,
AthenzService providerService, int documentVersion, String configServerHostname,
String instanceHostname, Instant createdAt, Set<String> ipAddresses,
- IdentityType identityType, ClusterType clusterType) {
+ IdentityType identityType, ClusterType clusterType, String ztsUrl, AthenzIdentity serviceIdentity) {
this(signature, signingKeyVersion, providerUniqueId, providerService, documentVersion, configServerHostname,
- instanceHostname, createdAt, ipAddresses, identityType, clusterType, Map.of());
+ instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, serviceIdentity, Map.of());
}
- public static final int DEFAULT_DOCUMENT_VERSION = 2;
+ public static final int DEFAULT_DOCUMENT_VERSION = 3;
public boolean outdated() { return documentVersion < DEFAULT_DOCUMENT_VERSION; }
+ public SignedIdentityDocument withServiceIdentity(AthenzIdentity identity) {
+ return new SignedIdentityDocument(signature, signingKeyVersion, providerUniqueId, providerService, documentVersion, configServerHostname, instanceHostname, createdAt,
+ ipAddresses, identityType, clusterType, ztsUrl, identity);
+ }
+
+
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/bindings/SignedIdentityDocumentEntity.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/bindings/SignedIdentityDocumentEntity.java
index c37dd2f9147..fc0dff3b97b 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/bindings/SignedIdentityDocumentEntity.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/bindings/SignedIdentityDocumentEntity.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.athenz.identityprovider.api.bindings;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant;
@@ -14,10 +15,11 @@ import java.util.Set;
/**
* @author bjorncs
*/
+@JsonInclude(JsonInclude.Include.NON_NULL)
public record SignedIdentityDocumentEntity(
String signature, int signingKeyVersion, String providerUniqueId, String providerService, int documentVersion,
String configServerHostname, String instanceHostname, Instant createdAt, Set<String> ipAddresses,
- String identityType, String clusterType, Map<String, Object> unknownAttributes) {
+ String identityType, String clusterType, String ztsUrl, String serviceIdentity, Map<String, Object> unknownAttributes) {
@JsonCreator
public SignedIdentityDocumentEntity(@JsonProperty("signature") String signature,
@@ -30,9 +32,11 @@ public record SignedIdentityDocumentEntity(
@JsonProperty("created-at") Instant createdAt,
@JsonProperty("ip-addresses") Set<String> ipAddresses,
@JsonProperty("identity-type") String identityType,
- @JsonProperty("cluster-type") String clusterType) {
+ @JsonProperty("cluster-type") String clusterType,
+ @JsonProperty("zts-url") String ztsUrl,
+ @JsonProperty("service-identity") String serviceIdentity) {
this(signature, signingKeyVersion, providerUniqueId, providerService, documentVersion, configServerHostname,
- instanceHostname, createdAt, ipAddresses, identityType, clusterType, new HashMap<>());
+ instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, serviceIdentity, new HashMap<>());
}
@JsonProperty("signature") @Override public String signature() { return signature; }
@@ -46,6 +50,8 @@ public record SignedIdentityDocumentEntity(
@JsonProperty("ip-addresses") @Override public Set<String> ipAddresses() { return ipAddresses; }
@JsonProperty("identity-type") @Override public String identityType() { return identityType; }
@JsonProperty("cluster-type") @Override public String clusterType() { return clusterType; }
+ @JsonProperty("zts-url") @Override public String ztsUrl() { return ztsUrl; }
+ @JsonProperty("service-identity") @Override public String serviceIdentity() { return serviceIdentity; }
@JsonAnyGetter @Override public Map<String, Object> unknownAttributes() { return unknownAttributes; }
@JsonAnySetter public void set(String name, Object value) { unknownAttributes.put(name, value); }
}
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java
index 14d06fe83f2..019f73fc6bf 100644
--- a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java
+++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSigner.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.athenz.identityprovider.client;
import com.yahoo.security.SignatureUtils;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identityprovider.api.IdentityType;
import com.yahoo.vespa.athenz.identityprovider.api.SignedIdentityDocument;
@@ -18,6 +19,7 @@ import java.util.Base64;
import java.util.Set;
import java.util.TreeSet;
+import static com.yahoo.vespa.athenz.identityprovider.api.SignedIdentityDocument.DEFAULT_DOCUMENT_VERSION;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
@@ -35,13 +37,15 @@ public class IdentityDocumentSigner {
Instant createdAt,
Set<String> ipAddresses,
IdentityType identityType,
- PrivateKey privateKey) {
+ PrivateKey privateKey,
+ AthenzIdentity serviceIdentity) {
try {
Signature signer = SignatureUtils.createSigner(privateKey);
signer.initSign(privateKey);
writeToSigner(
signer, providerUniqueId, providerService, configServerHostname, instanceHostname, createdAt,
ipAddresses, identityType);
+ writeToSigner(signer, serviceIdentity);
byte[] signature = signer.sign();
return Base64.getEncoder().encodeToString(signature);
} catch (GeneralSecurityException e) {
@@ -56,6 +60,9 @@ public class IdentityDocumentSigner {
writeToSigner(
signer, doc.providerUniqueId(), doc.providerService(), doc.configServerHostname(),
doc.instanceHostname(), doc.createdAt(), doc.ipAddresses(), doc.identityType());
+ if (doc.documentVersion() >= DEFAULT_DOCUMENT_VERSION) {
+ writeToSigner(signer, doc.serviceIdentity());
+ }
return signer.verify(Base64.getDecoder().decode(doc.signature()));
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
@@ -82,4 +89,8 @@ public class IdentityDocumentSigner {
}
signer.update(identityType.id().getBytes(UTF_8));
}
+
+ private static void writeToSigner(Signature signer, AthenzIdentity serviceIdentity) throws SignatureException{
+ signer.update(serviceIdentity.getFullName().getBytes(UTF_8));
+ }
}
diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapperTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapperTest.java
index f8c119190a6..2a68f6fd231 100644
--- a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapperTest.java
+++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapperTest.java
@@ -30,6 +30,7 @@ class EntityBindingsMapperTest {
"ip-addresses": [],
"identity-type": "node",
"cluster-type": "admin",
+ "zts-url": "https://zts.url/",
"unknown-string": "string-value",
"unknown-object": { "member-in-unknown-object": 123 }
}
diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java
index 0b8ff4277f1..ff85cb79f02 100644
--- a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java
+++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java
@@ -3,11 +3,13 @@ package com.yahoo.vespa.athenz.identityprovider.client;
import com.yahoo.security.KeyAlgorithm;
import com.yahoo.security.KeyUtils;
+import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.identityprovider.api.ClusterType;
import com.yahoo.vespa.athenz.identityprovider.api.IdentityType;
import com.yahoo.vespa.athenz.identityprovider.api.SignedIdentityDocument;
import com.yahoo.vespa.athenz.identityprovider.api.VespaUniqueInstanceId;
+import com.yahoo.vespa.athenz.utils.AthenzIdentities;
import org.junit.jupiter.api.Test;
import java.security.KeyPair;
@@ -36,37 +38,54 @@ public class IdentityDocumentSignerTest {
private static final Instant createdAt = Instant.EPOCH;
private static final HashSet<String> ipAddresses = new HashSet<>(Arrays.asList("1.2.3.4", "::1"));
private static final ClusterType clusterType = ClusterType.CONTAINER;
+ private static final String ztsUrl = "https://foo";
+ private static final AthenzIdentity serviceIdentity = new AthenzService("vespa", "node");
@Test
void generates_and_validates_signature() {
IdentityDocumentSigner signer = new IdentityDocumentSigner();
String signature =
signer.generateSignature(id, providerService, configserverHostname, instanceHostname, createdAt,
- ipAddresses, identityType, keyPair.getPrivate());
+ ipAddresses, identityType, keyPair.getPrivate(), serviceIdentity);
SignedIdentityDocument signedIdentityDocument = new SignedIdentityDocument(
signature, KEY_VERSION, id, providerService, DEFAULT_DOCUMENT_VERSION, configserverHostname,
- instanceHostname, createdAt, ipAddresses, identityType, clusterType);
+ instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, serviceIdentity);
assertTrue(signer.hasValidSignature(signedIdentityDocument, keyPair.getPublic()));
}
@Test
- void ignores_cluster_type() {
+ void ignores_cluster_type_and_zts_url() {
IdentityDocumentSigner signer = new IdentityDocumentSigner();
String signature =
signer.generateSignature(id, providerService, configserverHostname, instanceHostname, createdAt,
- ipAddresses, identityType, keyPair.getPrivate());
+ ipAddresses, identityType, keyPair.getPrivate(), serviceIdentity);
- var docWithoutClusterType = new SignedIdentityDocument(
+ var docWithoutIgnoredFields = new SignedIdentityDocument(
signature, KEY_VERSION, id, providerService, DEFAULT_DOCUMENT_VERSION, configserverHostname,
- instanceHostname, createdAt, ipAddresses, identityType, null);
- var docWithClusterType = new SignedIdentityDocument(
+ instanceHostname, createdAt, ipAddresses, identityType, null, null, serviceIdentity);
+ var docWithIgnoredFields = new SignedIdentityDocument(
signature, KEY_VERSION, id, providerService, DEFAULT_DOCUMENT_VERSION, configserverHostname,
- instanceHostname, createdAt, ipAddresses, identityType, clusterType);
+ instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, serviceIdentity);
+
+ assertTrue(signer.hasValidSignature(docWithoutIgnoredFields, keyPair.getPublic()));
+ assertEquals(docWithIgnoredFields.signature(), docWithoutIgnoredFields.signature());
+ }
+
+ @Test
+ void validates_signature_for_new_and_old_versions() {
+ IdentityDocumentSigner signer = new IdentityDocumentSigner();
+ String signature =
+ signer.generateSignature(id, providerService, configserverHostname, instanceHostname, createdAt,
+ ipAddresses, identityType, keyPair.getPrivate(), serviceIdentity);
+
+ SignedIdentityDocument signedIdentityDocument = new SignedIdentityDocument(
+ signature, KEY_VERSION, id, providerService, DEFAULT_DOCUMENT_VERSION, configserverHostname,
+ instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, serviceIdentity);
+
+ assertTrue(signer.hasValidSignature(signedIdentityDocument, keyPair.getPublic()));
- assertTrue(signer.hasValidSignature(docWithoutClusterType, keyPair.getPublic()));
- assertEquals(docWithClusterType.signature(), docWithoutClusterType.signature());
}
} \ No newline at end of file