Skip to content

Commit 537bc2c

Browse files
author
m.shvets
committed
Enhance: Introduce HostMachineShortName type and refactor RID Manager components to utilize it, improving clarity and consistency in domain controller and RID set management. Update various functions to streamline object SID handling and enhance overall data integrity.
1 parent 01c8d78 commit 537bc2c

20 files changed

Lines changed: 162 additions & 196 deletions

app/alembic/versions/01f3f05a5b11_add_primary_group_id.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ async def _add_domain_computers_group(connection: AsyncConnection) -> None: # n
6868

6969
dir_, group_ = await create_group(
7070
name=DOMAIN_COMPUTERS_GROUP_NAME,
71-
sid=515,
7271
attribute_value_validator=AttributeValueValidator(),
7372
session=session,
7473
)

app/alembic/versions/552b4eafb1aa_remove_objectsid_vals.py

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
77
"""
88

9-
import secrets
10-
119
import sqlalchemy as sa
1210
from alembic import op
1311
from dishka import AsyncContainer, Scope
@@ -180,26 +178,19 @@ async def _migrate_object_sids(
180178
),
181179
)
182180

183-
identifier: str | None = None
181+
domain_identifier: str | None = None
184182
if domain_sid_from_column:
185183
parts = domain_sid_from_column.split("-")
186184
# "S-1-5-21-AAA-BBB-CCC" -> "AAA-BBB-CCC"
187185
if len(parts) >= 7 and domain_sid_from_column.startswith(
188186
"S-1-5-21-",
189187
):
190-
identifier = "-".join(parts[4:7])
191-
192-
if identifier is None:
193-
identifier = (
194-
f"{secrets.randbits(32)}-"
195-
f"{secrets.randbits(32)}-"
196-
f"{secrets.randbits(32)}"
197-
)
188+
domain_identifier = "-".join(parts[4:7])
198189

199190
session.add(
200191
Attribute(
201192
name="DomainIdentifier",
202-
value=identifier,
193+
value=domain_identifier,
203194
directory_id=domain.id,
204195
),
205196
)
@@ -228,7 +219,7 @@ async def _migrate_object_sids(
228219
),
229220
)
230221

231-
built_in_sid_prefix = "S-1-5-32"
222+
sid_prefix = "S-1-5-21"
232223
for dir_name, rid in (
233224
(DOMAIN_ADMIN_GROUP_NAME, SecurityPrincipalRid.DOMAIN_ADMINS),
234225
(DOMAIN_USERS_GROUP_NAME, SecurityPrincipalRid.DOMAIN_USERS),
@@ -249,7 +240,7 @@ async def _migrate_object_sids(
249240
),
250241
)
251242
.values(
252-
value=f"{built_in_sid_prefix}-{int(rid)}",
243+
value=f"{sid_prefix}-{domain_identifier}-{int(rid)}",
253244
),
254245
)
255246

@@ -263,8 +254,8 @@ async def _migrate_object_sids(
263254
)
264255
.values(
265256
value=(
266-
f"{built_in_sid_prefix}"
267-
f"-{int(SecurityPrincipalRid.ADMINISTRATOR)}"
257+
f"{sid_prefix}"
258+
f"-{domain_identifier}-{int(SecurityPrincipalRid.ADMINISTRATOR)}"
268259
),
269260
),
270261
)
@@ -286,19 +277,16 @@ async def _init_rid_manager(
286277
rid_set_use_case = await cnt.get(RIDSetUseCase)
287278
role_use_case = await cnt.get(RoleUseCase)
288279

289-
if not await get_base_directories(session):
280+
base_dn_list = await get_base_directories(session)
281+
if not base_dn_list:
290282
return
283+
domain = base_dn_list[0]
291284

292285
try:
293286
rid_manager_dir = await rid_gateway.get_rid_manager()
294287
except RIDManagerNotFoundError:
295288
rid_manager_dir = await rid_setup_gateway.set_rid_manager()
296289

297-
base_dn_list = await get_base_directories(session)
298-
if not base_dn_list:
299-
return
300-
domain = base_dn_list[0]
301-
302290
domain_identifier = await session.scalar(
303291
select(Attribute).where(
304292
qa(Attribute.directory_id) == domain.id,
@@ -341,21 +329,17 @@ async def _init_rid_manager(
341329
directory=rid_manager_dir,
342330
)
343331

344-
domain_controller = await rid_gateway.get_domain_controller()
345-
rid_set_dir: Directory | None = None
332+
domain_controller = await rid_setup_gateway.get_domain_controller()
346333
try:
347-
rid_set_dir = await rid_set_gateway.get(domain_controller)
334+
await rid_set_gateway.get(domain_controller)
348335
except RIDManagerRidSetNotFoundError:
349-
rid_set_dir = None
350-
351-
if rid_set_dir is None:
352336
previous_allocation_pool = (
353337
await rid_manager_use_case.allocate_pool()
354338
)
355339
allocation_pool = await rid_manager_use_case.allocate_pool()
356340
lower, _ = from_qword(previous_allocation_pool)
357341

358-
rid_set_dir = await rid_set_use_case.add(
342+
await rid_set_use_case.add(
359343
domain_controller,
360344
RIDSetAllocationParamsDTO(
361345
next_rid=lower,

app/alembic/versions/fafc3d0b11ec_.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ async def _create_readonly_grp_and_plcy(
6161
if not group_dir:
6262
dir_, _ = await create_group(
6363
name="readonly domain controllers",
64-
sid=521,
6564
attribute_value_validator=attribute_value_validator,
6665
session=session,
6766
)

app/ioc.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@
188188
RIDSetGateway,
189189
RIDSetUseCase,
190190
)
191+
from ldap_protocol.rid_manager.types import HostMachineShortName
191192
from ldap_protocol.roles.access_manager import AccessManager
192193
from ldap_protocol.roles.ace_dao import AccessControlEntryDAO
193194
from ldap_protocol.roles.migrations_ace_dao import (
@@ -216,6 +217,13 @@ class MainProvider(Provider):
216217
scope = Scope.APP
217218
settings = from_context(provides=Settings, scope=Scope.APP)
218219

220+
@provide(scope=Scope.APP)
221+
def host_machine_short_name(
222+
self,
223+
settings: Settings,
224+
) -> HostMachineShortName:
225+
return HostMachineShortName(settings.HOST_MACHINE_SHORT_NAME)
226+
219227
@provide(scope=Scope.APP)
220228
def get_engine_registry(self, settings: Settings) -> EngineRegistry:
221229
return EngineRegistry(

app/ldap_protocol/auth/setup_gateway.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from sqlalchemy.ext.asyncio import AsyncSession
1313

1414
from entities import Attribute, Directory, Group, NetworkPolicy, User
15-
from enums import EntityTypeNames, SidPrefix
15+
from enums import EntityTypeNames
1616
from ldap_protocol.ldap_schema.attribute_value_validator import (
1717
AttributeValueValidator,
1818
)
@@ -168,7 +168,6 @@ async def create_dir(
168168
await self._object_sid_use_case.add(
169169
directory_id=dir_.id,
170170
rid=int(data["objectSid"]),
171-
sid_prefix=SidPrefix.BUILT_IN_DOMAIN,
172171
)
173172

174173
if dir_.object_class == "group":

app/ldap_protocol/auth/use_cases.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,6 @@ async def _create(self, dto: SetupDTO, data: list) -> None:
253253
await self._role_use_case.create_read_only_role()
254254
await self._audit_use_case.create_policies()
255255
await self._rid_manager_setup_use_case.setup()
256-
dc = await self._rid_manager_use_case.get_domain_controller()
257-
await self._object_sid_use_case.add(
258-
directory_id=dc.id,
259-
)
260256

261257
await self._session.commit()
262258
except IntegrityError:

app/ldap_protocol/rid_manager/object_sid_use_case.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ def __init__(
2828
self._session = session
2929
self._rid_manager_use_case = rid_manager_use_case
3030

31-
async def get(self, directory_id: int) -> str:
32-
"""Get object SID."""
33-
return await self._gateway.get(directory_id)
31+
async def get_domain_identifier(self) -> str:
32+
"""Get domain identifier."""
33+
return await self._gateway.get_domain_identifier()
3434

3535
async def add(
3636
self,
@@ -40,8 +40,7 @@ async def add(
4040
) -> None:
4141
"""Add object SID."""
4242
if rid is None:
43-
rid_set_id = await self._rid_set_use_case.get_rid_set_id()
44-
rid = await self._rid_set_use_case.allocate_next_rid(rid_set_id)
43+
rid = await self._rid_set_use_case.allocate_next_rid()
4544

4645
if sid_prefix == SidPrefix.BUILT_IN_DOMAIN:
4746
object_sid = f"{sid_prefix}-{rid}"

app/ldap_protocol/rid_manager/rid_manager_gateway.py

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,26 @@
77
from sqlalchemy import select, update
88
from sqlalchemy.ext.asyncio import AsyncSession
99

10-
from config import Settings
11-
from constants import DOMAIN_CONTROLLERS_OU_NAME
1210
from entities import Attribute, Directory
1311
from ldap_protocol.rid_manager.exceptions import (
1412
RIDManagerAvailablePoolNotFoundError,
15-
RIDManagerDomainControllerNotFoundError,
1613
RIDManagerNotFoundError,
1714
)
15+
from ldap_protocol.rid_manager.types import HostMachineShortName
1816
from repo.pg.tables import queryable_attr as qa
1917

2018

2119
class RIDManagerGateway:
2220
"""RID Manager gateway."""
2321

24-
def __init__(self, session: AsyncSession, settings: Settings) -> None:
22+
def __init__(
23+
self,
24+
session: AsyncSession,
25+
host_machine_short_name: HostMachineShortName,
26+
) -> None:
2527
"""Initialize RID Manager gateway."""
2628
self._session = session
27-
self._settings = settings
29+
self._host_machine_short_name = host_machine_short_name
2830

2931
async def get_rid_manager(self) -> Directory:
3032
"""Get RID Manager directory."""
@@ -55,41 +57,3 @@ async def update_rid_available_pool(self, available_pool: int) -> None:
5557
.where(qa(Attribute.name) == "rIDAvailablePool")
5658
.values(value=str(available_pool)),
5759
)
58-
59-
async def get_domain_controller(
60-
self,
61-
) -> Directory:
62-
"""Get domain controller."""
63-
domain = await self._session.scalar(
64-
select(Directory).where(
65-
qa(Directory.object_class) == "domain",
66-
qa(Directory.parent_id).is_(None),
67-
),
68-
)
69-
if not domain:
70-
raise RIDManagerDomainControllerNotFoundError(
71-
"Domain controller not found",
72-
)
73-
74-
domain_controllers_ou = await self._session.scalar(
75-
select(Directory).where(
76-
qa(Directory.name) == DOMAIN_CONTROLLERS_OU_NAME,
77-
qa(Directory.parent_id) == domain.id,
78-
),
79-
)
80-
if not domain_controllers_ou:
81-
raise RIDManagerDomainControllerNotFoundError(
82-
"Domain controllers OU not found",
83-
)
84-
85-
domain_controller = await self._session.scalar(
86-
select(Directory).where(
87-
qa(Directory.name) == self._settings.HOST_MACHINE_SHORT_NAME,
88-
qa(Directory.parent_id) == domain_controllers_ou.id,
89-
),
90-
)
91-
if not domain_controller:
92-
raise RIDManagerDomainControllerNotFoundError(
93-
"Domain controller not found",
94-
)
95-
return domain_controller

app/ldap_protocol/rid_manager/rid_manager_use_case.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
from sqlalchemy.ext.asyncio import AsyncSession
88

9-
from entities import Directory
109
from ldap_protocol.rid_manager.exceptions import RIDManagerPoolExceededError
1110
from ldap_protocol.rid_manager.rid_manager_gateway import RIDManagerGateway
1211
from ldap_protocol.rid_manager.utils import from_qword, to_qword
@@ -41,7 +40,3 @@ async def allocate_pool(self) -> int:
4140
await self._gateway.update_rid_available_pool(new_available_pool)
4241

4342
return to_qword(lower, lower + self.RID_BLOCK_SIZE)
44-
45-
async def get_domain_controller(self) -> Directory:
46-
"""Locate best Domain Controller via DNS SRV records."""
47-
return await self._gateway.get_domain_controller()

app/ldap_protocol/rid_manager/rid_set_gateway.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from sqlalchemy.ext.asyncio import AsyncSession
99
from sqlalchemy.orm import aliased
1010

11-
from config import Settings
1211
from constants import DOMAIN_CONTROLLERS_OU_NAME
1312
from entities import Attribute, Directory
1413
from ldap_protocol.rid_manager.dtos import RIDSetAllocationParamsDTO
@@ -18,17 +17,22 @@
1817
RIDManagerRidPreviousAllocationPoolNotFoundError,
1918
RIDManagerRidSetNotFoundError,
2019
)
20+
from ldap_protocol.rid_manager.types import HostMachineShortName
2121
from ldap_protocol.utils.async_cache import rid_set_id_cache
2222
from repo.pg.tables import queryable_attr as qa
2323

2424

2525
class RIDSetGateway:
2626
"""RID Set gateway."""
2727

28-
def __init__(self, session: AsyncSession, settings: Settings) -> None:
28+
def __init__(
29+
self,
30+
session: AsyncSession,
31+
host_machine_short_name: HostMachineShortName,
32+
) -> None:
2933
"""Initialize RID Set gateway."""
3034
self._session = session
31-
self._settings = settings
35+
self._host_machine_short_name = host_machine_short_name
3236

3337
@rid_set_id_cache
3438
async def get_rid_set_id(self) -> int:
@@ -63,7 +67,7 @@ async def get_rid_set_id_value(self) -> int:
6367
qa(domain.parent_id).is_(None),
6468
qa(domain_controllers_ou.name) == DOMAIN_CONTROLLERS_OU_NAME,
6569
qa(domain_controller.name)
66-
== self._settings.HOST_MACHINE_SHORT_NAME,
70+
== self._host_machine_short_name,
6771
qa(rid_set.name) == "RID Set",
6872
),
6973
)
@@ -84,13 +88,15 @@ async def get(self, domain_controller: Directory) -> Directory:
8488

8589
return rid_set
8690

87-
async def add(self, domain_controller: Directory) -> Directory:
88-
"""Add RID Set directory."""
91+
async def create_rid_set_directory(
92+
self,
93+
domain_controller: Directory,
94+
) -> Directory:
95+
"""Create RID Set directory."""
8996
rid_set_dir = Directory(
9097
is_system=True,
9198
name="RID Set",
9299
)
93-
rid_set_dir.create_path(domain_controller, "cn")
94100

95101
self._session.add(rid_set_dir)
96102
await self._session.flush()
@@ -163,10 +169,12 @@ async def set_allocation_attrs(
163169
async def get_rid_allocation_pool(self, rid_set_id: int) -> int:
164170
"""Get RID allocation pool from RID Set directory."""
165171
allocation_pool = await self._session.scalar(
166-
select(Attribute).where(
172+
select(Attribute)
173+
.where(
167174
qa(Attribute.name) == "rIDAllocationPool",
168175
qa(Attribute.directory_id) == rid_set_id,
169-
),
176+
)
177+
.with_for_update(),
170178
)
171179
if not (allocation_pool and allocation_pool.value):
172180
raise RIDManagerRidAllocationPoolNotFoundError(
@@ -193,7 +201,7 @@ async def get_rid_previous_allocation_pool(
193201
)
194202
return int(previous_allocation_pool.value)
195203

196-
async def get_rid_next_rid(self, rid_set_id: int) -> int:
204+
async def get_next_rid_value(self, rid_set_id: int) -> int:
197205
"""Get next RID from RID Set directory."""
198206
next_rid = await self._session.scalar(
199207
select(Attribute)

0 commit comments

Comments
 (0)