Skip to content

Add HTTP Basic authentication to the Yamcs action for proxied servers - #1447

Merged
Paul Lizer (paullizer) merged 3 commits into
Developmentfrom
paullizer-yamcs-basic-auth
Sep 5, 2026
Merged

Add HTTP Basic authentication to the Yamcs action for proxied servers#1447
Paul Lizer (paullizer) merged 3 commits into
Developmentfrom
paullizer-yamcs-basic-auth

Conversation

@paullizer

Copy link
Copy Markdown
Contributor

Summary

  • Adds an optional Reverse Proxy Authentication layer to the Yamcs action so SimpleChat can reach a Yamcs server published through a reverse proxy (Apache) that enforces HTTP Basic authentication against Active Directory. Yamcs behind such a proxy typically has no authentication of its own.
  • Off by default, so a directly reachable Yamcs server — such as a local simulator — is unaffected and sends no extra credential.
  • The proxy credential can be typed inline (password stored in Key Vault) or supplied by a reusable username/password workspace identity, so a rotating directory-issued temporary password is maintained once under Workspace → Identities instead of by editing every action.
  • The proxy credential has its own identity reference, separate from the Yamcs credential reference, so one action can use both.

Linked issue

Fixes #1435

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

Version bump

  • application/single_app/config.py VERSION third segment bumped, or not needed because this is docs-only
  • deployers/version.txt bumped, or not needed because deployers/ was not changed

VERSION is 0.261.012. This branch was rebased onto Development after 0.261.010 and 0.261.011 shipped for the Azure Managed Redis work, so the version and release-notes section were re-numbered to avoid colliding with those releases.

Design notes

yamcs-client==2.1.0 is already pinned in requirements.txt and ships BasicAuthCredentials, so there is no dependency change. It is imported lazily and separately from the other credential classes, so a deployment running an older yamcs-client keeps working for every non-proxy auth method and only sees an actionable upgrade message when proxy auth is actually requested.

Authentication compatibility

Only one HTTP Authorization header can be sent, which makes two combinations genuinely impossible rather than merely unimplemented:

Yamcs auth method Allowed Mechanism
No Authentication Yes BasicAuthCredentials passed as credentials=
API Key Yes APIKeyCredentials uses x-api-key, leaving Authorization free for the proxy
Username and Password No Yamcs exchanges credentials for a bearer token on Authorization, and the /auth/token request would itself be refused by the proxy
Access Token No Bearer also requires Authorization

The rule is enforced in four places — the plugin, PluginHealthChecker at save time, the test-connection route, and the action modal — so the conflict surfaces before an agent depends on it.

Identity refactor

The proxy reference is resolved inside validate_action_identity_reference and hydrate_action_identity_reference, so all existing personal, group, and global action call sites pick it up with no changes. UI (TRIGGER) hydration returns the identity username but never the password; runtime (VALUE) hydration resolves both.

Testing / validation

  • functional_tests/test_yamcs_basic_auth.py12/12 (new)
  • functional_tests/test_yamcs_action_plugin.py14/14 (unchanged, no regression)
  • functional_tests/test_docs_app_surface_coverage.py7/7
  • functional_tests/test_docs_site_quality.py6/6
  • route_tests/test_route_blueprint_policy_inventory.py6/6; plus the unauthenticated-policy and policy-coverage route suites
  • Wider sweep across identity, plugin, health-check and Key Vault suites found zero new failures. One pre-existing failure in test_action_workspace_identity_scoping.py::test_workspace_identity_action_helpers was confirmed identical on the baseline via git stash.
  • node --check on plugin_modal_stepper.js; py_compile on every changed Python module; verified all functions_yamcs_operations imports resolve across the four importing modules.
  • A code review pass caught one real bug, now fixed: turning the toggle off blanked the stored credential, which would drop the Key Vault reference and orphan the secret. A regression test covers it and was verified to fail when the bug is reintroduced.

Not validated: live connectivity against a real proxied Yamcs server, which needs the partner team's dev environment.

Documentation

  • Release notes updated, or not needed
  • Feature documentation updated, or not needed
  • Fix documentation updated, or not needed

Updated docs/reference/actions/yamcs.md, docs/explanation/features/YAMCS_ACTION.md, and docs/explanation/release_notes.md (plus the generated release-notes index).

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security())
  • Settings sent to non-admin frontends use sanitize_settings_for_user()
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS
  • No secrets, keys, connection strings, or local-only artifacts are included

No new routes were added; the existing test-yamcs-connection route already carries the decorator and keeps it. basic_auth_password is registered in YAMCS_SENSITIVE_ADDITIONAL_FIELDS, so it inherits the existing Key Vault store/redact/retrieve/delete handling, and the test-connection route resolves it with ACTION_ADDITIONAL_SECRET_SOURCES scope enforcement. The password never reaches the browser, logs, or telemetry — only the boolean basic_auth_enabled is logged.

Known limitation

A reusable identity resolves within the workspace scope that owns the action, so a personal action paired with a personal identity gives each engineer their own credential. A single shared group action resolves one group-scoped credential rather than a distinct credential per member; per-user resolution at chat time would be a materially larger feature and is out of scope here.

Ground segments commonly publish Yamcs through a reverse proxy, such as Apache,
that challenges every request with HTTP Basic authentication against a directory
before the request reaches Yamcs. Yamcs behind that proxy often has no
authentication of its own. The Yamcs action could authenticate to Yamcs but had
no way to answer a front-door proxy challenge, so such a server was unreachable
even when every Yamcs setting was correct.

Adds an optional Reverse Proxy Authentication layer, independent of the Yamcs
authentication method and off by default so a directly reachable server, such as
a local simulator, is unaffected.

Credentials can be entered inline, with the password stored in Key Vault, or
supplied by a reusable username/password identity. The proxy credential gets its
own identity reference, separate from the Yamcs credential, so one action can use
both and a rotating temporary password is maintained once under Workspace >
Identities instead of by editing the action.

Proxy Basic auth combines with the none and api_key Yamcs methods. It is blocked
for username_password and bearer_token: only one Authorization header can be
sent, and the Yamcs token exchange would itself be refused by the proxy. The rule
is enforced in the plugin, the health checker, the test-connection route, and the
action modal, so the conflict surfaces before an agent depends on it.

Implementation notes:

- yamcs-client 2.1.0 already ships BasicAuthCredentials, so no dependency change
  is needed. It is imported separately from the other credential classes so a
  deployment on an older client keeps working for every non-proxy method.
- basic_auth_password is registered in YAMCS_SENSITIVE_ADDITIONAL_FIELDS, which
  routes it through the existing Key Vault store, redact, retrieve, and delete
  handling.
- The proxy identity reference is resolved inside validate_action_identity_reference
  and hydrate_action_identity_reference, so personal, group, and global action
  paths pick it up unchanged. UI hydration returns the identity username but never
  its password.
- Turning the toggle off preserves the stored credential rather than blanking it,
  which would drop the Key Vault reference and orphan the secret.

Fixes #1435

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread application/single_app/route_backend_plugins.py Outdated
… through an exception'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit 3ded21a into Development Sep 5, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants