Declare the service account DN before the OU loop and print the LDAP result code and server message when the password-change check fails. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3t4WL7bd9bdHHNjEsxzqC
Test environment runbook
There is no staging environment. The portal is tested against a separate test OU in your real Active Directory and a dedicated application in your real authentik. This runbook creates both, with the smallest possible rights. Nothing here touches existing users, groups or applications.
Time needed: about 45 minutes. You need domain-admin rights, access to authentik as an administrator, your reverse proxy (Zoraxy) and your mail provider's panel.
What gets created
| Where | What |
|---|---|
| Active Directory | A test OU with six test users and two groups; a separate OU with a service account; delegated rights for that account on user objects in the test OU only |
| authentik | One OIDC provider and one application, restricted to a test group |
| Zoraxy | One host name that forwards to the portal container |
| Mail provider | One test mailbox for sending |
Reading is not restricted by this setup: in Active Directory, authenticated users can read most attributes of user objects by default, and so can the service account. The spine's wording that read rights are limited to a list is not enforced here (see the deferred-work note).
The service account may change givenName, sn, displayName, mail, telephoneNumber, mobile, and may use "Change Password", on user objects inside the test OU. It cannot create or delete anything, cannot reset passwords (unless you add -AllowResetPassword), and cannot write anywhere else.
Step A: Active Directory
-
Copy
New-PortalTestEnvironment.ps1to a domain controller (or a machine with the AD tools). -
Pick the parent OU for the two new OUs. Run a dry run first and read the output:
.\New-PortalTestEnvironment.ps1 -ParentDn "OU=Organisation,DC=example,DC=local" -WhatIf -
Run it for real (drop
-WhatIf). The script prints the passwords once. Put them in your password manager now. It also prints the values to write down (see the values sheet below). -
The six test users:
ptest-user1,ptest-user2(for cross-user checks),ptest-publisher,ptest-admin,ptest-disabled(disabled account),ptest-expired(must change password at next logon). Their e-mail addresses use the example domain; change the address of one user to your test mailbox if you want to receive test e-mails.
Step B: The certificate authority file
The portal checks the directory server's certificate against your internal CA, so the file must contain the whole chain: the root CA and any intermediate CA that signed the domain controller's certificate.
-
On the certificate authority server, export each CA certificate that is part of the chain (
certutil -ca.cert root.cer, and the same for an intermediate if you have one), or export them from the "Certification Path" tab of the domain controller's LDAPS certificate. -
Convert each to PEM (
certutil -encode root.cer root.pem) and join them into one fileca.pem(the files can simply be put one after another). -
Check it from the Linux host (replace the names):
openssl s_client -connect dc1.example.local:636 -CAfile ca.pem -verify_return_error </dev/null | grep "Verify return code"It must say
Verify return code: 0 (ok).
Keep ca.pem on the Linux host. It is a public certificate, not a secret. Later the container mounts it.
Step C: Prove the rights over LDAPS
From a machine that trusts your CA and can reach the directory server on port 636:
.\Test-PortalLdaps.ps1 -Server dc1.example.local -BindUser svc-portal-test@example.local `
-TestOuDn "OU=PortalTest,OU=Organisation,DC=example,DC=local" `
-OutsideUserDn "CN=Some Person,OU=Elsewhere,DC=example,DC=local" -TestPasswordChange
Use the real server name and a real user outside the test OU for -OutsideUserDn (the check sends a request that changes nothing). -TestPasswordChange changes the password of ptest-user1; write the new one down. Every line must say PASS. If the password check fails with "access denied", tell the assistant: it then decides, before the password feature is built, whether the narrower right is enough or "Reset Password" is needed.
Step D: authentik
Do not change any existing application. Labels may differ slightly between authentik versions.
- Check, without changing anything, whether your existing LDAP source already covers the test OU (look at its base DN: a parent such as the whole domain or
OU=Organisationcovers it). If it does, wait for the next sync; the six test users, including the disabled and the expired one, will then appear in your production authentik and can be removed again at clean-up. If it does not cover the test OU, stop here and tell the assistant: the options are to widen the existing source (a change to existing configuration) or to add a second source just for the test OU (a new object only). After the sync,ptest-user1must have the same username in authentik as its AD logon name (the portal requirespreferred_usernameto equalsAMAccountName). - Create a group
portal-testand addptest-user1,ptest-user2,ptest-publisher,ptest-admin,ptest-disabledandptest-expiredto it. - Create an OAuth2/OpenID provider: client type confidential; redirect URI (strict)
https://<portal-test-host>/auth/callback(the sign-in ticket will use exactly this path; if it ever has to change, edit it here); scopesopenid,profile,email; choose a signing key. Write down client ID and client secret. - Create an application for it and bind the group
portal-testso only those users can use it. - Open the application's OpenID configuration page and write down the issuer address.
Please note what authentik does when you sign in as ptest-disabled and ptest-expired (it may refuse them). That answers an open question in the spec.
Step E: Zoraxy
- Add a host name for the test portal, for example
portal-test.<your domain>, with a valid certificate, forwarding tohttp://<docker host address>:8000. The compose file currently publishes port 8000 on every interface of the host. Either bind it to127.0.0.1:8000:8000when Zoraxy runs on the same host, or firewall port 8000 so that only Zoraxy can reach it; the portal trusts proxy headers and must not be reachable directly. - Write down the address Zoraxy connects from as seen by the container. If Zoraxy and Docker run on the same host, that is usually the Docker network gateway, not the host's LAN address. The sign-in ticket (1.5) sets
TRUSTED_PROXIESfrom it and checks it with a test request.
Step F: Test mailbox
Create a mailbox at your provider for test mail. Write down the SMTP server name, port, security mode (usually STARTTLS or SSL), user name, password and the sender address.
Values sheet (fill in; keep secrets out of this repository)
| Item | Value |
|---|---|
| Directory server (FQDN) | |
| Test OU (base DN) | |
| Service account (user name) | stored in password manager |
| Publisher group DN | |
| Admin group DN | |
| CA file location on the Linux host | |
| OIDC issuer address | |
| OIDC client ID | |
| OIDC client secret | stored in password manager |
| Portal test host name | |
| Zoraxy address as seen by the container | |
| SMTP server, port, mode | |
| SMTP user, sender address | |
| SMTP password | stored in password manager |
Clean up when you are done
Delete the authentik application, provider and group; the Zoraxy host; the test mailbox; and the two OUs. The script created the OUs without deletion protection, so they can be removed in Active Directory Users and Computers with "Advanced Features" switched on. Remove the service account's OU last.
When you are finished
Tell the assistant "1.2 is done". Ticket 1.2 stays open until you confirm that every check in Step C says PASS and that the authentik application lets ptest-user1 sign in.