aboutsummaryrefslogtreecommitdiffstats
path: root/vespa-athenz/src
diff options
context:
space:
mode:
authorMorten Tokle <mortent@yahooinc.com>2023-03-03 12:18:51 +0100
committerMorten Tokle <mortent@yahooinc.com>2023-03-03 12:18:51 +0100
commitebf52b0c236f8b6075491283a43d14cfc4732341 (patch)
tree1d7d77f5409a89a5e5a229736847054daa86683c /vespa-athenz/src
parent89cbc487884329348cfd0ccabd65703edc83a531 (diff)
Add service identity to identity document
Diffstat (limited to 'vespa-athenz/src')
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/EntityBindingsMapper.java4
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/SignedIdentityDocument.java10
-rw-r--r--vespa-athenz/src/main/java/com/yahoo/vespa/athenz/identityprovider/api/bindings/SignedIdentityDocumentEntity.java10
-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/client/IdentityDocumentSignerTest.java28
5 files changed, 52 insertions, 13 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 067e8a6b00f..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;
@@ -59,6 +61,7 @@ public class EntityBindingsMapper {
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());
}
@@ -76,6 +79,7 @@ public class EntityBindingsMapper {
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 eba89b72d87..ac37bb3368e 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,6 +1,7 @@
// 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;
@@ -18,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, String ztsUrl, Map<String, Object> unknownAttributes) {
+ IdentityType identityType, ClusterType clusterType, String ztsUrl,
+ AthenzIdentity serviceIdentity, Map<String, Object> unknownAttributes) {
public SignedIdentityDocument {
ipAddresses = Set.copyOf(ipAddresses);
@@ -34,12 +36,12 @@ 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, String ztsUrl) {
+ IdentityType identityType, ClusterType clusterType, String ztsUrl, AthenzIdentity serviceIdentity) {
this(signature, signingKeyVersion, providerUniqueId, providerService, documentVersion, configServerHostname,
- instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, 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; }
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 edbe032ec26..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, String ztsUrl, Map<String, Object> unknownAttributes) {
+ String identityType, String clusterType, String ztsUrl, String serviceIdentity, Map<String, Object> unknownAttributes) {
@JsonCreator
public SignedIdentityDocumentEntity(@JsonProperty("signature") String signature,
@@ -31,9 +33,10 @@ public record SignedIdentityDocumentEntity(
@JsonProperty("ip-addresses") Set<String> ipAddresses,
@JsonProperty("identity-type") String identityType,
@JsonProperty("cluster-type") String clusterType,
- @JsonProperty("zts-url") String ztsUrl) {
+ @JsonProperty("zts-url") String ztsUrl,
+ @JsonProperty("service-identity") String serviceIdentity) {
this(signature, signingKeyVersion, providerUniqueId, providerService, documentVersion, configServerHostname,
- instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, new HashMap<>());
+ instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, serviceIdentity, new HashMap<>());
}
@JsonProperty("signature") @Override public String signature() { return signature; }
@@ -48,6 +51,7 @@ public record SignedIdentityDocumentEntity(
@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/client/IdentityDocumentSignerTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/identityprovider/client/IdentityDocumentSignerTest.java
index 72798b03fa8..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;
@@ -37,17 +39,18 @@ public class IdentityDocumentSignerTest {
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, ztsUrl);
+ instanceHostname, createdAt, ipAddresses, identityType, clusterType, ztsUrl, serviceIdentity);
assertTrue(signer.hasValidSignature(signedIdentityDocument, keyPair.getPublic()));
}
@@ -57,17 +60,32 @@ public class IdentityDocumentSignerTest {
IdentityDocumentSigner signer = new IdentityDocumentSigner();
String signature =
signer.generateSignature(id, providerService, configserverHostname, instanceHostname, createdAt,
- ipAddresses, identityType, keyPair.getPrivate());
+ ipAddresses, identityType, keyPair.getPrivate(), serviceIdentity);
var docWithoutIgnoredFields = new SignedIdentityDocument(
signature, KEY_VERSION, id, providerService, DEFAULT_DOCUMENT_VERSION, configserverHostname,
- instanceHostname, createdAt, ipAddresses, identityType, null, null);
+ 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, ztsUrl);
+ 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()));
+
+ }
+
} \ No newline at end of file