summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorandreer <andreer@verizonmedia.com>2019-12-16 16:04:47 +0100
committerandreer <andreer@verizonmedia.com>2019-12-16 16:04:47 +0100
commit350592d77abf8fa001d53eb777a506bb62c538e1 (patch)
tree03c33c09cbfed33d3c8167008890a0ccdc7ad4fd /configserver
parent65dd6eb4932a7c29cbad7d717bc34da73d0bb723 (diff)
read new json format for tls secrets metadata (to store version)
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java64
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeysTest.java72
2 files changed, 130 insertions, 6 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java
index 78d39ef996b..da6fc490da9 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeys.java
@@ -1,12 +1,13 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.tenant;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.config.model.api.TlsSecrets;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.container.jdisc.secretstore.SecretStore;
import com.yahoo.path.Path;
+import com.yahoo.slime.Cursor;
+import com.yahoo.slime.Slime;
+import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.transaction.CuratorOperations;
import com.yahoo.vespa.curator.transaction.CuratorTransaction;
@@ -34,8 +35,22 @@ public class TlsSecretsKeys {
try {
Optional<byte[]> data = curator.getData(tlsSecretsKeyOf(application));
if (data.isEmpty() || data.get().length == 0) return Optional.empty();
- String tlsSecretsKey = new ObjectMapper().readValue(data.get(), new TypeReference<String>() {});
- return readFromSecretStore(Optional.ofNullable(tlsSecretsKey));
+
+ Slime slime = SlimeUtils.jsonToSlime(data.get());
+ final var inspector = slime.get();
+
+ switch (inspector.type()) {
+ case STRING: // TODO: Remove once all are stored as JSON
+ return readFromSecretStore(Optional.ofNullable(inspector.asString()));
+ case OBJECT:
+ var tlsSecretsInfo = new TlsSecretsMetadata();
+ tlsSecretsInfo.certName = inspector.field("certName").asString();
+ tlsSecretsInfo.keyName = inspector.field("keyName").asString();
+ tlsSecretsInfo.version = Math.toIntExact(inspector.field("version").asLong());
+ return Optional.of(readFromSecretStore(tlsSecretsInfo));
+ default:
+ throw new IllegalArgumentException("Unknown format encountered for TLS secrets metadata!");
+ }
} catch (Exception e) {
throw new RuntimeException("Error reading TLS secret key of " + application, e);
}
@@ -43,9 +58,27 @@ public class TlsSecretsKeys {
public void writeTlsSecretsKeyToZooKeeper(ApplicationId application, String tlsSecretsKey) {
if (tlsSecretsKey == null) return;
+ writeTlsSecretsAsString(application, tlsSecretsKey);
+ }
+
+ private void writeTlsSecretsAsString(ApplicationId application, String tlsSecretsKey) {
try {
- byte[] data = new ObjectMapper().writeValueAsBytes(tlsSecretsKey);
- curator.set(tlsSecretsKeyOf(application), data);
+ Slime slime = new Slime();
+ slime.setString(tlsSecretsKey);
+ curator.set(tlsSecretsKeyOf(application), SlimeUtils.toJsonBytes(slime));
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write TLS secret key of " + application, e);
+ }
+ }
+
+ void writeTlsSecretsMetadata(ApplicationId application, TlsSecretsMetadata tlsSecretsMetadata) {
+ try {
+ Slime slime = new Slime();
+ Cursor cursor = slime.setObject();
+ cursor.setString(TlsSecretsMetadata.certNameField, tlsSecretsMetadata.certName);
+ cursor.setString(TlsSecretsMetadata.keyNameField, tlsSecretsMetadata.keyName);
+ cursor.setLong(TlsSecretsMetadata.versionField, tlsSecretsMetadata.version);
+ curator.set(tlsSecretsKeyOf(application), SlimeUtils.toJsonBytes(slime));
} catch (Exception e) {
throw new RuntimeException("Could not write TLS secret key of " + application, e);
}
@@ -70,6 +103,17 @@ public class TlsSecretsKeys {
}
}
+ private TlsSecrets readFromSecretStore(TlsSecretsMetadata tlsSecretsMetadata) {
+ try {
+ String cert = secretStore.getSecret(tlsSecretsMetadata.certName, tlsSecretsMetadata.version);
+ String key = secretStore.getSecret(tlsSecretsMetadata.keyName, tlsSecretsMetadata.version);
+ return new TlsSecrets(cert, key);
+ } catch (RuntimeException e) {
+ // Assume not ready yet
+ return TlsSecrets.MISSING;
+ }
+ }
+
/** Returns a transaction which deletes these tls secrets key if they exist */
public CuratorTransaction delete(ApplicationId application) {
if (!curator.exists(tlsSecretsKeyOf(application))) return CuratorTransaction.empty(curator);
@@ -81,4 +125,12 @@ public class TlsSecretsKeys {
return path.append(application.serializedForm());
}
+ static class TlsSecretsMetadata {
+ final static String keyNameField = "keyName";
+ final static String certNameField = "certName";
+ final static String versionField = "version";
+ String keyName;
+ String certName;
+ int version;
+ }
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeysTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeysTest.java
new file mode 100644
index 00000000000..f20d6b8fcf8
--- /dev/null
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeysTest.java
@@ -0,0 +1,72 @@
+package com.yahoo.vespa.config.server.tenant;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ApplicationName;
+import com.yahoo.config.provision.InstanceName;
+import com.yahoo.config.provision.TenantName;
+import com.yahoo.path.Path;
+import com.yahoo.vespa.config.server.MockSecretStore;
+import com.yahoo.vespa.curator.mock.MockCurator;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TlsSecretsKeysTest {
+
+ private static final Path tenantPath = Path.createRoot();
+ private static final Path tlsSecretsKeysPath = Path.createRoot().append("tlsSecretsKeys").append("default:test:default");
+ private static final String tlskey = "vespa.tlskeys.tenant1--app1";
+ private static final ApplicationId applicationId = ApplicationId.from(TenantName.defaultName(),
+ ApplicationName.from("test"), InstanceName.defaultName());
+
+ private MockCurator curator;
+ private MockSecretStore secretStore = new MockSecretStore();
+ private TlsSecretsKeys tlsSecretsKeys;
+
+ @Before
+ public void setUp() {
+ curator = new MockCurator();
+ tlsSecretsKeys = new TlsSecretsKeys(curator, tenantPath, secretStore);
+ secretStore.put(tlskey + "-cert", "CERT");
+ secretStore.put(tlskey + "-key", "KEY");
+ }
+
+ @Test
+ public void reads_string_format() {
+ curator.set(tlsSecretsKeysPath, ('"' + tlskey + '"').getBytes());
+
+ // Read from zk and verify cert and key are available
+ var tlsSecrets = tlsSecretsKeys.readTlsSecretsKeyFromZookeeper(applicationId);
+ assertTrue(tlsSecrets.isPresent());
+ assertEquals("KEY", tlsSecrets.get().key());
+ assertEquals("CERT", tlsSecrets.get().certificate());
+ }
+
+ @Test
+ public void reads_object_format() {
+ curator.set(tlsSecretsKeysPath,
+ "{\"keyName\": \"vespa.tlskeys.tenant1--app1-key\", \"certName\":\"vespa.tlskeys.tenant1--app1-cert\", \"version\": 0}"
+ .getBytes());
+
+ // Read from zk and verify cert and key are available
+ var tlsSecrets = tlsSecretsKeys.readTlsSecretsKeyFromZookeeper(applicationId);
+ assertTrue(tlsSecrets.isPresent());
+ assertEquals("KEY", tlsSecrets.get().key());
+ assertEquals("CERT", tlsSecrets.get().certificate());
+ }
+
+ @Test
+ public void can_write_object_format() {
+ var tlsSecretsMetadata = new TlsSecretsKeys.TlsSecretsMetadata();
+ tlsSecretsMetadata.certName = "cert-name";
+ tlsSecretsMetadata.keyName = "key-name";
+ tlsSecretsMetadata.version = 1;
+
+ tlsSecretsKeys.writeTlsSecretsMetadata(applicationId, tlsSecretsMetadata);
+
+ assertEquals("{\"certName\":\"cert-name\",\"keyName\":\"key-name\",\"version\":1}",
+ new String(curator.getData(tlsSecretsKeysPath).get()));
+ }
+} \ No newline at end of file