Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JENKINS-61208 Allow system read to view more admin monitors #4685

Merged
merged 6 commits into from
May 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import hudson.RestrictedSince;
import hudson.Util;
import hudson.model.AdministrativeMonitor;
import hudson.security.Permission;
import jenkins.security.stapler.StaplerDispatchable;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
Expand Down Expand Up @@ -103,6 +104,11 @@ public void getTestForReverseProxySetup(String rest) {
}
}

@Override
public Permission getRequiredPermission() {
return Jenkins.SYSTEM_READ;
}

/**
* Depending on whether the user said "yes" or "no", send him to the right place.
*/
Expand All @@ -111,6 +117,7 @@ public void getTestForReverseProxySetup(String rest) {
@RequirePOST
public HttpResponse doAct(@QueryParameter String no) throws IOException {
if(no!=null) { // dismiss
Jenkins.get().checkPermission(Jenkins.ADMINISTER);
disable(true);
// of course the irony is that this redirect won't work
return HttpResponses.redirectViaContextPath("/manage");
Expand Down
15 changes: 13 additions & 2 deletions core/src/main/java/hudson/diagnosis/TooManyJobsButNoView.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package hudson.diagnosis;

import hudson.model.AdministrativeMonitor;
import hudson.security.Permission;
import jenkins.model.Jenkins;
import hudson.Extension;
import org.jenkinsci.Symbol;
Expand All @@ -50,15 +51,20 @@ public String getDisplayName() {
}

public boolean isActivated() {
Jenkins h = Jenkins.get();
return h.getViews().size()==1 && h.getItemMap().size()> THRESHOLD;
Jenkins j = Jenkins.get();
if (j.hasPermission(Jenkins.ADMINISTER)) {
return j.getViews().size() == 1 && j.getItemMap().size() > THRESHOLD;
}
// SystemRead
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or "Manage" soon, I suspect

return j.getViews().size() == 1 && j.getItems().size() > THRESHOLD;
}

/**
* Depending on whether the user said "yes" or "no", send him to the right place.
*/
@RequirePOST
public void doAct(StaplerRequest req, StaplerResponse rsp) throws IOException {
Jenkins.get().checkPermission(Jenkins.ADMINISTER);
if(req.hasParameter("no")) {
disable(true);
rsp.sendRedirect(req.getContextPath()+"/manage");
Expand All @@ -67,5 +73,10 @@ public void doAct(StaplerRequest req, StaplerResponse rsp) throws IOException {
}
}

@Override
public Permission getRequiredPermission() {
return Jenkins.SYSTEM_READ;
daniel-beck marked this conversation as resolved.
Show resolved Hide resolved
}

public static final int THRESHOLD = 16;
}
6 changes: 6 additions & 0 deletions core/src/main/java/hudson/model/UpdateCenter.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import hudson.PluginWrapper;
import hudson.ProxyConfiguration;
import hudson.security.ACLContext;
import hudson.security.Permission;
import hudson.util.VersionNumber;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
Expand Down Expand Up @@ -1111,6 +1112,11 @@ public Data getData() {
if (cs!=null) return cs.getData();
return null;
}

@Override
public Permission getRequiredPermission() {
return Jenkins.SYSTEM_READ;
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
import hudson.Extension;
import hudson.model.AdministrativeMonitor;
import hudson.model.DirectoryBrowserSupport;
import hudson.security.Permission;
import hudson.util.HttpResponses;
import jenkins.model.Jenkins;
import jenkins.util.SystemProperties;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
Expand Down Expand Up @@ -63,6 +65,7 @@ public boolean isActivated() {

@RequirePOST
public HttpResponse doAct(@QueryParameter String redirect, @QueryParameter String dismiss) throws IOException {
Jenkins.get().checkPermission(Jenkins.ADMINISTER);
if (dismiss != null) {
disable(true);
return HttpResponses.redirectViaContextPath("manage");
Expand All @@ -72,4 +75,9 @@ public HttpResponse doAct(@QueryParameter String redirect, @QueryParameter Strin
}
return HttpResponses.forwardToPreviousPage();
}

@Override
public Permission getRequiredPermission() {
return Jenkins.SYSTEM_READ;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import hudson.PluginWrapper;
import hudson.model.AdministrativeMonitor;
import hudson.model.UpdateSite;
import hudson.security.Permission;
import hudson.util.HttpResponses;
import jenkins.model.Jenkins;
import org.kohsuke.accmod.Restricted;
Expand Down Expand Up @@ -141,6 +142,7 @@ private Set<UpdateSite.Warning> getActiveWarnings() {
*/
@RequirePOST
public HttpResponse doForward(@QueryParameter String fix, @QueryParameter String configure) {
Jenkins.get().checkPermission(Jenkins.ADMINISTER);
if (fix != null) {
return HttpResponses.redirectViaContextPath("pluginManager");
}
Expand All @@ -162,6 +164,11 @@ public boolean hasApplicableHiddenWarnings() {
return getActiveWarnings().size() < configuration.getApplicableWarnings().size();
}

@Override
public Permission getRequiredPermission() {
return Jenkins.SYSTEM_READ;
daniel-beck marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public String getDisplayName() {
return Messages.UpdateSiteWarningsMonitor_DisplayName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:f="/lib/form">
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:f="/lib/form" xmlns:l="/lib/layout">
<div id="redirect-error" class="alert alert-danger reverse-proxy__hidden"
data-url="${rootURL}/${it.url}/test" data-context="${rootURL}">
<form method="post" action="${rootURL}/${it.url}/act" name="${it.id}">
<f:submit name="yes" value="${%More Info}"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this one allow to submit the yes? SYSTEM_READ does have access to view the information the button is redirecting to?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any problem if a non-admin user can see the More Info button. It's not configuring anything if IIRC

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<f:submit name="no" value="${%Dismiss}"/>
<l:isAdmin>
<f:submit name="no" value="${%Dismiss}"/>
</l:isAdmin>
</form>
<div>${%blurb}</div>
<div class="js-context-message reverse-proxy__hidden">${%missingContextMessage(rootURL)}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ THE SOFTWARE.

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<div class="alert alert-warning">
<form method="post" action="${rootURL}/${it.url}/act" name="${it.id}">
<f:submit name="yes" value="${%Create a view now}"/>
<f:submit name="no" value="${%Dismiss}"/>
</form>
<div id="tooManyJobsButNoView" class="alert alert-warning">
<l:isAdmin>
<form method="post" action="${rootURL}/${it.url}/act" name="${it.id}">
<f:submit name="yes" value="${%Create a view now}"/>
<f:submit name="no" value="${%Dismiss}"/>
</form>
</l:isAdmin>
${%blurb}
</div>
</j:jelly>
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@
package jenkins.security.ResourceDomainRecommendation

def f = namespace(lib.FormTagLib)
def l = namespace(lib.LayoutTagLib)

dl {
div(class: "alert alert-info") {
a(name: "resource-root-url")
form(method: "post", action: "${rootURL}/${my.url}/act") {
f.submit(name: 'redirect', value: _("Go to resource root URL configuration"))
f.submit(name: 'dismiss', value: _("Dismiss"))

l.isAdmin() {
form(method: "post", action: "${rootURL}/${my.url}/act") {
f.submit(name: 'redirect', value: _("Go to resource root URL configuration"))
f.submit(name: 'dismiss', value: _("Dismiss"))
}
}

raw(_("blurb"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package jenkins.security.UpdateSiteWarningsMonitor

def f = namespace(lib.FormTagLib)
def l = namespace(lib.LayoutTagLib)

def listWarnings(warnings) {
warnings.each { warning ->
Expand All @@ -39,11 +40,13 @@ def pluginWarnings = my.activePluginWarningsByPlugin

div(class: "alert alert-danger", role: "alert") {

form(method: "post", action: "${rootURL}/${my.url}/forward") {
if (!pluginWarnings.isEmpty()) {
f.submit(name: 'fix', value: _("pluginManager.link"))
l.isAdmin() {
form(method: "post", action: "${rootURL}/${my.url}/forward") {
if (!pluginWarnings.isEmpty()) {
f.submit(name: 'fix', value: _("pluginManager.link"))
}
f.submit(name: 'configure', value: _("configureSecurity.link"))
}
f.submit(name: 'configure', value: _("configureSecurity.link"))
}

text(_("blurb"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
package hudson.diagnosis;

import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.model.AdministrativeMonitor;
import hudson.model.Item;
import hudson.model.ListView;
import hudson.model.View;
import java.io.IOException;
import java.net.URL;
import static org.junit.Assert.*;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

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 org.xml.sax.SAXException;

/**
Expand Down Expand Up @@ -67,4 +81,58 @@ private void verifyNoForm() throws IOException, SAXException {

verifyNoForm();
}

@Test
public void systemReadNoViewAccessVerifyNoForm() throws Exception {
final String READONLY = "readonly";

r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy()
.grant(Jenkins.READ).everywhere().to(READONLY)
.grant(Jenkins.SYSTEM_READ).everywhere().to(READONLY)
);

for (int i = 0; i <= TooManyJobsButNoView.THRESHOLD; i++)
r.createFreeStyleProject();

JenkinsRule.WebClient wc = r.createWebClient();
wc.login(READONLY);

verifyNoMonitor(wc);
}

private void verifyNoMonitor(JenkinsRule.WebClient wc) throws IOException, SAXException {
HtmlPage p = wc.goTo("manage");
DomElement adminMonitorDiv = p.getElementById("tooManyJobsButNoView");
assertThat(adminMonitorDiv, is(nullValue()));
}

@Test
public void systemReadVerifyForm() throws Exception {
final String READONLY = "readonly";

r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy()
.grant(Jenkins.READ).everywhere().to(READONLY)
.grant(Jenkins.SYSTEM_READ).everywhere().to(READONLY)
.grant(Item.READ).everywhere().to(READONLY)
.grant(View.READ).everywhere().to(READONLY)
);

for (int i = 0; i <= TooManyJobsButNoView.THRESHOLD; i++)
r.createFreeStyleProject();

JenkinsRule.WebClient wc = r.createWebClient();
wc.login(READONLY);

verifyMonitor(wc);
}

private void verifyMonitor(JenkinsRule.WebClient wc) throws IOException, SAXException {
HtmlPage p = wc.goTo("manage");
DomElement adminMonitorDiv = p.getElementById("tooManyJobsButNoView");
assertThat(adminMonitorDiv, is(notNullValue()));
assertThat(adminMonitorDiv.getTextContent(), is(notNullValue()));
}

}