Jetty 12 merge from 11 and fix JAAS ldap login test (#10857)

* Merge from jetty-10.0.x to jetty-11.0.x

* Fixes #10812 - Correct awaitility dependency scope (#10813)

* Bump org.apache.logging.log4j:log4j-api from 2.20.0 to 2.21.1

Bumps org.apache.logging.log4j:log4j-api from 2.20.0 to 2.21.1.

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump maven.plugin-tools.version from 3.9.0 to 3.10.1

Bumps `maven.plugin-tools.version` from 3.9.0 to 3.10.1.

Updates `org.apache.maven.plugin-tools:maven-plugin-annotations` from 3.9.0 to 3.10.1
- [Release notes](https://github.com/apache/maven-plugin-tools/releases)
- [Commits](https://github.com/apache/maven-plugin-tools/compare/maven-plugin-tools-3.9.0...maven-plugin-tools-3.10.1)

Updates `org.apache.maven.plugin-tools:maven-plugin-tools-api` from 3.9.0 to 3.10.1
- [Release notes](https://github.com/apache/maven-plugin-tools/releases)
- [Commits](https://github.com/apache/maven-plugin-tools/compare/maven-plugin-tools-3.9.0...maven-plugin-tools-3.10.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugin-tools:maven-plugin-annotations
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.maven.plugin-tools:maven-plugin-tools-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump org.apache.maven.plugins:maven-clean-plugin from 3.3.1 to 3.3.2

Bumps [org.apache.maven.plugins:maven-clean-plugin](https://github.com/apache/maven-clean-plugin) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/apache/maven-clean-plugin/releases)
- [Commits](https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.3.1...maven-clean-plugin-3.3.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-clean-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump org.apache.maven.plugins:maven-dependency-plugin

Bumps [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) from 3.6.0 to 3.6.1.
- [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.0...maven-dependency-plugin-3.6.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-dependency-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump commons-io:commons-io from 2.14.0 to 2.15.0

Bumps commons-io:commons-io from 2.14.0 to 2.15.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump org.apache.maven.plugins:maven-plugin-plugin from 3.9.0 to 3.10.1

Bumps [org.apache.maven.plugins:maven-plugin-plugin](https://github.com/apache/maven-plugin-tools) from 3.9.0 to 3.10.1.
- [Release notes](https://github.com/apache/maven-plugin-tools/releases)
- [Commits](https://github.com/apache/maven-plugin-tools/compare/maven-plugin-tools-3.9.0...maven-plugin-tools-3.10.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-plugin-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump maven.surefire.plugin.version from 3.1.2 to 3.2.1

Bumps `maven.surefire.plugin.version` from 3.1.2 to 3.2.1.

Updates `org.apache.maven.plugins:maven-failsafe-plugin` from 3.1.2 to 3.2.1
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.1)

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.1.2 to 3.2.1
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.1)

Updates `org.apache.maven.surefire:surefire-junit47` from 3.1.2 to 3.2.1

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-failsafe-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.maven.surefire:surefire-junit47
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump org.apache.maven.plugins:maven-checkstyle-plugin

Bumps [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.0...maven-checkstyle-plugin-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump apacheds.version from 2.0.0.AM26 to 2.0.0.AM27 (#10836)

* Bump apacheds.version from 2.0.0.AM26 to 2.0.0.AM27

Bumps `apacheds.version` from 2.0.0.AM26 to 2.0.0.AM27.

Updates `org.apache.directory.server:apacheds-test-framework` from 2.0.0.AM26 to 2.0.0.AM27
- [Commits](https://github.com/apache/directory-server/compare/2.0.0.AM26...2.0.0.AM27)

Updates `org.apache.directory.server:apacheds-server-integ` from 2.0.0.AM26 to 2.0.0.AM27
- [Commits](https://github.com/apache/directory-server/compare/2.0.0.AM26...2.0.0.AM27)

Updates `org.apache.directory.server:apacheds-core-integ` from 2.0.0.AM26 to 2.0.0.AM27
- [Commits](https://github.com/apache/directory-server/compare/2.0.0.AM26...2.0.0.AM27)

---
updated-dependencies:
- dependency-name: org.apache.directory.server:apacheds-test-framework
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.directory.server:apacheds-server-integ
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.directory.server:apacheds-core-integ
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* get this work

Signed-off-by: Olivier Lamy <olamy@apache.org>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Olivier Lamy <olamy@apache.org>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Olivier Lamy <olamy@apache.org>

* Bump org.infinispan:infinispan-bom from 11.0.17.Final to 11.0.18.Final (#10724)

Bumps [org.infinispan:infinispan-bom](https://github.com/infinispan/infinispan) from 11.0.17.Final to 11.0.18.Final.
- [Release notes](https://github.com/infinispan/infinispan/releases)
- [Changelog](https://github.com/infinispan/infinispan/blob/main/Jenkinsfile-release)
- [Commits](https://github.com/infinispan/infinispan/compare/11.0.17.Final...11.0.18.Final)

---
updated-dependencies:
- dependency-name: org.infinispan:infinispan-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* not needed, bad merge

Signed-off-by: Olivier Lamy <olamy@apache.org>

* fix version

Signed-off-by: Olivier Lamy <olamy@apache.org>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Olivier Lamy <olamy@apache.org>
Co-authored-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Co-authored-by: Chad Wilson <chadw@thoughtworks.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Olivier Lamy 2023-11-06 14:27:40 +10:00 committed by GitHub
parent 81814dc226
commit 91d11941b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 489 additions and 325 deletions

View File

@ -90,6 +90,7 @@
<reconcile propertyName="skipExec" skipValue="true"/> <reconcile propertyName="skipExec" skipValue="true"/>
<reconcile propertyName="skipTests" skipValue="true"/> <reconcile propertyName="skipTests" skipValue="true"/>
<reconcile propertyName="testFailureIgnore" skipValue="true"/> <reconcile propertyName="testFailureIgnore" skipValue="true"/>
<reconcile propertyName="test" skipValue="true"/>
</reconciles> </reconciles>
<nologs> <nologs>
<nolog propertyName="systemPropertyVariables"/> <nolog propertyName="systemPropertyVariables"/>

View File

@ -13,11 +13,11 @@
<name>Build :: Resources</name> <name>Build :: Resources</name>
<properties> <properties>
<maven.deploy.skip>true</maven.deploy.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
<!-- versions for these plugins are not based on parent pom --> <!-- versions for these plugins are not based on parent pom -->
<maven.deploy.plugin.version>3.1.1</maven.deploy.plugin.version>
<maven.javadoc.plugin.version>3.4.0</maven.javadoc.plugin.version>
<maven.remote-resources.plugin.version>3.1.0</maven.remote-resources.plugin.version> <maven.remote-resources.plugin.version>3.1.0</maven.remote-resources.plugin.version>
<maven.surefire.plugin.version>3.1.2</maven.surefire.plugin.version> <maven.surefire.plugin.version>3.2.1</maven.surefire.plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<skipTests>true</skipTests> <skipTests>true</skipTests>
</properties> </properties>

View File

@ -175,7 +175,7 @@ To allow the greatest degree of flexibility in using JAAS with web applications,
Note that you don't ordinarily need to set these explicitly, as Jetty has defaults which will work in 99% of cases. Note that you don't ordinarily need to set these explicitly, as Jetty has defaults which will work in 99% of cases.
However, should you need to, you can configure: However, should you need to, you can configure:
* a CallbackHandler (Default: `org.eclipse.jetty.jaas.callback.DefaultCallbackHandler`) * a CallbackHandler (Default: `org.eclipse.jetty.security.jaas.callback.DefaultCallbackHandler`)
* a list of classnames for the Principal implementation that equate to a user role (Default: `org.eclipse.jetty.jaas.JAASRole`) * a list of classnames for the Principal implementation that equate to a user role (Default: `org.eclipse.jetty.jaas.JAASRole`)
Here's an example of setting each of these (to their default values): Here's an example of setting each of these (to their default values):
@ -186,7 +186,7 @@ Here's an example of setting each of these (to their default values):
<Set name="Name">Test JAAS Realm</Set> <Set name="Name">Test JAAS Realm</Set>
<Set name="LoginModuleName">xyz</Set> <Set name="LoginModuleName">xyz</Set>
<Set name="CallbackHandlerClass"> <Set name="CallbackHandlerClass">
org.eclipse.jetty.jaas.callback.DefaultCallbackHandler org.eclipse.jetty.security.jaas.callback.DefaultCallbackHandler
</Set> </Set>
<Set name="roleClassNames"> <Set name="roleClassNames">
<Array type="java.lang.String"> <Array type="java.lang.String">

View File

@ -12,11 +12,28 @@
<description>The common Jetty security implementation</description> <description>The common Jetty security implementation</description>
<properties> <properties>
<apache.directory.api.version>2.1.5</apache.directory.api.version>
<apacheds.version>2.0.0.AM27</apacheds.version>
<bundle-symbolic-name>${project.groupId}.security</bundle-symbolic-name> <bundle-symbolic-name>${project.groupId}.security</bundle-symbolic-name>
<spotbugs.onlyAnalyze>org.eclipse.jetty.security.*</spotbugs.onlyAnalyze> <spotbugs.onlyAnalyze>org.eclipse.jetty.security.*</spotbugs.onlyAnalyze>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-asn1-api</artifactId>
<version>${apache.directory.api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-ldap-model</artifactId>
<version>${apache.directory.api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-util</artifactId>
<version>${apache.directory.api.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId> <artifactId>jetty-server</artifactId>
@ -25,6 +42,70 @@
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-ldap-schema-data</artifactId>
<version>${apache.directory.api.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-core-integ</artifactId>
<version>${apacheds.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-ldap-schema-data</artifactId>
</exclusion>
<!-- exclude additional LDIF schema files to avoid conflicts through
multiple copies -->
<exclusion>
<groupId>org.apache.directory.shared</groupId>
<artifactId>shared-ldap-schema</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-server-integ</artifactId>
<version>${apacheds.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-ldap-schema-data</artifactId>
</exclusion>
<!-- exclude additional LDIF schema files to avoid conflicts through
multiple copies -->
<exclusion>
<groupId>org.apache.directory.shared</groupId>
<artifactId>shared-ldap-schema</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-test-framework</artifactId>
<version>${apacheds.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-ldap-schema-data</artifactId>
</exclusion>
<!-- exclude additional LDIF schema files to avoid conflicts through
multiple copies -->
<exclusion>
<groupId>org.apache.directory.shared</groupId>
<artifactId>shared-ldap-schema</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http-tools</artifactId> <artifactId>jetty-http-tools</artifactId>
@ -55,7 +136,8 @@
<configuration> <configuration>
<argLine>@{argLine} <argLine>@{argLine}
${jetty.surefire.argLine} ${jetty.surefire.argLine}
--add-reads org.eclipse.jetty.security=org.eclipse.jetty.logging</argLine> --add-reads org.eclipse.jetty.security=org.eclipse.jetty.logging
--add-exports org.eclipse.jetty.security/org.eclipse.jetty.security.jaas.spi=java.base</argLine>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -1,319 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.security.jaas;
/* TODO
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import javax.security.auth.login.Configuration;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.directory.server.annotations.CreateLdapServer;
import org.apache.directory.server.annotations.CreateTransport;
import org.apache.directory.server.core.annotations.ApplyLdifs;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.annotations.CreatePartition;
import org.apache.directory.server.core.integ.FrameworkRunner;
import org.apache.directory.server.ldap.LdapServer;
import org.eclipse.jetty.ee10.jaas.spi.LdapLoginModule;
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
import org.eclipse.jetty.ee10.servlet.ServletHandler;
import org.eclipse.jetty.ee10.servlet.ServletHolder;
import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler;
import org.eclipse.jetty.ee10.servlet.security.DefaultIdentityService;
import org.eclipse.jetty.ee10.servlet.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.junit.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.runner.RunWith;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.startsWith;
@EnabledForJreRange(max = JRE.JAVA_17, disabledReason = "sun.security.x509.X509CertInfo.set not present in Java 21, needs a Java 21 compatible version of Apache Directory Server")
@RunWith(FrameworkRunner.class)
@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP")})
@CreateDS(allowAnonAccess = false, partitions = {
@CreatePartition(name = "Users Partition", suffix = "ou=people,dc=jetty,dc=org"),
@CreatePartition(name = "Groups Partition", suffix = "ou=groups,dc=jetty,dc=org")
})
@ApplyLdifs({
// Entry 1
"dn: ou=people,dc=jetty,dc=org",
"objectClass: organizationalunit",
"objectClass: top",
"ou: people",
// Entry # 2
"dn:uid=someone,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: someone",
"sn: sn test",
"userPassword: complicatedpassword",
// Entry # 3
"dn:uid=someoneelse,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: someoneelse",
"sn: sn test",
"userPassword: verycomplicatedpassword",
// Entry 4
"dn: ou=groups,dc=jetty,dc=org",
"objectClass: organizationalunit",
"objectClass: top",
"ou: groups",
// Entry 5
"dn: ou=subdir,ou=people,dc=jetty,dc=org",
"objectClass: organizationalunit",
"objectClass: top",
"ou: subdir",
// Entry # 6
"dn:uid=uniqueuser,ou=subdir,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: uniqueuser",
"sn: unique user",
"userPassword: hello123",
// Entry # 7
"dn:uid=ambiguousone,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: ambiguous1",
"sn: ambiguous user",
"userPassword: foobar",
// Entry # 8
"dn:uid=ambiguousone,ou=subdir,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: ambiguous2",
"sn: ambiguous subdir user",
"userPassword: barfoo",
// Entry 9
"dn: cn=developers,ou=groups,dc=jetty,dc=org",
"objectClass: groupOfUniqueNames",
"objectClass: top",
"ou: groups",
"description: People who try to build good software",
"uniquemember: uid=someone,ou=people,dc=jetty,dc=org",
"uniquemember: uid=uniqueuser,ou=subdir,ou=people,dc=jetty,dc=org",
"cn: developers",
// Entry 10
"dn: cn=admin,ou=groups,dc=jetty,dc=org",
"objectClass: groupOfUniqueNames",
"objectClass: top",
"ou: groups",
"description: People who try to run software build by developers",
"uniquemember: uid=someone,ou=people,dc=jetty,dc=org",
"uniquemember: uid=someoneelse,ou=people,dc=jetty,dc=org",
"uniquemember: uid=uniqueuser,ou=subdir,ou=people,dc=jetty,dc=org",
"cn: admin"
})
*/
public class JAASLdapLoginServiceTest
{
/* TODO restore this test
public static class TestConfiguration extends Configuration
{
private boolean forceBindingLogin;
public TestConfiguration(boolean forceBindingLogin)
{
this.forceBindingLogin = forceBindingLogin;
}
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
{
Map<String, String> options = new HashMap<>();
options.put("hostname", "localhost");
options.put("port", Integer.toString(_ldapServer.getTransports()[0].getPort()));
options.put("contextFactory", "com.sun.jndi.ldap.LdapCtxFactory");
options.put("bindDn", "uid=admin,ou=system");
options.put("bindPassword", "secret");
options.put("userBaseDn", "ou=people,dc=jetty,dc=org");
options.put("roleBaseDn", "ou=groups,dc=jetty,dc=org");
options.put("roleNameAttribute", "cn");
options.put("forceBindingLogin", Boolean.toString(forceBindingLogin));
AppConfigurationEntry entry = new AppConfigurationEntry(LdapLoginModule.class.getCanonicalName(), LoginModuleControlFlag.REQUIRED, options);
return new AppConfigurationEntry[]{entry};
}
}
public static LdapServer getLdapServer()
{
return _ldapServer;
}
public static void setLdapServer(LdapServer ldapServer)
{
_ldapServer = ldapServer;
}
private static LdapServer _ldapServer;
private Server _server;
private LocalConnector _connector;
private ServletContextHandler _context;
public void setUp() throws Exception
{
_server = new Server();
_connector = new LocalConnector(_server);
_server.addConnector(_connector);
_context = new ServletContextHandler();
_context.setContextPath("/ctx");
_server.setHandler(_context);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
security.setAuthenticator(new BasicAuthenticator());
_context.setSecurityHandler(security);
}
private JAASLoginService jaasLoginService(String name)
{
JAASLoginService ls = new JAASLoginService("foo");
ls.setCallbackHandlerClass("org.eclipse.jetty.ee10.jaas.callback.DefaultCallbackHandler");
ls.setIdentityService(new DefaultIdentityService());
ls.setConfiguration(new TestConfiguration(true));
return ls;
}
private String doLogin(String username, String password, List<String> hasRoles, List<String> hasntRoles) throws Exception
{
JAASLoginService ls = jaasLoginService("foo");
_server.addBean(ls, true);
_context.setServletHandler(new ServletHandler());
ServletHolder holder = new ServletHolder();
holder.setServlet(new TestServlet(hasRoles, hasntRoles));
_context.getServletHandler().addServletWithMapping(holder, "/");
_server.start();
return _connector.getResponse("GET /ctx/test HTTP/1.0\n" + "Authorization: Basic " +
Base64.getEncoder().encodeToString((username + ":" + password).getBytes(ISO_8859_1)) + "\n\n");
}
@Test
public void testLdapUserIdentity() throws Exception
{
setUp();
_context.setServletHandler(new ServletHandler());
ServletHolder holder = new ServletHolder();
holder.setServlet(new TestServlet(Arrays.asList("developers", "admin"), Arrays.asList("blabla")));
_context.getServletHandler().addServletWithMapping(holder, "/");
JAASLoginService ls = new JAASLoginService("foo");
ls.setCallbackHandlerClass("org.eclipse.jetty.ee10.jaas.callback.DefaultCallbackHandler");
ls.setIdentityService(new DefaultIdentityService());
ls.setConfiguration(new TestConfiguration(false));
_server.addBean(ls, true);
_server.start();
String response = _connector.getResponse("GET /ctx/test HTTP/1.0\n" + "Authorization: Basic " +
Base64.getEncoder().encodeToString("someone:complicatedpassword".getBytes(ISO_8859_1)) + "\n\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
_server.stop();
_context.setServletHandler(new ServletHandler());
holder = new ServletHolder();
holder.setServlet(new TestServlet(Arrays.asList("admin"), Arrays.asList("developers, blabla")));
_context.getServletHandler().addServletWithMapping(holder, "/");
_server.start();
response = _connector.getResponse("GET /ctx/test HTTP/1.0\n" + "Authorization: Basic " +
Base64.getEncoder().encodeToString("someoneelse:verycomplicatedpassword".getBytes(ISO_8859_1)) + "\n\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
}
@Test
public void testLdapUserIdentityBindingLogin() throws Exception
{
setUp();
_context.setServletHandler(new ServletHandler());
ServletHolder holder = new ServletHolder();
holder.setServlet(new TestServlet(Arrays.asList("developers", "admin"), Arrays.asList("blabla")));
_context.getServletHandler().addServletWithMapping(holder, "/");
JAASLoginService ls = new JAASLoginService("foo");
ls.setCallbackHandlerClass("org.eclipse.jetty.ee10.jaas.callback.DefaultCallbackHandler");
ls.setIdentityService(new DefaultIdentityService());
ls.setConfiguration(new TestConfiguration(true));
_server.addBean(ls, true);
_server.start();
String response = _connector.getResponse("GET /ctx/test HTTP/1.0\n" + "Authorization: Basic " +
Base64.getEncoder().encodeToString("someone:complicatedpassword".getBytes(ISO_8859_1)) + "\n\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
_server.stop();
_context.setServletHandler(new ServletHandler());
_context.addServlet(new HttpServlet()
{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
//check authentication status
if (req.getUserPrincipal() == null)
req.authenticate(resp);
}
}, "/");
_server.start();
//TODO this test shows response already committed!
response = _connector.getResponse("GET /ctx/test HTTP/1.0\n" + "Authorization: Basic " +
Base64.getEncoder().encodeToString("someone:wrongpassword".getBytes(ISO_8859_1)) + "\n\n");
System.err.println(response);
assertThat(response, startsWith("HTTP/1.1 " + HttpServletResponse.SC_UNAUTHORIZED));
}
@Test
public void testLdapBindingSubdirUniqueUserName() throws Exception
{
setUp();
String response = doLogin("uniqueuser", "hello123", Arrays.asList("developers", "admin"), Arrays.asList("blabla"));
assertThat(response, startsWith("HTTP/1.1 200 OK"));
}
//TODO test is failing, needs more work
@Test
public void testLdapBindingAmbiguousUserName() throws Exception
{
setUp();
String response = doLogin("ambiguousone", "foobar", null, null);
assertThat(response, startsWith("HTTP/1.1 " + HttpServletResponse.SC_UNAUTHORIZED));
}
//TODO test is failing, needs more work
@Test
public void testLdapBindingSubdirAmbiguousUserName() throws Exception
{
setUp();
String response = doLogin("ambiguousone", "barfoo", null, null);
assertThat(response, startsWith("HTTP/1.1 " + HttpServletResponse.SC_UNAUTHORIZED));
}
*/
}

View File

@ -0,0 +1,400 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.security.jaas;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import javax.security.auth.login.Configuration;
import org.apache.directory.server.annotations.CreateLdapServer;
import org.apache.directory.server.annotations.CreateTransport;
import org.apache.directory.server.core.annotations.ApplyLdifs;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.annotations.CreatePartition;
import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
import org.apache.directory.server.core.integ.ApacheDSTestExtension;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.Content;
import org.eclipse.jetty.security.DefaultIdentityService;
import org.eclipse.jetty.security.UserIdentity;
import org.eclipse.jetty.security.jaas.spi.LdapLoginModule;
import org.eclipse.jetty.server.Components;
import org.eclipse.jetty.server.ConnectionMetaData;
import org.eclipse.jetty.server.Context;
import org.eclipse.jetty.server.HttpStream;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Session;
import org.eclipse.jetty.server.TunnelSupport;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* JAASLdapLoginServiceTest
*/
@ExtendWith(ApacheDSTestExtension.class)
@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP")})
@CreateDS(name = "JAASLdapLoginServiceTest-class", partitions = {
@CreatePartition(name = "Users Partition", suffix = "ou=people,dc=jetty,dc=org"),
@CreatePartition(name = "Groups Partition", suffix = "ou=groups,dc=jetty,dc=org")
})
@ApplyLdifs({
// Entry 1
"dn: ou=people,dc=jetty,dc=org",
"objectClass: organizationalunit",
"objectClass: top",
"ou: people",
// Entry # 2
"dn:uid=someone,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: someone",
"sn: sn test",
"userPassword: complicatedpassword",
// Entry # 3
"dn:uid=someoneelse,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: someoneelse",
"sn: sn test",
"userPassword: verycomplicatedpassword",
// Entry 4
"dn: ou=groups,dc=jetty,dc=org",
"objectClass: organizationalunit",
"objectClass: top",
"ou: groups",
// Entry 5
"dn: ou=subdir,ou=people,dc=jetty,dc=org",
"objectClass: organizationalunit",
"objectClass: top",
"ou: subdir",
// Entry # 6
"dn:uid=uniqueuser,ou=subdir,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: uniqueuser",
"sn: unique user",
"userPassword: hello123",
// Entry # 7
"dn:uid=ambiguousone,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: ambiguous1",
"sn: ambiguous user",
"userPassword: foobar",
// Entry # 8
"dn:uid=ambiguousone,ou=subdir,ou=people,dc=jetty,dc=org",
"objectClass: inetOrgPerson",
"cn: ambiguous2",
"sn: ambiguous subdir user",
"userPassword: barfoo",
// Entry 9
"dn: cn=developers,ou=groups,dc=jetty,dc=org",
"objectClass: groupOfUniqueNames",
"objectClass: top",
"ou: groups",
"description: People who try to build good software",
"uniquemember: uid=someone,ou=people,dc=jetty,dc=org",
"uniquemember: uid=uniqueuser,ou=subdir,ou=people,dc=jetty,dc=org",
"cn: developers",
// Entry 10
"dn: cn=admin,ou=groups,dc=jetty,dc=org",
"objectClass: groupOfUniqueNames",
"objectClass: top",
"ou: groups",
"description: People who try to run software build by developers",
"uniquemember: uid=someone,ou=people,dc=jetty,dc=org",
"uniquemember: uid=someoneelse,ou=people,dc=jetty,dc=org",
"uniquemember: uid=uniqueuser,ou=subdir,ou=people,dc=jetty,dc=org",
"cn: admin"
})
public class JAASLdapLoginServiceTest extends AbstractLdapTestUnit
{
private JAASLoginService jaasLoginService(String name)
{
JAASLoginService ls = new JAASLoginService("foo");
ls.setCallbackHandlerClass("org.eclipse.jetty.security.jaas.callback.DefaultCallbackHandler");
ls.setIdentityService(new DefaultIdentityService());
ls.setConfiguration(new TestConfiguration(true));
return ls;
}
private UserIdentity doLogin(String username, String password) throws Exception
{
JAASLoginService ls = jaasLoginService("foo");
Request request = new MockCoreRequest();
return ls.login(username, password, request, null);
}
public static class TestConfiguration extends Configuration
{
private boolean forceBindingLogin;
public TestConfiguration(boolean forceBindingLogin)
{
this.forceBindingLogin = forceBindingLogin;
}
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
{
Map<String, String> options = new HashMap<>();
options.put("hostname", "localhost");
options.put("port", Integer.toString(ldapServer.getTransports()[0].getPort()));
options.put("contextFactory", "com.sun.jndi.ldap.LdapCtxFactory");
options.put("bindDn", "uid=admin,ou=system");
options.put("bindPassword", "secret");
options.put("userBaseDn", "ou=people,dc=jetty,dc=org");
options.put("roleBaseDn", "ou=groups,dc=jetty,dc=org");
options.put("roleNameAttribute", "cn");
options.put("forceBindingLogin", Boolean.toString(forceBindingLogin));
AppConfigurationEntry entry = new AppConfigurationEntry(LdapLoginModule.class.getCanonicalName(), LoginModuleControlFlag.REQUIRED, options);
return new AppConfigurationEntry[]{entry};
}
}
@Test
public void testLdapUserIdentity() throws Exception
{
JAASLoginService ls = new JAASLoginService("foo");
ls.setCallbackHandlerClass("org.eclipse.jetty.security.jaas.callback.DefaultCallbackHandler");
ls.setIdentityService(new DefaultIdentityService());
ls.setConfiguration(new TestConfiguration(false));
Request request = new MockCoreRequest();
UserIdentity userIdentity = ls.login("someone", "complicatedpassword", request, null);
assertNotNull(userIdentity);
assertTrue(userIdentity.isUserInRole("developers"));
assertTrue(userIdentity.isUserInRole("admin"));
assertFalse(userIdentity.isUserInRole("blabla"));
userIdentity = ls.login("someoneelse", "verycomplicatedpassword", request, null);
assertNotNull(userIdentity);
assertFalse(userIdentity.isUserInRole("developers"));
assertTrue(userIdentity.isUserInRole("admin"));
assertFalse(userIdentity.isUserInRole("blabla"));
}
@Test
public void testLdapUserIdentityBindingLogin() throws Exception
{
JAASLoginService ls = new JAASLoginService("foo");
ls.setCallbackHandlerClass("org.eclipse.jetty.security.jaas.callback.DefaultCallbackHandler");
ls.setIdentityService(new DefaultIdentityService());
ls.setConfiguration(new TestConfiguration(true));
Request request = new MockCoreRequest();
UserIdentity userIdentity = ls.login("someone", "complicatedpassword", request, null);
assertNotNull(userIdentity);
assertTrue(userIdentity.isUserInRole("developers"));
assertTrue(userIdentity.isUserInRole("admin"));
assertFalse(userIdentity.isUserInRole("blabla"));
userIdentity = ls.login("someone", "wrongpassword", request, null);
assertNull(userIdentity);
}
@Test
public void testLdapBindingSubdirUniqueUserName() throws Exception
{
UserIdentity userIdentity = doLogin("uniqueuser", "hello123");
assertNotNull(userIdentity);
assertTrue(userIdentity.isUserInRole("developers"));
assertTrue(userIdentity.isUserInRole("admin"));
assertFalse(userIdentity.isUserInRole("blabla"));
}
@Test
public void testLdapBindingAmbiguousUserName() throws Exception
{
UserIdentity userIdentity = doLogin("ambiguousone", "foobar");
assertNull(userIdentity);
}
@Test
public void testLdapBindingSubdirAmbiguousUserName() throws Exception
{
UserIdentity userIdentity = doLogin("ambiguousone", "barfoo");
assertNull(userIdentity);
}
private static class MockCoreRequest implements Request
{
@Override
public Object removeAttribute(String name)
{
return null;
}
@Override
public Object setAttribute(String name, Object attribute)
{
return null;
}
@Override
public Object getAttribute(String name)
{
return null;
}
@Override
public Set<String> getAttributeNameSet()
{
return null;
}
@Override
public void clearAttributes()
{
}
@Override
public String getId()
{
return null;
}
@Override
public Components getComponents()
{
return null;
}
@Override
public ConnectionMetaData getConnectionMetaData()
{
return null;
}
@Override
public String getMethod()
{
return null;
}
@Override
public HttpURI getHttpURI()
{
return null;
}
@Override
public Context getContext()
{
return null;
}
@Override
public HttpFields getHeaders()
{
return null;
}
@Override
public HttpFields getTrailers()
{
return null;
}
public List<HttpCookie> getCookies()
{
return null;
}
@Override
public long getBeginNanoTime()
{
return 0;
}
@Override
public long getHeadersNanoTime()
{
return 0;
}
@Override
public boolean isSecure()
{
return false;
}
@Override
public long getLength()
{
return 0;
}
@Override
public Content.Chunk read()
{
return null;
}
@Override
public boolean consumeAvailable()
{
return false;
}
@Override
public void demand(Runnable demandCallback)
{
}
@Override
public void fail(Throwable failure)
{
}
@Override
public void addIdleTimeoutListener(Predicate<TimeoutException> onIdleTimeout)
{
}
@Override
public void addFailureListener(Consumer<Throwable> onFailure)
{
}
@Override
public TunnelSupport getTunnelSupport()
{
return null;
}
@Override
public void addHttpStreamWrapper(Function<HttpStream, HttpStream> wrapper)
{
}
@Override
public Session getSession(boolean create)
{
return null;
}
}
}