Skip to content

Commit 8df1dbf

Browse files
(PUP-12041) Handle libuser's unavailability in Fedora 40
- Starting from version 40, Fedora does not have the lgroup* commands available due to deprecation of libuser: https://fedoraproject.org/wiki/Changes/LibuserDeprecation. - groupadd relies on libuser to add/purge members to/from groups. - Add manages_members feature to Fedora 40 and above since groupmod can add members to groups now. Historically, it was unable to do so that's why puppet used lgroupmod for it. - Handle flags for lgroupmod (-M) and groupmod (-aU) commands properly. - Only use lgroup* commands if libuser is supported. - When libuser is not supported, members should be purged using the usermod command. Since usermod does not support comma separated list of users they should be removed one by one. (cherry picked from commit 6a1db9e)
1 parent e1c1b2d commit 8df1dbf

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

lib/puppet/provider/group/groupadd.rb

+30-9
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@
1515
value.is_a? Integer
1616
end
1717

18-
optional_commands :localadd => "lgroupadd", :localdelete => "lgroupdel", :localmodify => "lgroupmod"
19-
20-
has_feature :manages_local_users_and_groups, :manages_members if Puppet.features.libuser?
21-
22-
options :members, :flag => '-M', :method => :mem
18+
optional_commands :localadd => "lgroupadd", :localdelete => "lgroupdel", :localmodify => "lgroupmod", :purgemember => "usermod"
19+
20+
has_feature :manages_local_users_and_groups if Puppet.features.libuser?
21+
has_feature :manages_members if Puppet.features.libuser? ||
22+
(Puppet.runtime[:facter].value('os.name') == "Fedora" &&
23+
Puppet.runtime[:facter].value('os.release.major').to_i >= 40)
24+
25+
# Libuser's modify command 'lgroupmod' requires '-M' flag for member additions.
26+
# 'groupmod' command requires the '-aU' flags for it.
27+
if Puppet.features.libuser?
28+
options :members, :flag => '-M', :method => :mem
29+
else
30+
options :members, :flag => '-aU', :method => :mem
31+
end
2332

2433
def exists?
2534
return !!localgid if @resource.forcelocal?
@@ -58,7 +67,8 @@ def create
5867
end
5968

6069
def addcmd
61-
if @resource.forcelocal?
70+
# The localadd command (lgroupadd) must only be called when libuser is supported.
71+
if Puppet.features.libuser? && @resource.forcelocal?
6272
cmd = [command(:localadd)]
6373
@custom_environment = Puppet::Util::Libuser.getenv
6474
else
@@ -86,7 +96,8 @@ def validate_members(members)
8696
end
8797

8898
def modifycmd(param, value)
89-
if @resource.forcelocal? || @resource[:members]
99+
# The localmodify command (lgroupmod) must only be called when libuser is supported.
100+
if Puppet.features.libuser? && (@resource.forcelocal? || @resource[:members])
90101
cmd = [command(:localmodify)]
91102
@custom_environment = Puppet::Util::Libuser.getenv
92103
else
@@ -109,7 +120,8 @@ def modifycmd(param, value)
109120
end
110121

111122
def deletecmd
112-
if @resource.forcelocal?
123+
# The localdelete command (lgroupdel) must only be called when libuser is supported.
124+
if Puppet.features.libuser? && @resource.forcelocal?
113125
@custom_environment = Puppet::Util::Libuser.getenv
114126
[command(:localdelete), @resource[:name]]
115127
else
@@ -127,7 +139,16 @@ def members_to_s(current)
127139
end
128140

129141
def purge_members
130-
localmodify('-m', members_to_s(members), @resource.name)
142+
# The groupadd provider doesn't have the ability currently to remove members from a group, libuser does.
143+
# Use libuser's lgroupmod command to achieve purging members if libuser is supported.
144+
# Otherwise use the 'usermod' command.
145+
if Puppet.features.libuser?
146+
localmodify('-m', members_to_s(members), @resource.name)
147+
else
148+
members.each do |member|
149+
purgemember('-rG', @resource.name, member)
150+
end
151+
end
131152
end
132153

133154
private

spec/unit/provider/group/groupadd_spec.rb

+18-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
end
4545

4646
describe "on systems with libuser" do
47+
before do
48+
allow(Puppet.features).to receive(:libuser?).and_return(true)
49+
end
50+
4751
describe "with forcelocal=true" do
4852
before do
4953
described_class.has_feature(:manages_local_users_and_groups)
@@ -71,7 +75,7 @@
7175
describe "with a list of members" do
7276
before do
7377
members.each { |m| allow(Etc).to receive(:getpwnam).with(m).and_return(true) }
74-
78+
allow(provider).to receive(:flag).and_return('-M')
7579
described_class.has_feature(:manages_members)
7680
resource[:forcelocal] = false
7781
resource[:members] = members
@@ -92,6 +96,10 @@
9296
end
9397

9498
describe "on systems with libuser" do
99+
before do
100+
allow(Puppet.features).to receive(:libuser?).and_return(true)
101+
end
102+
95103
describe "with forcelocal=false" do
96104
before do
97105
described_class.has_feature(:manages_local_users_and_groups)
@@ -156,6 +164,7 @@
156164
before { resource[:auth_membership] = false }
157165

158166
it "should add to the existing users" do
167+
allow(provider).to receive(:flag).and_return('-M')
159168
new_members = ['user1', 'user2', 'user3', 'user4']
160169
allow(provider).to receive(:members).and_return(members)
161170
expect(provider).not_to receive(:localmodify).with('-m', members.join(','), 'mygroup')
@@ -235,6 +244,10 @@
235244
end
236245

237246
describe "on systems with the libuser and forcelocal=false" do
247+
before do
248+
allow(Puppet.features).to receive(:libuser?).and_return(true)
249+
end
250+
238251
before do
239252
described_class.has_feature(:manages_local_users_and_groups)
240253
resource[:forcelocal] = :false
@@ -247,6 +260,10 @@
247260
end
248261

249262
describe "on systems with the libuser and forcelocal=true" do
263+
before do
264+
allow(Puppet.features).to receive(:libuser?).and_return(true)
265+
end
266+
250267
before do
251268
described_class.has_feature(:manages_local_users_and_groups)
252269
resource[:forcelocal] = :true

0 commit comments

Comments
 (0)