diff --git a/enclave/build.gradle b/enclave/build.gradle index eebe14532f..dc35c30333 100644 --- a/enclave/build.gradle +++ b/enclave/build.gradle @@ -14,6 +14,7 @@ dependencies { testImplementation project(':testutil') testImplementation 'junit:junit' + testImplementation 'org.assertj:assertj-core' // integration test dependencies. integrationTestImplementation project(':testutil') diff --git a/enclave/src/main/java/org/hyperledger/besu/enclave/EnclaveFactory.java b/enclave/src/main/java/org/hyperledger/besu/enclave/EnclaveFactory.java index 66d56a76d8..545ea7623c 100644 --- a/enclave/src/main/java/org/hyperledger/besu/enclave/EnclaveFactory.java +++ b/enclave/src/main/java/org/hyperledger/besu/enclave/EnclaveFactory.java @@ -18,12 +18,12 @@ import org.hyperledger.besu.util.InvalidConfigurationException; import java.io.IOException; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.nio.file.AccessDeniedException; -import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; -import com.google.common.base.Charsets; +import com.google.common.io.Files; import io.vertx.core.Vertx; import io.vertx.core.http.HttpClientOptions; import io.vertx.core.net.PfxOptions; @@ -112,8 +112,12 @@ public class EnclaveFactory { return new PfxOptions().setPassword(password).setPath(keystoreFile.toString()); } - private static String readSecretFromFile(final Path path) throws IOException { - final byte[] fileContent = Files.readAllBytes(path); - return new String(fileContent, Charsets.UTF_8); + static String readSecretFromFile(final Path path) throws IOException { + final String password = + Files.asCharSource(path.toFile(), StandardCharsets.UTF_8).readFirstLine(); + if (password == null || password.isEmpty()) { + throw new InvalidConfigurationException("Keystore password file is empty: " + path); + } + return password; } } diff --git a/enclave/src/test/java/org/hyperledger/besu/enclave/EnclaveFactoryTest.java b/enclave/src/test/java/org/hyperledger/besu/enclave/EnclaveFactoryTest.java new file mode 100644 index 0000000000..1d37e21cd5 --- /dev/null +++ b/enclave/src/test/java/org/hyperledger/besu/enclave/EnclaveFactoryTest.java @@ -0,0 +1,57 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.enclave; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import org.hyperledger.besu.util.InvalidConfigurationException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class EnclaveFactoryTest { + @ClassRule public static final TemporaryFolder temporaryFolder = new TemporaryFolder(); + private static final String EMPTY_FILE_ERROR_MSG = "Keystore password file is empty: %s"; + + @Test + public void passwordCanBeReadFromFile() throws IOException { + final File passwordFile = temporaryFolder.newFile(); + Files.writeString(passwordFile.toPath(), "test" + System.lineSeparator() + "test2"); + assertThat(EnclaveFactory.readSecretFromFile(passwordFile.toPath())).isEqualTo("test"); + } + + @Test + public void emptyFileThrowsException() throws IOException { + final File passwordFile = temporaryFolder.newFile(); + assertThatExceptionOfType(InvalidConfigurationException.class) + .isThrownBy(() -> EnclaveFactory.readSecretFromFile(passwordFile.toPath())) + .withMessage(EMPTY_FILE_ERROR_MSG, passwordFile); + } + + @Test + public void fileWithOnlyEoLThrowsException() throws IOException { + final File passwordFile = temporaryFolder.newFile(); + Files.writeString(passwordFile.toPath(), System.lineSeparator()); + assertThatExceptionOfType(InvalidConfigurationException.class) + .isThrownBy(() -> EnclaveFactory.readSecretFromFile(passwordFile.toPath())) + .withMessage(EMPTY_FILE_ERROR_MSG, passwordFile); + } +}