diff --git a/.github/dependabot.yml b/.github/dependabot.yml index daec318..c426005 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,7 @@ updates: directory: "/" schedule: interval: "daily" + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/release-drafter.yaml b/.github/release-drafter.yaml deleted file mode 100644 index 264c5f2..0000000 --- a/.github/release-drafter.yaml +++ /dev/null @@ -1,3 +0,0 @@ -_extends: .github -tag-template: google-login-$NEXT_PATCH_VERSION -version-template: $MAJOR.$MINOR.$PATCH diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml new file mode 100644 index 0000000..f371773 --- /dev/null +++ b/.github/workflows/cd.yaml @@ -0,0 +1,19 @@ +# Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins + +name: cd +on: + workflow_dispatch: + check_run: + types: + - completed + +permissions: + checks: read + contents: write + +jobs: + maven-cd: + uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1 + secrets: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml deleted file mode 100644 index f87134b..0000000 --- a/.github/workflows/release-drafter.yml +++ /dev/null @@ -1,17 +0,0 @@ -# Note: additional setup is required, see https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc - -name: Release Drafter - -on: - push: - branches: - - master - -jobs: - update_release_draft: - runs-on: ubuntu-latest - steps: - # Drafts your next Release notes as Pull Requests are merged into the default branch - - uses: release-drafter/release-drafter@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml new file mode 100644 index 0000000..a64ab6f --- /dev/null +++ b/.mvn/extensions.xml @@ -0,0 +1,7 @@ + + + io.jenkins.tools.incrementals + git-changelist-maven-extension + 1.7 + + diff --git a/.mvn/maven.config b/.mvn/maven.config new file mode 100644 index 0000000..f7daf60 --- /dev/null +++ b/.mvn/maven.config @@ -0,0 +1,3 @@ +-Pconsume-incrementals +-Pmight-produce-incrementals +-Dchangelist.format=%d.v%s diff --git a/Jenkinsfile b/Jenkinsfile index 0cbabc2..ce1ee47 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,2 +1,7 @@ -// Build on ci.jenkins.io; see https://github.com/jenkins-infra/pipeline-library -buildPlugin() +buildPlugin( + useContainerAgent: true, + configurations: [ + [platform: 'linux', jdk: 21], + [platform: 'windows', jdk: 17], + ] +) diff --git a/pom.xml b/pom.xml index f45a859..226ebf5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,36 +1,19 @@ + 4.0.0 org.jenkins-ci.plugins plugin - 4.16 + 4.76 + google-login - 1.9-SNAPSHOT + ${changelist} hpi - - scm:git:ssh://github.com/jenkinsci/google-login-plugin.git - scm:git:ssh://git@github.com/jenkinsci/google-login-plugin.git - https://github.com/jenkinsci/google-login-plugin - google-login-1.8 - - - - 8 - 2.222 - - Google Login Plugin https://wiki.jenkins.io/display/JENKINS/Google+Login+Plugin - - - recampbell - Ryan Campbell - ryan.campbell@gmail.com - - @@ -39,38 +22,122 @@ + + scm:git:https://github.com/${gitHubRepo}.git + scm:git:https://github.com/${gitHubRepo}.git + ${scmTag} + https://github.com/${gitHubRepo} + + + + 999999-SNAPSHOT + jenkinsci/${project.artifactId}-plugin + 2.401.3 + false + + + - io.jenkins.tools.bom - bom-2.222.x - 21 + com.google.cloud + libraries-bom + 26.29.0 + pom import + + + io.jenkins.tools.bom + bom-2.401.x + 2663.vd11370dda_e5a_ pom + import + - com.google.oauth-client - google-oauth-client - 1.20.0 + com.google.http-client + google-http-client + + + + com.fasterxml.jackson.core + jackson-core + + + com.google.code.findbugs + jsr305 + + + + com.google.guava + guava + + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpcore + + com.google.http-client google-http-client-jackson2 - 1.20.0 + + + + com.fasterxml.jackson.core + jackson-core + + + com.google.http-client + google-http-client + + com.google.oauth-client - google-oauth-client-java6 - 1.20.0 + google-oauth-client + 1.34.1 + + + + com.google.code.gson + gson + + + + com.google.guava + guava + + + com.google.http-client + google-http-client + + + + + io.jenkins.plugins + gson-api + + + org.jenkins-ci.plugins + apache-httpcomponents-client-4-api + + + org.jenkins-ci.plugins + jackson2-api org.jenkins-ci.plugins mailer - 1.6 diff --git a/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealm.java b/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealm.java index 3b69ddb..31a67b7 100644 --- a/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealm.java +++ b/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealm.java @@ -47,6 +47,9 @@ import hudson.security.SecurityRealm; import hudson.util.HttpResponses; import hudson.util.Secret; +import java.io.IOException; +import java.util.Arrays; +import java.util.StringTokenizer; import jenkins.model.Jenkins; import jenkins.security.SecurityListener; import org.acegisecurity.Authentication; @@ -68,10 +71,6 @@ import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; -import java.io.IOException; -import java.util.Arrays; -import java.util.StringTokenizer; - /** * Login with Google using OpenID Connect / OAuth 2 * @@ -164,15 +163,12 @@ public String getLoginUrl() { */ @Override public SecurityComponents createSecurityComponents() { - return new SecurityComponents( - new AuthenticationManager() { - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - if (authentication instanceof AnonymousAuthenticationToken) - return authentication; - throw new BadCredentialsException("Unexpected authentication type: " + authentication); - } - } - ); + return new SecurityComponents(new AuthenticationManager() { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + if (authentication instanceof AnonymousAuthenticationToken) return authentication; + throw new BadCredentialsException("Unexpected authentication type: " + authentication); + } + }); } @Override @@ -185,12 +181,19 @@ protected String getPostLogOutUrl(StaplerRequest req, Authentication auth) { */ @SuppressWarnings("unused") // stapler @Restricted(DoNotUse.class) // stapler only - public HttpResponse doCommenceLogin(StaplerRequest request, @QueryParameter String from, @Header("Referer") final String referer) throws IOException { + public HttpResponse doCommenceLogin( + StaplerRequest request, @QueryParameter String from, @Header("Referer") final String referer) + throws IOException { final String redirectOnFinish = getRedirectOnFinish(from, referer); final AuthorizationCodeFlow flow = new AuthorizationCodeFlow.Builder( - BearerToken.queryParameterAccessMethod(), HTTP_TRANSPORT, JSON_FACTORY, TOKEN_SERVER_URL, - new ClientParametersAuthentication(clientId, clientSecret.getPlainText()), clientId, AUTHORIZATION_SERVER_URL) + BearerToken.queryParameterAccessMethod(), + HTTP_TRANSPORT, + JSON_FACTORY, + TOKEN_SERVER_URL, + new ClientParametersAuthentication(clientId, clientSecret.getPlainText()), + clientId, + AUTHORIZATION_SERVER_URL) .setScopes(Arrays.asList(SCOPE)) .build(); @@ -219,7 +222,7 @@ public void initialize(HttpRequest request) throws IOException { HttpRequest request = requestFactory.buildGetRequest(url); GoogleUserInfo info = request.execute().parseAs(GoogleUserInfo.class); - GrantedAuthority[] authorities = new GrantedAuthority[]{SecurityRealm.AUTHENTICATED_AUTHORITY}; + GrantedAuthority[] authorities = new GrantedAuthority[] {SecurityRealm.AUTHENTICATED_AUTHORITY}; // logs this user in. UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(info.getEmail(), "", authorities); @@ -241,7 +244,6 @@ public void initialize(HttpRequest request) throws IOException { } catch (IOException e) { return HttpResponses.error(500, e); } - } }; request.getSession().setAttribute(SESSION_NAME, oAuthSession); @@ -292,7 +294,6 @@ private String getRootURL() { } } - /** * This is where the user comes back to at the end of the OpenID redirect ping-pong. */ diff --git a/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleUserInfo.java b/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleUserInfo.java index 099cbbd..85c930e 100644 --- a/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleUserInfo.java +++ b/src/main/java/org/jenkinsci/plugins/googlelogin/GoogleUserInfo.java @@ -23,15 +23,13 @@ */ package org.jenkinsci.plugins.googlelogin; -import java.io.IOException; - import com.google.api.client.util.Key; - import hudson.Extension; import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; import hudson.tasks.Mailer; +import java.io.IOException; /** * Represents an identity information from the oauth provider. @@ -83,11 +81,9 @@ public String getName() { */ public void updateProfile(hudson.model.User u) throws IOException { // update the user profile by the externally given information - if (email != null) - u.addProperty(new Mailer.UserProperty(email)); + if (email != null) u.addProperty(new Mailer.UserProperty(email)); - if (name != null) - u.setFullName(name); + if (name != null) u.setFullName(name); u.addProperty(this); } diff --git a/src/main/java/org/jenkinsci/plugins/googlelogin/OAuthSession.java b/src/main/java/org/jenkinsci/plugins/googlelogin/OAuthSession.java index d009d3a..19aaf67 100644 --- a/src/main/java/org/jenkinsci/plugins/googlelogin/OAuthSession.java +++ b/src/main/java/org/jenkinsci/plugins/googlelogin/OAuthSession.java @@ -26,21 +26,17 @@ import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl; import com.google.api.client.auth.oauth2.AuthorizationCodeResponseUrl; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.model.Failure; import hudson.remoting.Base64; import hudson.util.HttpResponses; -import java.security.MessageDigest; -import org.kohsuke.stapler.HttpRedirect; -import org.kohsuke.stapler.HttpResponse; -import org.kohsuke.stapler.Stapler; -import org.kohsuke.stapler.StaplerRequest; - import java.io.IOException; import java.io.Serializable; -import java.lang.IllegalArgumentException; import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import java.util.UUID; +import org.kohsuke.stapler.HttpRedirect; +import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.StaplerRequest; /** * The state of the OAuth request. @@ -51,7 +47,8 @@ public abstract class OAuthSession implements Serializable { private static final long serialVersionUID = 1438835558745081350L; - private final String uuid = Base64.encode(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8)).substring(0,20); + private final String uuid = Base64.encode(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8)) + .substring(0, 20); /** * The url the user was trying to navigate to. */ @@ -74,12 +71,13 @@ public OAuthSession(String from, String redirectUrl, String domain) { * Starts the login session. */ public HttpResponse doCommenceLogin(AuthorizationCodeFlow flow) throws IOException { - AuthorizationCodeRequestUrl authorizationCodeRequestUrl = flow.newAuthorizationUrl().setState(uuid).setRedirectUri(redirectUrl); + AuthorizationCodeRequestUrl authorizationCodeRequestUrl = + flow.newAuthorizationUrl().setState(uuid).setRedirectUri(redirectUrl); if (domain != null) { if (domain.contains(",")) { - authorizationCodeRequestUrl.set("hd","*"); + authorizationCodeRequestUrl.set("hd", "*"); } else { - authorizationCodeRequestUrl.set("hd",domain); + authorizationCodeRequestUrl.set("hd", domain); } } return new HttpRedirect(authorizationCodeRequestUrl.toString()); @@ -100,7 +98,9 @@ public HttpResponse doFinishLogin(StaplerRequest request) throws IOException { try { AuthorizationCodeResponseUrl responseUrl = new AuthorizationCodeResponseUrl(buf.toString()); String state = responseUrl.getState(); - if (state == null || !MessageDigest.isEqual(uuid.getBytes(StandardCharsets.UTF_8), state.getBytes(StandardCharsets.UTF_8))) { + if (state == null + || !MessageDigest.isEqual( + uuid.getBytes(StandardCharsets.UTF_8), state.getBytes(StandardCharsets.UTF_8))) { return HttpResponses.error(401, "State is invalid"); } String code = responseUrl.getCode(); diff --git a/src/test/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealmTest.java b/src/test/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealmTest.java index d42f37b..3827a4c 100644 --- a/src/test/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealmTest.java +++ b/src/test/java/org/jenkinsci/plugins/googlelogin/GoogleOAuth2SecurityRealmTest.java @@ -1,15 +1,14 @@ package org.jenkinsci.plugins.googlelogin; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.JenkinsRule; - -import java.io.IOException; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.io.IOException; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + public class GoogleOAuth2SecurityRealmTest { @Rule