diff --git a/CHANGELOG.md b/CHANGELOG.md index d3b31a8d56b..3b8af16a166 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### 6.12-SNAPSHOT #### Bugs +* Fix #5817: NPE on EKS OIDC cluster when token needs to be refreshed #### Improvements diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java index 2da1e4c3bbb..72fe25c886a 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java @@ -29,6 +29,8 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; @@ -89,7 +91,7 @@ public static CompletableFuture resolveOIDCTokenFromAuthConfig(Config cu String clientId = currentAuthProviderConfig.get(CLIENT_ID_KUBECONFIG); String refreshToken = currentAuthProviderConfig.get(REFRESH_TOKEN_KUBECONFIG); String clientSecret = currentAuthProviderConfig.getOrDefault(CLIENT_SECRET_KUBECONFIG, ""); - String idpCert = currentAuthProviderConfig.getOrDefault(IDP_CERT_DATA, currentConfig.getCaCertData()); + String idpCert = currentAuthProviderConfig.getOrDefault(IDP_CERT_DATA, getClientCertDataFromConfig(currentConfig)); if (isTokenRefreshSupported(currentAuthProviderConfig)) { return getOIDCProviderTokenEndpointAndRefreshToken(issuer, clientId, refreshToken, clientSecret, idpCert, clientBuilder) .thenApply(map -> { @@ -352,4 +354,18 @@ private static boolean isValidJwt(String token) { } return false; } + + private static String getClientCertDataFromConfig(Config config) { + if (config.getCaCertData() != null && !config.getCaCertData().isEmpty()) { + return config.getCaCertData(); + } + try { + if (config.getCaCertFile() != null) { + return java.util.Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(config.getCaCertFile()))); + } + } catch (IOException e) { + LOGGER.debug("Failure in reading certificate data from {}", config.getCaCertFile()); + } + return null; + } } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java index 41c3759cdde..47e8b9bc567 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtilsTest.java @@ -24,6 +24,7 @@ import io.fabric8.kubernetes.client.internal.KubeConfigUtils; import io.fabric8.kubernetes.client.internal.SSLUtils; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -229,6 +230,34 @@ void resolveOIDCTokenFromAuthConfig_whenIDPCertNotPresentInAuthConfig_thenUseCer } } + @Test + void resolveOIDCTokenFromAuthConfig_whenIDPCertNotPresentInAuthConfig_thenUseCertFileFromConfig(@TempDir File temporaryFolder) + throws Exception { + try (MockedStatic sslUtilsMockedStatic = mockStatic(SSLUtils.class)) { + // Given + File caCertFile = new File(temporaryFolder, "ca.crt"); + Files.write(caCertFile.toPath(), "cert".getBytes(StandardCharsets.UTF_8)); + Map currentAuthProviderConfig = new HashMap<>(); + currentAuthProviderConfig.put(CLIENT_ID_KUBECONFIG, "client-id"); + currentAuthProviderConfig.put(CLIENT_SECRET_KUBECONFIG, "client-secret"); + currentAuthProviderConfig.put(ID_TOKEN_KUBECONFIG, "id-token"); + currentAuthProviderConfig.put(REFRESH_TOKEN_KUBECONFIG, "refresh-token"); + currentAuthProviderConfig.put(ISSUER_KUBECONFIG, "https://iam.cloud.example.com/identity"); + Config config = new ConfigBuilder(Config.empty()).withCaCertFile(caCertFile.getAbsolutePath()).build(); + HttpClient.Builder builder = mock(HttpClient.Builder.class); + HttpClient httpClient = mock(HttpClient.class, RETURNS_DEEP_STUBS); + when(builder.build()).thenReturn(httpClient); + + // When + OpenIDConnectionUtils.resolveOIDCTokenFromAuthConfig(config, currentAuthProviderConfig, builder).get(); + + // Then + sslUtilsMockedStatic.verify(() -> SSLUtils.trustManagers(eq("cert"), isNull(), anyBoolean(), isNull(), isNull())); + sslUtilsMockedStatic.verify( + () -> SSLUtils.keyManagers(eq("cert"), isNull(), isNull(), isNull(), isNull(), isNull(), isNull(), isNull())); + } + } + @Test void testgetParametersFromDiscoveryResponse() { // Given