diff --git a/core/src/main/java/hudson/logging/LogRecorder.java b/core/src/main/java/hudson/logging/LogRecorder.java index c6ec3e1b41..a2a233df07 100644 --- a/core/src/main/java/hudson/logging/LogRecorder.java +++ b/core/src/main/java/hudson/logging/LogRecorder.java @@ -68,7 +68,7 @@ import org.kohsuke.stapler.verb.POST; * TODO: still a work in progress. * *

Access Control

- * {@link LogRecorder} is only visible for administrators, and this access control happens at + * {@link LogRecorder} is only visible for administrators and system readers, and this access control happens at * {@link jenkins.model.Jenkins#getLog()}, the sole entry point for binding {@link LogRecorder} to URL. * * @author Kohsuke Kawaguchi @@ -332,6 +332,8 @@ public class LogRecorder extends AbstractModelObject implements Saveable { */ @POST public synchronized void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + JSONObject src = req.getSubmittedForm(); String newName = src.getString("name"), redirect = "."; @@ -358,6 +360,8 @@ public class LogRecorder extends AbstractModelObject implements Saveable { @RequirePOST public HttpResponse doClear() throws IOException { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + handler.clear(); return HttpResponses.redirectToDot(); } @@ -385,6 +389,8 @@ public class LogRecorder extends AbstractModelObject implements Saveable { */ @RequirePOST public synchronized void doDoDelete(StaplerResponse rsp) throws IOException, ServletException { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + getConfigFile().delete(); getParent().logRecorders.remove(name); // Disable logging for all our targets, diff --git a/core/src/main/java/hudson/logging/LogRecorderManager.java b/core/src/main/java/hudson/logging/LogRecorderManager.java index 4bf9730f3a..c74159049d 100644 --- a/core/src/main/java/hudson/logging/LogRecorderManager.java +++ b/core/src/main/java/hudson/logging/LogRecorderManager.java @@ -112,6 +112,8 @@ public class LogRecorderManager extends AbstractModelObject implements ModelObje */ @RequirePOST public HttpResponse doNewLogRecorder(@QueryParameter String name) { + Jenkins.get().checkPermission(Jenkins.ADMINISTER); + Jenkins.checkGoodName(name); logRecorders.put(name,new LogRecorder(name)); @@ -208,7 +210,7 @@ public class LogRecorderManager extends AbstractModelObject implements ModelObje @Restricted(NoExternalUse.class) public Object getTarget() { if (!SKIP_PERMISSION_CHECK) { - Jenkins.get().checkPermission(Jenkins.ADMINISTER); + Jenkins.get().checkPermission(Jenkins.SYSTEM_READ); } return this; } diff --git a/core/src/main/java/jenkins/management/SystemLogLink.java b/core/src/main/java/jenkins/management/SystemLogLink.java index f8c8e9e791..35fadad9fd 100644 --- a/core/src/main/java/jenkins/management/SystemLogLink.java +++ b/core/src/main/java/jenkins/management/SystemLogLink.java @@ -26,6 +26,8 @@ package jenkins.management; import hudson.Extension; import hudson.model.ManagementLink; +import hudson.security.Permission; +import jenkins.model.Jenkins; import org.jenkinsci.Symbol; import edu.umd.cs.findbugs.annotations.NonNull; @@ -55,6 +57,12 @@ public class SystemLogLink extends ManagementLink { return "log"; } + @NonNull + @Override + public Permission getRequiredPermission() { + return Jenkins.SYSTEM_READ; + } + @NonNull @Override public Category getCategory() { diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java index dfca35b678..36ce41cbf6 100644 --- a/core/src/main/java/jenkins/model/Jenkins.java +++ b/core/src/main/java/jenkins/model/Jenkins.java @@ -2559,7 +2559,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve * Everything below here is admin-only, so do the check here. */ public LogRecorderManager getLog() { - checkPermission(ADMINISTER); + checkPermission(SYSTEM_READ); return log; } diff --git a/core/src/main/resources/hudson/logging/LogRecorder/configure.jelly b/core/src/main/resources/hudson/logging/LogRecorder/configure.jelly index 6b2dbb9b1e..e1da3dfeb5 100644 --- a/core/src/main/resources/hudson/logging/LogRecorder/configure.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorder/configure.jelly @@ -27,9 +27,16 @@ THE SOFTWARE. --> - + +

${%Configure log recorder}

+

+ ${%Enter the name of the logger you want to enable}. +

+
+ ${%fine_warning} +
@@ -74,4 +81,4 @@ THE SOFTWARE.
-
\ No newline at end of file + diff --git a/core/src/main/resources/hudson/logging/LogRecorder/configure.properties b/core/src/main/resources/hudson/logging/LogRecorder/configure.properties new file mode 100644 index 0000000000..4b41a5d3f2 --- /dev/null +++ b/core/src/main/resources/hudson/logging/LogRecorder/configure.properties @@ -0,0 +1 @@ +fine_warning=Loggers that record messages at FINE, FINER, or even FINEST can cause performance issues when many messages are being logged. Additionally, more verbose log levels increase the likelihood of credentials being logged. It is recommended that you delete such loggers, or update them to a less verbose level, when you no longer need them. diff --git a/core/src/main/resources/hudson/logging/LogRecorder/delete.jelly b/core/src/main/resources/hudson/logging/LogRecorder/delete.jelly index 646f21523b..1dabebcd88 100644 --- a/core/src/main/resources/hudson/logging/LogRecorder/delete.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorder/delete.jelly @@ -27,7 +27,7 @@ THE SOFTWARE. --> - +
diff --git a/core/src/main/resources/hudson/logging/LogRecorder/index.jelly b/core/src/main/resources/hudson/logging/LogRecorder/index.jelly index a413db503c..34e2525d04 100644 --- a/core/src/main/resources/hudson/logging/LogRecorder/index.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorder/index.jelly @@ -27,7 +27,7 @@ THE SOFTWARE. --> - +

${it.displayName}

@@ -37,9 +37,11 @@ THE SOFTWARE. - - - + +
+ + +
diff --git a/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly b/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly index 686f05cf7e..e0460aea64 100644 --- a/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly @@ -32,8 +32,10 @@ THE SOFTWARE. - - + + + +
\ No newline at end of file diff --git a/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly b/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly index 1eb55cf888..3b69ab6489 100644 --- a/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly @@ -58,15 +58,19 @@ THE SOFTWARE. - - - + + + + + -
- - + +
+ + +
diff --git a/core/src/main/resources/hudson/logging/LogRecorderManager/levels.jelly b/core/src/main/resources/hudson/logging/LogRecorderManager/levels.jelly index 4a4de33506..fb349850a7 100644 --- a/core/src/main/resources/hudson/logging/LogRecorderManager/levels.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorderManager/levels.jelly @@ -51,25 +51,27 @@ THE SOFTWARE.

${%defaultLoggerMsg}

-

${%Adjust Levels}

-
- ${%Name}: - ${%Level}: - - - - + +

${%Adjust Levels}

+
+ ${%Name}: + ${%Level}: + + + + +
diff --git a/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly b/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly index f15d0032c5..1e08f2b659 100644 --- a/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly @@ -33,7 +33,9 @@ THE SOFTWARE. - + + + diff --git a/core/src/test/java/hudson/logging/LogRecorderTest.java b/core/src/test/java/hudson/logging/LogRecorderTest.java index 394a8f42e9..bbb146a637 100644 --- a/core/src/test/java/hudson/logging/LogRecorderTest.java +++ b/core/src/test/java/hudson/logging/LogRecorderTest.java @@ -30,10 +30,21 @@ import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.LogRecord; +import jenkins.model.Jenkins; import org.junit.Test; import static org.junit.Assert.*; -import org.jvnet.hudson.test.Issue; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; +import org.junit.runner.RunWith; +import org.jvnet.hudson.test.Issue; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*"}) +@RunWith(PowerMockRunner.class) public class LogRecorderTest { @Issue("JENKINS-17983") @@ -58,11 +69,13 @@ public class LogRecorderTest { assertFalse(matches("", "hudson.model.Hudson", Level.FINE)); } + @PrepareForTest(Jenkins.class) @Test public void testClearing() throws IOException { LogRecorder lr = new LogRecorder("foo"); LogRecorder.Target t = new LogRecorder.Target("", Level.FINE); lr.targets.add(t); + createMockJenkins(); LogRecord record = createLogRecord("jenkins", Level.INFO, "message"); lr.handler.publish(record); assertEquals(lr.handler.getView().get(0), record); @@ -73,6 +86,12 @@ public class LogRecorderTest { assertEquals(0, lr.handler.getView().size()); } + private void createMockJenkins() { + mockStatic(Jenkins.class); + Jenkins j = mock(Jenkins.class); + when(Jenkins.get()).thenReturn(j); + } + @Test public void testSpecificExclusion() { LogRecorder lr = new LogRecorder("foo");