From 4e6a8029faa24db84df281092a8ab71c00558c99 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Mon, 26 Nov 2018 13:36:38 +0100 Subject: Disallow empty 'authorized-peers' field - Fail deserializing if 'authorized-peers' is an empty list - Only serialize 'authorized-peers' field when necessary --- security-utils/pom.xml | 6 ++++ .../tls/json/TransportSecurityOptionsEntity.java | 5 +++- .../TransportSecurityOptionsJsonSerializer.java | 9 ++++-- ...TransportSecurityOptionsJsonSerializerTest.java | 32 ++++++++++++++++++++-- 4 files changed, 47 insertions(+), 5 deletions(-) (limited to 'security-utils') diff --git a/security-utils/pom.xml b/security-utils/pom.xml index 7006a0f5f86..6f094f28362 100644 --- a/security-utils/pom.xml +++ b/security-utils/pom.xml @@ -43,6 +43,12 @@ hamcrest-library test + + com.yahoo.vespa + testutil + ${project.version} + test + diff --git a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java index 80ef06d9cac..be2027f1c7d 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsEntity.java @@ -2,11 +2,14 @@ package com.yahoo.security.tls.json; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY; + /** * Jackson bindings for transport security options * @@ -16,7 +19,7 @@ import java.util.List; class TransportSecurityOptionsEntity { @JsonProperty("files") Files files; - @JsonProperty("authorized-peers") List authorizedPeers = new ArrayList<>(); + @JsonProperty("authorized-peers") @JsonInclude(NON_EMPTY) List authorizedPeers; static class Files { @JsonProperty("private-key") String privateKeyFile; diff --git a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java index 2e2148628e8..8b7c860fd85 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java @@ -18,6 +18,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -42,7 +43,7 @@ public class TransportSecurityOptionsJsonSerializer { public void serialize(OutputStream out, TransportSecurityOptions options) { try { - mapper.writeValue(out, toTransportSecurityOptionsEntity(options)); + mapper.writerWithDefaultPrettyPrinter().writeValue(out, toTransportSecurityOptionsEntity(options)); } catch (IOException e) { throw new UncheckedIOException(e); } @@ -62,7 +63,10 @@ public class TransportSecurityOptionsJsonSerializer { } } List authorizedPeersEntity = entity.authorizedPeers; - if (authorizedPeersEntity.size() > 0) { + if (authorizedPeersEntity != null) { + if (authorizedPeersEntity.size() == 0) { + throw new IllegalArgumentException("'authorized-peers' cannot be empty"); + } builder.withAuthorizedPeers(new AuthorizedPeers(toPeerPolicies(authorizedPeersEntity))); } return builder.build(); @@ -124,6 +128,7 @@ public class TransportSecurityOptionsJsonSerializer { options.getCertificatesFile().ifPresent(value -> entity.files.certificatesFile = value.toString()); options.getPrivateKeyFile().ifPresent(value -> entity.files.privateKeyFile = value.toString()); options.getAuthorizedPeers().ifPresent( authorizedPeers -> { + entity.authorizedPeers = new ArrayList<>(); for (PeerPolicy peerPolicy : authorizedPeers.peerPolicies()) { AuthorizedPeer authorizedPeer = new AuthorizedPeer(); authorizedPeer.name = peerPolicy.policyName(); diff --git a/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java index c59647a02d0..5e611b1eba5 100644 --- a/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java +++ b/security-utils/src/test/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializerTest.java @@ -7,24 +7,37 @@ import com.yahoo.security.tls.policy.HostGlobPattern; import com.yahoo.security.tls.policy.PeerPolicy; import com.yahoo.security.tls.policy.RequiredPeerCredential; import com.yahoo.security.tls.policy.Role; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import static com.yahoo.security.tls.policy.RequiredPeerCredential.Field.*; +import static com.yahoo.security.tls.policy.RequiredPeerCredential.Field.CN; +import static com.yahoo.security.tls.policy.RequiredPeerCredential.Field.SAN_DNS; +import static com.yahoo.test.json.JsonTestHelper.assertJsonEquals; import static java.util.Collections.singleton; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; /** * @author bjorncs */ public class TransportSecurityOptionsJsonSerializerTest { + @Rule public TemporaryFolder tempDirectory = new TemporaryFolder(); + + private static final Path TEST_CONFIG_FILE = Paths.get("src/test/resources/transport-security-options.json"); + @Test public void can_serialize_and_deserialize_transport_security_options() { TransportSecurityOptions options = new TransportSecurityOptions.Builder() @@ -46,4 +59,19 @@ public class TransportSecurityOptionsJsonSerializerTest { assertEquals(options, deserializedOptions); } + @Test + public void can_serialize_options_without_authorized_peers() throws IOException { + TransportSecurityOptions options = new TransportSecurityOptions.Builder() + .withCertificates(Paths.get("certs.pem"), Paths.get("myhost.key")) + .withCaCertificates(Paths.get("my_cas.pem")) + .build(); + File outputFile = tempDirectory.newFile(); + try (OutputStream out = Files.newOutputStream(outputFile.toPath())) { + new TransportSecurityOptionsJsonSerializer().serialize(out, options); + } + String expectedOutput = new String(Files.readAllBytes(TEST_CONFIG_FILE)); + String actualOutput = new String(Files.readAllBytes(outputFile.toPath())); + assertJsonEquals(expectedOutput, actualOutput); + } + } -- cgit v1.2.3