Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: SnakeYaml uses SafeConstructor or delegates to Fabric8 Kubernetes Client #1220

Merged
merged 1 commit into from Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -42,6 +42,7 @@ Usage:
* Fix #1190: OpenShiftBuildService doesn't apply resources in configured namespace
* Fix #1209: Remove WildFly Swarm support
* Fix #1219: Bump kubernetes-client to 5.11.2
* Fix #1213: SnakeYaml dependency from Kubernetes Client + uses SafeConstructor

### 1.5.1 (2021-10-28)
* Fix #1084: Gradle dependencies should be test or provided scope
Expand Down
Expand Up @@ -13,23 +13,16 @@
*/
package org.eclipse.jkube.kit.build.api.auth.handler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jkube.kit.build.api.auth.AuthConfig;
import org.eclipse.jkube.kit.build.api.auth.RegistryAuthConfig;
import org.eclipse.jkube.kit.build.api.auth.RegistryAuthHandler;
import org.eclipse.jkube.kit.common.KitLogger;
import org.yaml.snakeyaml.Yaml;

import static org.eclipse.jkube.kit.build.api.helper.KubernetesConfigAuthUtil.readKubeConfigAuth;

/**
* @author roland
Expand Down Expand Up @@ -63,7 +56,7 @@ public AuthConfig create(RegistryAuthConfig.Kind kind, String user, String regis
return null;
}
log.debug("AuthConfig: OpenShift credentials");
return validateMandatoryOpenShiftLogin(parseOpenShiftConfig());
return validateMandatoryOpenShiftLogin(readKubeConfigAuth());
}

boolean useOpenShiftAuth =
Expand All @@ -72,7 +65,7 @@ public AuthConfig create(RegistryAuthConfig.Kind kind, String user, String regis
.orElse(false);
if (useOpenShiftAuth) {
log.debug("AuthConfig: OpenShift credentials");
return validateMandatoryOpenShiftLogin(parseOpenShiftConfig());
return validateMandatoryOpenShiftLogin(readKubeConfigAuth());
}

return null;
Expand All @@ -87,87 +80,6 @@ private AuthConfig validateMandatoryOpenShiftLogin(AuthConfig openShiftRegistryA
throw new IllegalArgumentException(
String.format("OpenShift auth check enabled, but not active user and/or token found in %s. " +
"Please use 'oc login' for connecting to OpenShift.", kubeConfigEnv != null ? kubeConfigEnv : "~/.kube/config"));

}

// Parse OpenShift config to get credentials, but return null if not found
private AuthConfig parseOpenShiftConfig() {
Map kubeConfig = readKubeConfig();
if (kubeConfig == null) {
return null;
}

String currentContextName = (String) kubeConfig.get("current-context");
if (currentContextName == null) {
return null;
}

for (Map contextMap : (List<Map>) kubeConfig.get("contexts")) {
if (currentContextName.equals(contextMap.get("name"))) {
return parseContext(kubeConfig, (Map) contextMap.get("context"));
}
}

return null;
}

private Map<String, ?> readKubeConfig() {
String kubeConfig = System.getenv("KUBECONFIG");
Optional<Reader> reader =
getFileReaderFromDir(kubeConfig == null ? new File(getHomeDir(), ".kube/config") : new File(kubeConfig));

return (Map<String, ?>) reader.map(r -> new Yaml().load(r)).orElse(null);
}

private Optional<Reader> getFileReaderFromDir(File file) {
try {
return Optional.of(new FileReader(file));
} catch (FileNotFoundException e) {
return Optional.empty();
}
}

private File getHomeDir() {
String homeDir = System.getProperty("user.home") != null ? System.getProperty("user.home") : System.getenv("HOME");
return new File(homeDir);
}

private AuthConfig parseContext(Map kubeConfig, Map context) {
if (context == null) {
return null;
}
String userName = (String) context.get("user");
if (userName == null) {
return null;
}

List<Map> users = (List<Map>) kubeConfig.get("users");
if (users == null) {
return null;
}

for (Map userMap : users) {
if (userName.equals(userMap.get("name"))) {
return parseUser(userName, (Map) userMap.get("user"));
}
}
return null;
}

private AuthConfig parseUser(String userName, Map user) {
if (user == null) {
return null;
}
String token = (String) user.get("token");
if (token == null) {
return null;
}

// Strip off stuff after username
Matcher matcher = Pattern.compile("^([^/]+).*$").matcher(userName);
return AuthConfig.builder()
.username(matcher.matches() ? matcher.group(1) : userName)
.password(token)
.build();
}
}
Expand Up @@ -13,15 +13,6 @@
*/
package org.eclipse.jkube.kit.build.api.helper;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jkube.kit.common.JKubeFileInterpolator;
import org.eclipse.jkube.kit.config.image.ImageConfiguration;
import org.eclipse.jkube.kit.config.image.build.BuildConfiguration;
import org.yaml.snakeyaml.Yaml;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
Expand All @@ -41,6 +32,14 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jkube.kit.common.JKubeFileInterpolator;
import org.eclipse.jkube.kit.config.image.ImageConfiguration;
import org.eclipse.jkube.kit.config.image.build.BuildConfiguration;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.commons.lang3.StringUtils;

