Skip to content
Open
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d8a4191
SECURITY-771: Added an assertion for a page title.
A1exKH Sep 26, 2025
1fda975
SECURITY-771: Added a test for anonymous user.
A1exKH Sep 26, 2025
8b86aab
SECURITY-771: Updated the validation for user cannot see About Jenkin…
A1exKH Sep 26, 2025
37a51c7
SECURITY-771: Updated test's description in comments.
A1exKH Sep 26, 2025
8689f68
SECURITY-771: Improved method name.
A1exKH Sep 26, 2025
65d88a5
SECURITY-771: Improved implementation of tests to fix issue with Exce…
A1exKH Sep 27, 2025
ff25c03
SECURITY-771: Refactored code and split logic for positive and negati…
A1exKH Sep 27, 2025
e388c86
SECURITY-771: Refactored code. Created string constants.
A1exKH Sep 27, 2025
c0446cc
SECURITY-771: Refactored code. Created string constants for users.
A1exKH Sep 27, 2025
0c3d4f9
SECURITY-771: Fixed bug in the test.
A1exKH Sep 27, 2025
5e13a23
SECURITY-771: Refactored code. Updated method's names.
A1exKH Sep 27, 2025
ff0a44d
SECURITY-771: Refactored code. Implemented the usage of try-with-reso…
A1exKH Sep 27, 2025
343bcb2
SECURITY-771: Added missing trailing newline.
A1exKH Sep 27, 2025
3a89d66
SECURITY-771: Added missing test scenario for READ + SYSTEM_READ user…
A1exKH Sep 27, 2025
4cc01f5
Merge branch 'master' into SECURITY-771/Fix-test-logic
A1exKH Oct 2, 2025
8635a78
Merge branch 'master' into SECURITY-771/Fix-test-logic
A1exKH Oct 4, 2025
938074d
Merge branch 'master' into SECURITY-771/Fix-test-logic
A1exKH Oct 6, 2025
5a116b1
Merge branch 'master' into SECURITY-771/Fix-test-logic
A1exKH Oct 8, 2025
800708d
Merge branch 'master' into SECURITY-771/Fix-test-logic
A1exKH Oct 13, 2025
9b9a275
Merge branch 'master' into SECURITY-771/Fix-test-logic
A1exKH Oct 15, 2025
aaba461
Merge branch 'master' into SECURITY-771/Fix-test-logic
A1exKH Oct 17, 2025
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
146 changes: 96 additions & 50 deletions test/src/test/java/hudson/AboutJenkinsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,75 +45,121 @@ class AboutJenkinsTest {

private JenkinsRule j;

private static final String ABOUT_PAGE_URL = "about/";

private static final String ABOUT_PAGE_TITLE = "About Jenkins";
private static final String JENKINS_PAGE_TITLE = "Jenkins";
private static final String SIGN_IN_PAGE_TITLE = "Sign in";
private static final String MAVENIZED_DEPS_TEXT = "Mavenized dependencies";

private static final String ADMIN_USER = "admin";
private static final String MANAGER_USER = "manager";
private static final String MANAGER_READONLY_USER = "manager-readonly";
private static final String READ_AND_SYSTEM_READ_USER = "read-and-system-read";
private static final String READONLY_USER = "readonly";
private static final String REGULAR_USER = "user";

@BeforeEach
void setUp(JenkinsRule rule) {
j = rule;
setupTestAuthorization();
}

@Test
@Issue("SECURITY-771")
void onlyAdminOrManageOrSystemReadCanReadAbout() throws Exception {
final String ADMIN = "admin";
final String USER = "user";
final String MANAGER = "manager";
final String READONLY = "readonly";
final String MANAGER_READONLY = "manager-readonly";

private void setupTestAuthorization() {
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy()
// full access
.grant(Jenkins.ADMINISTER).everywhere().to(ADMIN)

// Read access
.grant(Jenkins.READ).everywhere().to(USER)
// admin full access
.grant(Jenkins.ADMINISTER).everywhere().to(ADMIN_USER)

// Read and Manage
.grant(Jenkins.READ).everywhere().to(MANAGER)
.grant(Jenkins.MANAGE).everywhere().to(MANAGER)

// Read and System read
.grant(Jenkins.READ).everywhere().to(READONLY)
.grant(Jenkins.SYSTEM_READ).everywhere().to(READONLY)
.grant(Jenkins.READ).everywhere().to(MANAGER_USER)
.grant(Jenkins.MANAGE).everywhere().to(MANAGER_USER)

// Read, Manage and System read
.grant(Jenkins.READ).everywhere().to(MANAGER_READONLY)
.grant(Jenkins.MANAGE).everywhere().to(MANAGER_READONLY)
.grant(Jenkins.SYSTEM_READ).everywhere().to(MANAGER_READONLY)
);
.grant(Jenkins.READ).everywhere().to(MANAGER_READONLY_USER)
.grant(Jenkins.MANAGE).everywhere().to(MANAGER_READONLY_USER)
.grant(Jenkins.SYSTEM_READ).everywhere().to(MANAGER_READONLY_USER)

JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
// Read and System read
.grant(Jenkins.READ).everywhere().to(READ_AND_SYSTEM_READ_USER)
.grant(Jenkins.SYSTEM_READ).everywhere().to(READ_AND_SYSTEM_READ_USER)

{ // user cannot see it
wc.login(USER);
HtmlPage page = wc.goTo("about/");
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, page.getWebResponse().getStatusCode());
}
// Read access only (should NOT access About Jenkins page)
.grant(Jenkins.READ).everywhere().to(REGULAR_USER)

{ // admin can access it
wc.login(ADMIN);
HtmlPage page = wc.goTo("about/");
assertEquals(HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode());
assertThat(page.getWebResponse().getContentAsString(), containsString("Mavenized dependencies"));
}
// System read-only (should NOT access About Jenkins page)
.grant(Jenkins.SYSTEM_READ).everywhere().to(READONLY_USER)
);
}

