Skip to content

Commit

Permalink
fix imports
Browse files Browse the repository at this point in the history
change machine account to async auth.
adds administrator docs and suggested settings.
  • Loading branch information
stgmsa committed Oct 15, 2024
1 parent f5685e8 commit 62670e2
Show file tree
Hide file tree
Showing 13 changed files with 455 additions and 154 deletions.
12 changes: 0 additions & 12 deletions bin/pyntlm_auth/app.py

This file was deleted.

17 changes: 15 additions & 2 deletions bin/pyntlm_auth/config_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@


def expand_machine_account_list():
r = [global_vars.c_username]
r = [global_vars.s_computer_account_base]

m = global_vars.c_username.replace("$", "")
m = global_vars.s_computer_account_base.replace("$", "")
for i in range(global_vars.c_additional_machine_accounts):
r.append(f"{m}-{i}$")

Expand Down Expand Up @@ -381,3 +381,16 @@ def config_load():
global_vars.c_db_pass = c_db_pass
global_vars.c_db = c_db
global_vars.c_db_unix_socket = c_db_unix_socket

global_vars.s_computer_account_base = username


def reload_worker_config():
computer_account = global_vars.s_bind_account.replace("$", "")

global_vars.c_username = computer_account.upper() + "$"
global_vars.c_netbios_name = computer_account.upper()
global_vars.c_workstation = computer_account.upper()
global_vars.c_server_string = computer_account

global_vars.s_password_ro = global_vars.c_password
22 changes: 19 additions & 3 deletions bin/pyntlm_auth/entrypoint.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import logging
import os
import time
from threading import Thread

import pymysql
from flask import Flask, g, request
from flaskext.mysql import MySQL

import config_loader
import global_vars
import handlers

import t_health_checker
import t_async_job

app = Flask(__name__)

time.sleep(1)
Expand All @@ -20,12 +25,23 @@
while True:
m = config_loader.bind_machine_account(worker_pid)
if m is not None:
global_vars.s_bind_account = m
break

print(f"---- worker {worker_pid} failed to bind machine account: no available accounts, retrying.")
global_vars.s_worker.log.warning(f"failed to bind machine account: no available accounts, retrying.")
time.sleep(1)

print(f"---- worker {worker_pid} successfully registered with machine account '{m}', ready to handle requests.")
config_loader.reload_worker_config()
global_vars.s_worker.log.info(f"successfully registered with machine account '{m}', ready to handle requests.")

flask_jobs = (
Thread(target=t_async_job.async_auth, daemon=False, args=(global_vars.s_worker,)),
Thread(target=t_async_job.async_test, daemon=False, args=(global_vars.s_worker,)),
Thread(target=t_health_checker.health_check, daemon=True, args=(global_vars.s_worker,))
)

for job in flask_jobs:
job.start()

werkzeug_logger = logging.getLogger('werkzeug')

Expand Down Expand Up @@ -78,7 +94,7 @@ def teardown_request(exception=None):
app.route('/ntlm/expire', methods=['POST'])(handlers.ntlm_expire_handler)
app.route('/event/report', methods=['POST'])(handlers.event_report_handler)
app.route('/ntlm/connect', methods=['GET'])(handlers.ntlm_connect_handler)
app.route('/ntlm/connect', methods=['POST'])(handlers.test_password_handler)
app.route('/ntlm/connect', methods=['POST'])(handlers.ntlm_connect_handler_with_password)
app.route('/ping', methods=['GET'])(handlers.ping_handler)

if __name__ == '__main__':
Expand Down
14 changes: 9 additions & 5 deletions bin/pyntlm_auth/global_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ def get_value(key, value=None):

s_lock = threading.Lock()

s_worker = None # gunicorn worker object.
s_bind_account = None # machine account bind to specific worker
s_computer_account_base = None
s_password_ro = None # machine account password loaded from config file

# config for domain.conf - AD
c_netbios_name = None
c_realm = None
Expand Down Expand Up @@ -56,10 +61,9 @@ def get_value(key, value=None):
c_nt_key_cache_enabled = None
c_nt_key_cache_expire = None

c_ad_account_lockout_threshold = 0 # 0..999. Default=0, never locks
c_ad_account_lockout_duration = None # Default not set
c_ad_reset_account_lockout_counter_after = None # Default not set
c_ad_old_password_allowed_period = None # Windows 2003+, Default not set, if not set, 60
c_ad_account_lockout_threshold = 0 # 0..999. Default=0, never locks
c_ad_account_lockout_duration = None # Default not set
c_ad_reset_account_lockout_counter_after = None # Default not set
c_ad_old_password_allowed_period = None # Windows 2003+, Default not set, if not set, 60

c_max_allowed_password_attempts_per_device = None

30 changes: 22 additions & 8 deletions bin/pyntlm_auth/gunicorn.conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

import config_loader
import global_vars
import t_async_job
import t_health_checker
import t_sdnotify
import t_worker_register

NAME = "NTLM Auth API"

config_loader.config_load()

try:
LISTEN = os.getenv("LISTEN")
bind_port = int(LISTEN)
Expand All @@ -21,16 +21,17 @@
print(f"failed to extract parameter 'LISTEN' from environment variable: {str(e)}. {NAME} terminated.")
sys.exit(1)

config_loader.config_load()
worker_num = global_vars.c_additional_machine_accounts + 1

wsgi_app = 'entrypoint:app'

bind = f"127.0.0.1:{bind_port}"
bind = f"0.0.0.0:{bind_port}"
backlog = 2048
workers = worker_num
worker_class = 'sync' # use sync, do not use 'gevent', or 'eventlet' due to block operations.
timeout = 30
graceful_timeout = 30
graceful_timeout = 10

accesslog = '-' # to stdout
errorlog = '-' # to stdout/err
Expand All @@ -40,7 +41,7 @@
access_log_format = '%(h)s %(l)s %(u)s %(p)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'

keepalive = 2
max_requests = 100000
max_requests = 10000
max_requests_jitter = 50

daemon = False
Expand All @@ -54,10 +55,23 @@
reload = True # reload apps when the source code changes, For debugging purpose only.


def on_exit(server):
server.log.info(f"master process on-exit clean up started...")
server.log.info(f"master process on-exit clean up done...")


def worker_exit(server, worker):
worker.log.info(f"worker process pre-exit clean up started, sending thread stop event...")

t_async_job.stop_event.set()
t_health_checker.stop_event.set()
t_worker_register.stop_event.set()
t_sdnotify.stop_event.set()


def post_fork(server, worker):
master_pid = os.getppid()
worker_pid = os.getpid()
worker.log.info(f" worker spawned with PID of {worker_pid} by master process {master_pid}")
worker.log.info(f"post fork hook: worker spawned with PID of {worker.pid} by master {server.pid}")
global_vars.s_worker = worker

background_jobs = (
Thread(target=t_worker_register.primary_worker_register, daemon=True, args=(worker,)),
Expand Down
Loading

0 comments on commit 62670e2

Please sign in to comment.