Skip to content

Commit

Permalink
Rewrite tests using RealJenkinsRule
Browse files Browse the repository at this point in the history
Signed-off-by: Olivier Lamy <olamy@apache.org>
  • Loading branch information
olamy committed Aug 5, 2024
1 parent cd2d483 commit 34e0458
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 156 deletions.
288 changes: 148 additions & 140 deletions src/test/java/hudson/plugins/git/FIPSModeUrlCheckTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.List;
import jenkins.branch.MultiBranchProject;
import jenkins.plugins.git.GitSCMSource;
import jenkins.security.FIPS140;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.StoredConfig;
Expand Down Expand Up @@ -100,197 +99,206 @@ public void testGitSCMSourceCheck() throws Throwable {

@Test
public void testUserRemoteConfigCheck() throws Throwable {
rule.then( r -> {
SystemCredentialsProvider.getInstance()
.getCredentials()
.add(new UsernamePasswordCredentialsImpl(
CredentialsScope.GLOBAL, "mycreds", null, "jenkins", "s3cr3t"));
SystemCredentialsProvider.getInstance().save();
FreeStyleProject p = r.createProject(FreeStyleProject.class, "mbp");
UserRemoteConfig.DescriptorImpl descriptor =
ExtensionList.lookupSingleton(UserRemoteConfig.DescriptorImpl.class);
Assume.assumeTrue(DockerClientFactory.instance().isDockerAvailable());
// ssh with credentials all good
try (GitServerContainer containerUnderTest =
new GitServerContainer(GitServerVersions.V2_45.getDockerImageName()).withGitRepo("someRepo")) {
containerUnderTest.withClasspathResourceMapping(
"ssh-keys/id_rsa.pub", "/home/git/.ssh/authorized_keys", BindMode.READ_ONLY);
containerUnderTest.withClasspathResourceMapping(
"sshd_config", "/etc/ssh/sshd_config", BindMode.READ_ONLY);

{
// http with credentials rejected
FormValidation validation = descriptor.doCheckUrl(p, "mycreds", "http://github.com/olamy/beer");
assertThat(validation.kind, is(FormValidation.Kind.ERROR));
assertThat(validation.getMessage(), containsString(Messages.git_fips_url_notsecured()));
}
containerUnderTest.start();

{
// https without credentials all good
FormValidation validation = descriptor.doCheckUrl(p, null, "https://github.com/jenkinsci/git-plugin");
assertThat(validation.kind, is(FormValidation.Kind.OK));
}
SshIdentity sshClientIdentity = new SshIdentity(
this.getClass()
.getClassLoader()
.getResourceAsStream("ssh-keys/id_rsa")
.readAllBytes(),
this.getClass()
.getClassLoader()
.getResourceAsStream("ssh-keys/id_rsa.pub")
.readAllBytes(),
new byte[0]);
byte[] privateKey = sshClientIdentity.getPrivateKey();
byte[] passphrase = sshClientIdentity.getPassphrase();
// ssh://git@localhost:33011/srv/git/someRepo.git
// we don't want the user part of the uri or jgit will use this user
// and we want to be sure to test our implementation with dynamic user
final String repoUrl = StringUtils.remove(containerUnderTest.getGitRepoURIAsSSH().toString(), "git@");
rule.then( r -> {
BasicSSHUserPrivateKey sshUserPrivateKey = getBasicSSHUserPrivateKey(privateKey, passphrase);
SystemCredentialsProvider.getInstance().getCredentials().add(sshUserPrivateKey);
SystemCredentialsProvider.getInstance()
.getCredentials()
.add(new UsernamePasswordCredentialsImpl(
CredentialsScope.GLOBAL, "mycreds", null, "jenkins", "s3cr3t"));
SystemCredentialsProvider.getInstance().save();
FreeStyleProject p = r.createProject(FreeStyleProject.class, "mbp");
UserRemoteConfig.DescriptorImpl descriptor =
ExtensionList.lookupSingleton(UserRemoteConfig.DescriptorImpl.class);

Assume.assumeTrue(DockerClientFactory.instance().isDockerAvailable());
{
// http with credentials rejected
FormValidation validation = descriptor.doCheckUrl(p, "mycreds", "http://github.com/olamy/beer");
assertThat(validation.kind, is(FormValidation.Kind.ERROR));
assertThat(validation.getMessage(), containsString(Messages.git_fips_url_notsecured()));
}

{
// ssh with credentials all good
try (GitServerContainer containerUnderTest =
new GitServerContainer(GitServerVersions.V2_45.getDockerImageName()).withGitRepo("someRepo")) {
containerUnderTest.withClasspathResourceMapping(
"ssh-keys/id_rsa.pub", "/home/git/.ssh/authorized_keys", BindMode.READ_ONLY);
containerUnderTest.withClasspathResourceMapping(
"sshd_config", "/etc/ssh/sshd_config", BindMode.READ_ONLY);
{
// https without credentials all good
FormValidation validation = descriptor.doCheckUrl(p, null, "https://github.com/jenkinsci/git-plugin");
assertThat(validation.kind, is(FormValidation.Kind.OK));
}

containerUnderTest.start();
Assume.assumeTrue(DockerClientFactory.instance().isDockerAvailable());

SshIdentity sshClientIdentity = new SshIdentity(
this.getClass()
.getClassLoader()
.getResourceAsStream("ssh-keys/id_rsa")
.readAllBytes(),
this.getClass()
.getClassLoader()
.getResourceAsStream("ssh-keys/id_rsa.pub")
.readAllBytes(),
new byte[0]);
BasicSSHUserPrivateKey sshUserPrivateKey = getBasicSSHUserPrivateKey(sshClientIdentity);
SystemCredentialsProvider.getInstance().getCredentials().add(sshUserPrivateKey);
String repoUrl = containerUnderTest.getGitRepoURIAsSSH().toString();
// ssh://git@localhost:33011/srv/git/someRepo.git
// we don't want the user part of the uri or jgit will use this user
// and we want to be sure to test our implementation with dynamic user
repoUrl = StringUtils.remove(repoUrl, "git@");
{
FormValidation validation = descriptor.doCheckUrl(p, sshUserPrivateKey.getId(), repoUrl);
assertThat(validation.kind, is(FormValidation.Kind.OK));
}
}
});
}

// http without credentials all good
try (GitHttpServerContainer containerUnderTest =
new GitHttpServerContainer(GitServerVersions.V2_45.getDockerImageName())) {
containerUnderTest.start();
String repoUri = containerUnderTest.getGitRepoURIAsHttp().toString();
rule.then( r -> {
FreeStyleProject p = r.createProject(FreeStyleProject.class, "mbp2");
UserRemoteConfig.DescriptorImpl descriptor =
ExtensionList.lookupSingleton(UserRemoteConfig.DescriptorImpl.class);
// no TLS is fine without credentials
FormValidation validation = descriptor.doCheckUrl(
p, null, repoUri);
assertThat(validation.kind, is(FormValidation.Kind.OK));
});
}

{
// http without credentials all good
try (GitHttpServerContainer containerUnderTest =
new GitHttpServerContainer(GitServerVersions.V2_45.getDockerImageName())) {
containerUnderTest.start();
// no TLS is fine without credentials
FormValidation validation = descriptor.doCheckUrl(
p, null, containerUnderTest.getGitRepoURIAsHttp().toString());
assertThat(validation.kind, is(FormValidation.Kind.OK));
}
}
});
}

private static BasicSSHUserPrivateKey getBasicSSHUserPrivateKey(SshIdentity sshIdentity) {
private static BasicSSHUserPrivateKey getBasicSSHUserPrivateKey(byte[] privateKey, byte[] passphrase) {
BasicSSHUserPrivateKey.PrivateKeySource privateKeySource = new BasicSSHUserPrivateKey.PrivateKeySource() {
@NotNull
@Override
public List<String> getPrivateKeys() {
return List.of(new String(sshIdentity.getPrivateKey()));
return List.of(new String(privateKey));
}
};
return new BasicSSHUserPrivateKey(
CredentialsScope.GLOBAL,
"some-id",
"git",
privateKeySource,
new String(sshIdentity.getPassphrase()),
new String(passphrase),
"description");
}

@Test
public void gitStepTLSCheck() throws Throwable {
rule.then( r -> {
WorkflowJob p = r.createProject(WorkflowJob.class, "some project");
{
// http with creds rejected
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" dir('foo') {\n" +
" git url: 'http://foo.com/beer.git', credentialsId: 'yup'\n" +
" }\n" +
"}", true));
WorkflowRun b = r.buildAndAssertStatus(Result.FAILURE, p);
r.assertLogContains(Messages.git_fips_url_notsecured(), b);
}

Assume.assumeTrue(DockerClientFactory.instance().isDockerAvailable());

{
// http without creds not rejected
try (GitHttpServerContainer containerUnderTest =
new GitHttpServerContainer(GitServerVersions.V2_45.getDockerImageName())) {
containerUnderTest.start();
// need to have at least on revision to avoid build failure
File tmp = directory.newFolder();
Git git = Git.cloneRepository()
.setURI(containerUnderTest.getGitRepoURIAsHttp().toString())
.setDirectory(tmp)
.call();
StoredConfig storedConfig = git.getRepository().getConfig();
storedConfig.setBoolean("commit", null, "gpgsign", false);
storedConfig.setBoolean("tag", null, "gpgSign", false);
storedConfig.save();
Files.writeString(new File(tmp, "foo.txt").toPath(), "nothing too see here");
git.add().addFilepattern("foo.txt").call();
git.commit().setMessage("add foo").call();
git.push().call();
Assume.assumeTrue(DockerClientFactory.instance().isDockerAvailable());
try (GitHttpServerContainer containerUnderTest =
new GitHttpServerContainer(GitServerVersions.V2_45.getDockerImageName())) {
containerUnderTest.start();
// need to have at least on revision to avoid build failure
File tmp = directory.newFolder();
Git git = Git.cloneRepository()
.setURI(containerUnderTest.getGitRepoURIAsHttp().toString())
.setDirectory(tmp)
.call();
StoredConfig storedConfig = git.getRepository().getConfig();
storedConfig.setBoolean("commit", null, "gpgsign", false);
storedConfig.setBoolean("tag", null, "gpgSign", false);
storedConfig.save();
Files.writeString(new File(tmp, "foo.txt").toPath(), "nothing too see here");
git.add().addFilepattern("foo.txt").call();
git.commit().setMessage("add foo").call();
git.push().call();
String repoUri = containerUnderTest.getGitRepoURIAsHttp().toString();
rule.then(r -> {
WorkflowJob p = r.createProject(WorkflowJob.class, "some project");
{
// http with creds rejected
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" dir('foo') {\n" +
" git url: 'http://foo.com/beer.git', credentialsId: 'yup'\n" +
" }\n" +
"}", true));
WorkflowRun b = r.buildAndAssertStatus(Result.FAILURE, p);
r.assertLogContains(Messages.git_fips_url_notsecured(), b);
}

{
// http without creds not rejected
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" dir('foo') {\n" +
" git url: '" + containerUnderTest.getGitRepoURIAsHttp() + "', changelog: false\n" +
" git url: '" + repoUri + "', changelog: false\n" +
" }\n" +
"}", true));
WorkflowRun b = r.buildAndAssertStatus(Result.SUCCESS, p);

}
}
});
});
}
}

