blob: 2ef08fbc2f40c7ef447348a1a73f72293987c14b [file] [log] [blame] [view]
# Jetty 12 Migration Guide
## Overview
Apache Drill has been upgraded from Jetty 9 to Jetty 12 to address security vulnerabilities and maintain compatibility with modern Java versions.
## What Changed
### Core API Changes
1. **Servlet API Migration**: `javax.servlet.*` → `jakarta.servlet.*`
2. **Package Restructuring**: Servlet components moved to `org.eclipse.jetty.ee10.servlet.*`
3. **Handler API Redesign**: New `org.eclipse.jetty.server.Handler` interface
4. **Authentication APIs**: New `LoginService.login()` and authenticator signatures
### Modified Files
#### Key Changes
- **WebServer.java**: Updated resource loading, handler configuration, and security handler setup
- **DrillHttpSecurityHandlerProvider.java**: Refactored from `Handler.Wrapper` to extend `ee10.servlet.security.ConstraintSecurityHandler` for proper session management
- **DrillSpnegoAuthenticator.java**: Updated to Jetty 12 APIs with new `validateRequest(Request, Response, Callback)` signature
- **DrillSpnegoLoginService.java**: Updated `login()` method signature
- **DrillErrorHandler.java**: Migrated to use `generateAcceptableResponse()` for content negotiation
- **YARN WebServer.java**: Updated for Jetty 12 APIs and `IdentityService.newUserIdentity()`
#### Authentication Architecture
The authentication system was redesigned for Jetty 12:
- **DrillHttpSecurityHandlerProvider** now extends `ConstraintSecurityHandler` (previously `Handler.Wrapper`)
- Implements a `RoutingAuthenticator` that delegates to child authenticators (SPNEGO, FORM, BASIC)
- Handles session caching manually since delegated authenticators require explicit session management
- Properly integrated with `ServletContextHandler` via `setSecurityHandler()`
## Known Limitations
### Hadoop MiniDFSCluster Test Incompatibility
**Issue**: Tests using Hadoop's MiniDFSCluster cannot run due to Jetty version conflicts (Hadoop 3.x uses Jetty 9).
**Affected Tests** (temporarily disabled):
- `TestImpersonationDisabledWithMiniDFS.java`
- `TestImpersonationMetadata.java`
- `TestImpersonationQueries.java`
- `TestInboundImpersonation.java`
**Resolution**: Tests will be re-enabled when Apache Hadoop 4.x or a Hadoop 3.x maintenance release upgrades to Jetty 12 (tracked in [HADOOP-19625](https://issues.apache.org/jira/browse/HADOOP-19625)).
## Developer Guidelines
### Writing New Web Server Code
1. Use Jakarta EE 10 imports:
```java
import jakarta.servlet.http.HttpServletRequest;
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
```
2. Use Jetty constants:
```java
import org.eclipse.jetty.security.Authenticator;
String authMethod = Authenticator.SPNEGO_AUTH; // Not "SPNEGO"
```
3. For custom error handling, use `generateAcceptableResponse()`:
```java
@Override
protected void generateAcceptableResponse(ServletContextRequest baseRequest,
HttpServletRequest request,
HttpServletResponse response,
int code, String message,
String contentType) {
// Use contentType parameter, not request path
}
```
### Writing Authentication Code
When implementing custom authenticators:
1. Extend `LoginAuthenticator` and implement `validateRequest(Request, Response, Callback)`
2. Use `Request.as(request, ServletContextRequest.class)` to access servlet APIs from core Request
3. Return `AuthenticationState` (CHALLENGE, SEND_SUCCESS, or UserAuthenticationSucceeded)
4. Use `Response.writeError()` to properly send challenges with callback completion
Example:
```java
public class CustomAuthenticator extends LoginAuthenticator {
@Override
public AuthenticationState validateRequest(Request request, Response response, Callback callback) {
ServletContextRequest servletRequest = Request.as(request, ServletContextRequest.class);
// ... authentication logic ...
if (authFailed) {
response.getHeaders().put(HttpHeader.WWW_AUTHENTICATE, "Bearer");
Response.writeError(request, response, callback, HttpStatus.UNAUTHORIZED_401);
return AuthenticationState.CHALLENGE;
}
return new UserAuthenticationSucceeded(getAuthenticationType(), userIdentity);
}
}
```
### Writing Tests
1. **Use integration tests**: Test with real Drill server and `OkHttpClient`, not mocked servlets
```java
public class MyWebTest extends ClusterTest {
@Test
public void testEndpoint() throws Exception {
String url = String.format("http://localhost:%d/api/endpoint", port);
Request request = new Request.Builder().url(url).build();
try (Response response = httpClient.newCall(request).execute()) {
assertEquals(200, response.code());
}
}
}
```
2. **Avoid MiniDFSCluster** in tests that start Drill's HTTP server
3. **Session cookie names**: Tests should accept both "JSESSIONID" and "Drill-Session-Id"
## Dependency Management
Drill's parent POM includes the Jetty 12 BOM:
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-bom</artifactId>
<version>12.0.16</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
```
## Migration Checklist for Future Updates
- [ ] Update Jetty BOM version in parent POM
- [ ] Run full test suite including integration tests
- [ ] Verify checkstyle compliance
- [ ] Check HADOOP-19625 status for MiniDFSCluster test re-enablement
- [ ] Update this document with any new changes
## References
- [Jetty 12 Migration Guide](https://eclipse.dev/jetty/documentation/jetty-12/migration-guide/index.html)
- [Jakarta EE 10 Documentation](https://jakarta.ee/specifications/platform/10/)
- [HADOOP-19625: Upgrade Jetty to 12.x](https://issues.apache.org/jira/browse/HADOOP-19625)