Skip to content

Commit

Permalink
ipa config: add --enable-sid option
Browse files Browse the repository at this point in the history
Add new options to ipa config-mod, allowing to enable
SID generation on upgraded servers:
ipa config-mod --enable-sid --add-sids --netbios-name NAME

The new option uses Dbus to launch an oddjob command,
org.freeipa.server.config-enable-sid
that runs the installation steps related to SID generation.

--add-sids is optional and triggers the sid generation task that
populates SID for existing users / groups.
--netbios-name is optional and allows to specify the NetBIOS Name.
When not provided, the NetBIOS name is generated based on the leading
component of the DNS domain name.

This command can be run multiple times.

Fixes: https://pagure.io/freeipa/issue/8995
Signed-off-by: Florence Blanc-Renaud <[email protected]>
Reviewed-By: Christian Heimes <[email protected]>
Reviewed-By: Rob Crittenden <[email protected]>
Reviewed-By: Alexander Bokovoy <[email protected]>
  • Loading branch information
flo-renaud committed Nov 2, 2021
1 parent b054532 commit ed001c9
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 5 deletions.
5 changes: 4 additions & 1 deletion API.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1076,11 +1076,13 @@ args: 0,1,1
option: Str('version?')
output: Output('result')
command: config_mod/1
args: 0,29,3
args: 0,32,3
option: Flag('add_sids?', autofill=True, default=False)
option: Str('addattr*', cli_name='addattr')
option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('ca_renewal_master_server?', autofill=False)
option: Str('delattr*', cli_name='delattr')
option: Flag('enable_sid?', autofill=True, default=False)
option: StrEnum('ipaconfigstring*', autofill=False, cli_name='ipaconfigstring', values=[u'AllowNThash', u'KDC:Disable Last Success', u'KDC:Disable Lockout', u'KDC:Disable Default Preauth for SPNs'])
option: Str('ipadefaultemaildomain?', autofill=False, cli_name='emaildomain')
option: Str('ipadefaultloginshell?', autofill=False, cli_name='defaultshell')
Expand All @@ -1102,6 +1104,7 @@ option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', v
option: Bool('ipauserdefaultsubordinateid?', autofill=False, cli_name='user_default_subid')
option: Str('ipauserobjectclasses*', autofill=False, cli_name='userobjectclasses')
option: IA5Str('ipausersearchfields?', autofill=False, cli_name='usersearch')
option: Str('netbios_name?', autofill=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Flag('rights', autofill=True, default=False)
option: Str('setattr*', cli_name='setattr')
Expand Down
4 changes: 2 additions & 2 deletions VERSION.m4
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000)
# #
########################################################
define(IPA_API_VERSION_MAJOR, 2)
# Last change: make sudorule option multivalue
define(IPA_API_VERSION_MINOR, 244)
# Last change: add enable_sid to config
define(IPA_API_VERSION_MINOR, 245)


########################################################
Expand Down
1 change: 1 addition & 0 deletions freeipa.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,7 @@ fi
%dir %{_libexecdir}/ipa/oddjob
%attr(0755,root,root) %{_libexecdir}/ipa/oddjob/org.freeipa.server.conncheck
%attr(0755,root,root) %{_libexecdir}/ipa/oddjob/org.freeipa.server.trust-enable-agent
%attr(0755,root,root) %{_libexecdir}/ipa/oddjob/org.freeipa.server.config-enable-sid
%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freeipa.server.conf
%config(noreplace) %{_sysconfdir}/oddjobd.conf.d/ipa-server.conf
%dir %{_libexecdir}/ipa/certmonger
Expand Down
2 changes: 2 additions & 0 deletions install/oddjob/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dbusconfdir = $(sysconfdir)/dbus-1/system.d
dist_noinst_DATA = \
com.redhat.idm.trust-fetch-domains.in \
org.freeipa.server.trust-enable-agent.in \
org.freeipa.server.config-enable-sid.in \
etc/oddjobd.conf.d/oddjobd-ipa-trust.conf.in \
etc/oddjobd.conf.d/ipa-server.conf.in \
$(NULL)
Expand All @@ -18,6 +19,7 @@ dist_oddjob_SCRIPTS = \
nodist_oddjob_SCRIPTS = \
com.redhat.idm.trust-fetch-domains \
org.freeipa.server.trust-enable-agent \
org.freeipa.server.config-enable-sid \
$(NULL)


Expand Down
6 changes: 6 additions & 0 deletions install/oddjob/etc/oddjobd.conf.d/ipa-server.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
prepend_user_name="no"
argument_passing_method="cmdline"/>
</method>
<method name="config_enable_sid">
<helper exec="@ODDJOBDIR@/org.freeipa.server.config-enable-sid"
arguments="10"
prepend_user_name="no"
argument_passing_method="cmdline"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Introspectable">
<allow min_uid="0" max_uid="0"/>
Expand Down
76 changes: 76 additions & 0 deletions install/oddjob/org.freeipa.server.config-enable-sid.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/python3
#
# Copyright (C) 2021 FreeIPA Contributors see COPYING for license
#

