attempted fix on group shares not appearing (GID not found) (3)

This commit is contained in:
Ludwig Lehnert
2026-02-18 19:40:13 +01:00
parent 66c7005e7d
commit c4fa01cb0e
2 changed files with 35 additions and 3 deletions

View File

@@ -150,10 +150,11 @@ Kerberos requires close time alignment.
### Dynamic Group Shares
- AD groups: `FileShare_*` and `FS_*`
- Share name: prefix removed (`FileShare_Finance` -> `\\server\Finance`, `FS_Finance` -> `\\server\Finance`)
- Share name: group title from AD (`displayName` -> `name`/`cn` fallback). Prefix stripping from `sAMAccountName` is only a fallback when no title exists.
- Backing path: `/data/groups/<objectGUID>`
- Share exposure generated in `/etc/samba/generated/shares.conf`
- Dynamic share names are validated for SMB compatibility and deduplicated case-insensitively.
- Group membership changes are refreshed during each reconciliation cycle (winbind cache flush + Samba config reload).
## Useful Commands

View File

@@ -27,6 +27,7 @@ LDAP_FILTER = (
)
GROUP_PREFIXES = ("FileShare_", "FS_")
USER_STATUS_FILTER = "(&(objectClass=user)(!(objectClass=computer))(sAMAccountName=*))"
GROUP_TITLE_ATTRS = ("displayname", "name", "cn")
REQUIRED_ENV = ["REALM", "WORKGROUP", "DOMAIN"]
ATTR_RE = re.compile(r"^([^:]+)(::?)\s*(.*)$")
@@ -123,6 +124,15 @@ def derive_share_name(sam_account_name: str) -> Optional[str]:
return None
def derive_group_title(entry: Dict[str, Tuple[str, bool]]) -> Optional[str]:
for attr in GROUP_TITLE_ATTRS:
if attr in entry:
value = entry[attr][0].strip()
if value:
return value
return None
def parse_groups_from_ldap_output(output: str) -> List[Dict[str, str]]:
entries = parse_ldap_entries(output)
@@ -133,7 +143,7 @@ def parse_groups_from_ldap_output(output: str) -> List[Dict[str, str]]:
sam_value, _ = entry["samaccountname"]
sam = sam_value.strip()
share_name = derive_share_name(sam)
share_name = derive_group_title(entry) or derive_share_name(sam)
if not share_name:
continue
@@ -157,7 +167,18 @@ def parse_groups_from_ldap_output(output: str) -> List[Dict[str, str]]:
def fetch_groups_via_net_ads() -> List[Dict[str, str]]:
result = run_command(
["net", "ads", "search", "-P", LDAP_FILTER, "objectGUID", "sAMAccountName"],
[
"net",
"ads",
"search",
"-P",
LDAP_FILTER,
"objectGUID",
"sAMAccountName",
"displayName",
"name",
"cn",
],
check=False,
)
if result.returncode != 0:
@@ -204,6 +225,9 @@ def fetch_groups_via_ldap_bind() -> List[Dict[str, str]]:
LDAP_FILTER,
"objectGUID",
"sAMAccountName",
"displayName",
"name",
"cn",
]
)
return parse_groups_from_ldap_output(result.stdout)
@@ -447,6 +471,12 @@ def reload_samba() -> None:
log("smbcontrol reload-config failed; will retry on next run")
def refresh_winbind_cache() -> None:
result = run_command(["net", "cache", "flush"], check=False)
if result.returncode != 0:
log("net cache flush failed; group membership updates may be delayed")
def resolve_user_uid(qualified_user: str) -> Optional[int]:
try:
return pwd.getpwnam(qualified_user).pw_uid
@@ -701,6 +731,7 @@ def with_lock() -> bool:
sync_public_directory()
sync_private_directories()
refresh_winbind_cache()
reload_samba()
log("Reconciliation completed")
return True