authorities;
+ if (user != null) {
+ authorities = authToken.getAuthorities();
+ } else {
+ authorities = List.of();
+ }
+ return new GithubOAuthUserDetails(username, authorities);
}
try {
@@ -711,7 +724,7 @@ public UserDetails loadUserByUsername(String username)
return userDetails;
} catch (IOException | Error e) {
- throw new DataRetrievalFailureException("loadUserByUsername (username=" + username +")", e);
+ throw new AuthenticationServiceException("loadUserByUsername (username=" + username +")", e);
}
}
@@ -751,8 +764,8 @@ public int hashCode() {
* @return groupDetails
*/
@Override
- public GroupDetails loadGroupByGroupname(String groupName)
- throws UsernameNotFoundException, DataAccessException {
+ public GroupDetails loadGroupByGroupname2(String groupName, boolean fetchMembers)
+ throws UsernameNotFoundException {
GithubAuthenticationToken authToken = (GithubAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if(authToken == null)
@@ -778,7 +791,7 @@ public GroupDetails loadGroupByGroupname(String groupName)
return new GithubOAuthGroupDetails(ghOrg);
}
} catch (Error e) {
- throw new DataRetrievalFailureException("loadGroupByGroupname (groupname=" + groupName + ")", e);
+ throw new AuthenticationServiceException("loadGroupByGroupname (groupname=" + groupName + ")", e);
}
}
diff --git a/src/main/resources/org/jenkinsci/plugins/GithubAuthorizationStrategy/config.jelly b/src/main/resources/org/jenkinsci/plugins/GithubAuthorizationStrategy/config.jelly
index 2455a404..abd722d1 100644
--- a/src/main/resources/org/jenkinsci/plugins/GithubAuthorizationStrategy/config.jelly
+++ b/src/main/resources/org/jenkinsci/plugins/GithubAuthorizationStrategy/config.jelly
@@ -8,6 +8,10 @@
+
+
+
+
diff --git a/src/main/webapp/help/auth/agent-user-name-help.html b/src/main/webapp/help/auth/agent-user-name-help.html
new file mode 100644
index 00000000..eee865b0
--- /dev/null
+++ b/src/main/webapp/help/auth/agent-user-name-help.html
@@ -0,0 +1,3 @@
+
+If you are using inbound Jenkins agents, this is the user that is used for authenticating agents. This user will receive rights to create, connect and configure agents.
+
\ No newline at end of file
diff --git a/src/test/java/org/jenkinsci/plugins/GithubAccessTokenPropertySEC797Test.java b/src/test/java/org/jenkinsci/plugins/GithubAccessTokenPropertySEC797Test.java
index a270482e..7875afe1 100644
--- a/src/test/java/org/jenkinsci/plugins/GithubAccessTokenPropertySEC797Test.java
+++ b/src/test/java/org/jenkinsci/plugins/GithubAccessTokenPropertySEC797Test.java
@@ -23,156 +23,145 @@
*/
package org.jenkinsci.plugins;
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.WebRequest;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
import hudson.model.UnprotectedRootAction;
import hudson.util.HttpResponses;
-import java.util.Collections;
+import jakarta.servlet.http.HttpSession;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import org.eclipse.jetty.util.Fields;
+import org.eclipse.jetty.util.UrlEncoded;
+import org.htmlunit.Page;
+import org.htmlunit.WebRequest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
import org.kohsuke.stapler.HttpResponse;
-import org.kohsuke.stapler.StaplerRequest;
+import org.kohsuke.stapler.StaplerRequest2;
-import edu.umd.cs.findbugs.annotations.CheckForNull;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
//TODO merge with GithubAccessTokenPropertyTest after security release, just meant to ease the security merge
// or with GithubSecurityRealmTest, but will require more refactor to move out the mock server
-public class GithubAccessTokenPropertySEC797Test {
-
- @Rule
- public JenkinsRule j = new JenkinsRule();
-
+@WithJenkins
+class GithubAccessTokenPropertySEC797Test {
+
+ private JenkinsRule j;
private JenkinsRule.WebClient wc;
-
- private Server server;
+
+ private HttpServer server;
private URI serverUri;
private MockGithubServlet servlet;
-
- public void setupMockGithubServer() throws Exception {
- server = new Server();
- ServerConnector connector = new ServerConnector(server);
- // auto-bind to available port
- connector.setPort(0);
- server.addConnector(connector);
-
+
+ private void setupMockGithubServer() throws Exception {
+ server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
servlet = new MockGithubServlet(j);
-
- ServletContextHandler context = new ServletContextHandler();
- ServletHolder servletHolder = new ServletHolder("default", servlet);
- context.addServlet(servletHolder, "/*");
- server.setHandler(context);
-
+ server.createContext("/", servlet);
server.start();
-
- String host = connector.getHost();
- if (host == null) {
- host = "localhost";
- }
-
- int port = connector.getLocalPort();
- serverUri = new URI(String.format("http://%s:%d/", host, port));
+
+ InetSocketAddress address = server.getAddress();
+ serverUri = new URI(String.format("http://%s:%d/", address.getHostString(), address.getPort()));
servlet.setServerUrl(serverUri);
}
-
+
/**
* Based on documentation found at
* https://developer.github.com/v3/users/
* https://developer.github.com/v3/orgs/
* https://developer.github.com/v3/orgs/teams/
*/
- private static class MockGithubServlet extends DefaultServlet {
+ private static class MockGithubServlet implements HttpHandler {
private String currentLogin;
private List organizations;
private List teams;
-
- private JenkinsRule jenkinsRule;
+
+ private final JenkinsRule jenkinsRule;
private URI serverUri;
-
+
public MockGithubServlet(JenkinsRule jenkinsRule) {
this.jenkinsRule = jenkinsRule;
}
-
+
public void setServerUrl(URI serverUri) {
this.serverUri = serverUri;
}
-
- @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- switch (req.getRequestURI()) {
+
+ @Override
+ public void handle(HttpExchange he) throws IOException {
+ switch (he.getRequestURI().getPath()) {
case "/user":
- this.onUser(req, resp);
+ this.onUser(he);
break;
case "/users/_specific_login_":
- this.onUser(req, resp);
+ this.onUser(he);
break;
case "/user/orgs":
- this.onUserOrgs(req, resp);
+ this.onUserOrgs(he);
break;
case "/user/teams":
- this.onUserTeams(req, resp);
+ this.onUserTeams(he);
break;
case "/orgs/org-a":
- this.onOrgs(req, resp, "org-a");
+ this.onOrgs(he, "org-a");
break;
case "/orgs/org-a/teams":
- this.onOrgsTeam(req, resp, "org-a");
+ this.onOrgsTeam(he, "org-a");
break;
case "/orgs/org-a/members/alice":
- this.onOrgsMember(req, resp, "org-a", "alice");
+ this.onOrgsMember(he, "org-a", "alice");
break;
case "/teams/7/members/alice":
- this.onTeamMember(req, resp, "team-b", "alice");
+ this.onTeamMember(he, "team-b", "alice");
break;
case "/orgs/org-c":
- this.onOrgs(req, resp, "org-c");
+ this.onOrgs(he, "org-c");
break;
case "/orgs/org-c/teams":
- this.onOrgsTeam(req, resp, "org-c");
+ this.onOrgsTeam(he, "org-c");
break;
case "/orgs/org-c/members/bob":
- this.onOrgsMember(req, resp, "org-c", "bob");
+ this.onOrgsMember(he, "org-c", "bob");
break;
case "/teams/7/members/bob":
- this.onTeamMember(req, resp, "team-d", "bob");
+ this.onTeamMember(he, "team-d", "bob");
break;
case "/login/oauth/authorize":
- this.onLoginOAuthAuthorize(req, resp);
+ this.onLoginOAuthAuthorize(he);
break;
case "/login/oauth/access_token":
- this.onLoginOAuthAccessToken(req, resp);
+ this.onLoginOAuthAccessToken(he);
break;
default:
- throw new RuntimeException("Url not mapped yet: " + req.getRequestURI());
+ throw new RuntimeException("Url not mapped yet: " + he.getRequestURI().getPath());
}
+ he.close();
}
-
- private void onUser(HttpServletRequest req, HttpServletResponse resp) throws IOException {
- resp.getWriter().write(JSONObject.fromObject(
+
+ private void onUser(HttpExchange he) throws IOException {
+ sendResponse(he, JSONObject.fromObject(
new HashMap() {{
put("login", currentLogin);
put("name", currentLogin + "_name");
@@ -182,42 +171,42 @@ private void onUser(HttpServletRequest req, HttpServletResponse resp) throws IOE
}}
).toString());
}
-
- private void onUserOrgs(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+
+ private void onUserOrgs(HttpExchange he) throws IOException {
List