0

Application: Spring Boot,
Image: OpenJDK 8,
PaaS: Openshift,
Package: jar,
Error: No such file error. java.nio.file.NoSuchFileException
File Location: /servicename/src/main/resources/cert/trust.cer
Error Location: String certs = readFile((trustCertPath).getPath(), Charset.defaultCharset());
Error Location after Update 1: try (InputStream is = classloader.getResourceAsStream(resourcePath)) is null.

I have used cert/trust.cer as path. Since it did not work I gave it a try with /cert/trust.cer, trust.cer, ./cert/trust.cer. I was able to run this class on local using Windows (/cert/trust.cer) but fails from command line and also fails when deployed obviosly.

Update 1: I am using getResourceAsStream(cert/trust.cer). Inputstream is results to null.

public class CertsUtility implements InitializingBean {
public static final Logger logger = LoggerFactory.getLogger("CertsUtility");
private String keystorePaaS;
private String keystorePass;
private String CertPath = "cert/trust.cer";

public void setKeystorePaaS(String keystorePaaS) {
    this.keystorePaaS = keystorePaaS;
}

public void setKeystorePass(String keystorePass) {
    this.keystorePass = keystorePass;
}

static File getPath(String path) {
    URL url = CertsUtility.class.getClass().getResource(path);
    if (url != null) {
        File file = new File(url.getPath());
        return file;
    } else {
        File file = new File(path);
        return file;
    }
}

static String getResourceFileAsString(String resourcePath) throws IOException {
    ClassLoader classloader = ClassLoader.getSystemClassLoader();
    try (InputStream is = classloader.getResourceAsStream(resourcePath)) {
        if (is == null)
            return null;
        try (InputStreamReader isr = new InputStreamReader(is)) {
            BufferedReader reader = new BufferedReader(isr);
            String targetString = reader.lines().collect(Collectors.joining());
            return targetString;
        }
    }

}

void genIndividualandLoad() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException,
        CertificateException, IOException, InterruptedException {
    try {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        InputStream fileInputStream = new FileInputStream(keystorePaaS);
        keyStore.load(fileInputStream, keystorePass.toCharArray());
        fileInputStream.close();
        String certs = readFile((trustCertPath).getPath(), Charset.defaultCharset());
        String[] certificates = certs.split("(?<=-----END CERTIFICATE-----\n)");

        for (int i = 0; i < certificates.length - 1; i++) {
            String individualName = getPath(CertPath).getParent() + i + ".cer";
            try (FileOutputStream outputStream = new FileOutputStream(individualName)) {
                byte[] strToBytes = certificates[i].getBytes();
                outputStream.write(strToBytes);
                try (InputStream inStream = new FileInputStream(individualName)) {
                    CertificateFactory cf = CertificateFactory.getInstance("X.509");
                    X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
                    keyStore.setCertificateEntry("" + i, cert);
                }
                FileOutputStream fileOutputStream = new FileOutputStream(getPath(keystorePaaS));
                keyStore.store(fileOutputStream, keystorePass.toCharArray());
                fileOutputStream.close();
                outputStream.close();
            }
        }
    } catch (KeyStoreException e) {
        logger.error("| genIndividualandLoad() | Keystore exception occurred", e);
    } catch (FileNotFoundException e) {
        logger.error("| genIndividualandLoad() | File not found exception occurred", e);
    } catch (NoSuchAlgorithmException e) {
        logger.error("| genIndividualandLoad() | Algorithm related exception occurred", e);
    } catch (CertificateException e) {
        logger.error("| genIndividualandLoad() | X.509 Certificate exception occurred", e);
    } catch (IOException e) {
        logger.error("| genIndividualandLoad() | I/O exception occured", e);
    }
}

public void afterPropertiesSet() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException,
        CertificateException, IOException, InterruptedException {
    genIndividualandLoad();
}

}

MAV
  • 92
  • 10
  • Where is the certificate actually located on disk? Can you run a command like `find / -name 'trust.cer'` to find it? – omajid May 28 '20 at 18:45
  • @omajid: No access to the terminal on pods. – MAV May 28 '20 at 18:49
  • Can you implement `find` in java? Have something in your application walk through all files starting with `/` to find a `trust.cert` and print out the path? – omajid May 28 '20 at 21:00
  • Uh, your cert is in cert/trust.cer (from the classpath root), and you're trying to access trust.cer, without mentioning the cert/ folder. Are you sure that's correct? –  May 28 '20 at 21:19
  • let me edit it.First when I tried to fix the issue I was using cert/trust.cer and it did not work with getResource. – MAV May 28 '20 at 21:38
  • Could you possibly download the JAR, open it with a ZIP manager and check where the cert file actually is relative to the root folder? –  May 28 '20 at 21:42
  • @Taschi: Ignore my previous comment, it was missing lot of stuff in there. I was trying to get the tree structure but let me try again. – MAV May 28 '20 at 22:08
  • @Taschi: BOOT-INF ->classes -> cert, package folder structure, spring. Cert has trust.cer and package folder has multiple subfolders leading to the .class files . Let me know if this makes sense. I am using Maven and everything is normal, plain spring boot app. – MAV May 28 '20 at 22:10
  • I've deleted my previous comment because it was completely wrong. –  May 28 '20 at 22:19

2 Answers2

0

You're trying to load the cert as a file, which will work if it actually is a file in your file system (i. e. in your local workspace), but not when the cert is nested inside your JAR file.

Rather you need to do something akin to

getClass().getClassLoader().getResourceAsStream("cert/trust.cer");

and then read from the resulting stream.

  • I have implemented getResourceAsStream(resourcePath) but this is resulting to null with cert/trust.cer – MAV May 28 '20 at 22:50
  • 1
    You migt need to try a different classloader, check this question and its many answers: https://stackoverflow.com/questions/16570523/getresourceasstream-returns-null Or you could try one of the approaches listed here: https://www.baeldung.com/spring-classpath-file-access - the @Value method is probably the one I'd prefer. –  May 28 '20 at 22:53
0

I used ClassPathResource from org.springframework.core.io.ClassPathResource to solve this problem.

MAV
  • 92
  • 10