import logging

from ipalib import api
from ipalib.install import sysrestore
from ipaplatform.paths import paths
from ipapython import ipaldap
from ipapython.admintool import AdminTool
from ipaserver.install import adtrust, adtrustinstance

logger = logging.getLogger(__name__)

class IPAConfigEnableSid(AdminTool):
command_name = "ipa-enable-sid"
log_file_name = paths.IPASERVER_ENABLESID_LOG
usage = "%prog"
description = "Enable SID generation"

@classmethod
def add_options(cls, parser):
super(IPAConfigEnableSid, cls).add_options(parser)

parser.add_option(
"--add-sids",
dest="add_sids", default=False, action="store_true",
help="Add SIDs for existing users and groups as the final step"
)

parser.add_option(
"--netbios-name",
dest="netbios_name", default=None,
help="NetBIOS name of the IPA domain"
)

parser.add_option(
"--reset-netbios-name",
dest="reset_netbios_name", default=False, action="store_true",
help="Force reset of the existing NetBIOS name"
)


def validate_options(self):
super(IPAConfigEnableSid, self).validate_options(needs_root=True)

def run(self):
api.bootstrap(in_server=True, confdir=paths.ETC_IPA)
api.finalize()

try:
api.Backend.ldap2.connect()
fstore = sysrestore.FileStore(paths.SYSRESTORE)

smb = adtrustinstance.ADTRUSTInstance(fstore, False)
smb.realm = api.env.realm
smb.autobind = ipaldap.AUTOBIND_ENABLED
smb.setup(api.env.host, api.env.realm,
self.options.netbios_name,
self.options.reset_netbios_name,
adtrust.DEFAULT_PRIMARY_RID_BASE,
adtrust.DEFAULT_SECONDARY_RID_BASE,
self.options.add_sids,
enable_compat=False)
smb.find_local_id_range()
smb.create_instance()

finally:
if api.Backend.ldap2.isconnected():
api.Backend.ldap2.disconnect()

return 0

IPAConfigEnableSid.run_cli()
1 change: 1 addition & 0 deletions ipaplatform/base/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ class BasePathNamespace:
IPAREPLICA_CONNCHECK_LOG = "/var/log/ipareplica-conncheck.log"
IPAREPLICA_INSTALL_LOG = "/var/log/ipareplica-install.log"
IPARESTORE_LOG = "/var/log/iparestore.log"
IPASERVER_ENABLESID_LOG = "/var/log/ipaserver-enable-sid.log"
IPASERVER_INSTALL_LOG = "/var/log/ipaserver-install.log"
IPASERVER_ADTRUST_INSTALL_LOG = "/var/log/ipaserver-adtrust-install.log"
IPASERVER_DNS_INSTALL_LOG = "/var/log/ipaserver-dns-install.log"
Expand Down
2 changes: 2 additions & 0 deletions ipaserver/install/adtrustinstance.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ def __add_fallback_group(self):
# _ldap_mod does not return useful error codes, so we must check again
# if the fallback group was created properly.
try:
# Remove entry from cache otherwise get_entry won't find it
api.Backend.ldap2.remove_cache_entry(fb_group_dn)
api.Backend.ldap2.get_entry(fb_group_dn)
except errors.NotFound:
self.print_msg("Failed to add fallback group.")
Expand Down
99 changes: 97 additions & 2 deletions ipaserver/plugins/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,29 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import dbus
import dbus.mainloop.glib
import logging

from ipalib import api
from ipalib import Bool, Int, Str, IA5Str, StrEnum, DNParam
from ipalib import Bool, Int, Str, IA5Str, StrEnum, DNParam, Flag
from ipalib import errors
from ipalib.constants import MAXHOSTNAMELEN
from ipalib.plugable import Registry
from ipalib.request import context
from ipalib.util import validate_domain_name
from .baseldap import (
LDAPObject,
LDAPUpdate,
LDAPRetrieve)
from .selinuxusermap import validate_selinuxuser
from ipalib import _
from ipapython.admintool import ScriptError
from ipapython.dn import DN
from ipaserver.plugins.privilege import principal_has_privilege
from ipaserver.install.adtrust import set_and_check_netbios_name

logger = logging.getLogger(__name__)

# 389-ds attributes that should be skipped in attribute checks
OPERATIONAL_ATTRIBUTES = ('nsaccountlock', 'member', 'memberof',
Expand Down Expand Up @@ -340,6 +349,24 @@ class config(LDAPObject):
doc=_('DNSec key master'),
flags={'virtual_attribute', 'no_create', 'no_update'}
),
Flag(
'enable_sid?',
label=_('Setup SID configuration'),
doc=_('New users and groups automatically get a SID assigned'),
flags={'virtual_attribute', 'no_create'}
),
Flag(
'add_sids?',
label=_('Add SIDs'),
doc=_('Add SIDs for existing users and groups'),
flags={'virtual_attribute', 'no_create'}
),
Str(
'netbios_name?',
label=_('NetBIOS name of the IPA domain'),
doc=_('NetBIOS name of the IPA domain'),
flags={'virtual_attribute', 'no_create'}
),
)

