PyPass is a simple self-service password change web app for Active Directory. It is built with Python, Flask, LDAP3, and a lightweight UI.
- Self-service password reset for AD users
- reCAPTCHA support
- Responsive UI for mobile and desktop
- Optional Slack notifications
- LDAP connectivity status badge (top-right)
- UI renders even if LDAP is offline (badge turns red)
- Python 3.12
- LDAP server reachable on port 636 (LDAPS)
python3.12 -m venv .venv
.venv/bin/pip install -r app/requirements.txt
cp .env.example .env
PYTHONPATH=app .venv/bin/flask --app app run --host 0.0.0.0 --port 5001Set these variables in your .env file (for local/dev) or as GitHub/CI/CD
secrets (for production):
# Flask secret key (required)
SECRET_KEY_FLASK=replace-with-flask-secret
# LDAP/Active Directory connection
DOMAIN=your-ldap-server.example.com
BASEDN=OU=Users,DC=example,DC=com
USER_ADMIN=your-ldap-service-account
PASSWD_ADMIN=your-ldap-service-password
# Slack integration (optional)
SLACK_BOT_TOKEN=xoxb-your-token
SLACK_ACTIVATION=True
# Google reCAPTCHA (optional but recommended)
RECAPTCHA_PUBLIC_KEY=your-recaptcha-site-key
RECAPTCHA_PRIVATE_KEY=your-recaptcha-secret-key
RECAPTCHA_ENABLED=True
# TLS/SSL certificates (required for HTTPS)
CRT_CERTIFICATE=app/src/name.crt
KEY_CERTIFICATE=app/src/name.key
# App/company info (optional)
COMPANY=YourCompanyName
DEBUG=TrueAdd the same variables as repository or environment secrets. All sensitive values (passwords, tokens, keys) must be set as secrets, not in code or config files.
TLS assets:
- You can provide certificate/key as file paths (
CRT_CERTIFICATE,KEY_CERTIFICATE) or as inline PEM values (CRT_CERTIFICATE_PEM,KEY_CERTIFICATE_PEM).
python3.12 - <<'PY'
import secrets
print(secrets.token_hex(16))
PYThe UI shows a green/red indicator based on /health/ldap, which attempts a TCP
connect to the configured LDAP host on port 636. The page still loads if LDAP is
offline, so you can verify the UI and config without a live LDAP connection. When
LDAP is available, the badge turns green.
PyPass uses Google reCAPTCHA via Flask-WTF.
- Create keys at https://www.google.com/recaptcha/admin/create
- Set
RECAPTCHA_PUBLIC_KEYandRECAPTCHA_PRIVATE_KEYin.envor your deployment environment:
RECAPTCHA_PUBLIC_KEY=YOUR_SITE_KEY
RECAPTCHA_PRIVATE_KEY=YOUR_SECRET_KEY
RECAPTCHA_ENABLED=TrueIf you want to disable reCAPTCHA, set RECAPTCHA_ENABLED to False.
To enable LDAP/LDAPS connectivity from any LDAP server, confirm the items below:
- LDAPS endpoint
- Ensure the LDAP server supports LDAPS on port 636.
- Open firewall rules to allow inbound 636 from the app host.
- If you must use LDAP (389), update the code to use port 389 and disable SSL (not recommended).
- Certificates (LDAPS)
- The LDAP server must present a valid certificate.
- If you use an internal CA, add the CA certificate to the OS trust store on the app host.
- Service account
- Create an LDAP user/service account with permission to read user attributes and change passwords.
- In Active Directory, the account must be allowed to reset passwords for the target OU.
- Environment variables
DOMAIN: LDAP hostname or IP (e.g.,ldap.example.com)BASEDN: Base DN for users (e.g.,OU=Users,DC=example,DC=com)USER_ADMIN/PASSWD_ADMIN: service account credentials
- Connectivity tests (optional)
-
Test TLS handshake:
openssl s_client -connect ldap.example.com:636
-
Test LDAP bind (if you have ldapsearch):
ldapsearch -H ldaps://ldap.example.com:636 -D "user@example.com" -W -b "OU=Users,DC=example,DC=com"
-
If LDAP is unreachable, the app will still render and show a warning message, and the status badge turns red.
To enable Slack notifications:
- Set
SLACK_BOT_TOKENandSLACK_ACTIVATION=Truein your.envor deployment environment. - Export your Slack user list and save it in
app/src/:
import json
from slack_sdk import WebClient
SLACK_BOT_TOKEN = "xoxb-YOUR-TOKEN"
sc = WebClient(token=SLACK_BOT_TOKEN)
response = sc.users_list()
data = json.dumps(response.data, indent=4, sort_keys=True)
print(data)Set SLACK_BOT_TOKEN in .env or your deployment environment before running
this script.
python3.12 slack_file.py >> app/src/slack_db.jsondocker build -t pypass:latest .
docker run --dns <dns-or-ad-ip> \
--env-file .env \
--name pypass \
-d -p 80:5000 \
--rm pypass:latestapiVersion: apps/v1
kind: Deployment
metadata:
name: pypass
spec:
replicas: 1
selector:
matchLabels:
app: pypass
template:
metadata:
labels:
app: pypass
spec:
containers:
- name: pypass
image: pypass:latest
ports:
- containerPort: 5000
env:
- name: PYTHONPATH
value: "/app"
volumeMounts:
- name: config
mountPath: /app/src/config.json
subPath: config.json
volumes:
- name: config
configMap:
name: pypass-config
---
apiVersion: v1
kind: Service
metadata:
name: pypass
spec:
selector:
app: pypass
ports:
- port: 80
targetPort: 5000Create a ConfigMap named pypass-config with your config.json before applying
the manifest.
For secrets, use Kubernetes Secrets or your platform's secret store and expose
them as environment variables with the same names shown in .env.example.
- If LDAP is unreachable, the app shows a warning message and the status badge turns red.
- For LDAPS on Windows, ensure certificate services are installed on the domain controller.
MIT. See LICENSE.