-
Notifications
You must be signed in to change notification settings - Fork 4
Add dependency-free "light" WinRM backend behind a runtime toggle #109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
b1a19ef
Add dependency-free "light" WinRM backend behind a runtime toggle
bertysentry bb266b8
Address Codex review: honor backend toggle for file copy, harden XML …
bertysentry 1da7d38
Harden light backend: reject unencrypted responses, fix timeout/close…
bertysentry b549182
Harden light backend NTLM/HTTP protocol parsing (P2 review)
bertysentry dbb0ad4
Make the light backend the default (CXF now opt-in)
bertysentry df65e97
Harden light default: auth downgrade, hostname parsing, EndOfSequence…
bertysentry 40d5410
Serialize operations on the light backend's NTLM connection (P1 review)
bertysentry 9c8af0b
Reconnect the light backend after a peer closes an idle keep-alive so…
bertysentry 6b61322
Harden light backend: reject unknown backend, clamp timeout, closed-s…
bertysentry 1a93929
Add HTTPS support to the light backend (validate TLS by default)
bertysentry c6e924a
Extract an AuthScheme seam; move NTLM into NtlmAuthScheme (no behavio…
bertysentry ab656c7
Add Kerberos (SPNEGO) support to the light backend via JDK JGSS (#105)
bertysentry e2261c6
Remove unused imports left by the AuthScheme extraction (checkstyle)
bertysentry 324154b
Don't wedge on an auth rejection; fall back on a server-side 401 (rev…
bertysentry 2625fcf
Fall through on active-scheme re-auth failure; dispose auth on close …
bertysentry 782604e
Document the light-default upgrade warning (README, site, CHANGELOG)
bertysentry 38c51ab
Decode command output once, not per chunk, to preserve split multibyt…
bertysentry ccfeed6
Match the CXF backend's exception surface and fault mapping (#106)
bertysentry b9b41c9
Add the recorded-exchange protocol test rig and differential harness …
bertysentry 70c2546
Remove the CXF backend; the dependency-free client is the only one (2…
bertysentry 83884ba
Add AGENTS.md and CLAUDE.md agent instructions
bertysentry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # Instructions for AI Agents | ||
|
|
||
| ## Code format | ||
|
|
||
| You never need to worry about code formatting at all. Simply run `mvn formatter:format` before committing changes to make sure the new code follows this project's code formatting rules. Make sure not to run `mvn formatter:format` separately before other Maven commands, to avoid concurrency issues. | ||
|
|
||
| All files must include the proper license header. When you add a new file, make sure to include the proper license header by running the `mvn license:update-file-header` command before committing (or even before trying the build and test, since the build will fail if a file doesn't include the proper license header). | ||
|
|
||
| All public methods must have proper Javadoc. Check the output of Maven to identify issues with Javadoc and fix these issues. | ||
|
|
||
| ## Build | ||
|
|
||
| The project uses Maven to build. A full build is performed with `mvn verify site` (or `mvn clean verify site` when applicable). | ||
|
|
||
| @codex, please don't try to use `mvnw` (Maven Wrapper). Maven is already installed and runs perfectly well. | ||
|
|
||
| ## Test | ||
|
|
||
| Whenever required, when you add code or when you modify code that is not covered with unit tests, add the corresponding unit tests. All tests must pass with `mvn test`. Don't use the `-q` (silent) option, as you want to see the result of successful tests. Tests are run with the Maven surefire plugin and results are stored in the ./target/surefire-reports directory. | ||
|
|
||
| ## Code quality reports | ||
|
|
||
| Code quality checks are performed during the build with `mvn verify` (checkstyle, pmd, and spotbugs). Always build the project with `mvn verify` and fix any problem reported in ./target/checkstyle-result.xml, ./target/pmd.xml, and ./target/spotbugsXml.xml before committing and submitting your code! | ||
|
|
||
| ## Documentation | ||
|
|
||
| Any change that affects the end user of this library must be properly documented in README.md. | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Changelog | ||
|
|
||
| All notable changes to this project are documented in this file. | ||
|
|
||
| ## [Unreleased] — 2.0.0 | ||
|
|
||
| ### ⚠️ Breaking — the CXF backend was removed | ||
|
|
||
| Version 2.0.0 removes the legacy Apache CXF backend. The dependency-free client introduced in the | ||
| previous release is the only implementation; the public API is unchanged, so calling code is | ||
| unaffected. Consequences: | ||
|
|
||
| - **WinRM over HTTPS with self-signed certificates**: unlike the CXF-based client — which silently | ||
| trusted every TLS certificate and skipped hostname verification — this client **validates the | ||
| server certificate and verifies the hostname by default**. Connections to hosts with self-signed | ||
| or otherwise untrusted certificates **fail** during the TLS handshake unless you: | ||
| - install the server certificate (or its issuing CA) into a Java trust store | ||
| (`-Djavax.net.ssl.trustStore=...`); or | ||
| - disable TLS validation with `-Dorg.metricshub.winrm.tls.insecure=true` | ||
| (**insecure — for testing only**). | ||
| - Setting `-Dorg.metricshub.winrm.backend=cxf` now fails with a clear error instead of selecting | ||
| the removed backend: remove the property (or stay on winrm-java 1.x). | ||
| - The jar shrinks dramatically: the Apache CXF / JAX-WS / JAXB stack is gone and the only runtime | ||
| dependency left is `smbj` (used for copying files to remote shares). | ||
|
|
||
| ### Removed | ||
|
|
||
| - The Apache CXF-based backend (`WinRMService` and the `service.client` internals), the CXF / | ||
| JAX-WS / JAXB / `jaxws-rt` dependencies, and the WSDL/XSD resources and code generation. | ||
| - `KerberosCredentialsException` (was thrown only by CXF internals). | ||
|
|
||
| ### Added | ||
|
|
||
| - Dependency-free WinRM client with no Apache CXF / JAX-WS / JAXB stack, immune by construction to | ||
| JAXP `ServiceLoader` conflicts (it uses the JDK-default XML factories). Supports NTLM over HTTP | ||
| (with message encryption) and HTTPS, and Kerberos (SPNEGO, via the JDK GSS-API) over HTTPS. | ||
| - `org.metricshub.winrm.tls.insecure` system property to trust all TLS certificates and skip | ||
| hostname verification (insecure — for testing only). | ||
| - In-process protocol tests (`WsmanProtocolTest` + `FakeWsmanServer`) covering the full WSMan | ||
| path — NTLM handshake, message encryption, multipart framing, Enumerate/Pull paging, shell | ||
| lifecycle, and fault mapping — with no Windows host required (they run in `mvn verify`). | ||
| - `WinRMLiveTest`: a one-command smoke run against a real host (see README). Before the CXF | ||
| removal, its predecessor (`BackendDifferentialTest`) proved result parity between the two | ||
| backends on live hosts. | ||
|
|
||
| ### Changed | ||
|
|
||
| - HTTPS connections validate certificates and verify hostnames by default (see the breaking | ||
| change above). | ||
| - The exception surface matches the pre-2.0.0 CXF backend (feature parity): authentication | ||
| rejections raise the same `Authentication error on <endpoint> with user name "<user>"` message, | ||
| operations on a closed executor raise the same `IllegalStateException` message, the WSMan | ||
| `OperationTimeout` header uses the same `PT#.###S` millisecond-precision format, and the | ||
| `EndOfSequence` / `Items` enumeration markers are recognized in both their WS-Enumeration and | ||
| WSMan namespace variants. WSMan fault exceptions additionally carry the detailed `WSManFault` | ||
| message (including the provider-level detail, e.g. WMI `WBEM_E_*` mnemonics) alongside the SOAP | ||
| reason text. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| @AGENTS.md |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| package org.metricshub.winrm.light; | ||
|
|
||
| /*- | ||
| * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ | ||
| * WinRM Java Client | ||
| * ჻჻჻჻჻჻ | ||
| * Copyright 2023 - 2026 MetricsHub | ||
| * ჻჻჻჻჻჻ | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ | ||
| */ | ||
|
|
||
| /** | ||
| * Authentication and message protection for one WSMan connection. A scheme owns its handshake, its | ||
| * connection-bound session state, and how it wraps/unwraps the SOAP payload — the two things that | ||
| * differ between NTLM and Kerberos. {@link WsmanClient} is otherwise mechanism-agnostic and just | ||
| * delegates to the scheme, so a new mechanism is added by implementing this interface rather than | ||
| * branching the client. | ||
| * | ||
| * <p>All methods are called while {@code WsmanClient} holds its operation lock, so implementations | ||
| * need no internal synchronization. | ||
| */ | ||
| interface AuthScheme { | ||
| /** | ||
| * Run the full authentication handshake over the given transport (which may involve several | ||
| * request/response legs), leaving the connection authenticated. | ||
| * | ||
| * @param transport the connection to authenticate | ||
| * @return the {@code Authorization} header value to attach to the first real request, or | ||
| * {@code null} if none is needed | ||
| * @throws Exception if the handshake fails | ||
| */ | ||
| String authenticate(HttpTransport transport) throws Exception; | ||
|
|
||
| /** @return whether the connection is currently authenticated. */ | ||
| boolean isAuthenticated(); | ||
|
|
||
| /** | ||
| * Drop the authenticated state so the next request re-runs the handshake. Called when the | ||
| * underlying connection was lost, since the session state is bound to the TCP connection. | ||
| */ | ||
| void reset(); | ||
|
|
||
| /** | ||
| * Encode an outgoing SOAP body for the wire (sealing it over plain HTTP, or passing it through | ||
| * over HTTPS where TLS provides confidentiality). | ||
| * | ||
| * @param soapUtf8 the SOAP envelope, UTF-8 encoded | ||
| * @return the bytes to send as the request body | ||
| */ | ||
| byte[] wrap(byte[] soapUtf8); | ||
|
|
||
| /** @return the {@code Content-Type} for the body produced by {@link #wrap(byte[])}. */ | ||
| String wrapContentType(); | ||
|
|
||
| /** | ||
| * Decode a response body back to plaintext SOAP bytes, verifying integrity where the mechanism | ||
| * provides it. | ||
| * | ||
| * @param response the HTTP response | ||
| * @return the plaintext SOAP bytes to parse | ||
| * @throws Exception if the body cannot be trusted or decoded | ||
| */ | ||
| byte[] unwrap(HttpTransport.Response response) throws Exception; | ||
|
|
||
| /** | ||
| * After the server rejects this scheme on a real request (HTTP 401) — which for Kerberos/NTLM only | ||
| * surfaces after {@link #authenticate} has returned, because the token/Type-3 rides the first real | ||
| * request — move to the next candidate of an ordered fallback list, if any. A single scheme cannot | ||
| * advance. | ||
| * | ||
| * @return {@code true} if a further scheme is now available so the caller should re-authenticate and | ||
| * retry; {@code false} if there is nothing left to try | ||
| */ | ||
| default boolean advance() { | ||
| return false; | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.