提交 4fd4bd3a 编写于 作者: J Jesse Glick 提交者: GitHub

Merge pull request #2790 from jglick/security-settings-save

Save after calling setSecurityRealm or setAuthorizationStrategy
......@@ -128,7 +128,7 @@ public class SetupWizard extends PageDecorator {
jenkins.getInjector().getInstance(AdminWhitelistRule.class)
.setMasterKillSwitch(false);
jenkins.save(); // !!
jenkins.save(); // TODO could probably be removed since some of the above setters already call save
bc.commit();
}
}
......
......@@ -2534,6 +2534,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
// for binary compatibility, this method cannot throw a checked exception
throw new AcegiSecurityException("Failed to configure filter",e) {};
}
saveQuietly();
}
public void setAuthorizationStrategy(AuthorizationStrategy a) {
......@@ -2541,6 +2542,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
a = AuthorizationStrategy.UNSECURED;
useSecurity = true;
authorizationStrategy = a;
saveQuietly();
}
public boolean isDisableRememberMe() {
......@@ -3146,6 +3148,13 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
SaveableListener.fireOnChange(this, getConfigFile());
}
private void saveQuietly() {
try {
save();
} catch (IOException x) {
LOGGER.log(Level.WARNING, null, x);
}
}
/**
* Called to shut down the system.
......
......@@ -9,6 +9,7 @@ import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices
import org.acegisecurity.userdetails.User
import org.acegisecurity.userdetails.UserDetails
import org.acegisecurity.userdetails.UsernameNotFoundException
import org.junit.Before
import com.gargoylesoftware.htmlunit.util.Cookie
import org.junit.Rule
import org.junit.Test
......@@ -33,7 +34,10 @@ class TokenBasedRememberMeServices2Test {
@Rule
public LoggerRule logging = new LoggerRule()
private boolean failureInduced;
private static boolean failureInduced;
@Before
public void resetFailureInduced() {failureInduced = false}
@Test
public void rememberMeAutoLoginFailure() {
......@@ -66,7 +70,7 @@ class TokenBasedRememberMeServices2Test {
wc.cookieManager.getCookie(TokenBasedRememberMeServices2.ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY)
}
private class InvalidUserWhenLoggingBackInRealm extends AbstractPasswordBasedSecurityRealm {
private static class InvalidUserWhenLoggingBackInRealm extends AbstractPasswordBasedSecurityRealm {
@Override
protected UserDetails authenticate(String username, String password) throws AuthenticationException {
if (username==password)
......@@ -115,7 +119,7 @@ class TokenBasedRememberMeServices2Test {
}
}
private class StupidRealm extends InvalidUserWhenLoggingBackInRealm {
private static class StupidRealm extends InvalidUserWhenLoggingBackInRealm {
@Override
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
failureInduced = true
......
......@@ -106,12 +106,13 @@ public class ConnectNodeCommandTest {
@Test public void connectNodeShouldSucceedWithForce() throws Exception {
DumbSlave slave = j.createSlave("aNode", "", null);
slave.toComputer().connect(false).get(); // avoid a race condition in the test
CLICommandInvoker.Result result = command
.authorizedTo(Computer.CONNECT, Jenkins.READ)
.invokeWithArgs("-f", "aNode");
assertThat(result, succeededSilently());
assertThat(slave.toComputer().isOnline(), equalTo(true));
assertThat(slave.toComputer().getLog(), result, succeededSilently());
assertThat(slave.toComputer().getLog(), slave.toComputer().isOnline(), equalTo(true));
result = command
.authorizedTo(Computer.CONNECT, Jenkins.READ)
......
......@@ -25,18 +25,10 @@
package hudson.cli;
import static hudson.cli.CLICommandInvoker.Matcher.*;
import hudson.model.AbstractItem;
import hudson.model.FreeStyleProject;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.AuthorizationStrategy;
import hudson.security.SparseACL;
import java.util.Collection;
import java.util.Collections;
import jenkins.model.Jenkins;
import org.acegisecurity.acls.sid.PrincipalSid;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.*;
import org.junit.Before;
......@@ -44,6 +36,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.MockFolder;
public class CopyJobCommandTest {
......@@ -76,51 +69,12 @@ public class CopyJobCommandTest {
final FreeStyleProject p = d1.createProject(FreeStyleProject.class, "p");
final MockFolder d2 = j.createFolder("d2");
// alice has no real permissions. bob has READ on everything but no more. charlie has CREATE on d2 but not EXTENDED_READ on p. debbie has both.
final SparseACL rootACL = new SparseACL(null);
rootACL.add(new PrincipalSid("alice"), Jenkins.READ, true);
rootACL.add(new PrincipalSid("bob"), Jenkins.READ, true);
rootACL.add(new PrincipalSid("charlie"), Jenkins.READ, true);
rootACL.add(new PrincipalSid("debbie"), Jenkins.READ, true);
final SparseACL d1ACL = new SparseACL(null);
d1ACL.add(new PrincipalSid("bob"), Item.READ, true);
d1ACL.add(new PrincipalSid("charlie"), Item.READ, true);
d1ACL.add(new PrincipalSid("debbie"), Item.READ, true);
final SparseACL pACL = new SparseACL(null);
pACL.add(new PrincipalSid("bob"), Item.READ, true);
pACL.add(new PrincipalSid("charlie"), Item.READ, true);
pACL.add(new PrincipalSid("debbie"), Item.READ, true);
pACL.add(new PrincipalSid("debbie"), Item.EXTENDED_READ, true);
final SparseACL d2ACL = new SparseACL(null);
d2ACL.add(new PrincipalSid("bob"), Item.READ, true);
d2ACL.add(new PrincipalSid("charlie"), Item.READ, true);
d2ACL.add(new PrincipalSid("charlie"), Item.CREATE, true);
d2ACL.add(new PrincipalSid("debbie"), Item.READ, true);
d2ACL.add(new PrincipalSid("debbie"), Item.CREATE, true);
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(new AuthorizationStrategy() {
@Override public ACL getRootACL() {
return rootACL;
}
@Override public ACL getACL(Job<?, ?> project) {
if (project == p) {
return pACL;
} else {
throw new AssertionError(project);
}
}
@Override public ACL getACL(AbstractItem item) {
if (item == d1) {
return d1ACL;
} else if (item == d2) {
return d2ACL;
} else {
throw new AssertionError(item);
}
}
@Override public Collection<String> getGroups() {
return Collections.emptySet();
}
});
j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().
grant(Jenkins.READ).everywhere().toAuthenticated(). // including alice
grant(Item.READ).onItems(d1, p, d2).to("bob", "charlie", "debbie").
grant(Item.CREATE).onItems(d2).to("charlie", "debbie").
grant(Item.EXTENDED_READ).onItems(p).to("debbie"));
copyJobCommand.setTransportAuth(User.get("alice").impersonate());
assertThat(command.invokeWithArgs("d1/p", "d2/p"), failedWith(3));
copyJobCommand.setTransportAuth(User.get("bob").impersonate());
......
......@@ -26,23 +26,17 @@ package hudson.cli;
import static hudson.cli.CLICommandInvoker.Matcher.failedWith;
import static hudson.cli.CLICommandInvoker.Matcher.succeededSilently;
import hudson.model.AbstractItem;
import hudson.model.Item;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.AuthorizationStrategy;
import hudson.security.SparseACL;
import java.io.ByteArrayInputStream;
import java.util.Collection;
import java.util.Collections;
import jenkins.model.Jenkins;
import org.acegisecurity.acls.sid.PrincipalSid;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.MockFolder;
public class CreateJobCommandTest {
......@@ -54,29 +48,11 @@ public class CreateJobCommandTest {
CLICommand cmd = new CreateJobCommand();
CLICommandInvoker invoker = new CLICommandInvoker(r, cmd);
final MockFolder d = r.createFolder("d");
final SparseACL rootACL = new SparseACL(null);
rootACL.add(new PrincipalSid("alice"), Jenkins.READ, true);
rootACL.add(new PrincipalSid("bob"), Jenkins.READ, true);
final SparseACL dACL = new SparseACL(null);
dACL.add(new PrincipalSid("alice"), Item.READ, true);
dACL.add(new PrincipalSid("bob"), Item.READ, true);
dACL.add(new PrincipalSid("bob"), Item.CREATE, true);
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
r.jenkins.setAuthorizationStrategy(new AuthorizationStrategy() {
@Override public ACL getRootACL() {
return rootACL;
}
@Override public ACL getACL(AbstractItem item) {
if (item == d) {
return dACL;
} else {
throw new AssertionError(item);
}
}
@Override public Collection<String> getGroups() {
return Collections.emptySet();
}
});
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().
grant(Jenkins.READ).everywhere().toAuthenticated().
grant(Item.READ).onItems(d).toAuthenticated(). // including alice
grant(Item.CREATE).onItems(d).to("bob"));
cmd.setTransportAuth(User.get("alice").impersonate());
assertThat(invoker.withStdin(new ByteArrayInputStream("<project/>".getBytes("US-ASCII"))).invokeWithArgs("d/p"), failedWith(6));
cmd.setTransportAuth(User.get("bob").impersonate());
......
......@@ -48,6 +48,7 @@ import static hudson.cli.CLICommandInvoker.Matcher.succeededSilently;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
/**
* @author pjanouse
......@@ -59,13 +60,17 @@ public class ReloadConfigurationCommandTest {
@Rule public final JenkinsRule j = new JenkinsRule();
@Before public void setUp() {
command = new CLICommandInvoker(j, "reload-configuration");
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
ReloadConfigurationCommand cmd = new ReloadConfigurationCommand();
cmd.setTransportAuth(User.get("user").impersonate()); // TODO https://github.com/jenkinsci/jenkins-test-harness/pull/53 use CLICommandInvoker.asUser
command = new CLICommandInvoker(j, cmd);
j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().grant(Jenkins.ADMINISTER).everywhere().toAuthenticated());
}
@Test
public void reloadConfigurationShouldFailWithoutAdministerPermission() throws Exception {
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.READ).invoke();
j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().grant(Jenkins.READ).everywhere().toAuthenticated());
final CLICommandInvoker.Result result = command.invoke();
assertThat(result, failedWith(6));
assertThat(result, hasNoStandardOutput());
......@@ -165,8 +170,7 @@ public class ReloadConfigurationCommandTest {
}
private void reloadJenkinsConfigurationViaCliAndWait() throws Exception {
final CLICommandInvoker.Result result = command
.authorizedTo(Jenkins.READ, Jenkins.ADMINISTER).invoke();
final CLICommandInvoker.Result result = command.invoke();
assertThat(result, succeededSilently());
......
......@@ -120,7 +120,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeFalse;
/**
* @author Kohsuke Kawaguchi
......@@ -631,21 +630,7 @@ public class QueueTest {
// scheduling algorithm would prefer running the same job on the same node
// kutzi: 'prefer' != 'enforce', therefore disabled this assertion: assertSame(b1.getBuiltOn(),b2.getBuiltOn());
// ACL that allow anyone to do anything except Alice can't build.
final SparseACL aliceCantBuild = new SparseACL(null);
aliceCantBuild.add(new PrincipalSid(alice), Computer.BUILD, false);
aliceCantBuild.add(new PrincipalSid("anonymous"), Jenkins.ADMINISTER, true);
GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy() {
@Override
public ACL getACL(Node node) {
if (node==b1.getBuiltOn())
return aliceCantBuild;
return super.getACL(node);
}
};
auth.add(Jenkins.ADMINISTER,"anonymous");
r.jenkins.setAuthorizationStrategy(auth);
r.jenkins.setAuthorizationStrategy(new AliceCannotBuild(b1.getBuiltOnStr()));
// now that we prohibit alice to do a build on the same node, the build should run elsewhere
for (int i=0; i<3; i++) {
......@@ -653,6 +638,24 @@ public class QueueTest {
assertNotSame(b3.getBuiltOnStr(), b1.getBuiltOnStr());
}
}
private static class AliceCannotBuild extends GlobalMatrixAuthorizationStrategy {
private final String blocked;
AliceCannotBuild(String blocked) {
add(Jenkins.ADMINISTER, "anonymous");
this.blocked = blocked;
}
@Override
public ACL getACL(Node node) {
if (node.getNodeName().equals(blocked)) {
// ACL that allow anyone to do anything except Alice can't build.
SparseACL acl = new SparseACL(null);
acl.add(new PrincipalSid(alice), Computer.BUILD, false);
acl.add(new PrincipalSid("anonymous"), Jenkins.ADMINISTER, true);
return acl;
}
return super.getACL(node);
}
}
@Test public void pendingsConsistenceAfterErrorDuringMaintain() throws IOException, ExecutionException, InterruptedException{
FreeStyleProject project1 = r.createFreeStyleProject();
......@@ -763,7 +766,6 @@ public class QueueTest {
@Test public void testBlockBuildWhenUpstreamBuildingLock() throws Exception {
final String prefix = "JENKINS-27871";
r.getInstance().setNumExecutors(4);
r.getInstance().save();
final FreeStyleProject projectA = r.createFreeStyleProject(prefix+"A");
projectA.getBuildersList().add(new SleepBuilder(5000));
......
......@@ -179,12 +179,7 @@ public class UserTest {
@Test
public void caseInsensitivity() {
j.jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(true, false, null){
@Override
public IdStrategy getUserIdStrategy() {
return new IdStrategy.CaseInsensitive();
}
});
j.jenkins.setSecurityRealm(new IdStrategySpecifyingSecurityRealm(new IdStrategy.CaseInsensitive()));
User user = User.get("john smith");
User user2 = User.get("John Smith");
assertSame("Users should have the same id.", user.getId(), user2.getId());
......@@ -194,12 +189,7 @@ public class UserTest {
@Test
public void caseSensitivity() {
j.jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(true, false, null){
@Override
public IdStrategy getUserIdStrategy() {
return new IdStrategy.CaseSensitive();
}
});
j.jenkins.setSecurityRealm(new IdStrategySpecifyingSecurityRealm(new IdStrategy.CaseSensitive()));
User user = User.get("john smith");
User user2 = User.get("John Smith");
assertNotSame("Users should not have the same id.", user.getId(), user2.getId());
......@@ -213,12 +203,7 @@ public class UserTest {
@Test
public void caseSensitivityEmail() {
j.jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(true, false, null){
@Override
public IdStrategy getUserIdStrategy() {
return new IdStrategy.CaseSensitiveEmailAddress();
}
});
j.jenkins.setSecurityRealm(new IdStrategySpecifyingSecurityRealm(new IdStrategy.CaseSensitiveEmailAddress()));
User user = User.get("john.smith@acme.org");
User user2 = User.get("John.Smith@acme.org");
assertNotSame("Users should not have the same id.", user.getId(), user2.getId());
......@@ -234,6 +219,18 @@ public class UserTest {
assertEquals(user2.getId(), User.idStrategy().idFromFilename(User.idStrategy().filenameOf(user2.getId())));
}
private static class IdStrategySpecifyingSecurityRealm extends HudsonPrivateSecurityRealm {
private final IdStrategy idStrategy;
IdStrategySpecifyingSecurityRealm(IdStrategy idStrategy) {
super(true, false, null);
this.idStrategy = idStrategy;
}
@Override
public IdStrategy getUserIdStrategy() {
return idStrategy;
}
}
@Issue("JENKINS-24317")
@LocalData
@Test public void migration() throws Exception {
......
......@@ -58,8 +58,6 @@ import hudson.util.HttpResponses;
import hudson.model.FreeStyleProject;
import hudson.model.TaskListener;
import hudson.security.GlobalMatrixAuthorizationStrategy;
import hudson.security.LegacySecurityRealm;
import hudson.security.Permission;
import hudson.slaves.ComputerListener;
import hudson.slaves.DumbSlave;
import hudson.slaves.OfflineCause;
......@@ -79,12 +77,12 @@ import org.mockito.Mockito;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.junit.Assume;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
/**
* @author kingfai
......@@ -306,17 +304,11 @@ public class JenkinsTest {
@Test
public void testDoScript() throws Exception {
j.jenkins.setSecurityRealm(new LegacySecurityRealm());
GlobalMatrixAuthorizationStrategy gmas = new GlobalMatrixAuthorizationStrategy() {
@Override public boolean hasPermission(String sid, Permission p) {
return p == Jenkins.RUN_SCRIPTS ? hasExplicitPermission(sid, p) : super.hasPermission(sid, p);
}
};
gmas.add(Jenkins.ADMINISTER, "alice");
gmas.add(Jenkins.RUN_SCRIPTS, "alice");
gmas.add(Jenkins.READ, "bob");
gmas.add(Jenkins.ADMINISTER, "charlie");
j.jenkins.setAuthorizationStrategy(gmas);
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().
grant(Jenkins.ADMINISTER).everywhere().to("alice").
grant(Jenkins.READ).everywhere().to("bob").
grantWithoutImplication(Jenkins.ADMINISTER, Jenkins.READ).everywhere().to("charlie"));
WebClient wc = j.createWebClient();
wc.login("alice");
wc.goTo("script");
......@@ -337,17 +329,11 @@ public class JenkinsTest {
@Test
public void testDoEval() throws Exception {
j.jenkins.setSecurityRealm(new LegacySecurityRealm());
GlobalMatrixAuthorizationStrategy gmas = new GlobalMatrixAuthorizationStrategy() {
@Override public boolean hasPermission(String sid, Permission p) {
return p == Jenkins.RUN_SCRIPTS ? hasExplicitPermission(sid, p) : super.hasPermission(sid, p);
}
};
gmas.add(Jenkins.ADMINISTER, "alice");
gmas.add(Jenkins.RUN_SCRIPTS, "alice");
gmas.add(Jenkins.READ, "bob");
gmas.add(Jenkins.ADMINISTER, "charlie");
j.jenkins.setAuthorizationStrategy(gmas);
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().
grant(Jenkins.ADMINISTER).everywhere().to("alice").
grant(Jenkins.READ).everywhere().to("bob").
grantWithoutImplication(Jenkins.ADMINISTER, Jenkins.READ).everywhere().to("charlie"));
WebClient wc = j.createWebClient();
wc.login("alice");
wc.assertFails("eval", HttpURLConnection.HTTP_BAD_METHOD);
......
......@@ -36,7 +36,6 @@ import hudson.model.Item;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
import hudson.model.User;
import hudson.security.GlobalMatrixAuthorizationStrategy;
import hudson.util.Secret;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
......@@ -53,6 +52,8 @@ import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.DataBoundConstructor;
......@@ -80,6 +81,7 @@ public class PasswordTest extends HudsonTestCase implements Describable<Password
@Issue({"SECURITY-266", "SECURITY-304"})
public void testExposedCiphertext() throws Exception {
boolean saveEnabled = Item.EXTENDED_READ.getEnabled();
Item.EXTENDED_READ.setEnabled(true);
try {
//final String plain_regex_match = ".*\\{[A-Za-z0-9+/]+={0,2}}.*";
......@@ -89,16 +91,12 @@ public class PasswordTest extends HudsonTestCase implements Describable<Password
//Just a quick verification on what could be on the page and that the regexp is correctly set up
assertThat(xml_regex_pattern.matcher(staticTest).find(), is(true));
jenkins.setSecurityRealm(createDummySecurityRealm());
// TODO 1.645+ use MockAuthorizationStrategy
GlobalMatrixAuthorizationStrategy pmas = new GlobalMatrixAuthorizationStrategy();
pmas.add(Jenkins.ADMINISTER, "admin");
pmas.add(Jenkins.READ, "dev");
pmas.add(Item.READ, "dev");
Item.EXTENDED_READ.setEnabled(true);
pmas.add(Item.EXTENDED_READ, "dev");
pmas.add(Item.CREATE, "dev"); // so we can show CopyJobCommand would barf; more realistic would be to grant it only in a subfolder
jenkins.setAuthorizationStrategy(pmas);
jenkins.setSecurityRealm(new JenkinsRule().createDummySecurityRealm());
jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().
grant(Jenkins.ADMINISTER).everywhere().to("admin").
grant(Jenkins.READ, Item.READ, Item.EXTENDED_READ,
Item.CREATE // so we can show CopyJobCommand would barf; more realistic would be to grant it only in a subfolder
).everywhere().to("dev"));
Secret s = Secret.fromString("s3cr3t");
//String sEnc = s.getEncryptedValue();
FreeStyleProject p = createFreeStyleProject("p");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册