-
Notifications
You must be signed in to change notification settings - Fork 494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NAS-133586 / 25.04 / Fix domain join in Samba 4.21 #15402
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,10 @@ | ||
import logging | ||
import os | ||
import base64 | ||
import subprocess | ||
import stat | ||
|
||
from contextlib import suppress | ||
|
||
logger = logging.getLogger(__name__) | ||
kdir = "/etc/kerberos" | ||
keytabfile = "/etc/krb5.keytab" | ||
unified_keytab = os.path.join(kdir, 'tmp_keytab') | ||
|
||
|
||
def mit_copy(temp_keytab): | ||
kt_copy = subprocess.run( | ||
['ktutil'], | ||
input=f'rkt {temp_keytab}\nwkt {unified_keytab}'.encode(), | ||
capture_output=True | ||
) | ||
if kt_copy.stderr: | ||
logger.error("%s: failed to add to uinified keytab: %s", | ||
temp_keytab, kt_copy.stderr.decode()) | ||
|
||
|
||
def write_keytab(db_keytabname, db_keytabfile): | ||
dirfd = None | ||
|
||
def opener(path, flags): | ||
return os.open(path, flags, mode=0o600, dir_fd=dirfd) | ||
|
||
with suppress(FileExistsError): | ||
os.mkdir(kdir, mode=0o700) | ||
|
||
try: | ||
dirfd = os.open(kdir, os.O_DIRECTORY) | ||
st = os.fstat(dirfd) | ||
if stat.S_IMODE(st.st_mode) != 0o700: | ||
os.fchmod(dirfd, 0o700) | ||
|
||
with open(db_keytabname, "wb", opener=opener) as f: | ||
f.write(db_keytabfile) | ||
kt_name = os.readlink(f'/proc/self/fd/{f.fileno()}') | ||
|
||
mit_copy(kt_name) | ||
os.remove(db_keytabname, dir_fd=dirfd) | ||
|
||
finally: | ||
os.close(dirfd) | ||
from base64 import b64decode | ||
from middlewared.utils.directoryservices import krb5 | ||
|
||
|
||
def render(service, middleware, render_ctx): | ||
keytabs = middleware.call_sync('kerberos.keytab.query') | ||
keytabs = [b64decode(x['file']) for x in middleware.call_sync('kerberos.keytab.query')] | ||
if not keytabs: | ||
logger.trace('No keytabs in configuration database, skipping keytab generation') | ||
return | ||
|
||
for keytab in keytabs: | ||
db_keytabfile = base64.b64decode(keytab['file'].encode()) | ||
db_keytabname = f'keytab_{keytab["id"]}' | ||
write_keytab(db_keytabname, db_keytabfile) | ||
|
||
with open(unified_keytab, 'rb') as f: | ||
keytab_bytes = f.read() | ||
|
||
os.unlink(unified_keytab) | ||
return keytab_bytes | ||
return krb5.concatenate_keytab_data(keytabs) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
from logging import getLogger | ||
from middlewared.utils import filter_list | ||
from middlewared.utils.directoryservices.constants import DSType | ||
from middlewared.utils.directoryservices.krb5_constants import SAMBA_KEYTAB_DIR | ||
from middlewared.utils.filesystem.acl import FS_ACL_Type, path_get_acltype | ||
from middlewared.utils.io import get_io_uring_enabled | ||
from middlewared.utils.path import FSLocation, path_location | ||
|
@@ -28,6 +29,11 @@ | |
"0x3e:0xf024,0x3f:0xf025,0x5c:0xf026,0x7c:0xf027" | ||
) | ||
|
||
AD_KEYTAB_PARAMS = ( | ||
f"{SAMBA_KEYTAB_DIR}/krb5.keytab0:account_name:sync_kvno:machine_password", | ||
f"{SAMBA_KEYTAB_DIR}/krb5.keytab1:sync_spns:sync_kvno:machine_password", | ||
f"{SAMBA_KEYTAB_DIR}/krb5.keytab2:spn_prefixes=nfs:sync_kvno:machine_password" | ||
) | ||
|
||
class TrueNASVfsObjects(enum.StrEnum): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The obligatory flake8 comment: Need an extra blank line between |
||
# Ordering here determines order in which objects entered into | ||
|
@@ -457,7 +463,8 @@ def generate_smb_conf_dict( | |
ac = ds_config | ||
smbconf.update({ | ||
'server role': 'member server', | ||
'kerberos method': 'secrets and keytab', | ||
'kerberos method': 'secrets only', | ||
'sync machine password to keytab': ' '.join(AD_KEYTAB_PARAMS), | ||
'security': 'ADS', | ||
'local master': False, | ||
'domain master': False, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
import subprocess | ||
import time | ||
|
||
from contextlib import contextmanager | ||
from .krb5_constants import krb_tkt_flag, krb5ccache, KRB_ETYPE, KRB_Keytab | ||
from middlewared.service_exception import CallError | ||
from middlewared.utils import filter_list | ||
|
@@ -108,6 +109,15 @@ def __tmp_krb5_keytab() -> str: | |
return tmpfile.name | ||
|
||
|
||
@contextmanager | ||
def temporary_keytab() -> str: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flake8 doesn't like the |
||
kt = __tmp_krb5_keytab() | ||
try: | ||
yield kt | ||
finally: | ||
os.remove(kt) | ||
|
||
|
||
def parse_klist_output(klistbuf: str) -> list: | ||
""" | ||
This is an internal method that parses the output of `klist -ef` | ||
|
@@ -436,3 +446,24 @@ def extract_from_keytab( | |
|
||
os.remove(tmp_keytab) | ||
return kt_bytes | ||
|
||
|
||
def concatenate_keytab_data(keytab_data: list[bytes]) -> bytes: | ||
with temporary_keytab() as unified: | ||
for data in keytab_data: | ||
with temporary_keytab() as kt: | ||
with open(kt, 'wb') as f: | ||
f.write(data) | ||
f.flush() | ||
|
||
kt_copy = subprocess.run( | ||
['ktutil'], | ||
input=f'rkt {kt}\nwkt {unified}'.encode(), | ||
capture_output=True | ||
) | ||
if kt_copy.stderr: | ||
raise RuntimeError('Failed to concatenate keytabs: %s', | ||
kt_copy.stderr.decode()) | ||
|
||
with open(unified, 'rb') as f: | ||
return f.read() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be renamed to
_ad_set_nfs_spns
?