Skip to content

Add vault integration for permanent users (break glass)#211

Closed
marcinpsk wants to merge 30 commits into
MarcJHuber:masterfrom
marcinpsk:add_vault
Closed

Add vault integration for permanent users (break glass)#211
marcinpsk wants to merge 30 commits into
MarcJHuber:masterfrom
marcinpsk:add_vault

Conversation

@marcinpsk
Copy link
Copy Markdown
Contributor

No description provided.

marcinpsk and others added 30 commits February 6, 2026 11:22
- Python MAVIS external script (mavis_tacplus_keycloak.py) that
  authenticates against Keycloak using Resource Owner Password
  Credentials grant and maps Keycloak groups to TACACS+ membership
- Multi-stage Dockerfile based on Debian Trixie to build tac_plus-ng
  with the Keycloak backend included
- GitHub Actions workflow to build and push Docker image to GHCR
- Sample tac_plus-ng configuration for Keycloak with admin/engineering/
  readonly profiles
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Marcin Zieba <49913098+marcinpsk@users.noreply.github.com>
- Dockerfile: run as non-root tacplus user, force CC=clang, add
  CAP_NET_BIND_SERVICE guidance for port 49
- mavis_tacplus_keycloak.py: document JWT trust model in
  decode_jwt_payload, validate access_token key in token response,
  catch RequestException instead of broad Exception, sanitize group
  names against quote injection, add is_tacplus() bug workaround comment
- Sample config: mark KEYCLOAK_URL as required, add explicit deny
  fallback in ruleset
- CLAUDE.md: document is_tacplus() bug workaround in example pattern
- .dockerignore: remove redundant entries already covered by *.md glob
Set up pre-commit with ruff (lint+format), markdownlint, hadolint,
trailing-whitespace, end-of-file-fixer, check-yaml, and
check-added-large-files. Fix hadolint-docker entry to include the
hadolint command (image has no ENTRYPOINT). Add language specifiers
to fenced code blocks in CLAUDE.md to satisfy MD040.

Fix a bug in mavis_tacplus_keycloak.py where decode_token_claims()
returning None (malformed/missing access_token) was not caught,
allowing authentication to succeed without valid token claims.
Now emits RESULT_FAIL and continues the loop. Remove the dead
`if claims` guard on set_dn since None is handled earlier.
Move pre-commit and ruff from project dependencies to a dev
dependency group. Remove uv-generated main.py boilerplate. Fix
.envrc trailing whitespace and replace --extra dev with default
dev group sync. Add .venv to .gitignore.
…failures

Narrow the except block around error-response JSON parsing from
broad Exception to (json.JSONDecodeError, ValueError) to avoid
swallowing unrelated exceptions. Change the decode_token_claims
None result from RESULT_FAIL to RESULT_ERROR since a server-side
token decode failure is not a user auth rejection.
Narrow decode_token_claims except clause from broad Exception to
(ValueError, json.JSONDecodeError, binascii.Error) to satisfy
Ruff BLE001. Handle non-list group claims in extract_groups: wrap
bare strings into a list, reject non-iterable types. Normalize
KEYCLOAK_REQUIRE_GROUP at config load by stripping whitespace and
leading slashes so it matches extract_groups output (fixes "/admin"
never matching "admin").
Add Keycloak ROPC authentication backend, Dockerfile, and CI
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…s/checkout-6

build(deps): bump actions/checkout from 4 to 6
Replace default code scanning setup with a custom workflow that
actually builds the project, giving CodeQL access to generated
headers and accurate preprocessor state.
Cache Keycloak groups in Redis/Valkey on AUTH success so that
subsequent INFO and HOST requests (which lack a password) can
return group membership without re-authenticating. This enables
tac_plus-ng authorization and host-access rules for Keycloak users.
- Replace one-shot module-level Redis init with _get_redis() that
  retries connections on each cache operation, with suppressed logging
  after the first failure (logs again every 50th attempt).
- Scope cache keys by realm (tacplus:keycloak:{realm}:{user}) to
  prevent collisions when multiple realms share the same Redis.
- Narrow exception handlers: redis.RedisError for Redis operations,
  json.JSONDecodeError for corrupted cache payloads, with distinct
  log messages for each.
- Make redis import conditional (try/except ImportError) so the script
  loads without python3-redis; caching is silently disabled.
- Store sanitized (safe) groups in the cache instead of raw groups,
  removing duplicate sanitization on the INFO/HOST read path.
- Return MAVIS_DOWN on cache miss for INFO/HOST instead of OK with no
  groups — without group data there is nothing useful to authorize.
- Reject KEYCLOAK_CACHE_TTL <= 0 at startup to prevent invalid setex.
- Remove ping on every _get_redis() call; return existing client
  immediately and only ping when establishing a new connection.
  Callers invalidate _redis on RedisError so the next call reconnects.
- Update fallthrough comment to "Unsupported request type".
- Add workflow_dispatch trigger to CodeQL workflow.
Avoid blocking reconnect attempts on every cache call when Redis is
down. _get_redis() now skips reconnection if fewer than 10 seconds
have elapsed since the last attempt.
feat: add INFO/HOST authorization with Redis group cache
Add mavis_tacplus_vault.py that authenticates against HashiCorp Vault
KV v2 using AppRole auth, intended as a fallback behind Keycloak in the
MAVIS module chain. Includes in-process caching, Redis group persistence,
and automatic token renewal.

Add sample failover config (tac_plus-ng-keycloak-vault.cfg) showing the
Keycloak→Vault chain with action error = continue, and documenting the
setenv/execve environment gotcha.
@marcinpsk marcinpsk closed this Feb 12, 2026
@marcinpsk
Copy link
Copy Markdown
Contributor Author

sorry, wasn't meant for this repo. :)

@github-advanced-security
Copy link
Copy Markdown

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

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