diff options
author | andreer <andreer@verizonmedia.com> | 2019-12-16 16:04:47 +0100 |
---|---|---|
committer | andreer <andreer@verizonmedia.com> | 2019-12-16 16:04:47 +0100 |
commit | 350592d77abf8fa001d53eb777a506bb62c538e1 (patch) | |
tree | 03c33c09cbfed33d3c8167008890a0ccdc7ad4fd /configserver | |
parent | 65dd6eb4932a7c29cbad7d717bc34da73d0bb723 (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.java | 64 | ||||
-rw-r--r-- | configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TlsSecretsKeysTest.java | 72 |
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 |