Files
freeipa/ipaserver/plugins/host.py
T

1367 lines
53 KiB
Python
Raw Normal View History

2009-05-27 15:55:49 +02:00
# Authors:
# Rob Crittenden <rcritten@redhat.com>
# Pavel Zuna <pzuna@redhat.com>
#
# Copyright (C) 2008 Red Hat
# see file 'COPYING' for use and warranty information
#
2010-12-09 13:59:11 +01:00
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
2009-05-27 15:55:49 +02:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
2010-12-09 13:59:11 +01:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
2017-05-23 18:35:57 +02:00
import logging
import dns.resolver
2015-09-11 13:43:28 +02:00
import six
from ipalib import api, errors, util
from ipalib import messages
2017-07-03 17:10:34 +02:00
from ipalib import Str, Flag
from ipalib.parameters import Principal, Certificate
from ipalib.plugable import Registry
from .baseldap import (LDAPQuery, LDAPObject, LDAPCreate,
LDAPDelete, LDAPUpdate, LDAPSearch,
LDAPRetrieve, LDAPAddMember,
LDAPRemoveMember, host_is_master,
pkey_to_value, add_missing_object_class,
LDAPAddAttribute, LDAPRemoveAttribute,
LDAPAddAttributeViaOption,
LDAPRemoveAttributeViaOption)
from .service import (
2017-07-03 17:10:34 +02:00
validate_realm, normalize_principal,
set_certificate_attrs, ticket_flags_params, update_krbticketflags,
2014-10-02 16:57:08 +02:00
set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap,
rename_ipaallowedtoperform_to_ldap, revoke_certs)
from .dns import (dns_container_exists,
2012-02-28 09:05:01 +01:00
add_records_for_host_validation, add_records_for_host,
2014-03-20 09:47:20 +01:00
get_reverse_zone)
from ipalib import _, ngettext
from ipalib import output
from ipalib.request import context
from ipalib.util import (normalize_sshpubkey, validate_sshpubkey_no_options,
2016-06-13 20:02:21 +02:00
convert_sshpubkey_post,
add_sshpubkey_to_attrs_pre,
remove_sshpubkey_from_output_post,
2016-06-13 20:02:21 +02:00
remove_sshpubkey_from_output_list_post,
normalize_hostname,
hostname_validator,
set_krbcanonicalname
2016-06-13 20:02:21 +02:00
)
from ipapython.ipautil import (
ipa_generate_password,
CheckedIPAddress,
2016-12-21 15:07:34 +01:00
TMP_PWD_ENTROPY_BITS
)
2014-05-16 12:21:04 +02:00
from ipapython.dnsutil import DNSName
from ipapython.ssh import SSHPublicKey
2012-05-13 07:36:35 -04:00
from ipapython.dn import DN
from ipapython import kerberos
2015-07-30 17:49:16 +02:00
from functools import reduce
2015-09-11 13:43:28 +02:00
if six.PY3:
unicode = str
__doc__ = _("""
Hosts/Machines
2010-06-02 14:08:50 -04:00
A host represents a machine. It can be used in a number of contexts:
- service entries are associated with a host
- a host stores the host/ service principal
- a host can be used in Host-based Access Control (HBAC) rules
2010-06-02 14:08:50 -04:00
- every enrolled client generates a host entry
2013-10-09 14:52:04 +02:00
""") + _("""
2010-06-02 14:08:50 -04:00
ENROLLMENT:
There are three enrollment scenarios when enrolling a new client:
2010-06-02 14:08:50 -04:00
1. You are enrolling as a full administrator. The host entry may exist
or not. A full administrator is a member of the hostadmin role
or the admins group.
2. You are enrolling as a limited administrator. The host must already
exist. A limited administrator is a member a role with the
Host Enrollment privilege.
2010-06-02 14:08:50 -04:00
3. The host has been created with a one-time password.
2013-10-09 14:52:04 +02:00
""") + _("""
2013-08-02 17:06:29 +02:00
RE-ENROLLMENT:
Host that has been enrolled at some point, and lost its configuration (e.g. VM
destroyed) can be re-enrolled.
For more information, consult the manual pages for ipa-client-install.
2010-06-02 14:08:50 -04:00
A host can optionally store information such as where it is located,
the OS that it runs, etc.
2013-10-09 14:52:04 +02:00
""") + _("""
2010-06-02 14:08:50 -04:00
EXAMPLES:
2013-10-09 14:52:04 +02:00
""") + _("""
Add a new host:
ipa host-add --location="3rd floor lab" --locality=Dallas test.example.com
2013-10-09 14:52:04 +02:00
""") + _("""
Delete a host:
2010-06-02 14:08:50 -04:00
ipa host-del test.example.com
2013-10-09 14:52:04 +02:00
""") + _("""
Add a new host with a one-time password:
2010-06-02 14:08:50 -04:00
ipa host-add --os='Fedora 12' --password=Secret123 test.example.com
2013-10-09 14:52:04 +02:00
""") + _("""
Add a new host with a random one-time password:
ipa host-add --os='Fedora 12' --random test.example.com
2013-10-09 14:52:04 +02:00
""") + _("""
Modify information about a host:
2010-06-02 14:08:50 -04:00
ipa host-mod --os='Fedora 12' test.example.com
2013-10-09 14:52:04 +02:00
""") + _("""
Remove SSH public keys of a host and update DNS to reflect this change:
ipa host-mod --sshpubkey= --updatedns test.example.com
2013-10-09 14:52:04 +02:00
""") + _("""
Disable the host Kerberos key, SSL certificate and all of its services:
ipa host-disable test.example.com
2013-10-09 14:52:04 +02:00
""") + _("""
2010-11-10 16:47:29 -05:00
Add a host that can manage this host's keytab and certificate:
ipa host-add-managedby --hosts=test2 test
2014-10-02 16:57:08 +02:00
""") + _("""
Allow user to create a keytab:
ipa host-allow-create-keytab test2 --users=tuser1
""")
2009-05-27 15:55:49 +02:00
2017-05-23 18:35:57 +02:00
logger = logging.getLogger(__name__)
register = Registry()
2012-06-26 15:23:55 +02:00
def remove_ptr_rec(ipaddr, fqdn):
"""
Remove PTR record of IP address (ipaddr)
:return: True if PTR record was removed, False if record was not found
"""
logger.debug('deleting PTR record of ipaddr %s', ipaddr)
2011-01-31 15:30:43 +01:00
try:
2011-05-27 20:29:33 +02:00
revzone, revname = get_reverse_zone(ipaddr)
# assume that target in PTR record is absolute name (otherwise it is
# non-standard configuration)
delkw = {'ptrrecord': u"%s" % fqdn.make_absolute()}
2011-01-31 15:30:43 +01:00
api.Command['dnsrecord_del'](revzone, revname, **delkw)
except (errors.NotFound, errors.AttrValueNotFound):
logger.debug('PTR record of ipaddr %s not found', ipaddr)
return False
return True
2011-01-31 15:30:43 +01:00
2014-08-01 12:08:15 +02:00
def update_sshfp_record(zone, record, entry_attrs):
if 'ipasshpubkey' not in entry_attrs:
return
pubkeys = entry_attrs['ipasshpubkey'] or ()
2014-08-01 12:08:15 +02:00
sshfps = []
for pubkey in pubkeys:
try:
sshfp = SSHPublicKey(pubkey).fingerprint_dns_sha1()
except (ValueError, UnicodeDecodeError):
continue
if sshfp is not None:
sshfps.append(sshfp)
2014-08-01 12:08:15 +02:00
2013-01-08 16:13:07 +01:00
try:
sshfp = SSHPublicKey(pubkey).fingerprint_dns_sha256()
except (ValueError, UnicodeDecodeError):
2013-01-08 16:13:07 +01:00
continue
if sshfp is not None:
sshfps.append(sshfp)
try:
api.Command['dnsrecord_mod'](zone, record, sshfprecord=sshfps)
except errors.EmptyModlist:
pass
def convert_ipaassignedidview_post(entry_attrs, options):
"""
Converts the ID View DN to its name for the better looking output.
"""
if 'ipaassignedidview' in entry_attrs and not options.get('raw'):
idview_name = entry_attrs.single_value['ipaassignedidview'][0].value
entry_attrs.single_value['ipaassignedidview'] = idview_name
host_output_params = (
2011-11-10 13:46:16 +01:00
Flag('has_keytab',
label=_('Keytab'),
),
2010-11-10 16:47:29 -05:00
Str('managedby_host',
label='Managed by',
),
2011-06-13 16:23:09 +02:00
Str('managing_host',
label='Managing',
),
2012-08-17 11:00:37 +02:00
Str('managedby',
label=_('Failed managedby'),
),
2014-10-02 16:57:08 +02:00
Str('ipaallowedtoperform_read_keys_user',
label=_('Users allowed to retrieve keytab'),
),
Str('ipaallowedtoperform_read_keys_group',
label=_('Groups allowed to retrieve keytab'),
),
Str('ipaallowedtoperform_read_keys_host',
label=_('Hosts allowed to retrieve keytab'),
),
Str('ipaallowedtoperform_read_keys_hostgroup',
label=_('Host Groups allowed to retrieve keytab'),
),
2014-10-02 16:57:08 +02:00
Str('ipaallowedtoperform_write_keys_user',
label=_('Users allowed to create keytab'),
),
Str('ipaallowedtoperform_write_keys_group',
label=_('Groups allowed to create keytab'),
),
Str('ipaallowedtoperform_write_keys_host',
label=_('Hosts allowed to create keytab'),
),
Str('ipaallowedtoperform_write_keys_hostgroup',
label=_('Host Groups allowed to create keytab'),
),
2014-10-02 16:57:08 +02:00
Str('ipaallowedtoperform_read_keys',
label=_('Failed allowed to retrieve keytab'),
),
Str('ipaallowedtoperform_write_keys',
label=_('Failed allowed to create keytab'),
),
)
2014-08-01 12:08:15 +02:00
def validate_ipaddr(ugettext, ipaddr):
"""
Verify that we have either an IPv4 or IPv6 address.
"""
try:
2017-06-14 14:54:43 +02:00
CheckedIPAddress(ipaddr)
2015-07-30 16:49:29 +02:00
except Exception as e:
2012-01-20 15:15:11 +01:00
return unicode(e)
return None
2014-08-01 12:08:15 +02:00
@register()
2009-09-15 14:01:58 +02:00
class host(LDAPObject):
2009-05-27 15:55:49 +02:00
"""
Host object.
"""
2009-09-15 14:01:58 +02:00
container_dn = api.env.container_host
object_name = _('host')
object_name_plural = _('hosts')
object_class = ['ipaobject', 'nshost', 'ipahost', 'pkiuser', 'ipaservice']
2014-10-02 16:57:08 +02:00
possible_objectclasses = ['ipaallowedoperations']
permission_filter_objectclasses = ['ipahost']
2009-09-15 14:01:58 +02:00
# object_class_config = 'ipahostobjectclasses'
search_attributes = [
'fqdn', 'description', 'l', 'nshostlocation', 'krbcanonicalname',
'krbprincipalname', 'nshardwareplatform', 'nsosversion', 'managedby',
]
2009-09-15 14:01:58 +02:00
default_attributes = [
'fqdn', 'description', 'l', 'nshostlocation', 'krbcanonicalname',
'krbprincipalname',
'nshardwareplatform', 'nsosversion', 'usercertificate', 'memberof',
2015-03-31 10:59:37 +02:00
'managedby', 'memberofindirect', 'macaddress',
'userclass', 'ipaallowedtoperform', 'ipaassignedidview', 'krbprincipalauthind'
2009-09-15 14:01:58 +02:00
]
uuid_attribute = 'ipauniqueid'
attribute_members = {
'enrolledby': ['user'],
'memberof': ['hostgroup', 'netgroup', 'role', 'hbacrule', 'sudorule'],
2010-11-10 16:47:29 -05:00
'managedby': ['host'],
2011-06-13 16:23:09 +02:00
'managing': ['host'],
'memberofindirect': ['hostgroup', 'netgroup', 'role', 'hbacrule',
'sudorule'],
'ipaallowedtoperform_read_keys': ['user', 'group', 'host', 'hostgroup'],
'ipaallowedtoperform_write_keys': ['user', 'group', 'host', 'hostgroup'],
2009-09-15 14:01:58 +02:00
}
bindable = True
relationships = {
2011-01-06 17:14:13 -05:00
'memberof': ('Member Of', 'in_', 'not_in_'),
'enrolledby': ('Enrolled by', 'enroll_by_', 'not_enroll_by_'),
'managedby': ('Managed by', 'man_by_', 'not_man_by_'),
2011-06-13 16:23:09 +02:00
'managing': ('Managing', 'man_', 'not_man_'),
2014-10-02 16:57:08 +02:00
'ipaallowedtoperform_read_keys': ('Allow to retrieve keytab by', 'retrieve_keytab_by_', 'not_retrieve_keytab_by_'),
'ipaallowedtoperform_write_keys': ('Allow to create keytab by', 'write_keytab_by_', 'not_write_keytab_by'),
}
password_attributes = [('userpassword', 'has_password'),
('krbprincipalkey', 'has_keytab')]
2014-03-26 15:58:08 +01:00
managed_permissions = {
'System: Read Hosts': {
'replaces_global_anonymous_aci': True,
'ipapermbindruletype': 'all',
'ipapermright': {'read', 'search', 'compare'},
'ipapermdefaultattr': {
'cn', 'description', 'fqdn', 'ipaclientversion',
'ipakrbauthzdata', 'ipasshpubkey', 'ipauniqueid',
'krbprincipalname', 'l', 'macaddress', 'nshardwareplatform',
'nshostlocation', 'nsosversion', 'objectclass',
'serverhostname', 'usercertificate', 'userclass',
'enrolledby', 'managedby', 'ipaassignedidview',
2014-03-26 15:58:08 +01:00
'krbprincipalname', 'krbcanonicalname', 'krbprincipalaliases',
'krbprincipalexpiration', 'krbpasswordexpiration',
'krblastpwdchange', 'krbprincipalauthind',
2014-03-26 15:58:08 +01:00
},
},
'System: Read Host Membership': {
'replaces_global_anonymous_aci': True,
'ipapermbindruletype': 'all',
'ipapermright': {'read', 'search', 'compare'},
'ipapermdefaultattr': {
'memberof',
},
},
2014-05-30 18:35:31 +02:00
'System: Add Hosts': {
'ipapermright': {'add'},
'replaces': [
'(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Add Hosts";allow (add) groupdn = "ldap:///cn=Add Hosts,cn=permissions,cn=pbac,$SUFFIX";)',
],
'default_privileges': {'Host Administrators'},
},
'System: Add krbPrincipalName to a Host': {
# Allow an admin to enroll a host that has a one-time password.
# When a host is created with a password no krbPrincipalName is set.
# This will let it be added if the client ends up enrolling with
# an administrator instead.
'ipapermright': {'write'},
'ipapermtargetfilter': [
'(objectclass=ipahost)',
'(!(krbprincipalname=*))',
],
'ipapermdefaultattr': {'krbprincipalname'},
'replaces': [
'(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(targetfilter = "(!(krbprincipalname=*))")(targetattr = "krbprincipalname")(version 3.0;acl "permission:Add krbPrincipalName to a host"; allow (write) groupdn = "ldap:///cn=Add krbPrincipalName to a host,cn=permissions,cn=pbac,$SUFFIX";)',
],
'default_privileges': {'Host Administrators', 'Host Enrollment'},
},
'System: Enroll a Host': {
'ipapermright': {'write'},
'ipapermdefaultattr': {'objectclass', 'enrolledby'},
'replaces': [
'(targetattr = "objectclass")(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Enroll a host";allow (write) groupdn = "ldap:///cn=Enroll a host,cn=permissions,cn=pbac,$SUFFIX";)',
'(targetattr = "enrolledby || objectclass")(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Enroll a host";allow (write) groupdn = "ldap:///cn=Enroll a host,cn=permissions,cn=pbac,$SUFFIX";)',
],
'default_privileges': {'Host Administrators', 'Host Enrollment'},
},
'System: Manage Host SSH Public Keys': {
'ipapermright': {'write'},
'ipapermdefaultattr': {'ipasshpubkey'},
'replaces': [
'(targetattr = "ipasshpubkey")(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Manage Host SSH Public Keys";allow (write) groupdn = "ldap:///cn=Manage Host SSH Public Keys,cn=permissions,cn=pbac,$SUFFIX";)',
],
'default_privileges': {'Host Administrators'},
},
'System: Manage Host Keytab': {
'ipapermright': {'write'},
'ipapermtargetfilter': [
'(objectclass=ipahost)',
'(!(memberOf=%s))' % DN('cn=ipaservers',
api.env.container_hostgroup,
api.env.basedn),
],
2014-05-30 18:35:31 +02:00
'ipapermdefaultattr': {'krblastpwdchange', 'krbprincipalkey'},
'replaces': [
'(targetattr = "krbprincipalkey || krblastpwdchange")(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Manage host keytab";allow (write) groupdn = "ldap:///cn=Manage host keytab,cn=permissions,cn=pbac,$SUFFIX";)',
],
'default_privileges': {'Host Administrators', 'Host Enrollment'},
},
2014-10-02 16:57:08 +02:00
'System: Manage Host Keytab Permissions': {
'ipapermright': {'read', 'search', 'compare', 'write'},
'ipapermdefaultattr': {
'ipaallowedtoperform;write_keys',
'ipaallowedtoperform;read_keys', 'objectclass'
},
'default_privileges': {'Host Administrators'},
},
2014-05-30 18:35:31 +02:00
'System: Modify Hosts': {
'ipapermright': {'write'},
'ipapermdefaultattr': {
'description', 'l', 'nshardwareplatform', 'nshostlocation',
'nsosversion', 'macaddress', 'userclass', 'ipaassignedidview',
'krbprincipalauthind',
2014-05-30 18:35:31 +02:00
},
'replaces': [
'(targetattr = "description || l || nshostlocation || nshardwareplatform || nsosversion")(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Modify Hosts";allow (write) groupdn = "ldap:///cn=Modify Hosts,cn=permissions,cn=pbac,$SUFFIX";)',
],
'default_privileges': {'Host Administrators'},
},
'System: Remove Hosts': {
'ipapermright': {'delete'},
'replaces': [
'(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Remove Hosts";allow (delete) groupdn = "ldap:///cn=Remove Hosts,cn=permissions,cn=pbac,$SUFFIX";)',
],
'default_privileges': {'Host Administrators'},
},
'System: Manage Host Certificates': {
'ipapermbindruletype': 'permission',
'ipapermright': {'write'},
'ipapermdefaultattr': {'usercertificate'},
'default_privileges': {'Host Administrators', 'Host Enrollment'},
},
'System: Manage Host Principals': {
'ipapermbindruletype': 'permission',
'ipapermright': {'write'},
'ipapermdefaultattr': {'krbprincipalname', 'krbcanonicalname'},
'default_privileges': {'Host Administrators', 'Host Enrollment'},
},
'System: Manage Host Enrollment Password': {
'ipapermbindruletype': 'permission',
'ipapermright': {'write'},
'ipapermdefaultattr': {'userpassword'},
'default_privileges': {'Host Administrators', 'Host Enrollment'},
},
'System: Read Host Compat Tree': {
'non_object': True,
'ipapermbindruletype': 'anonymous',
'ipapermlocation': api.env.basedn,
'ipapermtarget': DN('cn=computers', 'cn=compat', api.env.basedn),
'ipapermright': {'read', 'search', 'compare'},
'ipapermdefaultattr': {
'objectclass', 'cn', 'macaddress',
},
},
2014-03-26 15:58:08 +01:00
}
2009-09-15 14:01:58 +02:00
label = _('Hosts')
2011-07-13 21:10:47 -05:00
label_singular = _('Host')
2009-05-27 15:55:49 +02:00
takes_params = (
2016-06-13 20:02:21 +02:00
Str('fqdn', hostname_validator,
2009-05-27 15:55:49 +02:00
cli_name='hostname',
2010-02-19 09:08:16 -07:00
label=_('Host name'),
2009-05-27 15:55:49 +02:00
primary_key=True,
normalizer=normalize_hostname,
2009-05-27 15:55:49 +02:00
),
Str('description?',
2009-09-15 14:01:58 +02:00
cli_name='desc',
2010-02-19 09:08:16 -07:00
label=_('Description'),
doc=_('A description of this host'),
2009-05-27 15:55:49 +02:00
),
Str('l?',
2009-05-27 15:55:49 +02:00
cli_name='locality',
2010-02-19 09:08:16 -07:00
label=_('Locality'),
doc=_('Host locality (e.g. "Baltimore, MD")'),
2009-05-27 15:55:49 +02:00
),
Str('nshostlocation?',
cli_name='location',
2010-02-19 09:08:16 -07:00
label=_('Location'),
doc=_('Host location (e.g. "Lab 2")'),
2009-05-27 15:55:49 +02:00
),
Str('nshardwareplatform?',
cli_name='platform',
2010-02-19 09:08:16 -07:00
label=_('Platform'),
doc=_('Host hardware platform (e.g. "Lenovo T61")'),
2009-05-27 15:55:49 +02:00
),
Str('nsosversion?',
cli_name='os',
2010-02-19 09:08:16 -07:00
label=_('Operating system'),
doc=_('Host operating system and version (e.g. "Fedora 9")'),
2009-05-27 15:55:49 +02:00
),
Str('userpassword?',
cli_name='password',
2010-02-19 09:08:16 -07:00
label=_('User password'),
doc=_('Password used in bulk enrollment'),
2009-05-27 15:55:49 +02:00
),
Flag('random?',
doc=_('Generate a random password to be used in bulk enrollment'),
2011-11-14 17:03:44 +01:00
flags=('no_search', 'virtual_attribute'),
default=False,
),
Str('randompassword?',
label=_('Random password'),
2011-11-14 17:03:44 +01:00
flags=('no_create', 'no_update', 'no_search', 'virtual_attribute'),
),
2017-07-03 17:10:34 +02:00
Certificate('usercertificate*',
cli_name='certificate',
2010-02-19 09:08:16 -07:00
label=_('Certificate'),
2016-03-04 12:45:39 +01:00
doc=_('Base-64 encoded host certificate'),
),
2016-06-30 06:37:16 +02:00
Str('subject',
label=_('Subject'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
Str('serial_number',
label=_('Serial Number'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
Str('serial_number_hex',
label=_('Serial Number (hex)'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
Str('issuer',
label=_('Issuer'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
Str('valid_not_before',
label=_('Not Before'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
Str('valid_not_after',
label=_('Not After'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
Str('sha1_fingerprint',
label=_('Fingerprint (SHA1)'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
2017-02-23 17:03:01 +01:00
Str('sha256_fingerprint',
label=_('Fingerprint (SHA256)'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
2016-06-30 06:37:16 +02:00
Str('revocation_reason?',
label=_('Revocation reason'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
Principal(
'krbcanonicalname?',
validate_realm,
2010-02-19 09:08:16 -07:00
label=_('Principal name'),
normalizer=normalize_principal,
flags={'no_create', 'no_update', 'no_search'},
),
Principal(
'krbprincipalname*',
validate_realm,
label=_('Principal alias'),
normalizer=normalize_principal,
flags=['no_create', 'no_search'],
),
Str('macaddress*',
normalizer=lambda value: value.upper(),
pattern='^([a-fA-F0-9]{2}[:|\-]?){5}[a-fA-F0-9]{2}$',
2014-08-01 12:08:15 +02:00
pattern_errmsg=('Must be of the form HH:HH:HH:HH:HH:HH, where '
'each H is a hexadecimal character.'),
label=_('MAC address'),
doc=_('Hardware MAC address(es) on this host'),
),
Str('ipasshpubkey*', validate_sshpubkey_no_options,
cli_name='sshpubkey',
label=_('SSH public key'),
normalizer=normalize_sshpubkey,
flags=['no_search'],
),
2016-06-30 06:37:16 +02:00
Str('sshpubkeyfp*',
label=_('SSH public key fingerprint'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
),
2013-04-23 09:59:24 +02:00
Str('userclass*',
cli_name='class',
label=_('Class'),
doc=_('Host category (semantics placed on this attribute are for '
'local interpretation)'),
),
Str('ipaassignedidview?',
label=_('Assigned ID View'),
flags=['no_option'],
),
Str('krbprincipalauthind*',
cli_name='auth_ind',
label=_('Authentication Indicators'),
doc=_("Defines a whitelist for Authentication Indicators."
" Use 'otp' to allow OTP-based 2FA authentications."
" Use 'radius' to allow RADIUS-based 2FA authentications."
" Other values may be used for custom configurations."),
),
) + ticket_flags_params
2009-05-27 15:55:49 +02:00
2009-09-15 14:01:58 +02:00
def get_dn(self, *keys, **options):
hostname = keys[-1]
dn = super(host, self).get_dn(hostname, **options)
2009-09-15 14:01:58 +02:00
try:
self.backend.get_entry(dn, [''])
except errors.NotFound:
try:
entry_attrs = self.backend.find_entry_by_attr(
'serverhostname', hostname, self.object_class, [''],
2013-02-04 09:47:00 +01:00
DN(self.container_dn, api.env.basedn))
dn = entry_attrs.dn
2009-09-15 14:01:58 +02:00
except errors.NotFound:
pass
return dn
2011-06-13 16:23:09 +02:00
def get_managed_hosts(self, dn):
host_filter = 'managedBy=%s' % dn
host_attrs = ['fqdn']
ldap = self.api.Backend.ldap2
managed_hosts = []
try:
2016-09-26 14:08:17 +02:00
(hosts, _truncated) = ldap.find_entries(
2013-02-04 09:47:00 +01:00
base_dn=DN(self.container_dn, api.env.basedn),
filter=host_filter, attrs_list=host_attrs)
2011-06-13 16:23:09 +02:00
for host in hosts:
managed_hosts.append(host.dn)
2011-06-13 16:23:09 +02:00
except errors.NotFound:
return []
return managed_hosts
def suppress_netgroup_memberof(self, ldap, entry_attrs):
"""
We don't want to show managed netgroups so remove them from the
memberofindirect list.
"""
ng_container = DN(api.env.container_netgroup, api.env.basedn)
for member in list(entry_attrs.get('memberofindirect', [])):
memberdn = DN(member)
if not memberdn.endswith(ng_container):
continue
filter = ldap.make_filter({'objectclass': 'mepmanagedentry'})
try:
ldap.get_entries(memberdn, ldap.SCOPE_BASE, filter, [''])
except errors.NotFound:
pass
else:
entry_attrs['memberofindirect'].remove(member)
2009-05-27 15:55:49 +02:00
@register()
2009-09-15 14:01:58 +02:00
class host_add(LDAPCreate):
__doc__ = _('Add a new host.')
has_output_params = LDAPCreate.has_output_params + host_output_params
msg_summary = _('Added host "%(value)s"')
2010-11-10 16:47:29 -05:00
member_attributes = ['managedby']
takes_options = LDAPCreate.takes_options + (
Flag('force',
2011-02-18 00:02:51 -06:00
label=_('Force'),
doc=_('force host name even if not in DNS'),
),
2010-12-14 19:02:18 +01:00
Flag('no_reverse',
doc=_('skip reverse DNS detection'),
),
2011-01-05 15:37:53 -05:00
Str('ip_address?', validate_ipaddr,
doc=_('Add the host to DNS with this IP address'),
2011-06-20 12:04:02 -04:00
label=_('IP Address'),
),
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
if options.get('ip_address') and dns_container_exists(ldap):
parts = keys[-1].split('.')
host = parts[0]
domain = unicode('.'.join(parts[1:]))
check_reverse = not options.get('no_reverse', False)
2014-05-16 12:21:04 +02:00
add_records_for_host_validation('ip_address',
DNSName(host),
2014-06-10 15:57:30 +02:00
DNSName(domain).make_absolute(),
options['ip_address'],
check_forward=True,
check_reverse=check_reverse)
2016-06-03 10:05:34 +02:00
if not options.get('force', False) and 'ip_address' not in options:
util.verify_host_resolvable(keys[-1])
if 'locality' in entry_attrs:
entry_attrs['l'] = entry_attrs['locality']
2009-09-15 14:01:58 +02:00
entry_attrs['cn'] = keys[-1]
entry_attrs['serverhostname'] = keys[-1].split('.', 1)[0]
if not entry_attrs.get('userpassword', False) and not options.get('random', False):
2009-05-27 15:55:49 +02:00
entry_attrs['krbprincipalname'] = 'host/%s@%s' % (
2009-09-15 14:01:58 +02:00
keys[-1], self.api.env.realm
2009-05-27 15:55:49 +02:00
)
2011-02-02 13:47:21 -05:00
if 'krbprincipalaux' not in entry_attrs['objectclass']:
entry_attrs['objectclass'].append('krbprincipalaux')
2011-02-02 13:47:21 -05:00
if 'krbprincipal' not in entry_attrs['objectclass']:
2009-05-27 15:55:49 +02:00
entry_attrs['objectclass'].append('krbprincipal')
set_krbcanonicalname(entry_attrs)
2011-01-18 15:43:07 -05:00
else:
if 'krbprincipalaux' in entry_attrs['objectclass']:
entry_attrs['objectclass'].remove('krbprincipalaux')
if 'krbprincipal' in entry_attrs['objectclass']:
entry_attrs['objectclass'].remove('krbprincipal')
2011-11-14 17:03:44 +01:00
if options.get('random'):
entry_attrs['userpassword'] = ipa_generate_password(
2016-12-21 15:07:34 +01:00
entropy_bits=TMP_PWD_ENTROPY_BITS)
2011-11-14 17:03:44 +01:00
# save the password so it can be displayed in post_callback
setattr(context, 'randompassword', entry_attrs['userpassword'])
2017-07-03 17:10:34 +02:00
entry_attrs['managedby'] = dn
entry_attrs['objectclass'].append('ieee802device')
entry_attrs['objectclass'].append('ipasshhost')
update_krbticketflags(ldap, entry_attrs, attrs_list, options, False)
if 'krbticketflags' in entry_attrs:
entry_attrs['objectclass'].append('krbticketpolicyaux')
2009-09-15 14:01:58 +02:00
return dn
2009-05-27 15:55:49 +02:00
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
exc = None
if dns_container_exists(ldap):
try:
parts = keys[-1].split('.')
host = parts[0]
domain = unicode('.'.join(parts[1:]))
2011-01-31 15:30:43 +01:00
if options.get('ip_address'):
add_reverse = not options.get('no_reverse', False)
2014-06-10 15:57:30 +02:00
add_records_for_host(DNSName(host),
DNSName(domain).make_absolute(),
2014-05-16 12:21:04 +02:00
options['ip_address'],
add_forward=True,
add_reverse=add_reverse)
del options['ip_address']
update_sshfp_record(domain, unicode(parts[0]), entry_attrs)
2015-07-30 16:49:29 +02:00
except Exception as e:
exc = e
if options.get('random', False):
try:
entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
except AttributeError:
# On the off-chance some other extension deletes this from the
# context, don't crash.
pass
if exc:
2011-02-23 16:47:49 -05:00
raise errors.NonFatalError(
reason=_('The host was added but the DNS update failed with: %(exc)s') % dict(exc=exc)
)
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
2014-10-02 16:57:08 +02:00
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
2011-06-13 16:23:09 +02:00
if options.get('all', False):
entry_attrs['managing'] = self.obj.get_managed_hosts(dn)
self.obj.get_password_attributes(ldap, dn, entry_attrs)
if entry_attrs['has_password']:
# If an OTP is set there is no keytab, at least not one
# fetched anywhere.
entry_attrs['has_keytab'] = False
2011-06-13 16:23:09 +02:00
convert_sshpubkey_post(entry_attrs)
return dn
2009-05-27 15:55:49 +02:00
@register()
2009-09-15 14:01:58 +02:00
class host_del(LDAPDelete):
__doc__ = _('Delete a host.')
msg_summary = _('Deleted host "%(value)s"')
2010-11-10 16:47:29 -05:00
member_attributes = ['managedby']
takes_options = LDAPDelete.takes_options + (
Flag('updatedns?',
doc=_('Remove A, AAAA, SSHFP and PTR records of the host(s) '
'managed by IPA DNS'),
default=False,
),
)
2009-09-15 14:01:58 +02:00
def pre_callback(self, ldap, dn, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
# If we aren't given a fqdn, find it
2016-06-13 20:02:21 +02:00
if hostname_validator(None, keys[-1]) is not None:
hostentry = api.Command['host_show'](keys[-1])['result']
fqdn = hostentry['fqdn'][0]
else:
fqdn = keys[-1]
host_is_master(ldap, fqdn)
2009-05-27 15:55:49 +02:00
# Remove all service records for this host
2009-09-15 14:01:58 +02:00
truncated = True
while truncated:
try:
ret = api.Command['service_find'](fqdn)
truncated = ret['truncated']
services = ret['result']
2009-09-15 14:01:58 +02:00
except errors.NotFound:
break
else:
for entry_attrs in services:
principal = kerberos.Principal(
entry_attrs['krbprincipalname'][0])
hostname = principal.hostname
if hostname.lower() == fqdn:
2009-09-15 14:01:58 +02:00
api.Command['service_del'](principal)
updatedns = options.get('updatedns', False)
if updatedns:
try:
updatedns = dns_container_exists(ldap)
except errors.NotFound:
updatedns = False
if updatedns:
# Remove A, AAAA, SSHFP and PTR records of the host
fqdn_dnsname = DNSName(fqdn).make_absolute()
zone = DNSName(dns.resolver.zone_for_name(fqdn_dnsname))
relative_hostname = fqdn_dnsname.relativize(zone)
# Get all resources for this host
rec_removed = False
try:
record = api.Command['dnsrecord_show'](
zone, relative_hostname)['result']
except errors.NotFound:
pass
else:
# remove PTR records first
for attr in ('arecord', 'aaaarecord'):
for val in record.get(attr, []):
rec_removed = (
remove_ptr_rec(val, fqdn_dnsname) or
rec_removed
)
try:
# remove all A, AAAA, SSHFP records of the host
api.Command['dnsrecord_mod'](
zone,
record['idnsname'][0],
arecord=[],
aaaarecord=[],
sshfprecord=[]
)
except errors.EmptyModlist:
pass
else:
rec_removed = True
if not rec_removed:
self.add_message(
messages.FailedToRemoveHostDNSRecords(
host=fqdn,
reason=_("No A, AAAA, SSHFP or PTR records found.")
)
)
if self.api.Command.ca_is_enabled()['result']:
certs = self.api.Command.cert_find(host=keys)['result']
revoke_certs(certs)
2009-09-15 14:01:58 +02:00
return dn
2009-05-27 15:55:49 +02:00
@register()
2009-09-15 14:01:58 +02:00
class host_mod(LDAPUpdate):
__doc__ = _('Modify information about a host.')
has_output_params = LDAPUpdate.has_output_params + host_output_params
msg_summary = _('Modified host "%(value)s"')
2010-11-10 16:47:29 -05:00
member_attributes = ['managedby']
2009-09-15 14:01:58 +02:00
takes_options = LDAPUpdate.takes_options + (
Flag('updatedns?',
doc=_('Update DNS entries'),
default=False,
),
2009-09-14 17:04:08 -04:00
)
2009-09-15 14:01:58 +02:00
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
# Allow an existing OTP to be reset but don't allow a OTP to be
# added to an enrolled host.
2012-06-26 15:23:55 +02:00
if options.get('userpassword') or options.get('random'):
entry = {}
self.obj.get_password_attributes(ldap, dn, entry)
if not entry['has_password'] and entry['has_keytab']:
2014-08-01 12:08:15 +02:00
raise errors.ValidationError(
name='password',
error=_('Password cannot be set on enrolled host.'))
2009-09-14 17:04:08 -04:00
# Once a principal name is set it cannot be changed
if 'cn' in entry_attrs:
2012-07-04 08:52:47 -04:00
raise errors.ACIError(info=_('cn is immutable'))
if 'locality' in entry_attrs:
entry_attrs['l'] = entry_attrs['locality']
2009-09-14 17:04:08 -04:00
if 'krbprincipalname' in entry_attrs:
entry_attrs_old = ldap.get_entry(
2009-09-15 14:01:58 +02:00
dn, ['objectclass', 'krbprincipalname']
)
if 'krbprincipalname' in entry_attrs_old:
msg = 'Principal name already set, it is unchangeable.'
raise errors.ACIError(info=msg)
obj_classes = entry_attrs_old['objectclass']
if 'krbprincipalaux' not in (item.lower() for item in
obj_classes):
2009-09-15 14:01:58 +02:00
obj_classes.append('krbprincipalaux')
entry_attrs['objectclass'] = obj_classes
# verify certificates
certs = entry_attrs.get('usercertificate') or []
# revoke removed certificates
ca_is_enabled = self.api.Command.ca_is_enabled()['result']
if 'usercertificate' in options and ca_is_enabled:
2015-06-03 13:11:58 +02:00
try:
entry_attrs_old = ldap.get_entry(dn, ['usercertificate'])
except errors.NotFound:
self.obj.handle_not_found(*keys)
old_certs = entry_attrs_old.get('usercertificate', [])
2017-08-23 15:23:43 +02:00
removed_certs = set(old_certs) - set(certs)
for cert in removed_certs:
rm_certs = api.Command.cert_find(certificate=cert)['result']
revoke_certs(rm_certs)
2015-06-03 13:11:58 +02:00
if certs:
2017-07-03 17:10:34 +02:00
entry_attrs['usercertificate'] = certs
2011-11-14 17:03:44 +01:00
if options.get('random'):
2016-12-21 15:07:34 +01:00
entry_attrs['userpassword'] = ipa_generate_password(
entropy_bits=TMP_PWD_ENTROPY_BITS)
2011-11-14 17:03:44 +01:00
setattr(context, 'randompassword', entry_attrs['userpassword'])
if 'macaddress' in entry_attrs:
if 'objectclass' in entry_attrs:
obj_classes = entry_attrs['objectclass']
else:
_entry_attrs = ldap.get_entry(dn, ['objectclass'])
obj_classes = _entry_attrs['objectclass']
if 'ieee802device' not in (item.lower() for item in obj_classes):
obj_classes.append('ieee802device')
entry_attrs['objectclass'] = obj_classes
if options.get('updatedns', False) and dns_container_exists(ldap):
parts = keys[-1].split('.')
domain = unicode('.'.join(parts[1:]))
try:
result = api.Command['dnszone_show'](domain)['result']
domain = result['idnsname'][0]
except errors.NotFound:
self.obj.handle_not_found(*keys)
update_sshfp_record(domain, unicode(parts[0]), entry_attrs)
if 'ipasshpubkey' in entry_attrs:
if 'objectclass' in entry_attrs:
obj_classes = entry_attrs['objectclass']
else:
_entry_attrs = ldap.get_entry(dn, ['objectclass'])
obj_classes = entry_attrs['objectclass'] = _entry_attrs['objectclass']
if 'ipasshhost' not in (item.lower() for item in obj_classes):
obj_classes.append('ipasshhost')
update_krbticketflags(ldap, entry_attrs, attrs_list, options, True)
if 'krbticketflags' in entry_attrs:
if 'objectclass' not in entry_attrs:
entry_attrs_old = ldap.get_entry(dn, ['objectclass'])
entry_attrs['objectclass'] = entry_attrs_old['objectclass']
if 'krbticketpolicyaux' not in (item.lower() for item in
entry_attrs['objectclass']):
entry_attrs['objectclass'].append('krbticketpolicyaux')
if 'krbprincipalauthind' in entry_attrs:
if 'objectclass' not in entry_attrs:
entry_attrs_old = ldap.get_entry(dn, ['objectclass'])
entry_attrs['objectclass'] = entry_attrs_old['objectclass']
if 'krbprincipalaux' not in (item.lower() for item in
entry_attrs['objectclass']):
entry_attrs['objectclass'].append('krbprincipalaux')
add_sshpubkey_to_attrs_pre(self.context, attrs_list)
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
if options.get('random', False):
entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
set_certificate_attrs(entry_attrs)
set_kerberos_attrs(entry_attrs, options)
2014-10-02 16:57:08 +02:00
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
self.obj.get_password_attributes(ldap, dn, entry_attrs)
if entry_attrs['has_password']:
# If an OTP is set there is no keytab, at least not one
# fetched anywhere.
entry_attrs['has_keytab'] = False
2011-06-13 16:23:09 +02:00
if options.get('all', False):
entry_attrs['managing'] = self.obj.get_managed_hosts(dn)
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
convert_sshpubkey_post(entry_attrs)
remove_sshpubkey_from_output_post(self.context, entry_attrs)
convert_ipaassignedidview_post(entry_attrs, options)
2009-09-15 14:01:58 +02:00
return dn
2009-05-27 15:55:49 +02:00
@register()
2009-09-15 14:01:58 +02:00
class host_find(LDAPSearch):
__doc__ = _('Search for hosts.')
2009-05-27 15:55:49 +02:00
has_output_params = LDAPSearch.has_output_params + host_output_params
msg_summary = ngettext(
2011-02-23 16:47:49 -05:00
'%(count)d host matched', '%(count)d hosts matched', 0
)
member_attributes = ['memberof', 'enrolledby', 'managedby']
def get_options(self):
for option in super(host_find, self).get_options():
yield option
# "managing" membership has to be added and processed separately
for option in self.get_member_options('managing'):
yield option
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(base_dn, DN)
if 'locality' in attrs_list:
attrs_list.remove('locality')
attrs_list.append('l')
if 'man_host' in options or 'not_man_host' in options:
hosts = []
if options.get('man_host') is not None:
for pkey in options.get('man_host', []):
dn = self.obj.get_dn(pkey)
try:
entry_attrs = ldap.get_entry(dn, ['managedby'])
except errors.NotFound:
self.obj.handle_not_found(pkey)
hosts.append(set(entry_attrs.get('managedby', '')))
hosts = list(reduce(lambda s1, s2: s1 & s2, hosts))
if not hosts:
# There is no host managing _all_ hosts in --man-hosts
filter = ldap.combine_filters(
(filter, '(objectclass=disabled)'), ldap.MATCH_ALL
)
not_hosts = []
if options.get('not_man_host') is not None:
for pkey in options.get('not_man_host', []):
dn = self.obj.get_dn(pkey)
try:
entry_attrs = ldap.get_entry(dn, ['managedby'])
except errors.NotFound:
self.obj.handle_not_found(pkey)
not_hosts += entry_attrs.get('managedby', [])
not_hosts = list(set(not_hosts))
for target_hosts, filter_op in ((hosts, ldap.MATCH_ANY),
(not_hosts, ldap.MATCH_NONE)):
hosts_avas = [DN(host)[0][0] for host in target_hosts]
2014-08-01 12:08:15 +02:00
hosts_filters = [ldap.make_filter_from_attr(ava.attr, ava.value)
for ava in hosts_avas]
hosts_filter = ldap.combine_filters(hosts_filters, filter_op)
filter = ldap.combine_filters(
(filter, hosts_filter), ldap.MATCH_ALL
)
add_sshpubkey_to_attrs_pre(self.context, attrs_list)
return (filter.replace('locality', 'l'), base_dn, scope)
def post_callback(self, ldap, entries, truncated, *args, **options):
2011-10-26 11:12:38 +02:00
if options.get('pkey_only', False):
return truncated
for entry_attrs in entries:
hostname = entry_attrs['fqdn']
if isinstance(hostname, (tuple, list)):
hostname = hostname[0]
try:
set_certificate_attrs(entry_attrs)
except errors.CertificateFormatError as e:
self.add_message(
messages.CertificateInvalid(
subject=hostname,
reason=e,
)
)
2017-05-23 18:35:57 +02:00
logger.error("Invalid certificate: %s", e)
del(entry_attrs['usercertificate'])
set_kerberos_attrs(entry_attrs, options)
2014-10-02 16:57:08 +02:00
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
2011-06-13 16:23:09 +02:00
if options.get('all', False):
entry_attrs['managing'] = self.obj.get_managed_hosts(entry_attrs.dn)
2011-06-13 16:23:09 +02:00
convert_sshpubkey_post(entry_attrs)
convert_ipaassignedidview_post(entry_attrs, options)
remove_sshpubkey_from_output_list_post(self.context, entries)
return truncated
2009-05-27 15:55:49 +02:00
@register()
2009-09-15 14:01:58 +02:00
class host_show(LDAPRetrieve):
__doc__ = _('Display information about a host.')
has_output_params = LDAPRetrieve.has_output_params + host_output_params
takes_options = LDAPRetrieve.takes_options + (
Str('out?',
doc=_('file to store certificate in'),
),
)
2010-11-10 16:47:29 -05:00
member_attributes = ['managedby']
def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
assert isinstance(dn, DN)
add_sshpubkey_to_attrs_pre(self.context, attrs_list)
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
self.obj.get_password_attributes(ldap, dn, entry_attrs)
if entry_attrs['has_password']:
# If an OTP is set there is no keytab, at least not one
# fetched anywhere.
entry_attrs['has_keytab'] = False
hostname = entry_attrs['fqdn']
if isinstance(hostname, (tuple, list)):
hostname = hostname[0]
try:
set_certificate_attrs(entry_attrs)
except errors.CertificateFormatError as e:
self.add_message(
messages.CertificateInvalid(
subject=hostname,
reason=e,
)
)
del(entry_attrs['usercertificate'])
set_kerberos_attrs(entry_attrs, options)
2014-10-02 16:57:08 +02:00
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
2010-10-15 23:40:38 -05:00
2011-06-13 16:23:09 +02:00
if options.get('all', False):
entry_attrs['managing'] = self.obj.get_managed_hosts(dn)
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
convert_sshpubkey_post(entry_attrs)
remove_sshpubkey_from_output_post(self.context, entry_attrs)
convert_ipaassignedidview_post(entry_attrs, options)
return dn
2009-05-27 15:55:49 +02:00
@register()
class host_disable(LDAPQuery):
__doc__ = _('Disable the Kerberos key, SSL certificate and all services of a host.')
has_output = output.standard_value
msg_summary = _('Disabled host "%(value)s"')
def execute(self, *keys, **options):
ldap = self.obj.backend
# If we aren't given a fqdn, find it
2016-06-13 20:02:21 +02:00
if hostname_validator(None, keys[-1]) is not None:
hostentry = api.Command['host_show'](keys[-1])['result']
fqdn = hostentry['fqdn'][0]
else:
fqdn = keys[-1]
host_is_master(ldap, fqdn)
# See if we actually do anthing here, and if not raise an exception
done_work = False
truncated = True
while truncated:
try:
ret = api.Command['service_find'](fqdn)
truncated = ret['truncated']
services = ret['result']
except errors.NotFound:
break
else:
for entry_attrs in services:
principal = kerberos.Principal(
entry_attrs['krbprincipalname'][0])
hostname = principal.hostname
if hostname.lower() == fqdn:
try:
api.Command['service_disable'](principal)
done_work = True
except errors.AlreadyInactive:
pass
dn = self.obj.get_dn(*keys, **options)
try:
entry_attrs = ldap.get_entry(dn, ['usercertificate'])
except errors.NotFound:
self.obj.handle_not_found(*keys)
if self.api.Command.ca_is_enabled()['result']:
certs = self.api.Command.cert_find(host=keys)['result']
if certs:
revoke_certs(certs)
# Remove the usercertificate altogether
entry_attrs['usercertificate'] = None
ldap.update_entry(entry_attrs)
done_work = True
self.obj.get_password_attributes(ldap, dn, entry_attrs)
if entry_attrs['has_keytab']:
ldap.remove_principal_key(dn)
done_work = True
if not done_work:
raise errors.AlreadyInactive()
return dict(
result=True,
value=pkey_to_value(keys[0], options),
)
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
return dn
2010-11-10 16:47:29 -05:00
@register()
2010-11-10 16:47:29 -05:00
class host_add_managedby(LDAPAddMember):
__doc__ = _('Add hosts that can manage this host.')
2010-11-10 16:47:29 -05:00
member_attributes = ['managedby']
has_output_params = LDAPAddMember.has_output_params + host_output_params
allow_same = True
2010-11-10 16:47:29 -05:00
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
return (completed, dn)
2010-11-10 16:47:29 -05:00
@register()
2010-11-10 16:47:29 -05:00
class host_remove_managedby(LDAPRemoveMember):
__doc__ = _('Remove hosts that can manage this host.')
2010-11-10 16:47:29 -05:00
member_attributes = ['managedby']
has_output_params = LDAPRemoveMember.has_output_params + host_output_params
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
2012-05-13 07:36:35 -04:00
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(ldap, entry_attrs)
return (completed, dn)
2014-10-02 16:57:08 +02:00
@register()
class host_allow_retrieve_keytab(LDAPAddMember):
__doc__ = _('Allow users, groups, hosts or host groups to retrieve a keytab'
' of this host.')
2014-10-02 16:57:08 +02:00
member_attributes = ['ipaallowedtoperform_read_keys']
has_output_params = LDAPAddMember.has_output_params + host_output_params
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
rename_ipaallowedtoperform_to_ldap(found)
rename_ipaallowedtoperform_to_ldap(not_found)
add_missing_object_class(ldap, u'ipaallowedoperations', dn)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
rename_ipaallowedtoperform_from_ldap(failed, options)
return (completed, dn)
@register()
class host_disallow_retrieve_keytab(LDAPRemoveMember):
__doc__ = _('Disallow users, groups, hosts or host groups to retrieve a '
'keytab of this host.')
2014-10-02 16:57:08 +02:00
member_attributes = ['ipaallowedtoperform_read_keys']
has_output_params = LDAPRemoveMember.has_output_params + host_output_params
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
rename_ipaallowedtoperform_to_ldap(found)
rename_ipaallowedtoperform_to_ldap(not_found)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
rename_ipaallowedtoperform_from_ldap(failed, options)
return (completed, dn)
@register()
class host_allow_create_keytab(LDAPAddMember):
__doc__ = _('Allow users, groups, hosts or host groups to create a keytab '
'of this host.')
2014-10-02 16:57:08 +02:00
member_attributes = ['ipaallowedtoperform_write_keys']
has_output_params = LDAPAddMember.has_output_params + host_output_params
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
rename_ipaallowedtoperform_to_ldap(found)
rename_ipaallowedtoperform_to_ldap(not_found)
add_missing_object_class(ldap, u'ipaallowedoperations', dn)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
rename_ipaallowedtoperform_from_ldap(failed, options)
return (completed, dn)
@register()
class host_disallow_create_keytab(LDAPRemoveMember):
__doc__ = _('Disallow users, groups, hosts or host groups to create a '
'keytab of this host.')
2014-10-02 16:57:08 +02:00
member_attributes = ['ipaallowedtoperform_write_keys']
has_output_params = LDAPRemoveMember.has_output_params + host_output_params
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
rename_ipaallowedtoperform_to_ldap(found)
rename_ipaallowedtoperform_to_ldap(not_found)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
rename_ipaallowedtoperform_from_ldap(entry_attrs, options)
rename_ipaallowedtoperform_from_ldap(failed, options)
return (completed, dn)
@register()
class host_add_cert(LDAPAddAttributeViaOption):
__doc__ = _('Add certificates to host entry')
msg_summary = _('Added certificates to host "%(value)s"')
attribute = 'usercertificate'
@register()
class host_remove_cert(LDAPRemoveAttributeViaOption):
__doc__ = _('Remove certificates from host entry')
msg_summary = _('Removed certificates from host "%(value)s"')
attribute = 'usercertificate'
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
for cert in options.get('usercertificate', []):
2017-08-23 15:23:43 +02:00
revoke_certs(api.Command.cert_find(certificate=cert)['result'])
return dn
@register()
class host_add_principal(LDAPAddAttribute):
__doc__ = _('Add new principal alias to host entry')
msg_summary = _('Added new aliases to host "%(value)s"')
attribute = 'krbprincipalname'
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
util.check_principal_realm_in_trust_namespace(self.api, *keys)
util.ensure_krbcanonicalname_set(ldap, entry_attrs)
return dn
@register()
class host_remove_principal(LDAPRemoveAttribute):
__doc__ = _('Remove principal alias from a host entry')
msg_summary = _('Removed aliases from host "%(value)s"')
attribute = 'krbprincipalname'
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
util.ensure_last_krbprincipalname(ldap, entry_attrs, *keys)
return dn