Files
wevads-platform/scripts/bulk_pwd_change.py

65 lines
2.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""Bulk password change for valid O365 accounts via ROPC"""
import requests,psycopg2,random,string,json,time,sys
from datetime import datetime
DB={"host":"localhost","dbname":"adx_system","user":"admin","password":"admin123"}
LOG="/opt/wevads/logs/bulk_pwd_change.log"
BATCH=int(sys.argv[1]) if len(sys.argv)>1 else 10
def log(m):
t=datetime.now().strftime("%H:%M:%S")
print(f"[{t}] {m}",flush=True)
with open(LOG,"a") as f: f.write(f"[{t}] {m}\n")
def gen():
while True:
p=''.join(random.choice(string.ascii_letters+string.digits+"!@#$") for _ in range(16))
if any(c.isupper() for c in p) and any(c.islower() for c in p) and any(c.isdigit() for c in p) and any(c in "!@#$" for c in p): return p
db=psycopg2.connect(**DB); db.autocommit=True; cur=db.cursor()
cur.execute("SELECT id,admin_email,admin_password,tenant_domain FROM admin.office_accounts WHERE password_status='valid' ORDER BY id LIMIT %s",[BATCH])
rows=cur.fetchall()
log(f"Processing {len(rows)} accounts")
ok=fail=skip=0
for aid,email,pwd,tenant in rows:
try:
r=requests.post(f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",data={
"grant_type":"password","client_id":"1b730954-1685-4b74-9bfd-dac224a7b894",
"scope":"https://graph.microsoft.com/.default","username":email,"password":pwd},timeout=20)
if r.status_code!=200:
err=r.json().get("error_description","")[:80]
if "50079" in err: status="mfa_required"
elif "50076" in err: status="mfa_required"
elif "50053" in err: status="locked"
elif "50057" in err: status="disabled"
elif "90002" in err: status="tenant_gone"
elif "50126" in err: status="invalid"
else: status="error"
cur.execute("UPDATE admin.office_accounts SET password_status=%s WHERE id=%s",[status,aid])
log(f"#{aid} {email}: {status} - {err[:50]}")
skip+=1; continue
token=r.json()["access_token"]
npwd=gen()
cp=requests.post("https://graph.microsoft.com/v1.0/me/changePassword",
json={"currentPassword":pwd,"newPassword":npwd},
headers={"Authorization":f"Bearer {token}","Content-Type":"application/json"},timeout=20)
if cp.status_code in [200,204]:
cur.execute("UPDATE admin.office_accounts SET admin_password=%s, password_status='pwd_changed', notes=%s WHERE id=%s",
[npwd, json.dumps({"old_pwd":pwd,"changed":datetime.now().isoformat(),"by":"bulk_pwd_change"}), aid])
log(f"#{aid} {email}: PWD CHANGED -> {npwd[:8]}...")
ok+=1
else:
log(f"#{aid} {email}: change fail {cp.status_code} {cp.text[:80]}")
fail+=1
except Exception as e:
log(f"#{aid} {email}: ERROR {e}")
fail+=1
time.sleep(0.5)
log(f"DONE: {ok} changed, {fail} failed, {skip} skipped")
db.close()