package de.mlessmann.certassist.service; import de.mlessmann.certassist.except.UnresolvableCLIDependency; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.SystemUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service @Slf4j public class ExecutableResolver { private static final AtomicBoolean loggedPath = new AtomicBoolean(false); @Value("${openssl.path:#{null}}") private String opensslPath; public String getOpenSSLPath() throws UnresolvableCLIDependency { if (opensslPath == null) { log.atDebug().log("No openssl path configured, falling back to resolving by shell."); var optSSLPath = searchCommandFromPath("openssl"); opensslPath = optSSLPath.orElseThrow(() -> new UnresolvableCLIDependency("openssl", "openssl.path")); } Path configuredPath = new File(opensslPath).toPath(); if (!Files.isRegularFile(configuredPath)) { throw new UnresolvableCLIDependency("openssl", "openssl.path"); } return opensslPath; } private Optional searchCommandFromPath(String executableName) { String envPath = System.getenv("PATH"); Objects.requireNonNull(envPath, "Environment variable 'PATH' is not set?!"); String[] pathEntries = envPath.split(File.pathSeparator); if (!loggedPath.get()) { loggedPath.set(true); for (String pathEntry : pathEntries) { log.atError().log("Path entry: {}", pathEntry); } } for (String pathEntry : pathEntries) { for (String fileExtension : getAllowedExtensions()) { Path executablePath = Path.of(pathEntry, executableName + fileExtension); if (Files.isRegularFile(executablePath) && Files.isExecutable(executablePath)) { return Optional.of(executablePath.toString()); } } } log.error( "Could not find executable '{}' in PATH. Make sure that it exists on the of the directory and is executable.", executableName ); return Optional.empty(); } public List getAllowedExtensions() { if (SystemUtils.IS_OS_WINDOWS) { return List.of(".exe", ".bat", ".cmd"); } else { return List.of("", ".sh"); } } }