def get_dn(self, *keys, **kwargs):
Expand Down Expand Up @@ -479,6 +506,60 @@ def validate_domain_resolution_order(self, entry_attrs):
class config_mod(LDAPUpdate):
__doc__ = _('Modify configuration options.')

def _enable_sid(self, ldap, options):
# the user must have the Replication Administrators privilege
privilege = 'Replication Administrators'
if not principal_has_privilege(self.api, context.principal, privilege):
raise errors.ACIError(
info=_("not allowed to enable SID generation"))

# NetBIOS name is either taken from options or generated
try:
netbios_name, reset_netbios_name = set_and_check_netbios_name(
options.get('netbios_name', None), True, self.api)
except ScriptError:
raise errors.ValidationError(name="NetBIOS name",
error=_('Up to 15 characters and only uppercase ASCII letters'
', digits and dashes are allowed. Empty string is '
'not allowed.'))

_ret = 0
_stdout = ''
_stderr = ''

dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

method_options = []
if options.get('add_sids', False):
method_options.extend(["--add-sids"])
method_options.extend(["--netbios-name", netbios_name])
if reset_netbios_name:
method_options.append("--reset-netbios-name")
# Dbus definition expects up to 10 arguments
method_options.extend([''] * (10 - len(method_options)))

try:
bus = dbus.SystemBus()
obj = bus.get_object('org.freeipa.server', '/',
follow_name_owner_changes=True)
server = dbus.Interface(obj, 'org.freeipa.server')
_ret, _stdout, _stderr = server.config_enable_sid(*method_options)
except dbus.DBusException as e:
logger.error('Failed to call org.freeipa.server.config_enable_sid.'
'DBus exception is %s', str(e))
raise errors.ExecutionError(message=_('Failed to call DBus'))

# The oddjob restarts dirsrv, we need to re-establish the conn
if self.api.Backend.ldap2.isconnected():
self.api.Backend.ldap2.disconnect()
self.api.Backend.ldap2.connect(ccache=context.ccache_name)

if _ret != 0:
logger.error("Helper config_enable_sid return code is %d", _ret)
raise errors.ExecutionError(
message=_('Configuration of SID failed. '
'See details in the error log'))

def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if 'ipadefaultprimarygroup' in entry_attrs:
Expand Down Expand Up @@ -606,13 +687,27 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):

self.obj.validate_domain_resolution_order(entry_attrs)

# The options add_sids or netbios_name need the enable_sid option
for sid_option in ['add_sids', 'netbios_name']:
if options.get(sid_option, None) and not options['enable_sid']:
opt = "--" + sid_option.replace("_", "-")
error_message = _("You cannot specify %s without "
"the --enable-sid option" % opt)
raise errors.ValidationError(
name=opt,
error=error_message)

if options['enable_sid']:
self._enable_sid(ldap, options)

return dn

def exc_callback(self, keys, options, exc, call_func,
*call_args, **call_kwargs):
if (isinstance(exc, errors.EmptyModlist) and
call_func.__name__ == 'update_entry' and
'ca_renewal_master_server' in options):
('ca_renewal_master_server' in options or
'enable_sid' in options)):
return

super(config_mod, self).exc_callback(
Expand Down
2 changes: 2 additions & 0 deletions ipaserver/rpcserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ def wsgi_execute(self, environ):
if self.api.env.debug:
time_start = time.perf_counter_ns()
try:
if 'KRB5CCNAME' in environ:
setattr(context, "ccache_name", environ['KRB5CCNAME'])
if ('HTTP_ACCEPT_LANGUAGE' in environ):
lang_reg_w_q = environ['HTTP_ACCEPT_LANGUAGE'].split(',')[0]
lang_reg = lang_reg_w_q.split(';')[0]
Expand Down
3 changes: 3 additions & 0 deletions selinux/ipa.te
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ manage_dirs_pattern(ipa_helper_t, ipa_var_run_t, ipa_var_run_t)
manage_files_pattern(ipa_helper_t, ipa_var_run_t, ipa_var_run_t)
files_pid_filetrans(ipa_helper_t, ipa_var_run_t, { dir file })

manage_files_pattern(ipa_helper_t, ipa_tmp_t, ipa_tmp_t)
files_tmp_filetrans(ipa_helper_t, ipa_tmp_t, { file })

kernel_read_system_state(ipa_helper_t)
kernel_read_network_state(ipa_helper_t)

Expand Down

0 comments on commit ed001c9

Please sign in to comment.