Skip to content

BUG1413418: Prevent false positives on health checks - #452

Open
Kinjal-Arista wants to merge 10 commits into
bigswitch:mainfrom
Kinjal-Arista:BUG1413418
Open

BUG1413418: Prevent false positives on health checks#452
Kinjal-Arista wants to merge 10 commits into
bigswitch:mainfrom
Kinjal-Arista:BUG1413418

Conversation

@Kinjal-Arista

@Kinjal-Arista Kinjal-Arista commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Health check on older controllers can return status 200 with port 443 and /a prefix even though they
are not suported

Here's a curl request run on an older 8.10.x DMF controller with /a and port 443:

bhattack@bhattaRFXCQ7m ~ % curl -sk -D - https://10.243.254.58:443/a/api/v1/auth/healthy
HTTP/2 200 
server: nginx/1.20.1
date: Sun, 26 Jul 2026 21:25:24 GMT
content-type: text/html
content-length: 1682
last-modified: Sun, 26 Jul 2026 12:31:15 GMT
etag: "6a65fe13-692"
content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:
cache-control: public, max-age=604800
strict-transport-security: max-age=31536000
accept-ranges: bytes

<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"><link rel="apple-touch-icon" sizes="180x180" href="/favicons/dmf/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicons/dmf/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicons/dmf/favicon-16x16.png"><link rel="manifest" href="/favicons/dmf/site.webmanifest"><link rel="mask-icon" href="/favicons/dmf/safari-pinned-tab.svg" color="#5bbad5"><link rel="shortcut icon" href="/favicons/dmf/favicon.ico"><meta name="msapplication-TileColor" content="#da532c"><meta name="msapplication-config" content="/favicons/dmf/browserconfig.xml"><meta name="theme-color" content="#000000"><script>const global = globalThis;</script><script type="module" crossorigin src="/ui-assets/index-DqKzWq2q.js"></script><link rel="modulepreload" crossorigin href="/ui-assets/antd-CGdjyTOk.js"><link rel="modulepreload" crossorigin href="/ui-assets/@arista/react-components-mCWPzMqs.js"><link rel="modulepreload" crossorigin href="/ui-assets/@arista/big-components-C018Nt5g.js"><link rel="modulepreload" crossorigin href="/ui-assets/recharts-3el1gYDM.js"><link rel="modulepreload" crossorigin href="/ui-assets/react-flow-renderer-CtDox3TI.js"><link rel="stylesheet" crossorigin href="/ui-assets/@arista/big-components-CuCGYpG2.css"><link rel="stylesheet" crossorigin href="/ui-assets/index-BdeNc5Xk.css"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>% 

As seen above, it return 200 but the output is unexpected as /a and port 443 is not supported here but it returns a GUI/nginx catch-all HTML page

The right url returns the following :

bhattack@bhattaRFXCQ7m ~ % curl -sk -D - https://10.243.254.58:/api/v1/auth/healthy 
HTTP/2 200 
server: nginx/1.20.1
date: Sun, 26 Jul 2026 21:36:13 GMT
content-type: application/json
accept-ranges: bytes
vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
content-security-policy: frame-ancestors 'none'; default-src 'none';

true%  

So, to differentiate between the 2, adding a new check here that checks if content-type is application/json in which case its a valid response, otherwise not
Added the previously reverted pybsn PR in the first commit of this PR as well

PartialFixes: BUG1413418

@Kinjal-Arista

Kinjal-Arista commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Test results:
Using the following command:

python3 -c "import sys; sys.path.insert(0, <local_pybsn_path>); import pybsn; c=pybsn.connect(<controller_ip>, username='admin', password='adminadmin', verify_tls=False); print(c.url)"

With 8.11 controllers:
https://10.226.74.20:443/a

With 8.10 controllers:
https://10.226.77.216:8443

bigswitch#446)

Enables pybsn to automatically discover and connect to BigDB services
that have been migrated to port 443 with the /a/api prefix
This PR is a follow-up after the previous PR ran into a bug. pybsn was
updated to discover the new REST base URL on
port 443 as https://<host>:443/a, but login still created the session
cookie with path /api. That meant login could
succeed, while the next authenticated request to /a/api/... failed with
401 because the cookie was not sent. In CVML
this showed up as repeated pybsn client NOT connected polling until
timeout.

This change derives the session cookie path from the base URL path
prefix, so https://<host>:443/a uses /a/api while
legacy URLs like https://<host>:443 and https://<host>:8443 continue to
use /api.

Tested with unit tests and against a CVML controller with a custom
script written using codex to utilise the new pybsn
to make a GET request to the controller:

- old reverted version resolved `https://10.226.78.185:443/a`, set
cookie path /api, and failed the first authenticated
    GET with 401
- this version resolved `https://10.226.78.185:443/a`, set cookie path
/a/api, and the same authenticated GET
    succeeded

Fixes: BUG1413418
(cherry picked from commit 4dc837a)
@Kinjal-Arista
Kinjal-Arista force-pushed the BUG1413418 branch 2 times, most recently from a1a75ae to 9af8745 Compare July 28, 2026 10:38
Comment thread pybsn/__init__.py Outdated
Comment thread pybsn/__init__.py Outdated
Comment thread pybsn/__init__.py Outdated
Comment thread pybsn/__init__.py Outdated
Comment thread pybsn/__init__.py Outdated
if parsed.port is not None:
raise ValueError(f"Schemeless hosts must not include an explicit port: {host!r}")
hostname = _format_url_authority(hostname)
path_prefix = _normalize_path_prefix(parsed.path)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why do we need this.
If host parameter is:

  1. just a hostname/ipaddress, e.g. 1.2.3.4 -> we try standard API endpoints, https://1.2.3.4:443/a, https://1.2.3.4:8443/, http://1.2.3.4:80/ and return the first reachable
  2. full url with schema, e.g. https://foo.example.com:1234/someprefix/ -> we just return the provided host
  3. hostname/ipaddress with path, e.g. 1.2.3.4/foo -> we try standard API ports, but with given prefix, this is, https://1.2.3.4:443/foo, https://1.2.3.4:8443/foo, `http://1.2.3.4:80/foo.

Use-case for 1 is obvious - user wants to connect to controller running on given host. Use-case for 2 is also obvious (but probably less common) - user wants to try only specific endpoint (e.g. knows that 8443/80 won't work) or the controller may be running behind some reverse-proxy that prepends adds its own prefix.
But what's the use-case for 3? Trying out all the standard ports suggests user is trying to connect to the controller directly, without any reverse proxy that might modify path. So, what's the point in allowing user to specify the path?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed support for schemeless host/prefix inputs

Comment thread pybsn/__init__.py Outdated

@YutaHiguchi-bsn YutaHiguchi-bsn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, there was a typos in PR description: suported

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.

4 participants