{ // manager can access it
wc.login(MANAGER);
HtmlPage page = wc.goTo("about/");
assertEquals(HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode());
private HtmlPage accessAsUser(String username) throws Exception {
try (JenkinsRule.WebClient webClient = j.createWebClient()) {
webClient.withThrowExceptionOnFailingStatusCode(false);
webClient.login(username);
return webClient.goTo(ABOUT_PAGE_URL);
}
}

{ // readonly can access it
wc.login(READONLY);
HtmlPage page = wc.goTo("about/");
assertEquals(HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode());
private HtmlPage accessAsAnonymous() throws Exception {
try (JenkinsRule.WebClient webClient = j.createWebClient()) {
webClient.withThrowExceptionOnFailingStatusCode(false);
return webClient.goTo(ABOUT_PAGE_URL);
}
}

{ // manager-readonly can access it
wc.login(MANAGER_READONLY);
HtmlPage page = wc.goTo("about/");
assertEquals(HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode());
}
/**
* Tests SECURITY-771: Access to About Jenkins page requires
* either ADMINISTER, MANAGE, or (READ + SYSTEM_READ) permissions.
* Basic READ or SYSTEM_READ alone should be not enough.
*/
@Test
@Issue("SECURITY-771")
void usersWithElevatedPermissionsCanSeeAboutPage() throws Exception {
// ADMINISTER permission: admin should see About Jenkins page
HtmlPage adminPage = accessAsUser(ADMIN_USER);
assertEquals(HttpURLConnection.HTTP_OK, adminPage.getWebResponse().getStatusCode());
assertThat(adminPage.getWebResponse().getContentAsString(), containsString(MAVENIZED_DEPS_TEXT));
assertThat(adminPage.getTitleText(), containsString(ABOUT_PAGE_TITLE));

// MANAGE permission: manager should see About Jenkins page
HtmlPage managerPage = accessAsUser(MANAGER_USER);
assertEquals(HttpURLConnection.HTTP_OK, managerPage.getWebResponse().getStatusCode());
assertThat(managerPage.getWebResponse().getContentAsString(), containsString(MAVENIZED_DEPS_TEXT));
assertThat(managerPage.getTitleText(), containsString(ABOUT_PAGE_TITLE));

// MANAGE + SYSTEM_READ permissions: manager-readonly should see About Jenkins page
HtmlPage managerReadonlyPage = accessAsUser(MANAGER_READONLY_USER);
assertEquals(HttpURLConnection.HTTP_OK, managerReadonlyPage.getWebResponse().getStatusCode());
assertThat(managerReadonlyPage.getWebResponse().getContentAsString(), containsString(MAVENIZED_DEPS_TEXT));
assertThat(managerReadonlyPage.getTitleText(), containsString(ABOUT_PAGE_TITLE));

// READ + SYSTEM_READ permissions: a combination should grant access to see About Jenkins page
HtmlPage readSystemReadPage = accessAsUser(READ_AND_SYSTEM_READ_USER);
assertEquals(HttpURLConnection.HTTP_OK, readSystemReadPage.getWebResponse().getStatusCode());
assertThat(readSystemReadPage.getWebResponse().getContentAsString(), containsString(MAVENIZED_DEPS_TEXT));
assertThat(readSystemReadPage.getTitleText(), containsString(ABOUT_PAGE_TITLE));
}

/**
* Tests that users with insufficient permissions (anonymous, READ-only,
* or SYSTEM_READ-only) are properly denied access to About Jenkins page.
*/
@Test
@Issue("SECURITY-771")
void usersWithBasicPermissionsCannotSeeAboutPage() throws Exception {
// anonymous user should not see About Jenkins page -> redirect to sign in page
HtmlPage anonymousPage = accessAsAnonymous();
assertEquals(HttpURLConnection.HTTP_OK, anonymousPage.getWebResponse().getStatusCode());
assertThat(anonymousPage.getTitleText(), containsString(SIGN_IN_PAGE_TITLE));

// only READ permission: user should not see About Jenkins page -> redirect to Access Denied Jenkins page
HtmlPage userPage = accessAsUser(REGULAR_USER);
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, userPage.getWebResponse().getStatusCode());
assertThat(userPage.getTitleText(), containsString(JENKINS_PAGE_TITLE));

// SYSTEM_READ permission: readonly should not see About Jenkins page -> redirect to Access Denied Jenkins page
HtmlPage readonlyPage = accessAsUser(READONLY_USER);
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, readonlyPage.getWebResponse().getStatusCode());
assertThat(readonlyPage.getTitleText(), containsString(JENKINS_PAGE_TITLE));
}
}
Loading