/**
* Utility class for dealing with dockerfiles
* @author roland
Expand Down Expand Up @@ -215,19 +214,6 @@ public static String[] extractDelimiters(String filter) {
return new String[] { filter, filter };
}

public static Map<String,?> readKubeConfig() {
String kubeConfig = System.getenv("KUBECONFIG");

Reader reader = kubeConfig == null
? getFileReaderFromDir(new File(getHomeDir(),".kube/config"))
: getFileReaderFromDir(new File(kubeConfig));
if (reader != null) {
Yaml ret = new Yaml();
return ret.load(reader);
}
return null;
}

public static boolean isSimpleDockerFileMode(File projectBaseDirectory) {
if (projectBaseDirectory != null) {
return getTopLevelDockerfile(projectBaseDirectory).exists();
Expand Down
@@ -0,0 +1,116 @@
/**
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.kit.build.api.helper;


import com.fasterxml.jackson.core.type.TypeReference;
import io.fabric8.kubernetes.client.utils.Serialization;
import org.eclipse.jkube.kit.build.api.auth.AuthConfig;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class KubernetesConfigAuthUtil {

private static final String KUBECONFIG_ENV = "KUBECONFIG";
private static final Path KUBECONFIG_FILE = Paths.get(".kube", "config");

private KubernetesConfigAuthUtil() {
}

public static AuthConfig readKubeConfigAuth() {
Map<String, ?> kubeConfig = readKubeConfig();
if (kubeConfig == null) {
return null;
}
String currentContextName = (String) kubeConfig.get("current-context");
if (currentContextName == null) {
return null;
}

for (Map<String, ?> contextMap : (List<Map<String, ?>>) kubeConfig.get("contexts")) {
if (currentContextName.equals(contextMap.get("name"))) {
return parseContext(kubeConfig, (Map<String, ?>) contextMap.get("context"));
}
}

return null;
}

private static AuthConfig parseContext(Map<String, ?> kubeConfig, Map<String, ?> context) {
if (context == null) {
return null;
}
String userName = (String) context.get("user");
if (userName == null) {
return null;
}

List<Map<String, ?>> users = (List<Map<String, ?>>) kubeConfig.get("users");
if (users == null) {
return null;
}

for (Map<String, ?> userMap : users) {
if (userName.equals(userMap.get("name"))) {
return parseUser(userName, (Map<String, ?>) userMap.get("user"));
}
}
return null;
}

private static AuthConfig parseUser(String userName, Map<String, ?> user) {
if (user == null) {
return null;
}
String token = (String) user.get("token");
if (token == null) {
return null;
}

// Strip off stuff after username
Matcher matcher = Pattern.compile("^([^/]+).*$").matcher(userName);
return AuthConfig.builder()
.username(matcher.matches() ? matcher.group(1) : userName)
.password(token)
.build();
}

private static Map<String, Object> readKubeConfig() {
String kubeConfig = System.getenv(KUBECONFIG_ENV);
final File applicableFile = kubeConfig == null ?
getHomeDir().toPath().resolve(KUBECONFIG_FILE).toFile() : new File(kubeConfig);
if (applicableFile.exists()) {
try (FileInputStream fis = new FileInputStream(applicableFile)) {
return Serialization.unmarshal(fis, new TypeReference<Map<String, Object>>() {});
} catch (IOException ex) {
// Ignore
}
}
return Collections.emptyMap();
}

private static File getHomeDir() {
String homeDir = System.getProperty("user.home") != null ? System.getProperty("user.home") : System.getenv("HOME");
return new File(homeDir);
}
}
Expand Up @@ -46,13 +46,13 @@ public class OpenShiftRegistryAuthHandlerTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Mocked
KitLogger log;

OpenShiftRegistryAuthHandler handler;

@Before
public void setup() {
log = new KitLogger.SilentLogger();
RegistryAuthConfig registryAuthConfig = RegistryAuthConfig.builder()
.skipExtendedAuthentication(false)
.propertyPrefix("docker")
Expand Down