Skip to main content

af-credmon v0.1.1

Actions Status Documentation Status

PyPI version PyPI platforms

GitHub Discussion

Coverage

An HTCondor credential monitor (credmon) that places a user's AF MCP broker-held credentials -- x509/VOMS proxy, CERN Kerberos ticket, ServiceX access token -- on worker nodes, without the job submitter (human or LLM agent) ever handling them.

It is the access-point half of the af-mcp-platform HTCondor credmon integration; see that repository's docs/credmon.md for the broker side. In short:

  1. The broker stores a per-user, per-kind top token in credd as <creddir>/<user>/af_<kind>.top.
  2. af-credmon presents it to the broker's POST /v1/credentials/<kind>/redeem and writes the credential to <creddir>/<user>/af_<kind>.use, renewing it before it expires.
  3. A job with use_oauth_services = af_krb5, af_x509 gets $_CONDOR_CREDS/af_krb5.use (a krb5 ccache) and $_CONDOR_CREDS/af_x509.use (a VOMS proxy PEM) on the worker node, refreshed by HTCondor every SEC_CREDENTIAL_REFRESH (default 300s).

Installing on the access point

af-credmon runs as root on the access point (the schedd host), next to credd. Install it as a pixi environment:

git clone https://github.com/maniaclab/af-credmon /opt/af-credmon
cd /opt/af-credmon && git checkout v0.1.1 && pixi install
# -> /opt/af-credmon/.pixi/envs/default/bin/af-credmon

or into any Python 3.11+ environment that has the HTCondor Python bindings:

pip install af-credmon

HTCondor configuration

The access point needs credd, an OAuth credential directory, and the identity the broker stores with listed as a credential super-user:

DAEMON_LIST = $(DAEMON_LIST) CREDD CREDMON_OAUTH
SEC_CREDENTIAL_DIRECTORY_OAUTH = /var/lib/condor/oauth_credentials
CRED_SUPER_USERS = <identity of the broker's htcondor-api token>

CREDMON_OAUTH = /opt/af-credmon/.pixi/envs/default/bin/af-credmon
CREDMON_OAUTH_ARGS = --broker-url https://mcp.example.org --log-file $(LOG)/AfCredmonLog

This is primary mode (the default): af-credmon is the credmon credd talks to. It owns <creddir>/pid (credd sends SIGHUP after every store, which triggers an immediate rescan), touches CREDMON_COMPLETE after each scan, and sends condor_master its ready message after the first one.

Next to an existing credmon

If the access point already runs condor_credmon_oauth (for SciTokens, an OAuth2 provider, ...), it keeps owning CREDMON_OAUTH, the pid file and CREDMON_COMPLETE. Run af-credmon as a separate daemon in alongside mode, which only polls:

DAEMON_LIST = $(DAEMON_LIST) AF_CREDMON
AF_CREDMON = /opt/af-credmon/.pixi/envs/default/bin/af-credmon
AF_CREDMON_ARGS = --mode alongside --broker-url https://mcp.example.org --log-file $(LOG)/AfCredmonLog

The existing credmons never touch af_* files, with one exception: if the Vault credmon is enabled with its default VAULT_CREDMON_PROVIDER_NAMES = *, it claims every unclaimed .top file. Set an explicit list instead.

Options

Option Default Meaning
--broker-url (required) AF MCP broker base URL
--cred-dir HTCondor's SEC_CREDENTIAL_DIRECTORY_OAUTH credd's OAuth credential directory
--prefix af_ credd service-name prefix; must match the broker's CREDMON_SERVICE_PREFIX
--mode primary primary or alongside (see above)
--interval 60 seconds between scans
--min-remaining 600 refuse a credential expiring sooner than this (twice the default SEC_CREDENTIAL_REFRESH)
--log-file stderr log destination; condor_master does not capture a daemon's stderr
--log-level INFO Python logging level

What a scan does

For every <creddir>/<user>/<prefix><kind>.top (kinds x509, krb5, servicex):

  • redeem the top token when the .use file is missing, not yet issued since startup, or in the last third of its lifetime, and write the .use atomically (temp file, mode 0400, rename);
  • remove the .use when the broker answers 404 (the identity is no longer linked), and any af_*.use whose .top credd has deleted;
  • keep the existing .use on any other failure (broker outage, expired top token) and retry on the next scan, so running jobs never lose a still-valid credential.

Files without the prefix belong to other credmons and are never touched. Nothing besides .use files (and, in primary mode, pid and CREDMON_COMPLETE) is written to the credential directory.

Keeping credentials out of job output

HTCondor does not redact job stdout/stderr, and tools that read job output back (including LLM agents through condor-mcp) see it verbatim. Job scripts should reference the credentials by path only:

export KRB5CCNAME="FILE:${_CONDOR_CREDS}/af_krb5.use"
export X509_USER_PROXY="${_CONDOR_CREDS}/af_x509.use"

and never cat, base64 or echo them. Keep SEC_DEBUG_PRINT_KEYS off on the access point; it writes credentials into the ShadowLog.

Development

pixi run -e dev pytest     # unit + integration tests
pixi run -e dev typecheck  # mypy
pixi run lint              # pre-commit hooks

To release, bump the version, commit and tag in one step, then push:

pixi run -e dev tbump 0.1.1

Metadata

Release files for af-credmon 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for af-credmon 0.1.1
File Size Uploaded
af_credmon-0.1.1.tar.gz 94.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for af-credmon 0.1.1
File Interpreter ABI Platform
af_credmon-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 111.6 kB

Release files / af_credmon-0.1.1.tar.gz

Download URL af_credmon-0.1.1.tar.gz
Size 94.1 kB
Tags Source
SHA-256 checksum
How to use checksums
bc0fee4bc274e010becce14387aee2c64becd88b0b0a66d50a9a6e4ddb9a0ef8
BLAKE2b-256 checksum
How to use checksums
660ccb9003ce8a8957d02243055dedec0b3494f890acb2fbf95e6390b041dd6c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / af_credmon-0.1.1-py3-none-any.whl

Download URL af_credmon-0.1.1-py3-none-any.whl
Size 17.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
00fe304aec0f97c349b540b7b5b6b4abf5258e752e2156ca6479d3e59c0f29ef
BLAKE2b-256 checksum
How to use checksums
a7cde6f0621c5f7c9a287c4db235b5b7bec3a4cc7d9f17fcb4bd63949e1219a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.2

2 release files

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page