1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-22 13:34:04 +03:00

Add Linux FreeIPA OS manager

This commit is contained in:
Alexander Burmatov 2023-05-17 15:03:21 +03:00
parent 03d705639a
commit 20fdd56ca2
2 changed files with 241 additions and 0 deletions

View File

@ -42,6 +42,7 @@ from uds.core import VERSION
from .linux_osmanager import LinuxOsManager
from .linux_randompass_osmanager import LinuxRandomPassManager
from .linux_ad_osmanager import LinuxOsADManager
from .linux_freeipa_osmanager import LinuxOsFreeIPAManager
downloadsManager().registerDownloadable(
'udsactor_{version}_all.deb'.format(version=VERSION),

View File

@ -0,0 +1,240 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2023 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
@author: Alexander Burmatov, thatman at altlinux dot org
"""
import codecs
import logging
import typing
from django.utils.translation import gettext_noop as _, gettext_lazy
from uds.core.ui import gui
from uds.core import exceptions
from uds.core.managers import cryptoManager
from .linux_osmanager import LinuxOsManager
if typing.TYPE_CHECKING:
from uds.models.user_service import UserService
logger = logging.getLogger(__name__)
class LinuxOsFreeIPAManager(LinuxOsManager):
typeName = _('Linux OS FreeIPA Manager')
typeType = 'LinuxFreeIPAManager'
typeDescription = _('Os Manager to control Linux virtual machines with FreeIPA')
iconFile = 'losmanager.png'
domain = gui.TextField(
length=64,
label=_('Domain'),
order=1,
tooltip=_(
'Domain to join machines to (use FQDN form, Netbios name not supported for most operations)'
),
required=True,
)
account = gui.TextField(
length=64,
label=_('Account'),
order=2,
tooltip=_('Account with rights to add machines to domain'),
required=True,
)
password = gui.PasswordField(
length=64,
label=_('Password'),
order=3,
tooltip=_('Password of the account'),
required=True,
)
clientSoftware = gui.ChoiceField(
label=_('Client software'),
order=4,
tooltip=_('Use specific client software'),
values=[
{'id': 'automatically', 'text': gettext_lazy('Automatically')},
{'id': 'sssd', 'text': gettext_lazy('SSSD')},
{'id': 'winbind', 'text': gettext_lazy('Winbind')},
],
tab=_('Advanced'),
defvalue='automatically',
)
membershipSoftware = gui.ChoiceField(
label=_('Membership software'),
order=5,
tooltip=_('Use specific membership software'),
values=[
{'id': 'automatically', 'text': gettext_lazy('Automatically')},
{'id': 'samba', 'text': gettext_lazy('Samba')},
{'id': 'adcli', 'text': gettext_lazy('adcli')},
],
tab=_('Advanced'),
defvalue='automatically',
)
removeOnExit = gui.CheckBoxField(
label=_('Machine clean'),
order=6,
tooltip=_(
'If checked, UDS will try to remove the machine from the domain USING the provided credentials'
),
tab=_('Advanced'),
defvalue=gui.TRUE,
)
ssl = gui.CheckBoxField(
label=_('Use SSL'),
order=7,
tooltip=_('If checked, a ssl connection to Active Directory will be used'),
tab=_('Advanced'),
defvalue=gui.TRUE,
)
automaticIdMapping = gui.CheckBoxField(
label=_('Automatic ID mapping'),
order=8,
tooltip=_('If checked, automatic ID mapping'),
tab=_('Advanced'),
defvalue=gui.TRUE,
)
# Inherits base "onLogout"
onLogout = LinuxOsManager.onLogout
idle = LinuxOsManager.idle
deadLine = LinuxOsManager.deadLine
_domain: str
_account: str
_password: str
_removeOnExit: str
_ssl: str
_automaticIdMapping: str
_clientSoftware: str
_serverSoftware: str
_membershipSoftware: str
def __init__(self, environment, values):
super(LinuxOsFreeIPAManager, self).__init__(environment, values)
if values:
if values['domain'] == '':
raise exceptions.ValidationError(_('Must provide a domain!'))
if values['account'] == '':
raise exceptions.ValidationError(
_('Must provide an account to add machines to domain!')
)
if values['password'] == '':
raise exceptions.ValidationError(
_('Must provide a password for the account!')
)
self._domain = values['domain']
self._account = values['account']
self._password = values['password']
self._clientSoftware = values['clientSoftware']
self._serverSoftware = 'ipa'
self._membershipSoftware = values['membershipSoftware']
self._removeOnExit = 'y' if values['removeOnExit'] else 'n'
self._ssl = 'y' if values['ssl'] else 'n'
self._automaticIdMapping = 'y' if values['automaticIdMapping'] else 'n'
else:
self._domain = ''
self._account = ''
self._password = '' # nosec: no encoded password
self._clientSoftware = ''
self._serverSoftware = 'ipa'
self._membershipSoftware = ''
self._removeOnExit = 'n'
self._ssl = 'n'
self._automaticIdMapping = 'n'
def actorData(
self, userService: 'UserService'
) -> typing.MutableMapping[str, typing.Any]:
return {
'action': 'rename_ad',
'name': userService.getName(),
'ad': self._domain,
'username': self._account,
'password': self._password,
'clientSoftware': self._clientSoftware,
'serverSoftware': self._serverSoftware,
'membershipSoftware': self._membershipSoftware,
'ssl': self._ssl,
'automaticIdMapping': self._automaticIdMapping,
'isPersistent': 'y' if self.isPersistent() else 'n',
}
def marshal(self) -> bytes:
"""
Serializes the os manager data so we can store it in database
"""
base = super().marshal()
return '\t'.join(
[
'v1',
self._domain,
self._account,
cryptoManager().encrypt(self._password),
self._clientSoftware,
self._serverSoftware,
self._membershipSoftware,
self._removeOnExit,
self._ssl,
self._automaticIdMapping,
codecs.encode(base, 'hex').decode(),
]
).encode('utf8')
def unmarshal(self, data: bytes) -> None:
values = data.decode('utf8').split('\t')
if values[0] in ('v1'):
self._domain = values[1]
self._account = values[2]
self._password = cryptoManager().decrypt(values[3])
self._clientSoftware = values[4]
self._serverSoftware = values[5]
self._membershipSoftware = values[6]
self._removeOnExit = values[7]
self._ssl = values[8]
self._automaticIdMapping = values[9]
super().unmarshal(codecs.decode(values[10].encode(), 'hex'))
def valuesDict(self) -> gui.ValuesDictType:
dct = super().valuesDict()
dct['domain'] = self._domain
dct['account'] = self._account
dct['password'] = self._password
dct['clientSoftware'] = self._clientSoftware
dct['serverSoftware'] = self._serverSoftware
dct['membershipSoftware'] = self._membershipSoftware
dct['removeOnExit'] = self._removeOnExit == 'y'
dct['ssl'] = self._ssl == 'y'
dct['automaticIdMapping'] = self._automaticIdMapping == 'y'
return dct