An edited mac.py that changes nothing is the usual first symptom. The file on disk is not what Access Server executes; the authentication service loads the script from the server's configuration database, and that stored copy is what decides a login. Until the stored value is replaced, every test you run proves only that the old script still works.

Three conditions decide the work: whether the value was ever put into the configuration database, whether the service was told to reload it, and whether the code you changed actually runs per connection. Each one has a different symptom, and fixing the wrong one wastes a maintenance window.

The file is a source, not the running copy

Access Server keeps the post-auth script under the key auth.module.post_auth_script. Editing the file updates your working copy and nothing else. The daemon reads the stored value, so the edit stays invisible until you delete the old entry and put the new file in its place. That stored value is the only copy the authentication service consults.

Read it before you change it. If it already matches the file you edited, the problem is not storage and you should skip to the scope question. If it shows an older version, the edit never reached the service.

./sacli -k auth.module.post_auth_script ConfigGet

Replace the stored copy, then apply it

Deleting before writing is not decoration. ConfigPut with --value_file replaces the value in one step, and ConfigDel first makes a stale or corrupt entry impossible to leave behind. Keep a copy of the working script outside the scripts directory before you start.

./sacli -k auth.module.post_auth_script ConfigDel
# store the file, then apply it
./sacli -k auth.module.post_auth_script --value_file=/root/post_auth.py ConfigPut
./sacli start

sacli start applies the changed configuration to the internal services, which is what makes the new script take effect. It is not the same as restarting the whole machine or the daemon, and it should not be replaced by one unless the change you are making requires it.

Use an absolute path for the value file and confirm root can read it. A path that resolves from your shell but not from the service account produces a stored value that looks fine in ConfigGet and fails at the first login. Check the stored result once more after sacli start, not before.

Module scope or per-connection: where the lookup belongs

Python runs module-level statements once, when the script is loaded. A database query written at the top of the file therefore reads the table at load time and keeps that answer for every later connection. That is the second reason an edit appears to do nothing: the code runs, but not when you expect.

Put the query inside the post_auth handler so it executes for each authentication. Keep the documented signature, adjust the auth result the handler receives, and return that same object rather than a bare number.

Keep the connection handling inside the handler too. A connection opened at import time can be closed by the server before the first user logs in, and the resulting error looks like a rejected credential rather than a broken script.

Two reject paths, one owner

If the decision is a local lookup, the Python handler owns the result. If it is an external HTTP check, let the command's exit status carry the answer: a wrapper that exits non-zero rejects the login, and the last command's status becomes the script's status without an explicit exit.

Keep the secret out of the process list. A root-readable file or an environment value passed by the service is safer than an argument that any local user can read from ps. Pin the endpoint in a variable before the call, so a typo fails at configuration time rather than during someone's login. Rotate that secret the same way you would any other credential.

Pick one owner per check. A script that both queries the database and calls an HTTP service needs a stated precedence rule for the case where the two disagree, or the reject reason in the log will not match what the user was told.

Apply it without locking out the administrator

Two safeguards make the change reversible: a second admin account that does not depend on the script, and a known-good copy kept outside the scripts directory. Apply the change in a maintenance window, then watch one test login and one deliberate rejection before you disconnect. If the log shows a syntax error instead of an auth decision, the stored script is broken and every login will fail.

Two conditions say wait: you cannot read the value file as root, or you have no second way into the admin UI. Both turn a small change into a lockout, and neither is worth testing on a production server at the end of the day. The Access Server documentation covers the post-auth interface and its supported fields.

Related articles