Skip to content

chore: add make token target and drop weak secret from inspector-up - #7120

Open
wak327 wants to merge 2 commits into
IBM:mainfrom
wak327:chore/6100-make-token-target
Open

wak327 wants to merge 2 commits into
IBM:mainfrom
wak327:chore/6100-make-token-target

Conversation

@wak327

@wak327 wak327 commented Oct 3, 2026 •

Copy link
Copy Markdown

Pull Request

🔗 Related Issue

Closes #6100


📝 Summary

Problem

  • No Makefile target prints a JWT for local API calls. A developer must know the python -m mcpgateway.utils.create_jwt_token command, its flags, and the value of JWT_SECRET_KEY.
  • The inspector-up hint prints --secret my-test-key-but-now-longer-than-32-bytes --algo HS256. That value is in WEAK_VALUES (mcpgateway/_security_constants.py:36). A gateway with a valid configuration does not use that key, so a token from the hint does not authenticate.

Root cause

The inspector-up recipe hardcodes a sample secret. It does not use the signing settings of the gateway. No wrapper target reads those settings for the developer.

Fix

  • Makefile:422-443 adds the token target. The recipe runs create_jwt_token --username <user> --admin --exp <minutes> with no --secret and no --algo. Settings loads JWT_SECRET_KEY and JWT_ALGORITHM from the environment, then from .env. The token therefore uses the same signing settings as a gateway started from the same shell. The secret stays out of argv.
  • The default subject is admin@example.com. The default lifetime is 10080 minutes.
  • USERNAME applies only from the make command line. Windows and many Linux desktop sessions export USERNAME as the OS login name. That name must not become the token subject.
  • EXP applies from the make command line or from the environment.
  • The recipe sets LOG_LEVEL to WARNING when the caller does not export LOG_LEVEL. The mcpgateway.config INFO lines then stay off stderr. The elevated-claims warning from the CLI still prints.
  • A missing .env fails with a make setup hint. A missing venv interpreter fails with a make install-dev hint. Both hints go to stderr. stdout holds only the token, so export MCPGATEWAY_BEARER_TOKEN=$(make -s token) works.
  • Makefile:1930 changes the inspector-up hint to make token.
  • docker-compose.yml:2546-2547 changes the mcp_inspector header comment to make token. The two hints for the inspector flow now match.
  • .secrets.baseline moves the line numbers of the existing allowlisted entries in Makefile and docker-compose.yml. Without this change the detect-secrets pre-commit hook rewrites the baseline and exits with code 3.
  • tests/unit/test_makefile_token_target.py adds 10 tests. They cover the help line, the inspector-up hint, the defaults, the USERNAME and EXP sources, both failure hints, and an end-to-end run. The end-to-end run patches a copy of .env.example with init_secrets, runs make -s token, and decodes the token with the .env key, audience and issuer.

Deviations from the recipe in the issue

Issue recipe This PR Reason
grep reads JWT_SECRET_KEY from .env and passes --secret No --secret; Settings loads the key Settings applies the same parsing and precedence as the gateway. The secret does not appear in the process list.
--algo HS256 No --algo; Settings loads JWT_ALGORITHM A gateway with a different JWT_ALGORITHM gets a matching token.
USERNAME=x EXP=60 make token make token USERNAME=x EXP=60; EXP also works from the environment An exported USERNAME is the OS login name on many desktops. EXP has no such collision.
Error when JWT_SECRET_KEY is empty Error when .env is missing or the venv interpreter is missing Settings rejects a missing or placeholder key with SecurityConfigurationError and a remediation hint.
Hints on stdout Hints on stderr stdout holds only the token for $(make -s token).

📏 Reviewability

  • This PR has one clear purpose
  • The linked issue is not labeled triage
  • Unrelated bugs or improvements are tracked in separate issues/PRs
  • Tests are included with the code they validate
  • If AI-assisted, I understand and can explain the generated changes

🏷️ Type of Change

  • Bug fix
  • Feature / Enhancement
  • Documentation
  • Refactor
  • Chore (deps, CI, tooling)
  • Other (describe below)

🧪 Verification

All commands run from the repository root with the project venv interpreter as python.

The branch is rebased onto main at a211ab7d. After the rebase, .secrets.baseline takes the main version, and the pinned detect-secrets pre-commit hook refreshes its line numbers. The diff of .secrets.baseline against main changes only line_number values and generated_at.

