Add polkit rule to allow kolla nova user access to libvirtd socket on docker host

The polkit rules are currently evaluated in the context of the docker host.
As a result the check fails for the kolla nova compute user, as the uids are not
consistent with the host uids (in fact we probably can't assume a nova user exists
on the docker host).

As a short-term workaround a 'docker_nova' user group is created on the docker host
and the polkit rule is updated to grant this user access to the libvirtd socket.

Longer term solution probably requires running polkitd in a container too.

Change-Id: I91be1f1eacf8eed9017bbfef393ee2d66771e8d6
Related-bug: #1693844
This commit is contained in:
Oliver Walsh 2017-06-06 12:12:43 +01:00
parent 0a75929ade
commit 016cef3ea7
2 changed files with 138 additions and 0 deletions

View File

@ -47,6 +47,18 @@
# [*step*]
# step defaults to hiera('step')
#
# [*configure_libvirt_polkit*]
# Configures libvirt polkit to grant the kolla nova user access to the libvirtd unix domain socket on the host.
# Defaults to true when nova_compute service is enabled, false when nova_compute is disabled
#
# [*docker_nova_uid*]
# When configure_libvirt_polkit = true, the uid/gid of the nova user within the docker container.
# Defaults to 42436
#
# [*services_enabled*]
# List of TripleO services enabled on the role.
# Defaults to hiera('services_names')
#
class tripleo::profile::base::docker (
$docker_namespace = undef,
$insecure_registry = false,
@ -55,7 +67,17 @@ class tripleo::profile::base::docker (
$configure_storage = true,
$storage_options = '-s overlay2',
$step = hiera('step'),
$configure_libvirt_polkit = undef,
$docker_nova_uid = 42436,
$services_enabled = hiera('service_names', [])
) {
if $configure_libvirt_polkit == undef {
$configure_libvirt_polkit_real = 'nova_compute' in $services_enabled
} else {
$configure_libvirt_polkit_real = $configure_libvirt_polkit
}
if $step >= 1 {
package {'docker':
ensure => installed,
@ -130,4 +152,41 @@ class tripleo::profile::base::docker (
}
}
if ($step >= 4 and $configure_libvirt_polkit_real) {
# Workaround for polkit authorization for libvirtd socket on host
#
# This creates a local user with the kolla nova uid, and sets the polkit rule to
# allow both it and the nova user from the nova rpms, should it exist (uid 162).
group { 'docker_nova_group':
name => 'docker_nova',
gid => $docker_nova_uid
} ->
user { 'docker_nova_user':
name => 'docker_nova',
uid => $docker_nova_uid,
gid => $docker_nova_uid,
shell => '/sbin/nologin',
comment => 'OpenStack Nova Daemons',
groups => ['nobody']
}
# Similar to the polkit rule in the openstack-nova rpm spec
# but allow both the 'docker_nova' and 'nova' user
$docker_nova_polkit_rule = '// openstack-nova libvirt management permissions
polkit.addRule(function(action, subject) {
if (action.id == "org.libvirt.unix.manage" &&
/^(docker_)?nova$/.test(subject.user)) {
return polkit.Result.YES;
}
});
'
package {'polkit':
ensure => installed,
} ->
file {'/etc/polkit-1/rules.d/50-nova.rules':
content => $docker_nova_polkit_rule,
mode => '0644'
}
}
}

View File

@ -124,6 +124,85 @@ describe 'tripleo::profile::base::docker' do
}
end
context 'with step 4 and configure_libvirt_polkit disabled' do
let(:params) { {
:step => 4,
:configure_libvirt_polkit => false
} }
it {
is_expected.to_not contain_group('docker_nova_group')
is_expected.to_not contain_user('docker_nova_user')
is_expected.to_not contain_package('polkit')
is_expected.to_not contain_file('/etc/polkit-1/rules.d/50-nova.rules')
}
end
context 'with step 4 and configure_libvirt_polkit enabled' do
let(:params) { {
:step => 4,
:configure_libvirt_polkit => true
} }
it {
is_expected.to contain_group('docker_nova_group').with(
:name => 'docker_nova',
:gid => 42436
)
is_expected.to contain_user('docker_nova_user').with(
:name => 'docker_nova',
:uid => 42436,
:gid => 42436,
:shell => '/sbin/nologin',
:groups => ['nobody']
)
is_expected.to contain_package('polkit')
is_expected.to contain_file('/etc/polkit-1/rules.d/50-nova.rules')
}
end
context 'with step 4 and nova_compute service installed' do
let(:params) { {
:step => 4,
:services_enabled => ['docker', 'nova_compute']
} }
it {
is_expected.to contain_group('docker_nova_group').with(
:name => 'docker_nova',
:gid => 42436
)
is_expected.to contain_user('docker_nova_user').with(
:name => 'docker_nova',
:uid => 42436,
:gid => 42436,
:shell => '/sbin/nologin',
:groups => ['nobody']
)
is_expected.to contain_package('polkit')
is_expected.to contain_file('/etc/polkit-1/rules.d/50-nova.rules')
}
end
context 'with step 4 and configure_libvirt_polkit enabled and docker_nova uid' do
let(:params) { {
:step => 4,
:configure_libvirt_polkit => true,
:docker_nova_uid => 12345
} }
it {
is_expected.to contain_group('docker_nova_group').with(
:name => 'docker_nova',
:gid => 12345
)
is_expected.to contain_user('docker_nova_user').with(
:name => 'docker_nova',
:uid => 12345,
:gid => 12345,
:shell => '/sbin/nologin',
:groups => ['nobody']
)
is_expected.to contain_package('polkit')
is_expected.to contain_file('/etc/polkit-1/rules.d/50-nova.rules')
}
end
end
on_supported_os.each do |os, facts|