auto-sync-opus46

This commit is contained in:
opus-wire
2026-04-20 15:47:49 +02:00
parent 4ba5c32b28
commit e62eb6418a
5 changed files with 151 additions and 2 deletions

6
check_auth.sh Normal file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
echo "=== login.php ==="
head -20 /var/www/html/login.php 2>/dev/null
echo ""
echo "=== auth-check.php ==="
head -80 /var/www/html/api/auth-check.php 2>/dev/null

7
check_nginx_auth.sh Normal file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
echo "=== nginx sites for weval-consulting ==="
find /etc/nginx/sites-enabled/ /etc/nginx/conf.d/ -name "*weval*" 2>/dev/null | head -5
# Find config for /wevia-em-big4.html or /enterprise-model.html auth rule
grep -l "auth_request\|weval-em\|enterprise-model\|auth-check" /etc/nginx/sites-enabled/* 2>/dev/null | head -3
# Search for auth_request directive
grep -rn "auth_request" /etc/nginx/sites-enabled/ /etc/nginx/conf.d/ 2>/dev/null | head -10

View File

@@ -1,5 +1,5 @@
{
"timestamp": "2026-04-20T15:35:02.521991",
"timestamp": "2026-04-20T15:45:02.056286",
"layers": {
"DOCKER": {
"pass": 19,

File diff suppressed because one or more lines are too long

136
v99-linkedin-auto-login.py Executable file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env python3
"""
V99 Doctrine #100 - AUTO-LOGIN LinkedIn with stored creds
Never asks user. Uses LI_EMAIL + LI_PASSWORD + optional LI_TOTP_SEED from secrets.env.
Handles 2FA via pyotp. Saves cookies to persistent Chromium context.
"""
import asyncio, sys, subprocess, json, time
from pathlib import Path
SESSION_DIR = Path('/opt/weval-l99/browser-sessions/linkedin')
SESSION_DIR.mkdir(parents=True, exist_ok=True)
SCREENSHOT_DIR = Path('/var/www/html/api/playwright-results/v99-linkedin-auto-login')
SCREENSHOT_DIR.mkdir(parents=True, exist_ok=True)
LOG = Path('/var/log/v99-linkedin-auto-login.log')
def log(msg):
LOG.open('a').write(f"[{time.strftime('%Y-%m-%dT%H:%M:%S')}] {msg}\n")
def get_secret(key):
try:
r = subprocess.run(['grep', f'^{key}=', '/etc/weval/secrets.env'], capture_output=True, text=True, timeout=3)
if r.returncode == 0:
return r.stdout.strip().split('=', 1)[1].strip().strip('"').strip("'")
except:
pass
return None
async def auto_login():
from playwright.async_api import async_playwright
email = get_secret('LI_EMAIL') or get_secret('LINKEDIN_EMAIL')
password = get_secret('LI_PASSWORD') or get_secret('LINKEDIN_PASSWORD')
totp_seed = get_secret('LI_TOTP_SEED') or get_secret('LINKEDIN_TOTP_SEED')
cookie = get_secret('LI_AT')
# Strategy 1: Direct cookie injection if provided
if cookie:
log("Strategy 1: injecting LI_AT cookie")
async with async_playwright() as p:
ctx = await p.chromium.launch_persistent_context(str(SESSION_DIR), headless=True)
await ctx.add_cookies([{
'name': 'li_at', 'value': cookie, 'domain': '.linkedin.com',
'path': '/', 'httpOnly': True, 'secure': True, 'sameSite': 'None',
}])
page = await ctx.new_page()
await page.goto('https://www.linkedin.com/feed/', wait_until='domcontentloaded', timeout=20000)
await page.wait_for_timeout(3000)
url = page.url
ok = 'login' not in url and 'checkpoint' not in url
await page.screenshot(path=str(SCREENSHOT_DIR / 'cookie-inject.png'))
await ctx.close()
if ok:
log("Strategy 1 SUCCESS")
return {'ok': True, 'strategy': 'cookie_inject', 'url': url}
log(f"Strategy 1 FAILED url={url}")
# Strategy 2: Auto-login with email+password
if email and password:
log(f"Strategy 2: auto-login with {email}")
async with async_playwright() as p:
ctx = await p.chromium.launch_persistent_context(
str(SESSION_DIR), headless=True,
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
args=['--disable-blink-features=AutomationControlled'],
)
page = await ctx.new_page()
try:
await page.goto('https://www.linkedin.com/login', wait_until='domcontentloaded', timeout=20000)
await page.fill('input#username', email)
await page.fill('input#password', password)
await page.screenshot(path=str(SCREENSHOT_DIR / 'autologin-1-form.png'))
await page.click('button[type="submit"]')
await page.wait_for_timeout(5000)
await page.screenshot(path=str(SCREENSHOT_DIR / 'autologin-2-after-submit.png'))
# 2FA handling
url = page.url
if 'checkpoint/challenge' in url or 'verify' in url.lower():
if totp_seed:
try:
import pyotp
code = pyotp.TOTP(totp_seed).now()
log(f"2FA required, generated code {code[:2]}...")
for sel in ['input[name="pin"]', 'input#input__phone_verification_pin', 'input[type="text"]']:
try:
await page.fill(sel, code)
break
except: continue
await page.click('button[type="submit"]')
await page.wait_for_timeout(5000)
except ImportError:
log("pyotp not installed - 2FA blocked")
await page.screenshot(path=str(SCREENSHOT_DIR / 'autologin-2fa-blocked.png'))
await ctx.close()
return {'ok': False, 'err': 'pyotp_missing', 'strategy': 'autologin'}
else:
log("2FA required but no TOTP_SEED")
await page.screenshot(path=str(SCREENSHOT_DIR / 'autologin-2fa-no-seed.png'))
await page.goto('https://www.linkedin.com/feed/', wait_until='domcontentloaded', timeout=15000)
await page.wait_for_timeout(3000)
url = page.url
ok = 'login' not in url and 'checkpoint' not in url
await page.screenshot(path=str(SCREENSHOT_DIR / 'autologin-3-feed.png'))
await ctx.close()
if ok:
log("Strategy 2 SUCCESS")
return {'ok': True, 'strategy': 'auto_login_creds', 'url': url}
log(f"Strategy 2 FAILED url={url}")
return {'ok': False, 'strategy': 'autologin', 'url': url, 'err': 'final_check_failed'}
except Exception as e:
log(f"Strategy 2 EXCEPTION {e}")
await ctx.close()
return {'ok': False, 'err': str(e)[:200], 'strategy': 'autologin'}
# All strategies exhausted
log("All strategies exhausted - no creds configured")
return {
'ok': False,
'err': 'NO_CREDS_CONFIGURED',
'missing': {
'LI_AT (cookie)': cookie is None,
'LI_EMAIL': email is None,
'LI_PASSWORD': password is None,
'LI_TOTP_SEED (optional for 2FA)': totp_seed is None,
},
'instruction': 'Admin: add LI_EMAIL + LI_PASSWORD to /etc/weval/secrets.env (ONE time) for future auto-login. Optional: LI_TOTP_SEED if 2FA enabled.',
}
async def main():
r = await auto_login()
print(json.dumps(r, indent=2))
if __name__ == '__main__':
asyncio.run(main())