Bug 49404

Summary: netcmdplus не работает с Samba >= 4.19
Product: Sisyphus Reporter: Evgeny Shesteperov <alimektor>
Component: netcmdplusAssignee: Evgeny Sinelnikov <sin>
Status: CLOSED FIXED QA Contact: qa-sisyphus
Severity: normal    
Priority: P5 CC: amakeenk, arzdez, greh, liannnix, liannnix, manowar
Version: unstable   
Hardware: x86_64   
OS: Linux   

Description Evgeny Shesteperov 2024-02-13 18:05:48 MSK
Версия

-   netcmdplus-0.1.2-alt2
-   samba-4.19.4-alt1

Шаги воспроизведения

Развернуть Samba домен, на сервере установить пакет netcmdplus, открыть
web интерфейс альтератора (https://<IP>:8080).

Открыть вкладку Пользователи, нажать Выбор источника, выбрать Samba
ActiveDirectory и выбрать имя домена

Выполнить команду на сервере:

    # samba-tool-plus domain info 127.0.0.1 -d 4

Ожидаемый результат:

В списке Samba ActiveDirectory присутствует созданный домен.

Команда возвращает информацию о домене.

Фактический результат:

В списке Samba ActiveDirectory отсутствует созданный домен (список
пуст).

Команда возвращает ошибку:

    /usr/lib/python3/site-packages/netcmdplus/samdb.py:58: SyntaxWarning: "is not" with 'str' literal. Did you mean "!="?
      if useusernameascn is None and displayname is not "":
    /usr/lib/python3/site-packages/netcmdplus/samdb.py:66: SyntaxWarning: "is not" with 'str' literal. Did you mean "!="?
      if val is not None and val is not "":
    /usr/lib/python3/site-packages/netcmdplus/samdb.py:86: SyntaxWarning: "is not" with 'str' literal. Did you mean "!="?
      if displayname is not "":
    /usr/lib/python3/site-packages/netcmdplus/samdb.py:185: SyntaxWarning: "is not" with 'str' literal. Did you mean "!="?
      if val is not None and val is not "":
    ERROR(<class 'AttributeError'>): uncaught exception - 'cmd_sambatoolplus' object has no attribute 'command_name'
      File "/usr/bin/samba-tool-plus", line 45, in <module>
        retval = cmd._run("samba-tool-plus", subcommand, *args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/usr/lib64/python3/site-packages/samba/netcmd/__init__.py", line 369, in _run
        f"{self.command_name} <subcommand> (-h|--help)\n")
Comment 1 Evgeny Sinelnikov 2024-02-14 00:23:53 MSK
Странно, ошибка имеется, но у выглядит иначе:

# samba-tool-plus domain info 127.0.0.1 -d 4
ERROR(<class 'AttributeError'>): uncaught exception - 'cmd_sambatoolplus' object has no attribute 'command_name'
  File "/usr/bin/samba-tool-plus", line 45, in <module>
    retval = cmd._run("samba-tool-plus", subcommand, *args)
  File "/usr/lib64/samba-dc/python3.9/samba/netcmd/__init__.py", line 369, in _run
    f"{self.command_name} <subcommand> (-h|--help)\n")
