diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index 94863e60..43d62816 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -2,6 +2,6 @@ io.jenkins.tools.incrementals git-changelist-maven-extension - 1.0-beta-7 + 1.2 diff --git a/Jenkinsfile b/Jenkinsfile index a601785c..dbea8b33 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,15 +1,16 @@ //def buildConfiguration = buildPlugin.recommendedConfigurations() -def lts = "2.176.1" -def weekly = "2.199" +def lts = "2.249.3" def buildConfiguration = [ - [ platform: "linux", jdk: "8", jenkins: lts, javaLevel: "8" ], - [ platform: "windows", jdk: "8", jenkins: lts, javaLevel: "8" ], - [ platform: "linux", jdk: "11", jenkins: lts, javaLevel: "8" ], - [ platform: "windows", jdk: "11", jenkins: lts, javaLevel: "8" ], +/* + [ platform: "linux", jdk: "8", jenkins: lts ], + [ platform: "windows", jdk: "8", jenkins: lts ], + [ platform: "linux", jdk: "11", jenkins: lts ], + [ platform: "windows", jdk: "11", jenkins: lts ], +*/ // Also build on recent weekly -// [ platform: "linux", jdk: "11", jenkins: weekly, javaLevel: "8" ], -// [ platform: "windows", jdk: "11", jenkins: weekly, javaLevel: "8" ] + [ platform: "linux", jdk: "11" ], + [ platform: "windows", jdk: "11" ] ] buildPlugin(configurations: buildConfiguration) diff --git a/pom.xml b/pom.xml index c80457af..417b665a 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ under the License. org.jenkins-ci.plugins plugin - 3.55 + 4.3 saml @@ -42,9 +42,9 @@ under the License. - 1.1.8 + 2.0.0 -SNAPSHOT - 2.176.1 + 2.266 8 1.35 @@ -90,8 +90,26 @@ under the License. org.pac4j pac4j-saml - 1.9.9 + + 3.9.0 + false + + org.springframework + spring-beans + + + org.springframework + spring-jdbc + + + org.springframework + spring-orm + + + org.springframework + spring-tx + org.springframework spring-core @@ -104,17 +122,65 @@ under the License. org.slf4j jcl-over-slf4j + + org.bouncycastle + bcprov-jdk15on + + + org.dom4j + dom4j + commons-codec commons-codec - org.bouncycastle - bcprov-jdk15on + antlr + antlr + + + org.hibernate + hibernate-core + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + + + org.hibernate + hibernate-entitymanager + + + org.hibernate + hibernate-commons-annotations + + + commons-collections + commons-collections + + + commons-io + commons-io + + + commons-codec + commons-codec - org.apache.httpcomponents - httpclient + com.google.guava + guava + + + xalan + xalan + + + jakarta.activation + jakarta.activation-api + + + javax.annotation + javax.annotation-api @@ -129,21 +195,6 @@ under the License. bouncycastle-api 2.18 - - net.shibboleth.utilities - java-support - 7.2.0 - - - commons-codec - commons-codec - - - org.slf4j - slf4j-api - - - org.mockito mockito-core @@ -171,10 +222,16 @@ under the License. + + io.jenkins.tools.bom + bom-2.249.x + 17 + pom + import + org.cryptacular cryptacular - 1.2.4 @@ -182,6 +239,12 @@ under the License. xmlsec 2.1.4 + + org.pac4j + pac4j-saml + + 3.9.0 + diff --git a/src/main/java/org/jenkinsci/plugins/saml/OpenSAMLWrapper.java b/src/main/java/org/jenkinsci/plugins/saml/OpenSAMLWrapper.java index 06daceb2..22c1fdb4 100644 --- a/src/main/java/org/jenkinsci/plugins/saml/OpenSAMLWrapper.java +++ b/src/main/java/org/jenkinsci/plugins/saml/OpenSAMLWrapper.java @@ -24,8 +24,12 @@ import org.opensaml.core.config.InitializationService; import org.pac4j.core.context.J2EContext; import org.pac4j.core.context.WebContext; +import org.pac4j.core.http.callback.NoParameterCallbackUrlResolver; +import org.pac4j.core.http.url.DefaultUrlResolver; import org.pac4j.saml.client.SAML2Client; +import org.pac4j.saml.config.SAML2Configuration; +import java.io.IOException; import java.util.logging.Logger; import static java.util.logging.Level.*; @@ -91,9 +95,9 @@ protected WebContext createWebContext() { * @return a SAML2Client object to interact with the IdP service. */ protected SAML2Client createSAML2Client() { - final SAML2ClientConfigurationCustom config = new SAML2ClientConfigurationCustom(); + final SAML2Configuration config = new SAML2Configuration(); config.setIdentityProviderMetadataResource(new SamlFileResource(SamlSecurityRealm.getIDPMetadataFilePath())); - config.setDestinationBindingType(samlPluginConfig.getBinding()); + config.setAuthnRequestBindingType(samlPluginConfig.getBinding()); config.setWantsAssertionsSigned(true); SamlEncryptionData encryptionData = samlPluginConfig.getEncryptionData(); @@ -150,10 +154,15 @@ protected SAML2Client createSAML2Client() { config.setServiceProviderMetadataResource(new SamlFileResource(SamlSecurityRealm.getSPMetadataFilePath())); final SAML2Client saml2Client = new SAML2Client(config); saml2Client.setCallbackUrl(samlPluginConfig.getConsumerServiceUrl()); - saml2Client.init(createWebContext()); + saml2Client.setCallbackUrlResolver(new NoParameterCallbackUrlResolver()); + saml2Client.init(); if (LOG.isLoggable(FINE)) { - LOG.fine(saml2Client.getServiceProviderMetadataResolver().getMetadata()); + try { + LOG.fine(saml2Client.getServiceProviderMetadataResolver().getMetadata()); + } catch (IOException e) { + LOG.fine("Is not possible to show the metadata : " + e.getMessage()); + } } return saml2Client; } diff --git a/src/main/java/org/jenkinsci/plugins/saml/SAML2ClientConfigurationCustom.java b/src/main/java/org/jenkinsci/plugins/saml/SAML2ClientConfigurationCustom.java deleted file mode 100644 index 771c16d6..00000000 --- a/src/main/java/org/jenkinsci/plugins/saml/SAML2ClientConfigurationCustom.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.jenkinsci.plugins.saml; - -import org.pac4j.saml.client.SAML2ClientConfiguration; - -public class SAML2ClientConfigurationCustom extends SAML2ClientConfiguration { - - private boolean authnRequestSigned = true; - - public SAML2ClientConfigurationCustom() { - } - - @Override - public boolean isAuthnRequestSigned() { - return authnRequestSigned; - } - - public void setAuthnRequestSigned(boolean authnRequestSigned) { - this.authnRequestSigned = authnRequestSigned; - setForceSignRedirectBindingAuthnRequest(authnRequestSigned); - } - } \ No newline at end of file diff --git a/src/main/java/org/jenkinsci/plugins/saml/SamlFileResource.java b/src/main/java/org/jenkinsci/plugins/saml/SamlFileResource.java index c53f9612..b68f8e1e 100644 --- a/src/main/java/org/jenkinsci/plugins/saml/SamlFileResource.java +++ b/src/main/java/org/jenkinsci/plugins/saml/SamlFileResource.java @@ -18,8 +18,10 @@ package org.jenkinsci.plugins.saml; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.NotImplementedException; import org.pac4j.core.exception.TechnicalException; -import org.pac4j.core.io.WritableResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.WritableResource; import javax.annotation.Nonnull; import java.io.File; @@ -27,6 +29,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URL; import java.util.logging.Logger; /** @@ -61,11 +65,36 @@ public boolean exists() { return getFile().exists(); } + @Override + public boolean isReadable() { + return getFile().canRead(); + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + public URL getURL() { + throw new NotImplementedException(); + } + + @Override + public URI getURI() { + throw new NotImplementedException(); + } + @Override public String getFilename() { return fileName; } + @Override + public String getDescription() { + return fileName; + } + @Override public InputStream getInputStream() throws IOException { return FileUtils.openInputStream(getFile()); @@ -76,8 +105,28 @@ public File getFile() { return new File(fileName); } + @Override + public long contentLength() { + return getFile().length(); + } + + @Override + public long lastModified() { + return getFile().lastModified(); + } + + @Override + public Resource createRelative(String s) { + throw new NotImplementedException(); + } + + @Override + public boolean isWritable() { + return getFile().canWrite(); + } + @Override public OutputStream getOutputStream() throws IOException { return FileUtils.openOutputStream(getFile()); } -} +} \ No newline at end of file diff --git a/src/main/java/org/jenkinsci/plugins/saml/SamlRedirectActionWrapper.java b/src/main/java/org/jenkinsci/plugins/saml/SamlRedirectActionWrapper.java index 4eea98ff..84a286e8 100644 --- a/src/main/java/org/jenkinsci/plugins/saml/SamlRedirectActionWrapper.java +++ b/src/main/java/org/jenkinsci/plugins/saml/SamlRedirectActionWrapper.java @@ -19,7 +19,7 @@ import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; -import org.pac4j.core.client.RedirectAction; +import org.pac4j.core.redirect.RedirectAction; import org.pac4j.core.context.WebContext; import org.pac4j.core.exception.HttpAction; import org.pac4j.saml.client.SAML2Client; diff --git a/src/main/java/org/jenkinsci/plugins/saml/SamlSPMetadataWrapper.java b/src/main/java/org/jenkinsci/plugins/saml/SamlSPMetadataWrapper.java index 07962275..c4283aae 100644 --- a/src/main/java/org/jenkinsci/plugins/saml/SamlSPMetadataWrapper.java +++ b/src/main/java/org/jenkinsci/plugins/saml/SamlSPMetadataWrapper.java @@ -23,6 +23,8 @@ import org.kohsuke.stapler.StaplerResponse; import org.pac4j.saml.client.SAML2Client; +import java.io.IOException; + /** * build the Service Provider(SP) metadata from the configuration. */ @@ -41,6 +43,12 @@ public SamlSPMetadataWrapper(SamlPluginConfig samlPluginConfig, StaplerRequest r @Override protected HttpResponse process() throws IllegalStateException { final SAML2Client client = createSAML2Client(); - return HttpResponses.plainText(client.getServiceProviderMetadataResolver().getMetadata()); + String metadata = ""; + try { + metadata = client.getServiceProviderMetadataResolver().getMetadata(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + return HttpResponses.text(metadata); } } diff --git a/src/main/java/org/jenkinsci/plugins/saml/SamlSecurityRealm.java b/src/main/java/org/jenkinsci/plugins/saml/SamlSecurityRealm.java index 3e670252..056584aa 100644 --- a/src/main/java/org/jenkinsci/plugins/saml/SamlSecurityRealm.java +++ b/src/main/java/org/jenkinsci/plugins/saml/SamlSecurityRealm.java @@ -39,8 +39,8 @@ import org.jenkinsci.plugins.saml.user.SamlCustomProperty; import org.kohsuke.stapler.*; import org.kohsuke.stapler.interceptor.RequirePOST; -import org.pac4j.core.client.RedirectAction; -import org.pac4j.core.client.RedirectAction.RedirectType; +import org.pac4j.core.redirect.RedirectAction; +import org.pac4j.core.redirect.RedirectAction.RedirectType; import org.springframework.dao.DataAccessException; import org.pac4j.saml.profile.SAML2Profile; @@ -245,6 +245,7 @@ public String getLoginUrl() { * @param request http request. * @param response http response. * @param referer referer. + * @param from http request "from" parameter. * @return the http response. */ public HttpResponse doCommenceLogin(final StaplerRequest request, final StaplerResponse response, @QueryParameter diff --git a/src/test/java/org/jenkinsci/plugins/saml/OpenSamlWrapperTest.java b/src/test/java/org/jenkinsci/plugins/saml/OpenSamlWrapperTest.java index 5035a101..937c332d 100644 --- a/src/test/java/org/jenkinsci/plugins/saml/OpenSamlWrapperTest.java +++ b/src/test/java/org/jenkinsci/plugins/saml/OpenSamlWrapperTest.java @@ -23,21 +23,17 @@ import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; import org.kohsuke.stapler.HttpResponse; -import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.mockito.Mockito; -import org.pac4j.saml.profile.SAML2Profile; import javax.servlet.ServletException; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.nio.charset.StandardCharsets; import static org.hamcrest.core.StringContains.containsString; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.when; import static org.opensaml.saml.common.xml.SAMLConstants.SAML2_REDIRECT_BINDING_URI; @@ -51,7 +47,10 @@ public class OpenSamlWrapperTest { @Test public void metadataWrapper() throws IOException, ServletException { - String metadata = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("org/jenkinsci/plugins/saml/OpenSamlWrapperTest/metadataWrapper/metadata.xml")); + String metadata = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("org/jenkinsci" + + "/plugins/saml" + + "/OpenSamlWrapperTest/metadataWrapper/metadata.xml"), + StandardCharsets.UTF_8); SamlSecurityRealm samlSecurity = new SamlSecurityRealm(new IdpMetadataConfiguration(metadata), "displayName", "groups", 10000, "uid", "email", "/logout", null, @@ -73,7 +72,10 @@ public void metadataWrapper() throws IOException, ServletException { @Test public void metadataWrapperWitEncrytionConfigured() throws IOException, ServletException { - String metadata = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("org/jenkinsci/plugins/saml/OpenSamlWrapperTest/metadataWrapper/metadata.xml")); + String metadata = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("org/jenkinsci" + + "/plugins/saml/" + + "OpenSamlWrapperTest/metadataWrapper/metadata.xml"), + StandardCharsets.UTF_8); BundleKeyStore ks = new BundleKeyStore(); SamlEncryptionData encryptionData = new SamlEncryptionData(ks.getKeystorePath(), Secret.fromString(ks.getKsPassword()), Secret.fromString(ks.getKsPkPassword()), ks.getKsPkAlias(), true); @@ -96,32 +98,4 @@ public void metadataWrapperWitEncrytionConfigured() throws IOException, ServletE assertThat(result, containsString("")); } - - //TODO [kuisathaverat] incomplete - public void profileWrapper() throws Exception { - String metadata = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("org/jenkinsci/plugins/saml/OpenSamlWrapperTest/metadataWrapper/metadata.xml")); - String samlResponse = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("org/jenkinsci/plugins/saml/OpenSamlWrapperTest/profileWrapper/samlresponse.xml")); - - SamlSecurityRealm samlSecurity = new SamlSecurityRealm(new IdpMetadataConfiguration(metadata), - "displayName", "groups", 10000, - "uid", "email", "/logout", null, - null, "none", SAML2_REDIRECT_BINDING_URI, - java.util.Collections.emptyList()); - jenkinsRule.jenkins.setSecurityRealm(samlSecurity); - - DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); - samlResponse = samlResponse.replace("DATE_NOW",df.format(new Date())); - samlResponse = samlResponse.replace("DATE_AFTER",df.format(new Date(System.currentTimeMillis() + 1000000))); - samlResponse = samlResponse.replace("CONSUMER_SERVICE",samlSecurity.getSamlPluginConfig().getConsumerServiceUrl()); - samlResponse = samlResponse.replace("ENTITY_ID","http://192.168.99.100:8080/simplesaml/saml2/idp/metadata.php"); - - StaplerResponse mockResponse = Mockito.mock(StaplerResponse.class); - StaplerRequest mockRequest = Mockito.mock(StaplerRequest.class); - when(mockRequest.getMethod()).thenReturn("POST"); - when(mockRequest.getParameter("SAMLResponse")).thenReturn(java.util.Base64.getEncoder().encodeToString(samlResponse.getBytes("UTF-8"))); - - SamlProfileWrapper samlProfileWrapper = new SamlProfileWrapper(samlSecurity.getSamlPluginConfig(), mockRequest, mockResponse); - SAML2Profile process = samlProfileWrapper.get(); - - } } diff --git a/src/test/java/org/jenkinsci/plugins/saml/SamlJCasCCompatibilityTest.java b/src/test/java/org/jenkinsci/plugins/saml/SamlJCasCCompatibilityTest.java index acb0e2d8..19c26e73 100644 --- a/src/test/java/org/jenkinsci/plugins/saml/SamlJCasCCompatibilityTest.java +++ b/src/test/java/org/jenkinsci/plugins/saml/SamlJCasCCompatibilityTest.java @@ -1,18 +1,17 @@ package org.jenkinsci.plugins.saml; +import java.util.List; import hudson.security.SecurityRealm; import io.jenkins.plugins.casc.misc.RoundTripAbstractTest; import org.jenkinsci.plugins.saml.conf.Attribute; import org.jenkinsci.plugins.saml.conf.AttributeEntry; import org.jvnet.hudson.test.RestartableJenkinsRule; -import java.util.List; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertTrue; public class SamlJCasCCompatibilityTest extends RoundTripAbstractTest { @Override diff --git a/src/test/java/org/jenkinsci/plugins/saml/SamlSecurityRealmTest.java b/src/test/java/org/jenkinsci/plugins/saml/SamlSecurityRealmTest.java index 538d167a..7bb59d7a 100644 --- a/src/test/java/org/jenkinsci/plugins/saml/SamlSecurityRealmTest.java +++ b/src/test/java/org/jenkinsci/plugins/saml/SamlSecurityRealmTest.java @@ -30,23 +30,18 @@ import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.recipes.LocalData; import org.jvnet.hudson.test.recipes.WithTimeout; -import org.mockito.Mockito; - -import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; -import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import org.jvnet.hudson.test.Issue; -import static org.mockito.Mockito.when; import static org.opensaml.saml.common.xml.SAMLConstants.SAML2_POST_BINDING_URI; import static org.opensaml.saml.common.xml.SAMLConstants.SAML2_REDIRECT_BINDING_URI; @@ -179,7 +174,7 @@ public void testLoadGroupByGroupname() { @WithTimeout(240) @Test public void testLoadUserByUsername() { - assertEquals(samlSecurityRealm.loadUserByUsername("tesla").getUsername(), "tesla"); + assertEquals(samlSecurityRealm.loadUserByUsername2("tesla").getUsername(), "tesla"); } @LocalData("testReadSimpleConfiguration") @@ -235,7 +230,4 @@ public void upgradeIDPMetadataFileTest() throws IOException { configuredMetadata = configuredMetadata.replace("\\n", ""); // remove new lines assertThat(idpMetadata, equalTo(configuredMetadata)); } - - - }