Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b7f3c51
commit d615e32
Showing
7 changed files
with
429 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/test/java/org/jenkinsci/plugins/configfiles/sec/PermissionChecker.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package org.jenkinsci.plugins.configfiles.sec; | ||
|
||
import edu.umd.cs.findbugs.annotations.NonNull; | ||
import hudson.security.AccessDeniedException2; | ||
import hudson.security.Permission; | ||
import org.hamcrest.core.IsEqual; | ||
|
||
import java.util.function.Supplier; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.junit.Assert.fail; | ||
|
||
/** | ||
* A class to run pieces of code with a certain user and assert either the code runs successfully, without even worrying | ||
* about the result, or the code fails with an {@link AccessDeniedException2} with the specified {@link Permission}. | ||
*/ | ||
public class PermissionChecker extends ProtectedCodeRunner<Void> { | ||
/** | ||
* Build a checker to run a specific code with this user and assert it runs successfully or it fails because certain | ||
* permission. | ||
* @param code The code to execute. | ||
* @param user The user to execute with. | ||
*/ | ||
public PermissionChecker(@NonNull Runnable code, @NonNull String user) { | ||
super(getSupplier(code), user); | ||
} | ||
|
||
/** | ||
* Assert the execution of the code by this user fails with this permission. The code throws an {@link AccessDeniedException2} | ||
* with the permission field being permission. Otherwise it fails. | ||
* @param permission The permission thrown by the code. | ||
*/ | ||
public void assertFailWithPermission(Permission permission) { | ||
Throwable t = getThrowable(); | ||
if (t instanceof AccessDeniedException2) { | ||
assertThat(((AccessDeniedException2) t).permission, IsEqual.equalTo(permission)); | ||
} else { | ||
fail(String.format("The code run by %s didn't throw an AccessDeniedException2 with %s. If failed with the unexpected throwable: %s", getUser(), permission, t)); | ||
} | ||
} | ||
|
||
/** | ||
* Assert the execution is done without any exception. The result doesn't matter. | ||
*/ | ||
public void assertPass() { | ||
getResult(); // The result doesn't matter | ||
} | ||
|
||
/** | ||
* Change the user to run the code with. | ||
* @param user The user. | ||
* @return This object. | ||
*/ | ||
@Override | ||
public PermissionChecker withUser(String user) { | ||
super.withUser(user); | ||
return this; | ||
} | ||
|
||
/** | ||
* Get a supplier from a runnable. | ||
* @param code The runnable to run. | ||
* @return A supplier executing the runnable code and returning just null. | ||
*/ | ||
private static Supplier<Void> getSupplier(Runnable code) { | ||
return () -> { | ||
code.run(); | ||
return null; | ||
}; | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/test/java/org/jenkinsci/plugins/configfiles/sec/PermissionCheckerTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package org.jenkinsci.plugins.configfiles.sec; | ||
|
||
import jenkins.model.Jenkins; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.jvnet.hudson.test.JenkinsRule; | ||
import org.jvnet.hudson.test.MockAuthorizationStrategy; | ||
|
||
public class PermissionCheckerTests { | ||
@Rule | ||
public JenkinsRule r = new JenkinsRule(); | ||
|
||
@Before | ||
public void setUpAuthorizationAndProject() { | ||
r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); | ||
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy(). | ||
grant(Jenkins.READ).everywhere().to("reader"). | ||
grant(Jenkins.ADMINISTER).everywhere().to("administer") | ||
); | ||
} | ||
|
||
@Test | ||
public void protectedCodeCheckerTest() { | ||
Runnable run = () -> r.jenkins.checkPermission(Jenkins.ADMINISTER); | ||
|
||
// The administer passes | ||
PermissionChecker checker = new PermissionChecker(run, "administer"); | ||
checker.assertPass(); | ||
|
||
// The reader fails | ||
checker.withUser("reader").assertFailWithPermission(Jenkins.ADMINISTER); | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
src/test/java/org/jenkinsci/plugins/configfiles/sec/ProtectedCodeRunner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package org.jenkinsci.plugins.configfiles.sec; | ||
|
||
import edu.umd.cs.findbugs.annotations.NonNull; | ||
import hudson.model.User; | ||
import hudson.security.ACL; | ||
import hudson.security.ACLContext; | ||
|
||
import java.util.function.Supplier; | ||
|
||
import static org.junit.Assert.fail; | ||
|
||
/** | ||
* Class to run a code returning something with a specific user. You can get the result or the {@link Throwable} thrown | ||
* by the code executed. Afterwards you can assert the result or the exception thrown. | ||
* @param <Result> | ||
*/ | ||
public class ProtectedCodeRunner<Result> { | ||
@NonNull | ||
private final Supplier<Result> code; | ||
@NonNull | ||
private String user; | ||
|
||
/** | ||
* Create an object to run this piece of code with this Jenkins user. | ||
* @param code The code to be executed. | ||
* @param user The user executing this code. | ||
*/ | ||
public ProtectedCodeRunner(@NonNull Supplier<Result> code, @NonNull String user) { | ||
this.code = code; | ||
this.user = user; | ||
} | ||
|
||
/** | ||
* We run the code expecting to get a result. If the execution throws an exception (Throwable), the test fails with | ||
* a descriptive message. | ||
* @return The result of the execution. | ||
*/ | ||
public Result getResult() { | ||
try (ACLContext ctx = ACL.as(User.getOrCreateByIdOrFullName(user))) { | ||
return code.get(); | ||
} catch (Throwable t) { | ||
fail(String.format("The code executed by %s didn't run successfully. The throwable thrown is: %s", user, t)); | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* We run the code expecting an exception to be thrown. If it's not the case, the test fails with a descriptive | ||
* message. | ||
* @return The {@link Throwable} thrown by the execution. | ||
*/ | ||
public Throwable getThrowable() { | ||
try (ACLContext ctx = ACL.as(User.getOrCreateByIdOrFullName(user))) { | ||
Result result = code.get(); | ||
fail(String.format("The code executed by %s was successful but we were expecting it to fail. The result of the execution was: %s", user, result)); | ||
return null; | ||
} catch (Throwable t) { | ||
return t; | ||
} | ||
} | ||
|
||
/** | ||
* Get the user. | ||
* @return The user. | ||
*/ | ||
public String getUser() { | ||
return user; | ||
} | ||
|
||
/** | ||
* Use a different user. | ||
* @param user The user. | ||
* @return This object. | ||
*/ | ||
public ProtectedCodeRunner<Result> withUser(String user) { | ||
this.user = user; | ||
return this; | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
src/test/java/org/jenkinsci/plugins/configfiles/sec/ProtectedCodeRunnerTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.jenkinsci.plugins.configfiles.sec; | ||
|
||
import hudson.security.AccessDeniedException2; | ||
import jenkins.model.Jenkins; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.jvnet.hudson.test.JenkinsRule; | ||
import org.jvnet.hudson.test.MockAuthorizationStrategy; | ||
|
||
import java.util.function.Supplier; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.Matchers.equalTo; | ||
import static org.hamcrest.Matchers.instanceOf; | ||
import static org.hamcrest.Matchers.is; | ||
|
||
/** | ||
* Check the {@link ProtectedCodeRunner} class works correctly. | ||
*/ | ||
public class ProtectedCodeRunnerTests { | ||
@Rule | ||
public JenkinsRule r = new JenkinsRule(); | ||
|
||
@Before | ||
public void setUpAuthorizationAndProject() { | ||
r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); | ||
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy(). | ||
grant(Jenkins.READ).everywhere().to("reader"). | ||
grant(Jenkins.ADMINISTER).everywhere().to("administer") | ||
); | ||
} | ||
|
||
@Test | ||
public void protectedCodeCheckerTest() { | ||
Supplier<String> supplier = () -> { | ||
r.jenkins.checkPermission(Jenkins.ADMINISTER); | ||
return "allowed"; | ||
}; | ||
|
||
ProtectedCodeRunner<String> checker = new ProtectedCodeRunner<>(supplier, "administer"); | ||
assertThat(checker.getResult(), is("allowed")); | ||
|
||
Throwable t = checker.withUser("reader").getThrowable(); | ||
assertThat(t, instanceOf(AccessDeniedException2.class)); | ||
assertThat(((AccessDeniedException2) t).permission, equalTo(Jenkins.ADMINISTER)); | ||
} | ||
} |
Oops, something went wrong.