Comment 2 Alexander Makeenkov 2024-02-16 18:40:42 MSK
(Ответ для Evgeny Sinelnikov на комментарий #1)
> Странно, ошибка имеется, но у выглядит иначе

В p10 и в сизифе вывод немного отличается из-за разных версий python.
Comment 3 Evgeny Sinelnikov 2024-02-17 17:58:23 MSK
Нужно определиться c тем, зачем мы этот пакет вообще тащим?
Кто и для каких задач его использует?

Оно так написано, by design, что его нужно постоянно подпинывать и сопровождать. Если больше никто не готов это делать и я должен взяться за этот пакет, то возникает вопрос: "А зачем мы этот пакет, вообще, создали?"

Предположу, что это было актуально, как обертка для alterator-net-domain. Но это очень слабая история. Функциональность этого модуля минимальна, поэтому нужно решить:
* Для каких практических задач сейчас используется netcmdplus?
* Какие существенные, функциональные возможности предоставляет этот пакет?
* Какими инструментами мы планируем замещать этот функционал в будущем?
* Кто его готов дорабатывать и сопровождать сегодня?
Comment 4 Evgeny Sinelnikov 2024-02-18 03:57:22 MSK
В новой samba появился обобщённый класс:

diff --git a/source4/scripting/bin/samba-tool b/source4/scripting/bin/samba-tool
index f8a70a6b295..b02ad4d0ef7 100755
--- a/source4/scripting/bin/samba-tool
+++ b/source4/scripting/bin/samba-tool
@@ -30,21 +30,7 @@ sys.path.insert(0, "bin/python")
 import signal
 signal.signal(signal.SIGINT, signal.SIG_DFL)
 
-from samba.netcmd.main import cmd_sambatool
-cmd = cmd_sambatool()
-subcommand = None
-args = ()
+from samba.netcmd.main import samba_tool
 
-if len(sys.argv) > 1:
-    subcommand = sys.argv[1]
-    if len(sys.argv) > 2:
-        args = sys.argv[2:]
-
-try:
-    retval = cmd._run("samba-tool", subcommand, *args)
-except SystemExit as e:
-    retval = e.code
-except Exception as e:
-    cmd.show_command_error(e)
-    retval = 1
+retval = samba_tool(*sys.argv[1:])
 sys.exit(retval)

Логику добавления новых команд в samba-tool-plus нужно выправлять в рамках новой реализации.
Comment 5 manowar@altlinux.org 2024-02-18 13:56:36 MSK
(Ответ для Evgeny Sinelnikov на комментарий #3)
> Нужно определиться c тем, зачем мы этот пакет вообще тащим?
> Кто и для каких задач его использует?

Кажется, cas@ попросил меня добавить подкоманду в net-tool, которой там не было, но в питоновском API нужная операция была. Причин, по которым мы не стали делать форк обычного net-tool (а сделали обёртку) я уже не помню.
Comment 6 Evgeny Sinelnikov 2024-02-19 06:14:23 MSK
"Причесал код". На пустом месте он перестал падать.

Оно делает, вроде, то, что ожидается:
# samba-tool-plus domain info 127.0.0.1 -d 4
lpcfg_load: refreshing parameters from /etc/samba/smb.conf
Processing section "[global]"
Processing section "[sysvol]"
Processing section "[netlogon]"
Processing section "[people]"
Processing section "[photo]"
Processing section "[iso]"
Processing section "[distr]"
pm_process() returned Yes
GENSEC backend 'gssapi_spnego' registered
GENSEC backend 'gssapi_krb5' registered
GENSEC backend 'gssapi_krb5_sasl' registered
GENSEC backend 'spnego' registered
GENSEC backend 'schannel' registered
GENSEC backend 'ncalrpc_as_system' registered
GENSEC backend 'sasl-EXTERNAL' registered
GENSEC backend 'ntlmssp' registered
GENSEC backend 'ntlmssp_resume_ccache' registered
GENSEC backend 'http_basic' registered
GENSEC backend 'http_ntlm' registered
GENSEC backend 'http_negotiate' registered
GENSEC backend 'krb5' registered
GENSEC backend 'fake_gssapi_krb5' registered
added interface lo ip=::1 bcast= netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
added interface lo ip=127.0.0.1 bcast=127.255.255.255 netmask=255.0.0.0
added interface eth0 ip=192.168.9.3 bcast=192.168.9.255 netmask=255.255.255.0
added interface lo ip=::1 bcast= netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
added interface lo ip=127.0.0.1 bcast=127.255.255.255 netmask=255.0.0.0
added interface eth0 ip=192.168.9.3 bcast=192.168.9.255 netmask=255.255.255.0
added interface lo ip=::1 bcast= netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
added interface lo ip=127.0.0.1 bcast=127.255.255.255 netmask=255.0.0.0
added interface eth0 ip=192.168.9.3 bcast=192.168.9.255 netmask=255.255.255.0
added interface lo ip=::1 bcast= netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
added interface lo ip=127.0.0.1 bcast=127.255.255.255 netmask=255.0.0.0
added interface eth0 ip=192.168.9.3 bcast=192.168.9.255 netmask=255.255.255.0
finddcs: searching for a DC by IP 127.0.0.1
finddcs: performing CLDAP query on 127.0.0.1
finddcs: Found matching DC 127.0.0.1 with server_type=0x000013fd
Forest           : darkmastersin.net
Domain           : darkmastersin.net
Netbios domain   : DARKMASTERSIN
DC name          : dc.darkmastersin.net
DC netbios name  : DC
Server site      : Default-First-Site-Name
Client site      : Default-First-Site-Name

Но modify, ради которого всё затекалось - отваливается:
# samba-tool-plus user update xtst --must-change-at-next-login
ERROR(ldb): Failed to modify user 'xtst':  - objectclass: modify message must have elements/attributes!
  File "/usr/lib/python3/site-packages/netcmdplus/user.py", line 58, in run
    samdb.usermod(username, password=password,
  File "/usr/lib/python3/site-packages/netcmdplus/samdb.py", line 160, in usermod
    self.modify(ldbmessage)

# samba-tool-plus user update xtst 
ERROR(ldb): Failed to modify user 'xtst':  - objectclass: modify message must have elements/attributes!
  File "/usr/lib/python3/site-packages/netcmdplus/user.py", line 58, in run
    samdb.usermod(username, password=password,
  File "/usr/lib/python3/site-packages/netcmdplus/samdb.py", line 160, in usermod
    self.modify(ldbmessage)

Нужно теперь с деталями разбираться ещё. Исходники выложил сюда:
https://git.altlinux.org/people/sin/packages/netcmdplus.git
https://gitlab.basealt.space/alt/netcmdplus
Comment 7 Evgeny Sinelnikov 2024-02-19 07:34:57 MSK
Ошибка "objectclass: modify message must have elements/attributes!" связана с логикой, когда ни один атрибут не задан, а команда на изменение даётся. Оно и понятно:

Смотрим и видим, что мне повезло выбрать именно тот параметр, который не меняет ни один атрибут:
--------
        self.transaction_start()
        try:
            self.modify(ldbmessage)
            if setpassword:
                self.setpassword(
                    "(samAccountName=%s)" % ldb.binary_encode(username),
                    password,
                    force_password_change_at_next_login_req)
--------
Тут можно просто не делать modify(), если не было задано ни одного атрибута.


А вот это как понимать?

[root@dc ~]# samba-tool-plus user update xtst --department="City"
ERROR(ldb): Failed to modify user 'xtst':  - No such Base DN: CN=xtst,CN=Users,DC=darkmastersin,DC=net
  File "/usr/lib/python3/site-packages/netcmdplus/user.py", line 58, in run
    samdb.usermod(username, password=password,
  File "/usr/lib/python3/site-packages/netcmdplus/samdb.py", line 160, in usermod
    self.modify(ldbmessage)

[root@dc ~]# samba-tool-plus user show xtst 
ldb_wrap open of secrets.ldb
dn: CN=Tester Functional,OU=Home,DC=darkmastersin,DC=net
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Tester Functional
instanceType: 4
whenCreated: 20231105225819.0Z
uSNCreated: 12843
name: Tester Functional
objectGUID: 49b9b2c1-39bb-414b-9a5e-134b77c97460
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
primaryGroupID: 513
objectSid: S-1-5-21-3813720-278734374-249828831-1117
accountExpires: 9223372036854775807
sAMAccountType: 805306368
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=darkmastersin,DC=net
givenName: Functional
sn: Tester
sAMAccountName: xtst
userPrincipalName: xtst@darkmastersin.net
userAccountControl: 512
lastLogonTimestamp: 133436987772250650
pwdLastSet: 133442918956692000
whenChanged: 20231112194455.0Z
uSNChanged: 12856
lastLogon: 133443861188327300
logonCount: 10
distinguishedName: CN=Tester Functional,OU=Home,DC=darkmastersin,DC=net

Это уже дичь, если вот так вычислять dn пользователя:
--------
        cn = username
        if useusernameascn is None and displayname is not "":
            cn = displayname
        user_dn = "CN=%s,%s,%s" % (cn, (userou or "CN=Users"), self.domain_dn())
--------
Ну, это же не FreeIPA, где свалка в одной куче всех пользователей. Тут сначала нужно выяснить dn по имени, а потом уже предлагать его атрибуты менять.


В общем, цель всего этого хозяйства понятна. Samba Team не осилила, а мы не им и всем запили, а очень ограниченную реализацию сделали. Она никогда не работала, получается с пользователями в разных ou. Если только вот так предполагалось:
--------
[root@dc ~]# samba-tool-plus user update xtst --userou="OU=Home" --department="City"
ERROR(ldb): Failed to modify user 'xtst':  - No such Base DN: CN=xtst,OU=Home,DC=darkmastersin,DC=net
  File "/usr/lib/python3/site-packages/netcmdplus/user.py", line 58, in run
    samdb.usermod(username, password=password,
  File "/usr/lib/python3/site-packages/netcmdplus/samdb.py", line 160, in usermod
    self.modify(ldbmessage)
-------

Но в том-то и дело, что CN объекта пользователь никак не должен, не обязан "биться" с его sAMAccountName или userPrincipalName:

sAMAccountName: xtst
userPrincipalName: xtst@darkmastersin.net

В общем, оно "работает". Но требуется доработка. Это ещё пилить и пилить.
Comment 8 Evgeny Sinelnikov 2024-02-19 07:37:53 MSK
Будем считать, что регрессий нет:

[root@dc ~]# samba-tool-plus user create ytst "XXXXXXXX"
descriptor_prepare_commit: changes: num_registrations=0
descriptor_prepare_commit: changes: num_registered=0
descriptor_prepare_commit: changes: num_toplevel=0
descriptor_prepare_commit: changes: num_processed=0
descriptor_prepare_commit: objects: num_processed=0
descriptor_prepare_commit: objects: num_skipped=0
User 'ytst' added successfully

[root@dc ~]# samba-tool-plus user update ytst --department="City"
descriptor_prepare_commit: changes: num_registrations=0
descriptor_prepare_commit: changes: num_registered=0
descriptor_prepare_commit: changes: num_toplevel=0
descriptor_prepare_commit: changes: num_processed=0
descriptor_prepare_commit: objects: num_processed=0
descriptor_prepare_commit: objects: num_skipped=0
User account 'ytst' updated successfully

[root@dc ~]# samba-tool-plus user show ytst 
ldb_wrap open of secrets.ldb
dn: CN=ytst,CN=Users,DC=darkmastersin,DC=net
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: ytst
instanceType: 4
whenCreated: 20240219043608.0Z
uSNCreated: 17555
name: ytst
objectGUID: 5658c610-d2a5-4331-97d3-9ffb6e4aebba
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
primaryGroupID: 513
objectSid: S-1-5-21-3813720-278734374-249828831-1119
accountExpires: 9223372036854775807
logonCount: 0
sAMAccountName: ytst
sAMAccountType: 805306368
userPrincipalName: ytst@darkmastersin.net
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=darkmastersin,DC=net
pwdLastSet: 133527909680720840
userAccountControl: 512
department: City
whenChanged: 20240219043621.0Z
uSNChanged: 17558
distinguishedName: CN=ytst,CN=Users,DC=darkmastersin,DC=net
Comment 9 Repository Robot 2024-02-19 08:30:04 MSK
netcmdplus-0.1.3-alt1 -> sisyphus:

 Mon Feb 19 2024 Evgeny Sinelnikov <sin@altlinux> 0.1.3-alt1
 - Add compatibility with stable releases of samba-4.18 and later (closes: 49404).
 - Replace python3 build to new pyproject_build process.
Comment 10 manowar@altlinux.org 2024-02-19 13:07:09 MSK
(Ответ для Evgeny Sinelnikov на комментарий #7)

> В общем, цель всего этого хозяйства понятна. Samba Team не осилила, а мы не
> им и всем запили, а очень ограниченную реализацию сделали. Она никогда не
> работала, получается с пользователями в разных ou.

Так какой у нас план? Может быть осилить "им и всем"?
Comment 11 Evgeny Sinelnikov 2024-02-23 06:10:14 MSK
(Ответ для manowar@altlinux.org на комментарий #10)
> (Ответ для Evgeny Sinelnikov на комментарий #7)
> 
> > В общем, цель всего этого хозяйства понятна. Samba Team не осилила, а мы не
> > им и всем запили, а очень ограниченную реализацию сделали. Она никогда не
> > работала, получается с пользователями в разных ou.
> 
> Так какой у нас план? Может быть осилить "им и всем"?

Давайте сформулируем, что мы хотим. А то угадывать, заглядывая одним глазом в код приходится. Перетащить текущий код в базовый инструмент - samba-tool не представляет собой особой технической проблемы.

Чтобы "осилить" требуется заняться такой цепочкой действий:
* дать подробное описание текущей доработки;
* перетащить код в проект samba (поверх ветки master, разумеется);
* зафиксировать подготовленное подробное описание в тексте коммита (правильно оформленном commit message на английском языке, конечно);
* добавить к этому коммиту, отдельный коммит с тестами (без тестов апстрим не захочет принимать);
* убедиться, что предложенный функционал работает, освоив для этого запуск этих тестов для samba;
* отправить, в соответствии с правилами Samba Team, патчи для принятия в основной код проекта.

По мне, функционал был добавлен полезный. Но описание требуется. Изложить же его на английском, исправить changelog в коммите, добавить тесты и т.п. требует времени, которого пока не нашлось.
Comment 12 Evgeny Sinelnikov 2024-02-23 06:11:47 MSK
(Ответ для manowar@altlinux.org на комментарий #10)
[...]
> Так какой у нас план? Может быть осилить "им и всем"?

Содержательно, этот вопрос к авторам задумки. Я предлагаю её сформулировать и передать с патчами и тестами в апстрим.