Skip to content

Commit

Permalink
update file with auth info when merging authinfos
Browse files Browse the repository at this point in the history
Signed-off-by: Andre Dietisheim <[email protected]>
  • Loading branch information
adietish committed Sep 4, 2024
1 parent 776b9c5 commit 2cc68dc
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.fabric8.kubernetes.api.model.Context;
import io.fabric8.kubernetes.api.model.ExecConfig;
import io.fabric8.kubernetes.api.model.ExecEnvVar;
import io.fabric8.kubernetes.api.model.NamedAuthInfo;
import io.fabric8.kubernetes.api.model.NamedContext;
import io.fabric8.kubernetes.client.http.TlsVersion;
import io.fabric8.kubernetes.client.internal.CertUtils;
Expand Down Expand Up @@ -961,56 +962,70 @@ private static void mergeKubeConfigContents(Config config, String context, io.fa
config.setDisableHostnameVerification(
currentCluster.getInsecureSkipTlsVerify() != null && currentCluster.getInsecureSkipTlsVerify());
config.setCaCertData(currentCluster.getCertificateAuthorityData());
AuthInfo currentAuthInfo = KubeConfigUtils.getUserAuthInfo(kubeConfig, currentContext);
NamedAuthInfo currentAuthInfo = KubeConfigUtils.getAuthInfo(kubeConfig, currentContext.getUser());
mergeKubeConfigAuthInfo(config, currentCluster, currentAuthInfo);
mergeProxyUrl(config, currentCluster.getProxyUrl());
}
}