Check Command Status
New tests python -m pytest tests/unit/test_makefile_token_target.py -v -p no:cacheprovider 10 passed
Makefile and compose tests python -m pytest tests/unit/test_makefile_token_target.py tests/unit/test_makefile_rust_targets.py tests/unit/test_issue_6083_compose_cleanup.py tests/unit/test_tls_compose.py tests/unit/test_secret_baseline_ci_decision_workflow.py -p no:cacheprovider 42 passed
Ruff lint make ruff RUFF_MODE=check TARGET=tests/unit/test_makefile_token_target.py All checks passed
Ruff format uv tool run ruff==0.15.20 format --check tests/unit/test_makefile_token_target.py 1 file already formatted
Black make black CHECK=1 TARGET=tests/unit/test_makefile_token_target.py 1 file unchanged
isort make isort CHECK=1 TARGET=tests/unit/test_makefile_token_target.py No diff
Pylint make pylint TARGET=tests/unit/test_makefile_token_target.py 10.00/10
Docstring coverage uv tool run interrogate==1.7.0 -vv tests/unit/test_makefile_token_target.py 100% (13/13)
YAML lint uv tool run yamllint==1.38.0 -c .yamllint docker-compose.yml Exit 0
Pre-commit on changed files pre-commit run --config .pre-commit-config.yaml --files Makefile docker-compose.yml .secrets.baseline tests/unit/test_makefile_token_target.py 36 passed, 0 failed, others skipped
detect-secrets, full tree detect-secrets-hook --baseline <copy of .secrets.baseline> --use-all-plugins --fail-on-unaudited -- <every file from git ls-files> with the pinned rev 076672a9 Exit 0 (exit 3 before the baseline change)
Gateway token check make -s token EXP=60 in a scratch directory with .env.example patched by python -m mcpgateway.scripts.init_secrets --patch-env .env, then verify_jwt_token() from mcpgateway.utils.verify_credentials with that .env Accepted: sub=admin@example.com, is_admin=True, teams=None, lifetime 60 minutes
Key precedence Same scratch directory, JWT_SECRET_KEY exported with a different value Token verifies with the exported key; the .env key gives InvalidSignatureError
Placeholder and empty .env make -s token in a scratch directory with an unpatched copy of .env.example, then with an empty .env Exit 2, empty stdout, SecurityConfigurationError: jwt_secret_key: unset placeholder (__REPLACE_ME__) rejected
Inspector hint make -n inspector-up Prints make token; no --secret
After rebase onto a211ab7d python -m pytest tests/unit/test_makefile_token_target.py tests/unit/test_makefile_rust_targets.py tests/unit/mcpgateway/utils/test_create_jwt_token.py -p no:cacheprovider 38 passed
detect-secrets after rebase pre-commit run detect-secrets --files Makefile docker-compose.yml tests/unit/test_makefile_token_target.py Passed

Checks not run:

  • make test: the change touches no mcpgateway/ source. The table lists the affected test modules.
  • make coverage diff-cover: the changed lines are in Makefile, docker-compose.yml, .secrets.baseline and a test module. diff-cover measures no source lines here.
  • make docker-nuke docker-prod-rust testing-up and make test-e2e: the change adds a developer Makefile target and changes no gateway runtime path. The gateway token check uses verify_jwt_token() in place of a live gateway.
  • make detect-secrets-scan: the full-tree hook run above uses the same pinned detect-secrets revision.

✅ Checklist

  • Code formatted (black, isort and pre-commit checks on the changed files; see Verification)
  • Tests added/updated for changes
  • Documentation updated (if applicable): make help line, inspector-up hint, mcp_inspector comment
  • No secrets or credentials committed

📓 Notes (optional)

  • The default subject is admin@example.com, as the issue specifies. It does not follow PLATFORM_ADMIN_EMAIL. When no admin@example.com user exists in the database, the gateway rejects the default token with 401 (mcpgateway/auth.py:2125-2150). Use make token USERNAME=<platform admin email> in that case. No issue tracks a PLATFORM_ADMIN_EMAIL default yet, so the "tracked in separate issues" box stays unchecked.
  • A Makefile run with -C <other directory> prints cd: tests/migration: No such file or directory on stderr. That message comes from existing Makefile code, not from this change. No issue tracks it yet.

@wak327

wak327 commented Oct 3, 2026

Copy link
Copy Markdown
Author

@Lang-Akshay @jonpspri @crivetimihai This PR adds the make token target from #6100 and replaces the weak secret in the inspector-up hint with make token.

The recipe does not use the ${VAR:-default} snippet from the issue. Make expands ${...} before the shell runs, so the defaults were empty. The recipe lets Settings load JWT_SECRET_KEY and JWT_ALGORITHM, so the secret stays out of argv. The PR description gives the full reasons. Please review when you have time.

@wak327
wak327 force-pushed the chore/6100-make-token-target branch 3 times, most recently from 0839697 to 84c353c Compare October 8, 2026 08:17
@wak327
wak327 force-pushed the chore/6100-make-token-target branch 2 times, most recently from 933cad9 to 04b9a89 Compare October 15, 2026 19:43
Add a `make token` target. It prints an admin JWT for admin@example.com.
The recipe calls `python -m mcpgateway.utils.create_jwt_token --admin`
without `--secret` or `--algo`. Settings loads JWT_SECRET_KEY and
JWT_ALGORITHM from the environment, then from .env. The token matches
the gateway JWT settings, and the secret stays out of argv.

USERNAME applies only from the make command line. Windows and many
Linux desktop sessions export USERNAME as the OS login name. The target
must not use that name as the token subject. EXP applies from the
command line or from the environment.

The recipe sets LOG_LEVEL to WARNING when the caller does not export
LOG_LEVEL. The mcpgateway.config INFO lines then stay off stderr.

The target fails with a `make setup` hint when .env is missing. It fails
with a `make install-dev` hint when the venv interpreter is missing.
Both hints go to stderr. stdout carries only the token, so
`export MCPGATEWAY_BEARER_TOKEN=$(make -s token)` works.

The `inspector-up` hint and the mcp_inspector comment in
docker-compose.yml now point to `make token`. The `inspector-up` hint
no longer prints a JWT secret from WEAK_VALUES.

The .secrets.baseline change moves the Makefile and docker-compose.yml
line numbers. The detect-secrets hook fails on stale line numbers.

Closes IBM#6100

Signed-off-by: Waleed Khalid <wak327@gmail.com>
@wak327
wak327 force-pushed the chore/6100-make-token-target branch from 04b9a89 to 250edd6 Compare October 20, 2026 14:52
Signed-off-by: Waleed Khalid <wak327@gmail.com>

# Conflicts:
#	.secrets.baseline

This branch has not been deployed

No deployments
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.

Add make token target for quick JWT generation; fix inspector hardcoded weak secret

1 participant