@Test
public void checkoutStepTLSCheck() throws Throwable {
rule.then( r -> {
WorkflowJob p = r.createProject(WorkflowJob.class, "some project");
{
// http with creds rejected
// Intentionally using modern syntax to check compatibility
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" dir('foo') {\n" +
" checkout scmGit(branches: [[name: 'master']],\n" +
" userRemoteConfigs: [[credentialsId: 'foocreds', url: 'http://github.com/foo/beer.git']])\n" +
" }\n" +
"}", true));
WorkflowRun b = r.buildAndAssertStatus(Result.FAILURE, p);
r.assertLogContains(Messages.git_fips_url_notsecured(), b);
}
Assume.assumeTrue(DockerClientFactory.instance().isDockerAvailable());
try (GitHttpServerContainer containerUnderTest =
new GitHttpServerContainer(GitServerVersions.V2_45.getDockerImageName())) {
containerUnderTest.start();
// need to have at least on revision to avoid build failure
File tmp = directory.newFolder();
Git git = Git.cloneRepository()
.setURI(containerUnderTest.getGitRepoURIAsHttp().toString())
.setDirectory(tmp)
.call();
StoredConfig storedConfig = git.getRepository().getConfig();
storedConfig.setBoolean("commit", null, "gpgsign", false);
storedConfig.setBoolean("tag", null, "gpgSign", false);
storedConfig.save();
Files.writeString(new File(tmp, "foo.txt").toPath(), "nothing too see here");
git.add().addFilepattern("foo.txt").call();
git.commit().setMessage("add foo").call();
git.push().call();
String repoUri = containerUnderTest.getGitRepoURIAsHttp().toString();
rule.then(r -> {
WorkflowJob p = r.createProject(WorkflowJob.class, "some project");
{
// http with creds rejected
// Intentionally using modern syntax to check compatibility
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" dir('foo') {\n" +
" checkout scmGit(branches: [[name: 'master']],\n" +
" userRemoteConfigs: [[credentialsId: 'foocreds', url: 'http://github.com/foo/beer.git']])\n" +
" }\n" +
"}", true));
WorkflowRun b = r.buildAndAssertStatus(Result.FAILURE, p);
r.assertLogContains(Messages.git_fips_url_notsecured(), b);
}

Assume.assumeTrue(DockerClientFactory.instance().isDockerAvailable());
{
// http without creds not rejected

{
// http without creds not rejected
try (GitHttpServerContainer containerUnderTest =
new GitHttpServerContainer(GitServerVersions.V2_45.getDockerImageName())) {
containerUnderTest.start();
// need to have at least on revision to avoid build failure
File tmp = directory.newFolder();
Git git = Git.cloneRepository()
.setURI(containerUnderTest.getGitRepoURIAsHttp().toString())
.setDirectory(tmp)
.call();
StoredConfig storedConfig = git.getRepository().getConfig();
storedConfig.setBoolean("commit", null, "gpgsign", false);
storedConfig.setBoolean("tag", null, "gpgSign", false);
storedConfig.save();
Files.writeString(new File(tmp, "foo.txt").toPath(), "nothing too see here");
git.add().addFilepattern("foo.txt").call();
git.commit().setMessage("add foo").call();
git.push().call();

// Intentionally using old syntax to check compatibility
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" dir('foo') {\n" +
" checkout([$class: 'GitSCM',\n" +
" branches: [[name: '*/master']],\n" +
" userRemoteConfigs: [[url: '" + containerUnderTest.getGitRepoURIAsHttp() + "']]])\n" +
" userRemoteConfigs: [[url: '" + repoUri + "']]])\n" +
" }\n" +
"}", true));
WorkflowRun b = r.buildAndAssertStatus(Result.SUCCESS, p);
}
}
});

});
}
}
}
Loading

0 comments on commit 34e0458

Please sign in to comment.