SAP LeanIX GraphQL proxy with browser token extraction via Playwright
Project description
lean-ix — SAP LeanIX GraphQL Proxy
A local proxy server that:
- Connects to your already-logged-in browser via Playwright CDP
- Extracts the active Bearer token from LeanIX network requests
- Exposes a local GraphQL endpoint that proxies to LeanIX
- Serves a GraphiQL UI for interactive exploration
Prerequisites
- Python 3.14+ and uv
- Google Chrome or Microsoft Edge installed
- Playwright browsers installed (one-time step)
# One-time: install Playwright browser binaries
uv run playwright install chromium
Quick Start
Step 1 — Launch a debug Edge/Chrome instance
If Edge or Chrome is already running, you cannot simply add
--remote-debugging-portto a new shortcut — the flag is silently ignored and the port never opens. You must launch a separate isolated instance using a different--user-data-dir.
# Edge (recommended — already installed on Windows)
Start-Process "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" `
"--remote-debugging-port=9222 --user-data-dir=C:\Temp\edge-debug --no-first-run --no-default-browser-check"
# Chrome
Start-Process "C:\Program Files\Google\Chrome\Application\chrome.exe" `
"--remote-debugging-port=9222 --user-data-dir=C:\Temp\chrome-debug --no-first-run"
Verify the debug port is active before continuing:
Invoke-RestMethod http://localhost:9222/json/version
You should see a JSON response with browser version info. If you get a connection error, the
browser did not start with the debug port — check that you closed all existing windows of
that browser first, or that the --user-data-dir path differs from your normal profile.
Log in to LeanIX in that browser window before proceeding.
Step 2 — Start the proxy
cd lean-ix
dvm-leanix
You will be prompted for the LeanIX workspace URL if not provided via --url.
The tool connects to Chrome, captures the Bearer token, then starts the local server.
Step 3 — Open GraphiQL
Navigate to: http://localhost:8765/graphql
CLI Options
dvm-leanix [OPTIONS]
Options:
--url URL LeanIX workspace base URL
(default: https://eu-10.leanix.net/VolvoInformationTechnologyABSandbox)
--port PORT Local port (default: 8765)
--connect CDP_URL Chrome DevTools Protocol endpoint (default: http://localhost:9222)
--token TOKEN Use this Bearer token directly — skips browser extraction
--ca-bundle PATH PEM CA bundle (corporate SSL proxy fix)
--no-verify-ssl Disable SSL verification entirely (insecure)
Examples
# Use default URL, prompted if missing
dvm-leanix
# Specify workspace URL explicitly
dvm-leanix --url https://eu-10.leanix.net/MyOtherWorkspace
# Corporate SSL proxy — point at exported CA bundle
dvm-leanix --ca-bundle "$env:USERPROFILE\.lean-ix\corporate-ca.pem"
# Disable SSL verification (quick test only)
dvm-leanix --no-verify-ssl
# Use a known token (no browser needed)
dvm-leanix --token "eyJhbGci..."
# Different port
dvm-leanix --port 9000
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | / |
Redirects to /graphql |
| GET | /graphql |
GraphiQL interactive UI |
| POST | /graphql |
GraphQL proxy to LeanIX |
| GET | /health |
Health check + upstream URL |
| GET | /token |
Show masked current Bearer token |
| POST | /token |
Replace Bearer token at runtime |
Replace token at runtime
If the token expires, refresh it without restarting:
Invoke-RestMethod -Uri http://localhost:8765/token -Method POST `
-ContentType "application/json" `
-Body '{"token": "eyJhbGci..."}'
LeanIX GraphQL API Reference
Full API documentation: https://help.sap.com/docs/leanix/ea/graphql-api
Example GraphQL Query
{
allFactSheets(first: 10) {
edges {
node {
id
name
type
}
}
}
}
Architecture
Browser (logged in)
│
│ Chrome DevTools Protocol (port 9222)
▼
token.py ── intercepts Authorization header ──► Bearer token
│
▼
server.py (FastAPI on localhost:8765)
│ POST /graphql { query, variables }
│
│ Authorization: Bearer <token>
▼
https://eu-10.leanix.net/services/pathfinder/v1/graphql
Troubleshooting
"Could not connect to browser at http://localhost:9222"
→ If Edge/Chrome is already running, the --remote-debugging-port flag is silently ignored by any new window you open — it only works on a fresh browser process. Launch a separate isolated instance with its own profile:
Start-Process "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" `
"--remote-debugging-port=9222 --user-data-dir=C:\Temp\edge-debug --no-first-run --no-default-browser-check"
Then verify the port is open before retrying lean-ix:
Invoke-RestMethod http://localhost:9222/json/version # must return JSON
"Timed out waiting for a Bearer token"
→ No LeanIX API calls were detected. Make sure you are logged in and try navigating within LeanIX to trigger an API request.
SSL: CERTIFICATE_VERIFY_FAILED — self-signed certificate in chain
→ Your corporate network uses SSL inspection (a man-in-the-middle proxy that replaces certificates with ones signed by an internal CA). Python's SSL stack rejects these because the corporate root CA is not in its trust bundle.
Option 1 — Export the corporate CA and point lean-ix at it (recommended)
# Export all trusted root CAs from the Windows certificate store to a PEM file
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root
$pem = $certs | ForEach-Object { "-----BEGIN CERTIFICATE-----`n" + [Convert]::ToBase64String($_.RawData, 'InsertLineBreaks') + "`n-----END CERTIFICATE-----" }
$pem | Set-Content -Path "$env:USERPROFILE\.lean-ix\corporate-ca.pem" -Encoding ascii
Then run lean-ix with the bundle:
dvm-leanix --ca-bundle "$env:USERPROFILE\.lean-ix\corporate-ca.pem"
Option 2 — Disable verification entirely (quick test only, not recommended)
dvm-leanix --no-verify-ssl
Token expired mid-session
→ Navigate in the LeanIX browser tab (which triggers a token refresh) then POST the new token to /token, or restart lean-ix.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dvm_leanix-0.3.1.tar.gz.
File metadata
- Download URL: dvm_leanix-0.3.1.tar.gz
- Upload date:
- Size: 93.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1469d755717fb14476326f4a8ede8c41808b319b083ae7e7a53e982b66f56a25
|
|
| MD5 |
44883b9a42fd399e4e0eb49c54e566d8
|
|
| BLAKE2b-256 |
923885f0a13569a46aa385ed10160b4000a156aa2fdf34379f6a65c54cb5c686
|
Provenance
The following attestation bundles were made for dvm_leanix-0.3.1.tar.gz:
Publisher:
publish.yml on divyavanmahajan/dvm-leanix
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dvm_leanix-0.3.1.tar.gz -
Subject digest:
1469d755717fb14476326f4a8ede8c41808b319b083ae7e7a53e982b66f56a25 - Sigstore transparency entry: 1271487279
- Sigstore integration time:
-
Permalink:
divyavanmahajan/dvm-leanix@6c2ebe38fe771dbfbe97a07241432f70944c3332 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/divyavanmahajan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6c2ebe38fe771dbfbe97a07241432f70944c3332 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dvm_leanix-0.3.1-py3-none-any.whl.
File metadata
- Download URL: dvm_leanix-0.3.1-py3-none-any.whl
- Upload date:
- Size: 29.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18d876bcfb750444388c99ce217842ccd9ab5402b039b31769d1b960c1537fb3
|
|
| MD5 |
a07096c68260bee402ed6fed9cdc0064
|
|
| BLAKE2b-256 |
7ba06bd06b607e90d7096db49576bceb48848941b0a858e6a27ed09ec1dc2bd9
|
Provenance
The following attestation bundles were made for dvm_leanix-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on divyavanmahajan/dvm-leanix
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dvm_leanix-0.3.1-py3-none-any.whl -
Subject digest:
18d876bcfb750444388c99ce217842ccd9ab5402b039b31769d1b960c1537fb3 - Sigstore transparency entry: 1271487302
- Sigstore integration time:
-
Permalink:
divyavanmahajan/dvm-leanix@6c2ebe38fe771dbfbe97a07241432f70944c3332 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/divyavanmahajan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6c2ebe38fe771dbfbe97a07241432f70944c3332 -
Trigger Event:
push
-
Statement type: