Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit aa1643c

Browse filesBrowse files
authored
Add Kubernetes environment check in AbstractKubernetesCredentialProvider (#11135)
1 parent a318b4f commit aa1643c
Copy full SHA for aa1643c

6 files changed

+44-6Lines changed: 44 additions & 6 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎commons/src/main/java/org/frankframework/util/Environment.java‎

Copy file name to clipboardExpand all lines: commons/src/main/java/org/frankframework/util/Environment.java
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@
2323
import java.net.URL;
2424
import java.net.URLDecoder;
2525
import java.nio.charset.StandardCharsets;
26+
import java.nio.file.Files;
2627
import java.nio.file.NoSuchFileException;
28+
import java.nio.file.Path;
2729
import java.util.Optional;
2830
import java.util.Properties;
2931
import java.util.jar.JarFile;
3032
import java.util.jar.JarInputStream;
3133
import java.util.jar.Manifest;
3234
import java.util.zip.ZipInputStream;
3335

36+
import org.apache.commons.lang3.StringUtils;
3437
import org.apache.logging.log4j.LogManager;
3538
import org.apache.logging.log4j.Logger;
3639
import org.jspecify.annotations.NonNull;
@@ -47,6 +50,8 @@ private Environment() {
4750
private static final Logger log = LogManager.getLogger(Environment.class);
4851
private static final String FRANKFRAMEWORK_NAMESPACE = "META-INF/maven/org.frankframework/";
4952

53+
private static String KUBERNETES_SERVICE_HOST = System.getenv("KUBERNETES_SERVICE_HOST");
54+
5055
public static Properties getEnvironmentVariables() throws IOException {
5156
try {
5257
Properties props = new Properties();
@@ -177,4 +182,11 @@ public static String extractPath(final URL url) throws IOException {
177182
throw new IOException("unable to read path from URL ["+url+"]", e);
178183
}
179184
}
185+
186+
/**
187+
* @return whether the current environment is running on Kubernetes
188+
*/
189+
public static boolean isRunningOnKubernetes() {
190+
return StringUtils.isNotBlank(KUBERNETES_SERVICE_HOST) || Files.exists(Path.of("/var/run/secrets/kubernetes.io/serviceaccount/token"));
191+
}
180192
}
Collapse file

‎credentialProvider/src/main/java/org/frankframework/credentialprovider/util/CredentialConstants.java‎

Copy file name to clipboardExpand all lines: credentialProvider/src/main/java/org/frankframework/credentialprovider/util/CredentialConstants.java
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.frankframework.credentialprovider.util;
1717

18-
1918
import org.jspecify.annotations.Nullable;
2019

2120
import org.frankframework.util.PropertyLoader;
Collapse file

‎kubernetes/src/main/java/org/frankframework/credentialprovider/AbstractKubernetesCredentialProvider.java‎

Copy file name to clipboardExpand all lines: kubernetes/src/main/java/org/frankframework/credentialprovider/AbstractKubernetesCredentialProvider.java
+10-3Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
import lombok.extern.java.Log;
3030

3131
import org.frankframework.credentialprovider.util.CredentialConstants;
32+
import org.frankframework.util.Environment;
3233

3334
/**
34-
* Abstract base class for Kubernetes-backed credential providers.
35+
* <p>Abstract base class for Kubernetes-backed credential providers. Checks if it's actually running on Kubernetes. If not, will throw
36+
* an UnsupportedOperationException</p>
3537
*
3638
* <p>Handles shared concerns: building and configuring the {@link KubernetesClient},
3739
* verifying connectivity to the cluster, and validating alias names against the
@@ -55,17 +57,22 @@ public abstract class AbstractKubernetesCredentialProvider implements ISecretPro
5557
static final String K8_PASSWORD = "credentialFactory.kubernetes.password";
5658
static final String K8_MASTER_URL = "credentialFactory.kubernetes.masterUrl";
5759
static final String K8_NAMESPACE_PROPERTY = "credentialFactory.kubernetes.namespace";
60+
static final String DEFAULT_NAMESPACE = "default";
5861

5962
static final int CACHE_DURATION_MILLIS = 60_000;
6063

61-
public static final String DEFAULT_NAMESPACE = "default";
62-
6364
protected String namespace;
6465
protected KubernetesClient client;
6566

6667
@Override
6768
public final void initialize() {
6869
CredentialConstants appConstants = CredentialConstants.getInstance();
70+
71+
// Check if we are running on kubernetes
72+
if (!Environment.isRunningOnKubernetes()) {
73+
throw new UnsupportedOperationException("Kubernetes service host is not set. This provider can only be used in a Kubernetes environment.");
74+
}
75+
6976
log.info("initializing " + getClass().getSimpleName());
7077

7178
initializeClientIfNull();
Collapse file

‎kubernetes/src/main/java/org/frankframework/credentialprovider/KubernetesCredentialFactory.java‎

Copy file name to clipboardExpand all lines: kubernetes/src/main/java/org/frankframework/credentialprovider/KubernetesCredentialFactory.java
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@
2828
import org.frankframework.credentialprovider.util.CredentialConstants;
2929

3030
/**
31-
*
3231
* {@inheritClassDoc}
3332
*
3433
* <p>CredentialFactory for Kubernetes Secret. Fetches credentials from Kubernetes secrets.</p>
3534
*
3635
* <p>The credentials are stored in Kubernetes secrets, which are base64 encoded. The keys used for the secrets are "username" and "password".</p>
3736
*
38-
* <p>The `KubernetesCredentialFactory` class uses several properties to configure its behavior. These properties are set in the
37+
* <p>The `KubernetesCredentialFactory` class uses several properties to configure its behaviour. These properties are set in the
3938
* {@code credentialproperties.properties} file and are used to customize the connection to the Kubernetes cluster and the namespace from which secrets are
4039
* fetched. Here's a description of the properties:</p>
4140
* <ul>
Collapse file

‎kubernetes/src/test/java/org/frankframework/credentialprovider/KubernetesNamedSecretProviderTest.java‎

Copy file name to clipboardExpand all lines: kubernetes/src/test/java/org/frankframework/credentialprovider/KubernetesNamedSecretProviderTest.java
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import static org.junit.jupiter.api.Assertions.assertThrows;
77
import static org.junit.jupiter.api.Assertions.assertTrue;
88
import static org.mockito.Mockito.mock;
9+
import static org.mockito.Mockito.mockStatic;
910
import static org.mockito.Mockito.when;
1011

1112
import java.io.IOException;
@@ -20,6 +21,7 @@
2021
import org.junit.jupiter.api.AfterAll;
2122
import org.junit.jupiter.api.BeforeAll;
2223
import org.junit.jupiter.api.Test;
24+
import org.mockito.MockedStatic;
2325

2426
import io.fabric8.kubernetes.api.model.ObjectMeta;
2527
import io.fabric8.kubernetes.api.model.Secret;
@@ -31,6 +33,7 @@
3133
import io.fabric8.kubernetes.client.dsl.Resource;
3234

3335
import org.frankframework.credentialprovider.util.CredentialConstants;
36+
import org.frankframework.util.Environment;
3437

3538
class KubernetesNamedSecretProviderTest {
3639

@@ -39,10 +42,14 @@ class KubernetesNamedSecretProviderTest {
3942

4043
private static final KubernetesNamedSecretProvider provider = new KubernetesNamedSecretProvider();
4144
private static final KubernetesClient client = mock(KubernetesClient.class);
45+
private static MockedStatic<Environment> environmentMock;
4246

4347
@BeforeAll
4448
@SuppressWarnings({ "unchecked", "rawtypes" })
4549
static void setUp() {
50+
environmentMock = mockStatic(Environment.class);
51+
environmentMock.when(Environment::isRunningOnKubernetes).thenReturn(true);
52+
4653
Map<String, String> dataA = new HashMap<>();
4754
dataA.put("authdatabase.username", encode("dbUser"));
4855
dataA.put("authdatabase.password", encode("dbPass"));
@@ -80,6 +87,9 @@ static void setUp() {
8087

8188
@AfterAll
8289
static void tearDown() {
90+
if (environmentMock != null) {
91+
environmentMock.close();
92+
}
8393
provider.close();
8494
}
8595

Collapse file

‎kubernetes/src/test/java/org/frankframework/credentialprovider/KubernetesSecretFactoryTest.java‎

Copy file name to clipboardExpand all lines: kubernetes/src/test/java/org/frankframework/credentialprovider/KubernetesSecretFactoryTest.java
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import static org.junit.jupiter.api.Assertions.assertThrows;
88
import static org.junit.jupiter.api.Assertions.assertTrue;
99
import static org.mockito.Mockito.mock;
10+
import static org.mockito.Mockito.mockStatic;
1011
import static org.mockito.Mockito.when;
1112

1213
import java.io.IOException;
@@ -22,6 +23,7 @@
2223
import org.junit.jupiter.api.AfterAll;
2324
import org.junit.jupiter.api.BeforeAll;
2425
import org.junit.jupiter.api.Test;
26+
import org.mockito.MockedStatic;
2527

2628
import io.fabric8.kubernetes.api.model.ObjectMeta;
2729
import io.fabric8.kubernetes.api.model.Secret;
@@ -34,15 +36,20 @@
3436
import io.fabric8.kubernetes.client.utils.KubernetesSerialization;
3537

3638
import org.frankframework.credentialprovider.util.CredentialConstants;
39+
import org.frankframework.util.Environment;
3740

3841
class KubernetesSecretFactoryTest {
3942

4043
private static final KubernetesCredentialFactory credentialFactory = new KubernetesCredentialFactory();
4144
private static final KubernetesClient client = mock(KubernetesClient.class);
45+
private static MockedStatic<Environment> environmentMock;
4246

4347
@BeforeAll
4448
@SuppressWarnings("unchecked")
4549
static void setUp() {
50+
environmentMock = mockStatic(Environment.class);
51+
environmentMock.when(Environment::isRunningOnKubernetes).thenReturn(true);
52+
4653
Secret secret1 = createSecret("alias1", "testUsername1", "testPassword1");
4754
Secret secret2 = createSecret("alias2", "testUsername2", "testPassword2");
4855
Secret secret3 = createSecret(null, "noAliasUsername", "noAliasPassword");
@@ -59,12 +66,16 @@ static void setUp() {
5966

6067
when(client.getConfiguration()).thenReturn(mock(Config.class));
6168
CredentialConstants.getInstance().setProperty(KubernetesCredentialFactory.K8_MASTER_URL, "http://localhost:8080");
69+
6270
credentialFactory.setClient(client);
6371
credentialFactory.initialize();
6472
}
6573

6674
@AfterAll
6775
static void tearDown() {
76+
if (environmentMock != null) {
77+
environmentMock.close();
78+
}
6879
credentialFactory.close();
6980
}
7081

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.