Skip to content

Commit

Permalink
fix (jkube-kit): Sanitize VCS remote URL used in `jkube.eclipse.org/g…
Browse files Browse the repository at this point in the history
…it-url` annotation (eclipse-jkube#2831)

* fix (jkube-kit) : Sanitize VCS remote URL used in `jkube.eclipse.org/git-url` annotation

Sanitize Git Remote URL before adding it to Git annotations.



* review: sanitize url


* fix: remove misleading URL from Javadoc
  • Loading branch information
rohanKanojia authored Apr 23, 2024
1 parent a621561 commit fb8e7da
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Usage:
### 1.17-SNAPSHOT
* Fix #2335: Add support for configuring nodeSelector spec for controller via xml/groovy DSL configuration
* Fix #2459: Allow configuring Buildpacks build via ImageConfiguration
* Fix #2662: Sanitize VCS remote URL used in `jkube.eclipse.org/git-url` annotation
* Fix #2860: Correctly pass Docker build-arg from the build configuration to the Openshift build strategy

### 1.16.2 (2024-03-27)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@
*/
package org.eclipse.jkube.kit.common.util;

import java.io.File;
import java.io.IOException;
import java.util.stream.StreamSupport;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.URIish;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.stream.StreamSupport;

/**
* @author roland
Expand Down Expand Up @@ -69,4 +72,33 @@ public static String getGitCommitId(Repository repository) throws GitAPIExceptio
}
return null;
}

/**
* Sanitize Git Repository's remote URL, trims username and access token from URL.
*
* @param remoteUrlStr URL string of a particular git remote
* @return sanitized URL
*/
public static String sanitizeRemoteUrl(String remoteUrlStr) {
if (StringUtils.isBlank(remoteUrlStr)) {
return remoteUrlStr;
}
try {
URIish uri = new URIish(remoteUrlStr);
final StringBuilder userInfo = new StringBuilder();
if (StringUtils.isNotBlank(uri.getUser())) {
userInfo.append(uri.getUser());
}
if (StringUtils.isNotBlank(uri.getPass())) {
userInfo.append(":").append(uri.getPass());
}
if (userInfo.length() > 0) {
remoteUrlStr = remoteUrlStr.replace(userInfo + "@", "");
}
return remoteUrlStr;
} catch (URISyntaxException e) {
//NO OP - Not a valid URL
}
return remoteUrlStr;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* 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.common.util;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.URIish;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.assertj.core.api.Assertions.assertThat;

class GitUtilTest {
@TempDir
private File temporaryFolder;

@Test
void getGitRepository_whenNoGitFolderFound_thenReturnNull() throws IOException {
assertThat(GitUtil.getGitRepository(temporaryFolder)).isNull();
}

@Test
void getGitRepository_whenValidGitRepositoryPresent_thenReturnGitRepository() throws IOException, URISyntaxException, GitAPIException {
try (Git ignore = createDummyGitRepository(temporaryFolder)) {
// Given
// When
Repository repository = GitUtil.getGitRepository(temporaryFolder);

// Then
assertThat(repository)
.isNotNull()
.satisfies(r -> assertThat(r.getBranch()).isEqualTo("test-branch"))
.satisfies(r -> assertThat(r.getDirectory()).isEqualTo(temporaryFolder.toPath().resolve(".git").toFile()));
}
}

@Test
void getGitCommitId_whenValidRepository_thenReturnValidCommit() throws IOException, GitAPIException, URISyntaxException {
try (Git ignore = createDummyGitRepository(temporaryFolder)) {
// Given
Repository repository = GitUtil.getGitRepository(temporaryFolder);

// When + Then
assertThat(GitUtil.getGitCommitId(repository)).isNotBlank().hasSize(40);
}
}

@Test
void getCommitId_whenNullRepository_thenReturnNull() throws GitAPIException {
assertThat(GitUtil.getGitCommitId(null)).isNull();
}

@Test
void findGitFolder_whenGitFolderAbsent_thenReturnNull() {
assertThat(GitUtil.findGitFolder(temporaryFolder)).isNull();
}

@Test
void findGitFolder_whenGitFolderInSameDirectory_thenReturnFolder() throws GitAPIException, URISyntaxException {
try (Git ignore = createDummyGitRepository(temporaryFolder)) {
assertThat(GitUtil.findGitFolder(temporaryFolder)).isEqualTo(new File(temporaryFolder, ".git"));
}
}

@Test
void findGitFolder_whenGitFolderInParentDirectory_thenReturnFolder() throws GitAPIException, URISyntaxException, IOException {
File childFolder = temporaryFolder.toPath().resolve("subfolder").toFile();
Files.createDirectory(childFolder.toPath());
try (Git ignore = createDummyGitRepository(temporaryFolder)) {
assertThat(GitUtil.findGitFolder(childFolder)).isEqualTo(new File(temporaryFolder, ".git"));
}
}

// These test cases are taken from https://stackoverflow.com/questions/31801271/what-are-the-supported-git-url-formats
@ParameterizedTest(name = "{0} should be sanitized to {1}")
@CsvSource({
",",
"https://user:[email protected]/repo.git?queryParam,https://example.com/repo.git?queryParam",
"git://user:[email protected]/repo.git?queryParam, git://example.com/repo.git?queryParam",
"[email protected]:repo.git, example.com:repo.git",
"user:[email protected]:repo.git, example.com:repo.git",
"git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git, git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git",
"https://@some.host/foo/bar, https://@some.host/foo/bar",
"https://secrettoken:[email protected]/path/to/repo.git, https://host.xz/path/to/repo.git",
"https://gitlab-ci-token:[email protected]/project.git, https://gitlab.onprem.com/project.git",
"[email protected]:myorg/myproject.git, github.com:myorg/myproject.git",
"https://github.com/myorg/myproject.git, https://github.com/myorg/myproject.git",
"https://gitlab.com/foo/bar.git, https://gitlab.com/foo/bar.git",
"[email protected]:foo/bar.git, gitlab.com:foo/bar.git",
"git+ssh://[email protected]/foo/bar.git, git+ssh://gitlab.com/foo/bar.git",
"git+ssh://[email protected]/foo/bar, git+ssh://gitlab.com/foo/bar",
"git://host.xz/~user/path/to/repo.git, git://host.xz/~user/path/to/repo.git",
"rsync://host.xz/path/to/repo.git,rsync://host.xz/path/to/repo.git",
"ssh://[email protected]:8080/path/to/repo.git, ssh://host.xz:8080/path/to/repo.git",
"ssh://[email protected]/path/to/repo.git, ssh://host.xz/path/to/repo.git",
"ssh://host.xz:8080/path/to/repo.git, ssh://host.xz:8080/path/to/repo.git",
"ssh://host.xz/path/to/repo.git, ssh://host.xz/path/to/repo.git",
"ssh://[email protected]/~user/path/to/repo.git, ssh://host.xz/~user/path/to/repo.git",
"ssh://host.xz/~user/path/to/repo.git, ssh://host.xz/~user/path/to/repo.git",
"ssh://[email protected]/~/path/to/repo.git, ssh://host.xz/~/path/to/repo.git",
"ssh://host.xz/~/path/to/repo.git, ssh://host.xz/~/path/to/repo.git",
"file:///path/to/repo.git, file:///path/to/repo.git",
"file://~/path/to/repo.git, file://~/path/to/repo.git",
"host.xz:path/to/repo.git, host.xz:path/to/repo.git",
"[email protected]:path/to/repo.git, host.xz:path/to/repo.git",
"[email protected]:~user/path/to/repo.git, host.xz:~user/path/to/repo.git",
"host.xz:~user/path/to/repo.git, host.xz:~user/path/to/repo.git",
"https://[::1]:456, https://[::1]:456"
})
void sanitizeRemoteUrl_whenInvoked_shouldSanitize(String original, String expected) {
assertThat(GitUtil.sanitizeRemoteUrl(original)).isEqualTo(expected);
}

private Git createDummyGitRepository(File gitFolder) throws GitAPIException, URISyntaxException {
Git git = Git.init().setDirectory(gitFolder).setInitialBranch("test-branch").call();
git.add().addFilepattern(".").call();
git.remoteAdd().setName("origin").setUri(new URIish("https://example.com/origin.git")).call();
git.commit().setMessage("Initial commit").call();
return git;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import java.util.HashMap;
import java.util.Map;

import static org.eclipse.jkube.kit.common.util.GitUtil.sanitizeRemoteUrl;

/**
* Enricher for adding build metadata:
*
Expand All @@ -54,7 +56,7 @@ private Map<String, String> getAnnotations(PlatformMode platformMode) {
try (Repository repository = GitUtil.getGitRepository(getContext().getProjectDirectory())) {
// Git annotations (if git is used as SCM)
if (repository != null) {
String gitRemoteUrl = getGitRemoteUrl(repository);
String gitRemoteUrl = sanitizeRemoteUrl(getGitRemoteUrl(repository));
if (gitRemoteUrl == null) {
log.warn("Could not detect any git remote");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,26 @@ void whenGitRemotePropertySpecified_thenUseProvidedGitRemoteInAnnotations() thro
.containsEntry("jkube.eclipse.org/git-url", "https://example.com/upstream.git");
}

@Test
@DisplayName("jkube.remoteName contains user crendentials, then sanitize git remote url")
void whenGitRemoteUrlContainsUserCredentials_thenSanitizeGitRemoteUrl() throws Exception {
// Given
git.remoteAdd().setName("upstream").setUri(new URIish("https://user:[email protected]/upstream.git")).call();
properties.put("jkube.remoteName", "upstream");

// When
gitEnricher.enrich(PlatformMode.kubernetes, klb);

// Then
HasMetadata result = klb.buildFirstItem();
assertThat(result)
.extracting("metadata.annotations")
.asInstanceOf(InstanceOfAssertFactories.MAP)
.containsEntry("jkube.eclipse.org/git-branch", "test-branch")
.containsEntry("jkube.eclipse.org/git-commit", commit.getName())
.containsEntry("jkube.eclipse.org/git-url", "https://example.com/upstream.git");
}

@Test
@DisplayName("git remote not found, then do not add git-url annotation")
void whenRemoteNotFound_thenGitUrlAnnotationNotAdded() throws Exception {
Expand Down

0 comments on commit fb8e7da

Please sign in to comment.