-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuac_sync.py
More file actions
82 lines (70 loc) · 2.29 KB
/
uac_sync.py
File metadata and controls
82 lines (70 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
"""userAccountControl sync.
Copyright (c) 2024 MultiFactor
License: https://github.com/MultiDirectoryLab/MultiDirectory/blob/main/LICENSE
"""
from sqlalchemy import Integer, String, cast, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.sql import func, select
from config import Settings
from entities import Attribute, User
from ldap_protocol.kerberos import AbstractKadmin
from ldap_protocol.objects import UserAccountControlFlag
from ldap_protocol.utils.queries import add_lock_and_expire_attributes
from repo.pg.tables import queryable_attr as qa
async def disable_accounts(
session: AsyncSession,
kadmin: AbstractKadmin,
settings: Settings,
) -> None:
"""Update userAccountControl attr.
:param AsyncSession session: db
Original query:
update "Attributes" a
set value = (CAST(a.value AS INTEGER) | 2)::text
from "Users" u
where (CAST(a.value AS INTEGER) & 2) = 0 and
u."accountExpires" < NOW() and
a."directoryId" = u."directoryId" and
a."name" = 'userAccountControl'
"""
subquery = (
select(qa(User.directory_id))
.where(
qa(User.account_exp) < func.now(),
qa(User.directory_id) == qa(Attribute.directory_id),
)
.scalar_subquery()
)
new_value = cast(
cast(Attribute.value, Integer).op("|")(
UserAccountControlFlag.ACCOUNTDISABLE,
),
String,
)
conditions = [
cast(Attribute.value, Integer).op("&")(
UserAccountControlFlag.ACCOUNTDISABLE,
)
== 0,
qa(Attribute.directory_id).in_(subquery),
qa(Attribute.name) == "userAccountControl",
]
ids = await session.scalars(
update(Attribute)
.values(value=new_value)
.where(*conditions)
.returning(qa(Attribute.directory_id))
.execution_options(synchronize_session=False),
)
users = await session.stream_scalars(
select(User)
.where(qa(User.directory_id).in_(ids)),
) # fmt: skip
async for user in users:
await kadmin.lock_principal(user.sam_account_name)
await add_lock_and_expire_attributes(
session,
user.directory,
settings.TIMEZONE,
)
await session.commit()