Repository navigation
Conversation
Bobbins228
left a comment
There was a problem hiding this comment.
Requesting changes for two reproducible cases:
-
crates/openshell-cli/src/commands/gateway.rs:1092-1098:mtls_certs_exist_for_gatewaychecks only whether all three paths are files. A zero-bytetls.keytherefore suppresses the package import. With a valid package bundle and a local mTLS test server, the base commit imported the package bundle and connected; this PR kept the empty key, reported "Using existing mTLS certificates," and could not connect. Please treat unusable files as an incomplete bundle before choosing the fallback (or reject registration with a clear error rather than reporting success). -
deploy/rpm/TROUBLESHOOTING.md:94-98: the externally-managed certificate example copies the bundle intogateways/openshell/mtls/but registershttps://<gateway-hostname>:17670without--name openshell. For a non-loopback hostname, the CLI derives the hostname as the gateway name and looks ingateways/<gateway-hostname>/mtls/. I reproduced the PR importing package credentials for that derived name while leaving the explicitopenshellbundle unused. Please add--name openshellto the example and cover that documented flow.
The primary preservation case works in a live before-and-after mTLS test, and all 33 gateway unit tests pass.
bba5b69 to
da2d21b
Compare
|
@Bobbins228 both findings addressed in da2d21b:
Thanks for the thorough review — the before/after repro caught exactly the flows we had not enumerated. |
TaylorMutch
left a comment
There was a problem hiding this comment.
Requesting one change before merge:
[P1] Reject partially present gateway bundles instead of importing over them.
gateway_mtls_bundle_state() classifies any missing expected file as Incomplete, and gateway_add() then imports the package bundle, replacing any gateway-specific files already present. If external provisioning copies ca.crt and tls.crt but is interrupted before tls.key, registration silently replaces those authoritative files with unrelated package credentials and recreates the UnknownIssuer failure this PR addresses. The new gateway_add_local_imports_package_bundle_when_existing_bundle_is_incomplete test confirms this behavior.
Please distinguish between no expected files, where package fallback is appropriate, and some-but-not-all expected files, which should fail while naming the missing files. The incomplete-bundle test should assert that registration fails and the existing files remain untouched; a separate no-files case can retain coverage for package fallback.
The complete-bundle preservation, malformed-PEM rejection, explicit --name openshell documentation, and associated tests otherwise look good. I ran all 36 gateway unit tests locally at da2d21bb; they passed, and git diff --check is clean.
da2d21b to
ce741db
Compare
|
@TaylorMutch , Adressed in my last push, I splitted the Thanks a ton for the review!! |
|
/ok to test ce741db |
Compatibility review (advisory)New or updated breaking changes; see the full report for all findings. 1. cli — No explicit risk acceptance found
Review details
Advisory review; publication gates are unchanged. |
TaylorMutch
left a comment
There was a problem hiding this comment.
The previous partial-bundle finding is resolved at ce741db9: Absent and Partial are now distinct, partial bundles fail with the missing paths, existing files remain untouched, and the no-files package fallback has separate coverage. I ran all 37 gateway unit tests locally; they pass, git diff --check is clean, and the full GitHub branch checks are green.
One newly surfaced compatibility issue still blocks approval:
[P1] Preserve the package-managed refresh behavior on the 0.1.x patch train.
The Stable v0.1.5 documentation explicitly says that openshell gateway add <endpoint> --local --name openshell refreshes the CLI bundle from the package-managed TLS directory. After gateway remove (which intentionally leaves mtls/ behind), the old add path imports the current package credentials over that complete stored bundle. This PR now classifies that bundle as Usable and skips the import, so existing package automation and users following the documented remove/add refresh flow retain stale credentials instead.
This is a breaking change to a Stable CLI behavior in the active 0.1.6 patch train. Please retain the existing refresh behavior by default and make preservation of externally managed credentials explicit through an additive flag or durable provenance marker, then update the external-certificate example and tests to select that path. Alternatively, this default behavior change needs a minor release with notice and migration guidance.
Evidence:
- Stable v0.1.5 contract: https://github.com/NVIDIA/OpenShell/blob/v0.1.5/docs/how-it-works/gateways/authentication.mdx#L51-L52
- New skip-import branch:
OpenShell/crates/openshell-cli/src/commands/gateway.rs
Lines 1198 to 1202 in ce741db
- Release policy: https://github.com/NVIDIA/OpenShell/blob/main/docs/about/support-matrix.mdx#L33-L36
The preservation logic itself otherwise looks correct.
Closes NVIDIA#2560 `gateway add --local` imports the package-managed mTLS bundle, refreshing a complete stored bundle so the documented remove/add flow rotates package credentials — the Stable v0.1.5 behavior. A caller that provisions gateway-specific credentials before registration (the documented externally-managed certificates flow in deploy/rpm/TROUBLESHOOTING.md) now opts out of the refresh with the additive --preserve-mtls-bundle flag, which keeps the existing complete bundle untouched. A present-but-partial or unusable bundle still fails registration naming the missing or broken paths: interrupted provisioning is never silently repaired or discarded, and the no-files package fallback keeps first-setup behavior. Signed-off-by: Gaizka Menendez Hernandez <gmenende@redhat.com>
ce741db to
94b7036
Compare
|
Addressed at 94b7036: The external-certificate examples (TROUBLESHOOTING.md Option 2 and the compose mTLS flow in container-deployment.mdx) and their tests now select the flag, and a new test pins the default refresh contract ( Happy to address anything else. |
Bobbins228
left a comment
There was a problem hiding this comment.
Reviewed and tested 94b7036d0be6b82796f98cc270eb224060a90375.
The specific reproductions from the previous reviews are addressed: empty/non-PEM files are rejected, ordinary partial bundles remain untouched, the external-certificate example names the gateway explicitly, and package-managed refresh is restored by default with preservation selected through --preserve-mtls-bundle.
Requesting changes for two narrower remaining cases, detailed in the inline comments:
- With all three expected paths represented by dangling symlinks,
--preserve-mtls-bundlestill replaces those entries with package credentials. - A PEM-wrapped invalid private key is classified as usable, so registration succeeds and saves metadata even though the TLS client rejects the material.
Both were reproduced locally with additional tests at this commit. The tests fail their safety assertions because the links are replaced and the invalid key is registered, respectively.
Validation passed:
- All 38 gateway unit tests.
- All six existing mTLS integration tests.
- An additional live mTLS test with two independent CAs: the preserve flag retains the supplied bundle and connects while a competing package bundle is available.
cargo fmt --all -- --check.- Clippy for the CLI library and binary with warnings denied.
- Documentation navigation validation and Fern check (zero errors; three warnings outside the changed pages).
Please also update the PR description to match the current implementation: preservation is opt-in, default package refresh is retained, and partial bundles are rejected. GitHub branch CI for this head is still waiting for authorization.
| mtls.join("tls.crt"), | ||
| mtls.join("tls.key"), | ||
| ]; | ||
| let present_count = files.iter().filter(|p| p.is_file()).count(); |
There was a problem hiding this comment.
Keep dangling certificate links distinct from an absent bundle. Before this change, local registration could replace externally provisioned credentials. The new --preserve-mtls-bundle path still does this when all three expected paths are dangling symlinks: is_file() follows the links and returns false, so the bundle becomes Absent and the package import replaces the entire directory, including the caller's links.
I reproduced this at 94b7036 with ca.crt, tls.crt, and tls.key pointing into a temporarily unavailable external directory, a valid package bundle, and registration with --local --preserve-mtls-bundle. Registration succeeded and all three symlinks were replaced by regular package credential files. This is a remaining edge case of the earlier preservation finding; ordinary partially present files are now handled correctly.
Please distinguish genuinely missing directory entries from existing links or unreadable entries, reject the latter without importing, and add a regression test asserting that the links remain intact.
| } | ||
| let mut cursor = std::io::Cursor::new(bytes); | ||
| if is_private_key { | ||
| let key = rustls_pemfile::private_key(&mut cursor) |
There was a problem hiding this comment.
Validate the decoded key before classifying the bundle as usable. The earlier empty-key/non-PEM reproductions are fixed, but the new validation still lets a caller register with credentials that the TLS client cannot use. rustls_pemfile::private_key() decodes the PEM envelope; finding a block does not establish that its contents are a valid private key or match the client certificate.
I reproduced this at 94b7036 with a valid CA/client certificate, a valid competing package bundle, and the following stored tls.key:
-----BEGIN PRIVATE KEY-----
AA==
-----END PRIVATE KEY-----
With --local --preserve-mtls-bundle, registration succeeds, saves metadata, and prints Using existing mTLS certificates, although build_rustls_config() rejects those same materials. This is a remaining case of the original unusable-bundle concern: the failure is reduced to a generic reachability warning instead of rejecting the broken bundle before registration.
Please validate the decoded certificate/key material with the client TLS configuration builder or a shared equivalent before returning Usable, and cover a PEM-wrapped invalid key in the regression tests.
…tls-bundle/gmenher # Conflicts: # crates/openshell-cli/src/tls.rs
Summary
gateway add --localcould replace an externally provisioned mTLS bundle with unrelated package-managed credentials. This PR keeps package-managed refresh as the default while adding an explicit--preserve-mtls-bundlepath for externally managed credentials.Related Issue
Closes #2560.
Compatibility
--preserve-mtls-bundleis supplied.Changes
symlink_metadataso existing dangling links cannot be mistaken for an absent bundle.Testing
cargo test -p openshell-cli --lib commands::gateway— 40 testscargo test -p openshell-cli --test mtls_integration— 6 testscargo fmt --all -- --checkcargo clippy -p openshell-cli --lib --bin openshell -- -D warningsmise run pre-commitChecklist