mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
service: allow creating services without a host to manage them
Add --skip-host-check option to ipa service-add command to allow creating services without corresponding host object. This is needed to cover use cases where Kerberos services created to handle client authentication in a dynamically generated environment like Kubernetes. Fixes: https://pagure.io/freeipa/issue/7514 Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
committed by
Rob Crittenden
parent
2a58fe6a32
commit
9e8fb94e87
3
API.txt
3
API.txt
@@ -4457,7 +4457,7 @@ output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: service_add/1
|
||||
args: 1,13,3
|
||||
args: 1,14,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
option: Str('addattr*', cli_name='addattr')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
@@ -4470,6 +4470,7 @@ option: Str('krbprincipalauthind*', cli_name='auth_ind')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('setattr*', cli_name='setattr')
|
||||
option: Flag('skip_host_check', autofill=True, default=False)
|
||||
option: Certificate('usercertificate*', cli_name='certificate')
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
|
||||
@@ -407,6 +407,7 @@ return {
|
||||
other_entity: 'host',
|
||||
other_field: 'fqdn',
|
||||
label: '@i18n:objects.service.host',
|
||||
editable: true,
|
||||
required: true,
|
||||
z_index: 1
|
||||
},
|
||||
@@ -414,6 +415,11 @@ return {
|
||||
$type: 'checkbox',
|
||||
name: 'force',
|
||||
metadata: '@mc-opt:service_add:force'
|
||||
},
|
||||
{
|
||||
$type: 'checkbox',
|
||||
name: 'skip_host_check',
|
||||
metadata: '@mc-opt:service_add:skip_host_check'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -543,6 +549,9 @@ IPA.service_adder_dialog = function(spec) {
|
||||
|
||||
field = that.fields.get_field('force');
|
||||
record['force'] = field.save();
|
||||
|
||||
field = that.fields.get_field('skip_host_check');
|
||||
record['skip_host_check'] = field.save();
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
@@ -601,9 +601,14 @@ class service_add(LDAPCreate):
|
||||
has_output_params = LDAPCreate.has_output_params + output_params
|
||||
takes_options = LDAPCreate.takes_options + (
|
||||
Flag('force',
|
||||
label=_('Force'),
|
||||
doc=_('force principal name even if not in DNS'),
|
||||
label=_('Force'),
|
||||
doc=_('force principal name even if host not in DNS'),
|
||||
),
|
||||
Flag('skip_host_check',
|
||||
label=_('Skip host check'),
|
||||
doc=_('force service to be created even when host '
|
||||
'object does not exist to manage it'),
|
||||
),
|
||||
)
|
||||
|
||||
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
|
||||
@@ -614,12 +619,13 @@ class service_add(LDAPCreate):
|
||||
if principal.is_host and not options['force']:
|
||||
raise errors.HostService()
|
||||
|
||||
try:
|
||||
hostresult = self.api.Command['host_show'](hostname)['result']
|
||||
except errors.NotFound:
|
||||
raise errors.NotFound(
|
||||
reason=_("The host '%s' does not exist to add a service to.") %
|
||||
hostname)
|
||||
if not options['skip_host_check']:
|
||||
try:
|
||||
hostresult = self.api.Command['host_show'](hostname)['result']
|
||||
except errors.NotFound:
|
||||
raise errors.NotFound(reason=_(
|
||||
"The host '%s' does not exist to add a service to.") %
|
||||
hostname)
|
||||
|
||||
self.obj.validate_ipakrbauthzdata(entry_attrs)
|
||||
|
||||
@@ -628,7 +634,7 @@ class service_add(LDAPCreate):
|
||||
# really want to discourage creating services for hosts that
|
||||
# don't exist in DNS.
|
||||
util.verify_host_resolvable(hostname)
|
||||
if not 'managedby' in entry_attrs:
|
||||
if not (options['skip_host_check'] or 'managedby' in entry_attrs):
|
||||
entry_attrs['managedby'] = hostresult['dn']
|
||||
|
||||
# Enforce ipaKrbPrincipalAlias to aid case-insensitive searches
|
||||
|
||||
@@ -47,6 +47,11 @@ service1dn = DN(('krbprincipalname',service1),('cn','services'),('cn','accounts'
|
||||
host1dn = DN(('fqdn',fqdn1),('cn','computers'),('cn','accounts'),api.env.basedn)
|
||||
host2dn = DN(('fqdn',fqdn2),('cn','computers'),('cn','accounts'),api.env.basedn)
|
||||
host3dn = DN(('fqdn',fqdn3),('cn','computers'),('cn','accounts'),api.env.basedn)
|
||||
d_service_no_realm = u'some/at.some.arbitrary.name'
|
||||
d_service = u'%s@%s' % (d_service_no_realm, api.env.realm)
|
||||
d_servicedn = DN(('krbprincipalname', d_service),
|
||||
('cn', 'services'), ('cn', 'accounts'),
|
||||
api.env.basedn)
|
||||
|
||||
role1 = u'Test Role'
|
||||
role1_dn = DN(('cn', role1), api.env.container_rolegroup, api.env.basedn)
|
||||
@@ -87,6 +92,7 @@ class test_service(Declarative):
|
||||
('host_del', [fqdn2], {}),
|
||||
('host_del', [fqdn3], {}),
|
||||
('service_del', [service1], {}),
|
||||
('service_del', [d_service], {}),
|
||||
]
|
||||
|
||||
tests = [
|
||||
@@ -732,6 +738,23 @@ class test_service(Declarative):
|
||||
),
|
||||
|
||||
|
||||
# Create a service disconnected from any host
|
||||
dict(
|
||||
desc='Try to create service %r without any host' % d_service,
|
||||
command=('service_add', [d_service_no_realm],
|
||||
dict(force=True, skip_host_check=True),),
|
||||
expected=dict(
|
||||
value=d_service,
|
||||
summary=u'Added service "%s"' % d_service,
|
||||
result=dict(
|
||||
dn=d_servicedn,
|
||||
krbprincipalname=[d_service],
|
||||
krbcanonicalname=[d_service],
|
||||
objectclass=objectclasses.service,
|
||||
ipauniqueid=[fuzzy_uuid],
|
||||
),
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user