Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add user/group/mode parameter to custom types #129

Merged
merged 11 commits into from
Feb 10, 2025
48 changes: 48 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,18 @@ The basic property that the resource should be in.

Default value: `present`

##### `group`

group of the file

##### `mode`

mode of the file

##### `owner`

owner of the file

#### Parameters

The following parameters are available in the `dhparam` type.
Expand Down Expand Up @@ -1252,6 +1264,18 @@ The basic property that the resource should be in.

Default value: `present`

##### `group`

group of the file

##### `mode`

mode of the file

##### `owner`

owner of the file

#### Parameters

The following parameters are available in the `ssl_pkey` type.
Expand Down Expand Up @@ -1314,6 +1338,18 @@ The basic property that the resource should be in.

Default value: `present`

##### `group`

group of the file

##### `mode`

mode of the file

##### `owner`

owner of the file

#### Parameters

The following parameters are available in the `x509_cert` type.
Expand Down Expand Up @@ -1408,6 +1444,18 @@ The basic property that the resource should be in.

Default value: `present`

##### `group`

group of the file

##### `mode`

mode of the file

##### `owner`

owner of the file

#### Parameters

The following parameters are available in the `x509_request` type.
Expand Down
8 changes: 7 additions & 1 deletion lib/puppet/provider/dhparam/openssl.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# frozen_string_literal: true

require 'pathname'
Puppet::Type.type(:dhparam).provide(:openssl) do
require File.join(__dir__, '..', '..', '..', 'puppet/provider/openssl')

Puppet::Type.type(:dhparam).provide(
:openssl,
parent: Puppet::Provider::Openssl
) do
desc 'Manages dhparam files with OpenSSL'

commands openssl: 'openssl'
Expand All @@ -19,6 +24,7 @@ def create
options.insert(1, '-dsaparam') if resource[:fastmode]

openssl options
set_file_perm(resource[:path], resource[:owner], resource[:group], resource[:mode])
end

def destroy
Expand Down
56 changes: 56 additions & 0 deletions lib/puppet/provider/openssl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

require 'etc'

# class to use in openssl providers to handle file permission (mode, group and owner)
class Puppet::Provider::Openssl < Puppet::Provider
include Puppet::Util::POSIX

def owner
if File.exist?(@resource[:path])
Etc.getpwuid(File.stat(@resource[:path]).uid).name
else
:absent
end
end

def owner=(should)
File.chown(uid(should), nil, resource[:path])
rescue StandardError => e
raise Puppet::Error, _("Failed to set owner to '#{should}': #{e}"), detail.backtrace
end

def group
if File.exist?(@resource[:path])
Etc.getgrgid(File.stat(@resource[:path]).gid).name
else
:absent
end
end

def group=(should)
File.chown(nil, gid(should), resource[:path])
rescue StandardError => e
raise Puppet::Error, _("Failed to set group to '#{should}': #{e}"), detail.backtrace
end

# Return the mode as an octal string, not as an integer.
def mode
if File.exist?(@resource[:path])
format('0%o', (File.stat(@resource[:path]).mode & 0o07777))
else
:absent
end
end

# Set the file mode, converting from a string to an integer.
def mode=(should)
File.chmod(Integer("0#{should}"), @resource[:path])
end

def set_file_perm(filename, owner = nil, group = nil, mode = nil)
File.chown(uid(owner), nil, resource[:path]) if owner
File.chown(nil, gid(group), resource[:path]) if group
File.chmod(Integer("0#{mode}"), filename) if mode
end
end
7 changes: 6 additions & 1 deletion lib/puppet/provider/ssl_pkey/openssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

require 'pathname'
require 'openssl'
Puppet::Type.type(:ssl_pkey).provide(:openssl) do
require File.join(__dir__, '..', '..', '..', 'puppet/provider/openssl')
Puppet::Type.type(:ssl_pkey).provide(
:openssl,
parent: Puppet::Provider::Openssl
) do
desc 'Manages private keys with OpenSSL'

def self.dirname(resource)
Expand Down Expand Up @@ -38,6 +42,7 @@ def create
key = self.class.generate_key(resource)
pem = self.class.to_pem(resource, key)
File.write(resource[:path], pem)
set_file_perm(resource[:path], resource[:owner], resource[:group], resource[:mode])
end

def destroy
Expand Down
7 changes: 6 additions & 1 deletion lib/puppet/provider/x509_cert/openssl.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# frozen_string_literal: true

require 'pathname'
Puppet::Type.type(:x509_cert).provide(:openssl) do
require File.join(__dir__, '..', '..', '..', 'puppet/provider/openssl')
Puppet::Type.type(:x509_cert).provide(
:openssl,
parent: Puppet::Provider::Openssl
) do
desc 'Manages certificates with OpenSSL'

