11 changes: 7 additions & 4 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,18 +232,21 @@ simple tests against it after applying the module. You can run this
with:

```sh
BEAKER_setfile=debian11-64 bundle exec rake beaker
BEAKER_PUPPET_COLLECTION=puppet7 BEAKER_setfile=debian11-64 bundle exec rake beaker
```

You can replace the string `debian10` with any common operating system.
You can replace the string `debian11` with any common operating system.
The following strings are known to work:

* ubuntu1804
* ubuntu2004
* debian10
* ubuntu2204
* debian11
* centos7
* centos8
* centos9
* almalinux8
* almalinux9
* fedora36

For more information and tips & tricks, see [voxpupuli-acceptance's documentation](https://github.com/voxpupuli/voxpupuli-acceptance#running-tests).

Expand Down
2 changes: 1 addition & 1 deletion .msync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# Managed by modulesync - DO NOT EDIT
# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/

modulesync_config_version: '6.0.0'
modulesync_config_version: '7.0.0'
3 changes: 1 addition & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
---
inherit_from: .rubocop_todo.yml

# Managed by modulesync - DO NOT EDIT
# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/

inherit_from: .rubocop_todo.yml
inherit_gem:
voxpupuli-test: rubocop.yml
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.
Each new release typically also includes the latest modulesync defaults.
These should not affect the functionality of the module.

## [v4.1.0](https://github.com/voxpupuli/puppet-selinux/tree/v4.1.0) (2023-10-31)

[Full Changelog](https://github.com/voxpupuli/puppet-selinux/compare/v4.0.0...v4.1.0)

**Implemented enhancements:**

- Add EL9 support [\#378](https://github.com/voxpupuli/puppet-selinux/pull/378) ([bastelfreak](https://github.com/bastelfreak))
- Add Rocky/AlmaLinux/OracleLinux support [\#377](https://github.com/voxpupuli/puppet-selinux/pull/377) ([bastelfreak](https://github.com/bastelfreak))
- Add Debian 12 support [\#376](https://github.com/voxpupuli/puppet-selinux/pull/376) ([bastelfreak](https://github.com/bastelfreak))

**Fixed bugs:**

- selinux::login: Miscellaneous fixes [\#364](https://github.com/voxpupuli/puppet-selinux/pull/364) ([EmRowlands](https://github.com/EmRowlands))

**Merged pull requests:**

- README: refer to metadata.json in the Requirements section [\#374](https://github.com/voxpupuli/puppet-selinux/pull/374) ([kenyon](https://github.com/kenyon))
- Remove now redundant variable and method [\#372](https://github.com/voxpupuli/puppet-selinux/pull/372) ([ekohl](https://github.com/ekohl))

## [v4.0.0](https://github.com/voxpupuli/puppet-selinux/tree/v4.0.0) (2023-06-29)

[Full Changelog](https://github.com/voxpupuli/puppet-selinux/compare/v3.4.1...v4.0.0)
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
source ENV['GEM_SOURCE'] || 'https://rubygems.org'

group :test do
gem 'voxpupuli-test', '~> 6.0', :require => false
gem 'voxpupuli-test', '~> 7.0', :require => false
gem 'coveralls', :require => false
gem 'simplecov-console', :require => false
gem 'puppet_metadata', '~> 3.0', :require => false
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ This class manages SELinux.

## Requirements

* Puppet 5 or later
* See `metadata.json`

## Module Description

Expand Down
6 changes: 6 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,12 @@ The name of the linux user or group to map.

The selinux user to map to.

##### `source`

Valid values: `policy`, `local`

Source of the login configuration - either policy or local

#### Parameters

The following parameters are available in the `selinux_login` type.
Expand Down
20 changes: 6 additions & 14 deletions lib/puppet/provider/selinux_fcontext/semanage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

mk_resource_methods

@old_semanage = false

@file_types = {
'all files' => 'a',
'-d' => 'd',
Expand All @@ -28,12 +26,6 @@ def self.file_type_map(val)
@file_types[val]
end

def self.type_param(file_type)
return file_type unless @old_semanage

@file_types.invert[file_type]
end

def self.parse_fcontext_lines(lines)
ret = []
lines.each do |line|
Expand Down Expand Up @@ -97,27 +89,27 @@ def self.prefetch(resources)

def create
# is there really no way to have a provider-global helper function cleanly?
args = ['fcontext', '-a', '-t', @resource[:seltype], '-f', self.class.type_param(@resource[:file_type])]
args.concat(['-s', @resource[:seluser]]) if @resource[:seluser]
args = ['fcontext', '-a', '-t', @resource[:seltype], '-f', @resource[:file_type]]
args.push('-s', @resource[:seluser]) if @resource[:seluser]
args.push(@resource[:pathspec])
semanage(*args)
end

def destroy
args = ['fcontext', '-d', '-t', @property_hash[:seltype], '-f', self.class.type_param(@property_hash[:file_type])]
args.concat(['-s', @property_hash[:seluser]]) if @property_hash[:seluser]
args = ['fcontext', '-d', '-t', @property_hash[:seltype], '-f', @property_hash[:file_type]]
args.push('-s', @property_hash[:seluser]) if @property_hash[:seluser]
args.push(@property_hash[:pathspec])
semanage(*args)
end

def seltype=(val)
val = '<<none>>' if val == :none
args = ['fcontext', '-m', '-t', val, '-f', self.class.type_param(@property_hash[:file_type]), @property_hash[:pathspec]]
args = ['fcontext', '-m', '-t', val, '-f', @property_hash[:file_type], @property_hash[:pathspec]]
semanage(*args)
end

def seluser=(val)
args = ['fcontext', '-m', '-s', val, '-t', @property_hash[:seltype], '-f', self.class.type_param(@property_hash[:file_type]), @property_hash[:pathspec]]
args = ['fcontext', '-m', '-s', val, '-t', @property_hash[:seltype], '-f', @property_hash[:file_type], @property_hash[:pathspec]]
semanage(*args)
end

Expand Down
43 changes: 30 additions & 13 deletions lib/puppet/provider/selinux_login/semanage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,29 @@ def self.parse_helper_lines(lines)
lines.each do |line|
split = line.split(%r{\s+})
# helper format is:
# root unconfined_u
# system_u system_u
# __default__ unconfined_u
# %cn_cegbu_aconex_fr-dev-ops-priv unconfined_u
# %cn_cegbu_aconex_fr-dev-platform-priv unconfined_u
selinux_login_name, selinux_user = split

key = selinux_login_name.to_s
# policy root unconfined_u
# policy system_u system_u
# policy __default__ unconfined_u
# policy %cn_cegbu_aconex_fr-dev-ops-priv unconfined_u
# policy %cn_cegbu_aconex_fr-dev-platform-priv unconfined_u
# local %cn_cegbu_aconex_fr-dev-ops-priv unconfined_u
# local %cn_cegbu_aconex_fr-dev-platform-priv unconfined_u
source_str, selinux_login_name, selinux_user = split

key = "#{selinux_login_name}_#{selinux_user}"
source =
case source_str
when 'policy' then :policy
when 'local' then :local
else
raise Puppet::ResourceError, "Selinux_login['#{key}']: unknown mapping source #{source_str}."
end

ret[key] = {
ensure: :present,
title: key,
name: key,
source: source,
selinux_login_name: selinux_login_name,
selinux_user: selinux_user
}
Expand All @@ -85,22 +97,22 @@ def self.instances
end

def self.prefetch(resources)
# is there a better way to do this? map port/protocol pairs to the provider regardless of the title
# is there a better way to do this? Map selinux_user/selinux_login_name to the provider regardless of the title
# and make sure all system resources have ensure => :present so that we don't try to remove them
instances.each do |provider|
resource = resources[provider.name]
if resource
unless resource[:selinux_user].to_s == provider.selinux_user && resource[:selinux_login_name].to_s == provider.selinux_login_name || resource.purging?
raise Puppet::ResourceError, "Selinux_port['#{resource[:name]}']: title does not match its port and protocol, and a conflicting resource exists"
unless resource[:selinux_login_name].to_s == provider.selinux_login_name || resource.purging?
raise Puppet::ResourceError, "Selinux_login['#{resource[:name]}']: title does not match its login ('#{provider.name}' != '#{provider.selinux_login_name}'), and a conflicting resource exists"
end

resource.provider = provider
resource[:ensure] = :present if provider.source == :policy
else
resources.each_value do |res|
resources.each_values do |res|
next unless res[:selinux_user] == provider.selinux_user && res[:selinux_login_name] == provider.selinux_login_name

warning("Selinux_login['#{resource[:name]}']: title does not match format selinux_login_name_selinux_user")
warning("Selinux_login['#{res[:name]}']: title does not match its login ('#{provider.name}' != '#{provider.selinux_login_name}')")
resource.provider = provider
resource[:ensure] = :present if provider.source == :policy
end
Expand All @@ -113,6 +125,11 @@ def create
semanage(*args)
end

def sync
args = ['login', '-m', '-s', @resource[:selinux_user], @resource[:selinux_login_name]]
semanage(*args)
end

def destroy
args = ['login', '-d', @property_hash[:selinux_login_name]]
semanage(*args)
Expand Down
15 changes: 15 additions & 0 deletions lib/puppet/type/selinux_login.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
newproperty(:selinux_user) do
desc 'The selinux user to map to.'
isrequired

def sync
event = super
provider.sync
event
end
end

newproperty(:source) do
desc 'Source of the login configuration - either policy or local'
newvalues(:policy, :local)

validate do |_value|
raise ArgumentError, ':source is a read-only property'
end
end

autorequire(:package) do
Expand Down
4 changes: 4 additions & 0 deletions lib/puppet_x/voxpupuli/selinux/semanage_ports.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@ def print_port(kind, port):

# Always list local ports afterwards so that the provider works correctly
retval, ports = semanage.semanage_port_list(handle)
if retval < 0:
raise ValueError("Could not list port config")

for port in ports:
print_port('policy', port)

retval, ports = semanage.semanage_port_list_local(handle)
if retval < 0:
raise ValueError("Could not list local port config")

for port in ports:
print_port('local', port)
Expand Down
28 changes: 19 additions & 9 deletions lib/puppet_x/voxpupuli/selinux/semanage_users.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# This script uses libsemanage directly to access the ports list
# it is *much* faster than semanage port -l
# This script uses libsemanage directly to access the logins list
# This is *much* faster than semanage login -l

# will work with python 2.6+
from __future__ import print_function
from sys import exit
try:
import semanage
except ImportError:
# The semanage python library does not exist, so let's assume SELinux is disabled...
# In this case, the correct response is to return no ports when puppet does a
# prefetch, to avoid an error. We depend on the semanage binary anyway, which
# is uses the library
# The semanage python library does not exist, so let's assume SELinux is
# disabled. In this case, the correct response is to return no logins when
# puppet does a prefetch, to avoid an error. We depend on the semanage binary
# anyway, which uses the library
exit(0)


Expand All @@ -21,16 +21,26 @@
if semanage.semanage_connect(handle) < 0:
exit(1)

def print_seuser(seuser):
def print_seuser(kind, seuser):
seuser_login = semanage.semanage_seuser_get_name(seuser)
selinux_user = semanage.semanage_seuser_get_sename(seuser)
print("{} {}".format(seuser_login, selinux_user))
print("{} {} {}".format(kind, seuser_login, selinux_user))


# Always list local config afterwards so that the provider works correctly
(status, seusers) = semanage.semanage_seuser_list(handle)
if status < 0:
raise ValueError("Could not list user config")

for seuser in seusers:
print_seuser(seuser)
print_seuser('policy', seuser)

(status, seusers) = semanage.semanage_seuser_list_local(handle)
if status < 0:
raise ValueError("Could not list local user config")

for seuser in seusers:
print_seuser('local', seuser)


semanage.semanage_disconnect(handle)
Expand Down
2 changes: 1 addition & 1 deletion manifests/login.pp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

# Do nothing unless SELinux is enabled
if $facts['os']['selinux']['enabled'] {
selinux_login { "${selinux_login_name}_${selinux_user}":
selinux_login { $selinux_login_name:
ensure => $ensure,
selinux_login_name => $selinux_login_name,
selinux_user => $selinux_user,
Expand Down
32 changes: 28 additions & 4 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppet-selinux",
"version": "4.0.0",
"version": "4.1.0",
"author": "Vox Pupuli",
"summary": "This class manages SELinux",
"license": "Apache-2.0",
Expand All @@ -12,14 +12,37 @@
"operatingsystem": "RedHat",
"operatingsystemrelease": [
"7",
"8"
"8",
"9"
]
},
{
"operatingsystem": "CentOS",
"operatingsystemrelease": [
"7",
"8"
"8",
"9"
]
},
{
"operatingsystem": "Rocky",
"operatingsystemrelease": [
"8",
"9"
]
},
{
"operatingsystem": "AlmaLinux",
"operatingsystemrelease": [
"8",
"9"
]
},
{
"operatingsystem": "OracleLinux",
"operatingsystemrelease": [
"8",
"9"
]
},
{
Expand All @@ -35,7 +58,8 @@
"operatingsystem": "Debian",
"operatingsystemrelease": [
"10",
"11"
"11",
"12"
]
},
{
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
add_custom_fact name.to_sym, value
end
end
Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f }
Loading