private static void mergeProxyUrl(Config config, String proxyUrl) {
if (Utils.isNotNullOrEmpty(proxyUrl)) {
if (proxyUrl.startsWith(SOCKS5_PROTOCOL_PREFIX) && config.getMasterUrl().startsWith(HTTPS_PROTOCOL_PREFIX)) {
config.setHttpsProxy(proxyUrl);
} else if (proxyUrl.startsWith(SOCKS5_PROTOCOL_PREFIX)) {
config.setHttpProxy(proxyUrl);
} else if (proxyUrl.startsWith(HTTP_PROTOCOL_PREFIX)) {
config.setHttpProxy(proxyUrl);
} else if (proxyUrl.startsWith(HTTPS_PROTOCOL_PREFIX)) {
config.setHttpsProxy(proxyUrl);
}
if (Utils.isNullOrEmpty(proxyUrl)) {
return;
}
if (proxyUrl.startsWith(SOCKS5_PROTOCOL_PREFIX) && config.getMasterUrl().startsWith(HTTPS_PROTOCOL_PREFIX)) {
config.setHttpsProxy(proxyUrl);
} else if (proxyUrl.startsWith(SOCKS5_PROTOCOL_PREFIX)) {
config.setHttpProxy(proxyUrl);
} else if (proxyUrl.startsWith(HTTP_PROTOCOL_PREFIX)) {
config.setHttpProxy(proxyUrl);
} else if (proxyUrl.startsWith(HTTPS_PROTOCOL_PREFIX)) {
config.setHttpsProxy(proxyUrl);
}
}

private static void mergeKubeConfigAuthInfo(Config config, Cluster currentCluster, AuthInfo currentAuthInfo)
private static void mergeKubeConfigAuthInfo(Config config, Cluster currentCluster, NamedAuthInfo currentAuthInfo)
throws IOException {
if (currentAuthInfo == null) {
return;
}
// rewrite tls asset paths if needed
AuthInfo user = currentAuthInfo.getUser();
KubeConfigFile kubeConfigFile = config.getFileWithAuthInfo(currentAuthInfo.getName());
if (kubeConfigFile != null) {
mergeCertFiles(config, kubeConfigFile.getFile(), currentCluster, user);
}
config.setClientCertData(user.getClientCertificateData());
config.setClientKeyData(user.getClientKeyData());
config.setClientKeyAlgo(getKeyAlgorithm(config.getClientKeyFile(), config.getClientKeyData()));
config.setAutoOAuthToken(user.getToken());
config.setUsername(user.getUsername());
config.setPassword(user.getPassword());

if (Utils.isNullOrEmpty(config.getAutoOAuthToken()) && user.getAuthProvider() != null) {
mergeKubeConfigAuthProviderConfig(config, user);
} else if (config.getOauthTokenProvider() == null
&& kubeConfigFile != null) { // https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins
mergeKubeConfigExecCredential(config, user.getExec(), kubeConfigFile.getFile());
}
}

private static void mergeCertFiles(Config config, File file, Cluster currentCluster, AuthInfo currentAuthInfo) {
if (config == null
|| currentCluster == null
|| currentAuthInfo == null) {
return;
}
String caCertFile = currentCluster.getCertificateAuthority();
String clientCertFile = currentAuthInfo.getClientCertificate();
String clientKeyFile = currentAuthInfo.getClientKey();
File configFile = config.getFile();
if (configFile != null) {
caCertFile = absolutify(configFile, currentCluster.getCertificateAuthority());
clientCertFile = absolutify(configFile, currentAuthInfo.getClientCertificate());
clientKeyFile = absolutify(configFile, currentAuthInfo.getClientKey());
if (file != null) {
// rewrite tls asset paths if needed
caCertFile = absolutify(file, currentCluster.getCertificateAuthority());
clientCertFile = absolutify(file, currentAuthInfo.getClientCertificate());
clientKeyFile = absolutify(file, currentAuthInfo.getClientKey());
}
config.setCaCertFile(caCertFile);
config.setClientCertFile(clientCertFile);
config.setClientCertData(currentAuthInfo.getClientCertificateData());
config.setClientKeyFile(clientKeyFile);
config.setClientKeyData(currentAuthInfo.getClientKeyData());
config.setClientKeyAlgo(getKeyAlgorithm(config.getClientKeyFile(), config.getClientKeyData()));
config.setAutoOAuthToken(currentAuthInfo.getToken());
config.setUsername(currentAuthInfo.getUsername());
config.setPassword(currentAuthInfo.getPassword());

if (Utils.isNullOrEmpty(config.getAutoOAuthToken()) && currentAuthInfo.getAuthProvider() != null) {
mergeKubeConfigAuthProviderConfig(config, currentAuthInfo);
} else if (config.getOauthTokenProvider() == null) { // https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins
mergeKubeConfigExecCredential(config, currentAuthInfo.getExec(), configFile);
}
}

private static void mergeKubeConfigAuthProviderConfig(Config config, AuthInfo currentAuthInfo) {
Expand Down Expand Up @@ -1728,7 +1743,7 @@ public KubeConfigFile getFileWithAuthInfo(String name) {
}
return kubeConfigFiles.stream()
.filter(KubeConfigFile::isReadable)
.filter(entry -> KubeConfigUtils.hasAuthInfoNamed(name, entry.getConfig()))
.filter(entry -> KubeConfigUtils.hasAuthInfoNamed(entry.getConfig(), name))
.findFirst()
.orElse(null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
import io.fabric8.kubernetes.client.utils.Utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;

/**
Expand All @@ -44,7 +44,7 @@ private KubeConfigUtils() {
}

public static Config parseConfig(File file) throws IOException {
return Serialization.unmarshal(new FileInputStream(file), Config.class);
return Serialization.unmarshal(Files.newInputStream(file.toPath()), Config.class);
}

public static Config parseConfigFromString(String contents) {
Expand Down Expand Up @@ -95,18 +95,26 @@ public static String getUserToken(Config config, Context context) {
* @return {@link AuthInfo} for current context
*/
public static AuthInfo getUserAuthInfo(Config config, Context context) {
AuthInfo authInfo = null;
if (config != null && context != null) {
String user = context.getUser();
if (user != null) {
List<NamedAuthInfo> users = config.getUsers();
if (users != null) {
authInfo = users.stream()
.filter(u -> u.getName().equals(user))
.findAny()
.map(NamedAuthInfo::getUser)
.orElse(null);
}
NamedAuthInfo namedAuthInfo = getAuthInfo(config, context.getUser());
return (namedAuthInfo != null)? namedAuthInfo.getUser() : null;
}

/**
* Returns the {@link NamedAuthInfo} with the given name.
* Returns {@code null} otherwise
* @param config the config to search
* @param name
* @return
*/
public static NamedAuthInfo getAuthInfo(Config config, String name) {
NamedAuthInfo authInfo = null;
if (config != null && name != null) {
List<NamedAuthInfo> users = config.getUsers();
if (users != null) {
authInfo = users.stream()
.filter(toInspect -> name.equals(toInspect.getName()))
.findAny()
.orElse(null);
}
}
return authInfo;
Expand All @@ -117,17 +125,16 @@ public static AuthInfo getUserAuthInfo(Config config, Context context) {
* Returns {@code false} otherwise.
*
* @param name the name of the NamedAuthInfo that we are looking for
* @param config the Config to be searched
* @param config the Config to search
* @return true if it contains a NamedAuthInfo with the given name
*/
public static boolean hasAuthInfoNamed(String name, Config config) {
public static boolean hasAuthInfoNamed(Config config, String name) {
if (Utils.isNullOrEmpty(name)
|| config == null
|| config.getUsers() == null) {
return false;
}
return config.getUsers().stream()
.anyMatch(namedAuthInfo -> name.equals(namedAuthInfo.getName()));
return getAuthInfo(config, name) != null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1378,10 +1378,6 @@ void getKubeconfigFilenames_given_severalFilenamesDefinedInKUBECONFIG_then_retur
}
}

private String getResourceAbsolutePath(String filename) throws URISyntaxException {
return new File(Objects.requireNonNull(getClass().getResource(filename)).toURI()).getAbsolutePath();
}

@Test
void getKubeconfigFilenames_given_KUBECONFNotSet_then_returnsDefault() {
// Given
Expand All @@ -1397,7 +1393,7 @@ void getKubeconfigFilenames_given_KUBECONFNotSet_then_returnsDefault() {
}

@Test
void getFilenames_given_KUBECONFNotSet_then_returnsDefault() throws URISyntaxException {
void getFileWithAuthInfo_given_2ConfigsExists_then_returnsFileWithUser() throws URISyntaxException {
try {
// Given
String fileWithToken = getResourceAbsolutePath("/test-kubeconfig-oidc");
Expand All @@ -1418,4 +1414,8 @@ void getFilenames_given_KUBECONFNotSet_then_returnsDefault() throws URISyntaxExc
}
}

private String getResourceAbsolutePath(String filename) throws URISyntaxException {
return new File(Objects.requireNonNull(getClass().getResource(filename)).toURI()).getAbsolutePath();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.fabric8.kubernetes.api.model.Config;
import io.fabric8.kubernetes.api.model.ConfigBuilder;
import io.fabric8.kubernetes.api.model.Context;
import io.fabric8.kubernetes.api.model.NamedAuthInfo;
import io.fabric8.kubernetes.api.model.NamedContext;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -116,12 +117,32 @@ void testGetUserAuthInfo() {
assertEquals("test-token-2", authInfo.getToken());
}

@Test
void getAuthInfo_when_authInfoExists_returnsAuthInfo() {
// given
Config config = getTestKubeConfig();
// when
NamedAuthInfo found = KubeConfigUtils.getAuthInfo(config, "test/api-test-com:443");
// then
assertThat(found).isNotNull();
}

@Test
void getAuthInfo_when_authInfoDoesntExist_returnsNull() {
// given
Config config = getTestKubeConfig();
// when
NamedAuthInfo found = KubeConfigUtils.getAuthInfo(config, "bogus");
// then
assertThat(found).isNull();
}

@Test
void hasAuthInfoNamed_when_authInfoExists_returnsTrue() {
// given
Config config = getTestKubeConfig();
// when
boolean hasIt = KubeConfigUtils.hasAuthInfoNamed("test/api-test-com:443", config);
boolean hasIt = KubeConfigUtils.hasAuthInfoNamed(config, "test/api-test-com:443");
// then
assertThat(hasIt).isTrue();
}
Expand All @@ -131,7 +152,7 @@ void hasAuthInfoNamed_when_authInfoDoesntExist_returnsFalse() {
// given
Config config = getTestKubeConfig();
// when
boolean hasIt = KubeConfigUtils.hasAuthInfoNamed("bogus", config);
boolean hasIt = KubeConfigUtils.hasAuthInfoNamed(config, "bogus");
// then
assertThat(hasIt).isFalse();
}
Expand All @@ -141,7 +162,7 @@ void hasAuthInfoNamed_when_hasNoAuthInfo_returnsFalse() {
// given
Config config = new ConfigBuilder().build();
// when
boolean hasIt = KubeConfigUtils.hasAuthInfoNamed("test/api-test-com:443", config);
boolean hasIt = KubeConfigUtils.hasAuthInfoNamed(config, "test/api-test-com:443");
// then
assertThat(hasIt).isFalse();
}
Expand Down

0 comments on commit 2cc68dc

Please sign in to comment.