commands openssl: 'openssl'
Expand Down Expand Up @@ -103,6 +107,7 @@ def create
# openssl(options) doesn't work because it's impossible to pass an env
# https://github.com/puppetlabs/puppet/issues/9493
execute([command('openssl')] + options, { failonfail: true, combine: true, custom_environment: env })
set_file_perm(resource[:path], resource[:owner], resource[:group], resource[:mode])
end

def destroy
Expand Down
8 changes: 7 additions & 1 deletion lib/puppet/provider/x509_request/openssl.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# frozen_string_literal: true

require 'pathname'
Puppet::Type.type(:x509_request).provide(:openssl) do
require File.join(__dir__, '..', '..', '..', 'puppet/provider/openssl')
Puppet::Type.type(:x509_request).provide(
:openssl,
parent: Puppet::Provider::Openssl
) do
desc 'Manages certificate signing requests with OpenSSL'

commands openssl: 'openssl'
Expand Down Expand Up @@ -45,6 +49,8 @@ def create
# openssl(options) doesn't work because it's impossible to pass an env
# https://github.com/puppetlabs/puppet/issues/9493
execute([command('openssl')] + options, { failonfail: true, combine: true, custom_environment: env })

set_file_perm(resource[:path], resource[:owner], resource[:group], resource[:mode])
end

def destroy
Expand Down
21 changes: 21 additions & 0 deletions lib/puppet/type/dhparam.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,25 @@
autorequire(:file) do
Pathname.new(self[:path]).parent.to_s
end

newproperty(:owner) do
desc 'owner of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid user name" unless value =~ %r{^\w+$}
end
end

newproperty(:group) do
desc 'group of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid group name" unless value =~ %r{^\w+$}
end
end

newproperty(:mode) do
desc 'mode of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid file mode" unless value =~ %r{^0\d\d\d$}
end
end
end
21 changes: 21 additions & 0 deletions lib/puppet/type/ssl_pkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,25 @@
autorequire(:file) do
Pathname.new(self[:path]).parent.to_s
end

newproperty(:owner) do
desc 'owner of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid user name" unless value =~ %r{^\w+$}
end
end

newproperty(:group) do
desc 'group of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid group name" unless value =~ %r{^\w+$}
end
end

newproperty(:mode) do
desc 'mode of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid file mode" unless value =~ %r{^0\d\d\d$}
end
end
end
21 changes: 21 additions & 0 deletions lib/puppet/type/x509_cert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,27 @@
desc 'The optional CA key password'
end

newproperty(:owner) do
desc 'owner of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid user name" unless value =~ %r{^\w+$}
end
end

newproperty(:group) do
desc 'group of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid group name" unless value =~ %r{^\w+$}
end
end

newproperty(:mode) do
desc 'mode of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid file mode" unless value =~ %r{^0\d\d\d$}
end
end

autorequire(:file) do
self[:template]
end
Expand Down
21 changes: 21 additions & 0 deletions lib/puppet/type/x509_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@
defaultto true
end

newproperty(:owner) do
desc 'owner of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid user name" unless value =~ %r{^\w+$}
end
end

newproperty(:group) do
desc 'group of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid group name" unless value =~ %r{^\w+$}
end
end

newproperty(:mode) do
desc 'mode of the file'
validate do |value|
raise ArgumentError, "#{value} is not a valid file mode" unless value =~ %r{^0\d\d\d$}
end
end

autorequire(:x509_cert) do
path = Pathname.new(self[:private_key])
"#{path.dirname}/#{path.basename(path.extname)}"
Expand Down
33 changes: 33 additions & 0 deletions spec/unit/puppet/type/dhparam_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,37 @@
resource[:size] = 1.5
end.to raise_error(Puppet::Error, %r{Size must be a positive integer: 1.5})
end

it 'accepts mode' do
resource[:mode] = '0700'
expect(resource[:mode]).to eq('0700')
end

it 'does not accept numeric mode' do
expect do
resource[:mode] = '700'
end.to raise_error(Puppet::Error, %r{700 is not a valid file mode})
end

it 'accepts owner' do
resource[:owner] = 'someone'
expect(resource[:owner]).to eq('someone')
end

it 'does not accept bad owner' do
expect do
resource[:owner] = 'someone else'
end.to raise_error(Puppet::Error, %r{someone else is not a valid user name})
end

it 'accepts group' do
resource[:group] = 'party'
expect(resource[:group]).to eq('party')
end

it 'does not accept bad group group' do
expect do
resource[:group] = 'party crasher'
end.to raise_error(Puppet::Error, %r{party crasher is not a valid group name})
end
end
Loading