API of Kubernetes in java: authentication error

7/30/2021

I am developing a simple java app that show the pods of the cluster.

This is the app:

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Pod;
import io.kubernetes.client.openapi.models.V1PodList;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
import java.io.FileReader;
import java.io.IOException;

/**
 * A simple example of how to use the Java API from an application outside a kubernetes cluster
 *
 * <p>Easiest way to run this: mvn exec:java
 * -Dexec.mainClass="io.kubernetes.client.examples.KubeConfigFileClientExample"
 *
 */
public class untitled4 {
    public static void main(String[] args) throws IOException, ApiException {

        // file path to your KubeConfig
        String kubeConfigPath = "/home/robin/.kube/config";

        // loading the out-of-cluster config, a kubeconfig from file-system
        ApiClient client =
                ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();

        // set the global default api-client to the in-cluster one from above
        Configuration.setDefaultApiClient(client);

        // the CoreV1Api loads default api-client from global configuration.
        CoreV1Api api = new CoreV1Api();

        // invokes the CoreV1Api client
        V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null);
        System.out.println("Listing all pods: ");
        for (V1Pod item : list.getItems()) {
            System.out.println(item.getMetadata().getName());
        }
    }
}

But I get this error:

Exception in thread "main" java.lang.IllegalStateException: Unimplemented
	at io.kubernetes.client.util.authenticators.GCPAuthenticator.refresh(GCPAuthenticator.java:61)
	at io.kubernetes.client.util.KubeConfig.getAccessToken(KubeConfig.java:215)
	at io.kubernetes.client.util.credentials.KubeconfigAuthentication.<init>(KubeconfigAuthentication.java:46)
	at io.kubernetes.client.util.ClientBuilder.kubeconfig(ClientBuilder.java:276)
	at untitled4.main(untitled4.java:28)

Process finished with exit code 1
-- xRobot
java
kubernetes
kubernetes-apiserver

1 Answer

8/2/2021

There is an open issue on GitHub related with this problem. For now you can use workarounds like the one, proposed by jhbae200 in this comment:

I am using it like this.

package kubernetes.gcp;

import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import io.kubernetes.client.util.KubeConfig;
import io.kubernetes.client.util.authenticators.Authenticator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.time.Instant;
import java.util.Date;
import java.util.Map;

public class ReplacedGCPAuthenticator implements Authenticator {
    private static final Logger log;
    private static final String ACCESS_TOKEN = "access-token";
    private static final String EXPIRY = "expiry";

    static {
        log = LoggerFactory.getLogger(io.kubernetes.client.util.authenticators.GCPAuthenticator.class);
    }

    private final GoogleCredentials credentials;

    public ReplacedGCPAuthenticator(GoogleCredentials credentials) {
        this.credentials = credentials;
    }

    public String getName() {
        return "gcp";
    }

    public String getToken(Map<String, Object> config) {
        return (String) config.get("access-token");
    }

    public boolean isExpired(Map<String, Object> config) {
        Object expiryObj = config.get("expiry");
        Instant expiry = null;
        if (expiryObj instanceof Date) {
            expiry = ((Date) expiryObj).toInstant();
        } else if (expiryObj instanceof Instant) {
            expiry = (Instant) expiryObj;
        } else {
            if (!(expiryObj instanceof String)) {
                throw new RuntimeException("Unexpected object type: " + expiryObj.getClass());
            }

            expiry = Instant.parse((String) expiryObj);
        }

        return expiry != null && expiry.compareTo(Instant.now()) <= 0;
    }

    public Map<String, Object> refresh(Map<String, Object> config) {
        try {
            AccessToken accessToken = this.credentials.refreshAccessToken();

            config.put(ACCESS_TOKEN, accessToken.getTokenValue());
            config.put(EXPIRY, accessToken.getExpirationTime());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return config;
    }
}

Running in.

//GoogleCredentials.fromStream(--something credential.json filestream--)
KubeConfig.registerAuthenticator(new ReplacedGCPAuthenticator(GoogleCredentials.getApplicationDefault()));
ApiClient client = Config.defaultClient();
Configuration.setDefaultApiClient(client);
CoreV1Api api = new CoreV1Api();
V1PodList list = api.listNamespacedPod("default", null, null, null, null, null, null, null, 30, Boolean.FALSE);
for (V1Pod item : list.getItems()) {
    System.out.println(item.getMetadata().getName());
}
-- mario
Source: StackOverflow