From 1e29f6d04c8049d0985b1a5c3e7c116306d86138 Mon Sep 17 00:00:00 2001
From: Martin Lowe <martin.lowe@eclipse-foundation.org>
Date: Tue, 19 Sep 2023 15:44:11 -0400
Subject: [PATCH] Add manual check of security provider presence in JDK for JWT
 helper

Previously, we had an issue crop up where the required provider was
absent. This was unexpected and had an unexpected failure with strange
logging. This should help avoid the stack traces and give us clear
indicators of the error.
---
 .../git/eca/helper/JwtHelper.java             | 26 ++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/eclipsefoundation/git/eca/helper/JwtHelper.java b/src/main/java/org/eclipsefoundation/git/eca/helper/JwtHelper.java
index a903c709..2a6821d9 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/helper/JwtHelper.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/helper/JwtHelper.java
@@ -14,6 +14,9 @@ package org.eclipsefoundation.git.eca.helper;
 import java.io.FileReader;
 import java.nio.file.Paths;
 import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.Security;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -42,6 +45,9 @@ import io.smallrye.jwt.build.Jwt;
 public class JwtHelper {
     private static final Logger LOGGER = LoggerFactory.getLogger(JwtHelper.class);
 
+    // security provider to use when ingesting the private key
+    private static final String PROVIDER_NAME = "BC";
+
     @ConfigProperty(name = "smallrye.jwt.sign.key.location")
     String location;
     @ConfigProperty(name = "eclipse.github.default-api-version", defaultValue = "2022-11-28")
@@ -95,10 +101,17 @@ public class JwtHelper {
      * @return the PrivateKey instance for the PEM file at the location, or null if it could not be read/parsed.
      */
     public static PrivateKey getExternalPrivateKey(String location) {
+        // do manual check of the provider to ensure presence before continuing
+        Provider p = checkProviderPresence(PROVIDER_NAME);
+        if (p == null) {
+            LOGGER.error("Could not find provider for '{}' in the JDK security providers list, cannot continue", PROVIDER_NAME);
+            return null;
+        }
+
         // create auto-closing reading resources for the external PEM file
         try (FileReader keyReader = new FileReader(Paths.get(location).toFile()); PEMParser pemParser = new PEMParser(keyReader)) {
             // use the BouncyCastle provider for PKCS#1 support (not available ootb)
-            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
+            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(p.getName());
             // create the key and retrieve the PrivateKey portion
             return converter.getKeyPair((PEMKeyPair) pemParser.readObject()).getPrivate();
         } catch (Exception e) {
@@ -107,4 +120,15 @@ public class JwtHelper {
         return null;
     }
 
+    /**
+     * Retrieves the target security provider given the name to assure presence. There was previously errors where this
+     * could be missing, so checking manually to ensure presence can help detect this and add logging.
+     * 
+     * @param name security provider name to be looked up
+     * @return the provider if present, or null.
+     */
+    private static Provider checkProviderPresence(String name) {
+        return Stream.of(Security.getProviders()).filter(p -> p.getName().equalsIgnoreCase(name)).findFirst().orElse(null);
+    }
+
 }
-- 
GitLab