Powershell notes

sum attribute of objects in array

( $foo.disksizerequired | Measure-Object -Sum ).Sum /1024/1024

Save down user photo from Active Directory

$path = "E:\test\output1.jpg"
$user = get-aduser "bgstack15" -properties thumbnailphoto

Display string of asterisks for a password. Obscure a password for display.

$output=""; For ($c=0; $c -lt $pass.length; $c++){$output+="*"}; Write-Host $output

Function uses -Verbose flag (from powershell – How to properly use the -verbose and -debug parameters in a custom cmdlet – Stack Overflow

function DoStuff {

    process {
        if ($PSBoundParameters['Verbose']) {
            # Do verbose stuff

        New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true)
DoStuff -Verbose

Also, this example from How to write a PowerShell function to use Confirm, Verbose and WhatIf | SQL DBA with A Beard

function Set-FileContent {
        [Parameter(Mandatory = $true)]
        [Parameter(Mandatory = $true)]
        [ValidateScript( {Test-Path $_ })]
    if ($PSCmdlet.ShouldProcess("$File" , "Adding $Content to ")) {
        Set-Content -Path $File -Value $Content


# Slightly more readable: 2020-01-15T17:07:59Z
#Also just fine
(Get-Date -Format FileDateTimeUniversal)

Creating a DateTime object with a specific UTC DateTime in PowerShell – Stack Overflow

Import CSV to dictionary

With column headings of ID and Data:

Import-Csv $filePath | % { $HashTable[$_.ID] = $_.Data }

Powershell CSV with headers to hashtable – Stack Overflow

Install CentOS 8 with kickstart and virt-install

This is a modification of my process for using virt-install to fully automate the install for CentOS/Fedora with kickstart.

Here is my kickstart file for CentOS 8. Only minor modifications were required. A few packages aren’t available yet, but I’ve stopped using them, and a few renames.

How I use this

I define a variable, and plug it into the important parts.

vm=c8-02a ; time sudo virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=centos7.0 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/Linux/CentOS-8-x86_64-1905-dvd1.iso --initrd-inject=/mnt/public/Support/Platforms/CentOS8/centos8-ks.cfg --extra-args "ks=file:/centos8-ks.cfg SERVERNAME=${vm} NOTIFYEMAIL=bgstack15@gmail.com net.ifnames=0 biosdevname=0" --debug --network type=bridge,source=br0 --noautoconsole

Some thoughts

The repository URLs are a little different for CentOS 8, but once I had one built I could examine the URLS and correct my kickstart to use my local repos.


The kickstart file

# File: /mnt/public/Support/Platforms/CentOS8/centos8-ks.cfg
# Locations:
#    /mnt/public/Support/Platforms/CentOS8/centos8-ks.cfg
# Author: bgstack15
# Startdate: 2017-06-02
# Title: Kickstart for CentOS 8 for ipa.example.com
# Purpose: To provide an easy installation for VMs and other systems in the Mersey network
# History:
#    2017-06 I learned how to use kickstart files for the RHCSA EX-200 exam
#    2017-08-08 Added notifyemail to --extra-args
#    2017-10-29 major revision to use local repository
#    2019-09-24 fork for CentOS 8
# Usage with virt-install:
#    vm=c8-01a ; time sudo virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=centos7.0 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/Linux/CentOS-8-x86_64-1905-dvd1.iso --initrd-inject=/mnt/public/Support/Platforms/CentOS8/centos8-ks.cfg --extra-args "ks=file:/centos8-ks.cfg SERVERNAME=${vm} NOTIFYEMAIL=bgstack15@gmail.com net.ifnames=0 biosdevname=0" --debug --network type=bridge,source=br0 --noautoconsole
#    vm=c8-01a; sudo virsh destroy "${vm}"; sudo virsh undefine --remove-all-storage "${vm}";
# Reference:
#    https://sysadmin.compxtreme.ro/automatically-set-the-hostname-during-kickstart-installation/
#    /mnt/public/Support/Platforms/CentOS7/install-vm.txt

#platform=x86, AMD64, or Intel EM64T
# Install OS instead of upgrade
# Keyboard layouts
keyboard 'us'
# Root password
rootpw --plaintext f0rg3tkickstart&
# my user
user --groups=wheel --name=bgstack15-local --password=$6$.gh9u7vg2HDJPPX/$g3X1l.q75fs7i0UKUt6h88bDIo1YSGGj/1DGeUzzbMTb0pBh4of6iNYWyxws/937qUiPgETqOsYFI5XNrkaUe. --iscrypted --gecos="bgstack15-local"

# System language
lang en_US.UTF-8
# Firewall configuration
firewall --enabled --ssh
# Reboot after installation
# Network information
#attempting to put it in the included ks file that accepts hostname from the virsh command.
#network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate
%include /tmp/network.ks
# System timezone
timezone America/New_York --utc
# System authorization information
auth  --useshadow  --passalgo=sha512
# Use network installation instead of CDROM installation media
url --url="http://www.ipa.example.com/mirror/centos/8/BaseOS/x86_64/os"

# Use text mode install
# SELinux configuration
selinux --enforcing
# Do not configure the X Window System

# Use all local repositories
# Online repos
repo --name=examplerpm --baseurl=http://www.ipa.example.com/example/repo/rpm/
repo --name=base --baseurl=https://www.ipa.example.com/mirror/centos/$releasever/BaseOS/$basearch/os/
repo --name=appstream --baseurl=https://www.ipa.example.com/mirror/centos/$releasever/AppStream/$basearch/os/
repo --name=extras --baseurl=https://www.ipa.example.com/mirror/centos/$releasever/extras/$basearch/os/
repo --name=powertools --baseurl=https://www.ipa.example.com/mirror/centos/$releasever/PowerTools/$basearch/os/
repo --name=epel --baseurl=https://www.ipa.example.com/mirror/fedora/epel/$releasever/Everything/$basearch

# Offline repos

firstboot --disabled

# System bootloader configuration
bootloader --location=mbr
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
autopart --type=lvm

echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname renameme.ipa.example.com" > /tmp/network.ks
for x in $( cat /proc/cmdline );
   case $x in
         eval $x
         echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname ${SERVERNAME}.ipa.example.com" > /tmp/network.ks
         eval $x
         echo "${NOTIFYEMAIL}" > /mnt/sysroot/root/notifyemail.txt
cp -p /run/install/repo/ca-ipa.example.com.crt /etc/pki/ca-trust/source/anchors/ 2>/dev/null || :
wget http://www.ipa.example.com/example/certs/ca-ipa.example.com.crt -O /etc/pki/ca-trust/source/anchors/ca-ipa.example-wget.com.crt || :
update-ca-trust || :

   # Set temporary hostname
   #hostnamectl set-hostname renameme.ipa.example.com;

   ifup eth0
   sed -i -r -e 's/ONBOOT=.*/ONBOOT=yes/;' /etc/sysconfig/network-scripts/ifcfg-e*

   # Get local mirror root ca certificate
   wget http://www.ipa.example.com/example/certs/ca-ipa.example.com.crt -O /etc/pki/ca-trust/source/anchors/ca-ipa.example.com.crt && update-ca-trust

   # Get local mirror repositories
   wget https://www.ipa.example.com/example/repo/rpm/examplerpm.repo -O /etc/yum.repos.d/examplerpm.repo;
   wget http://www.ipa.example.com/example/repo/rpm/examplerpm.mirrorlist -O /etc/yum.repos.d/examplerpm.mirrorlist
   distro=centos8 ; wget https://www.ipa.example.com/example/repo/mirror/example-bundle-${distro}.repo -O /etc/yum.repos.d/example-bundle-${distro}.repo && grep -oP "(?<=^\[).*(?=-example])" /etc/yum.repos.d/example-bundle-${distro}.repo | while read thisrepo; do yum-config-manager --disable "${thisrepo}"; done # NONE TO REMOVE dnf -y remove dnfdragora ; yum clean all ; yum update -y ; # Remove graphical boot and add serial console sed -i -r -e '/^GRUB_CMDLINE_LINUX=/{s/(\s*)(rhgb|quiet)\s*/\1/g;};' -e '/^GRUB_CMDLINE_LINUX=/{s/(\s*)\"$/ console=ttyS0 console=tty1\"/;}' /etc/default/grub grub2-mkconfig > /boot/grub2/grub.cfg

   # postfix is already started by default on centos8
   # Send IP address to myself
   thisip="$( ifconfig 2>/dev/null | awk '/Bcast|broadcast/{print $2}' | tr -cd '[^0-9\.\n]' | head -n1 )"
      echo "${SERVER} has IP ${thisip}."
      echo "system finished kickstart at $( date "+%Y-%m-%d %T" )";
   } | /usr/share/bgscripts/send.sh -f "root@$( hostname --fqdn )" \
      -h -s "${SERVER} is ${thisip}" $( cat /root/notifyemail.txt 2>/dev/null )

   # No changes to graphical boot

   # fix the mkhomedir problem
   systemctl enable oddjobd.service && systemctl start oddjobd.service

   # Personal customizations
   mkdir -p /mnt/bgstack15 /mnt/public
   su bgstack15-local -c "sudo /usr/share/bgconf/bgconf.py"

) >> /root/install.log 2>&1

@^minimal install

Script plus a zipped datum

I was inspired by some vendor script that started off with a shell script and had a bunch of binary content at the end. I was looking for binary files on a filesystem and was investigating. At the top of the script was the message, “You are probably here because of the scary-looking binary contents at the bottom. It is the zipped contents of the program [whatever it was].”

That script inspired me to write my own script for storing and using data on demand that is slightly obscured from casual users. In this case, the script merely prints out a message. It has very limited use cases, but it was amusing to research and use for the one instance so far.

See the source at my gitlab.

#!/usr/bin/env sh
# Filename: store-crypted.sh.in
# License: CC-BY-SA 4.0
# Author: bgstack15
# Startdate: 2019-08-28 08:00
# Title: Script Plus A Zipped Datum (spazd)
# Purpose: Script that stores a zip file at the end of this file, to obscurely and insecurely store a simple value
# History:
# Usage:
#    create crypted object:
#       printf '%s' "CUSTOMVALUE" | bzip2 > ~/foo3
#    learn value for "mysize" and update script
#       wc -c ~/foo3
#    remove comments from this input file and build final script
#       cat store-crypted.sh.in ~/foo3 > final.sh ; rm ~/foo3
# Reference:
#    various installer tarball/script combos from different vendors
#    original research
# Improve:
# Documentation:

cat="$( printf '\x62\x75\x6e\x7a\x69\x70\x32' )"
tail -c${mysize} "${0}" | $cat | cat
printf '\r\n'


All packages in my copr are CentOS 8-ready

I have confirmed that all the packages in my COPR have compiled for CentOS 8! I personally only have a single headless vm for CentOS 8 so the applications might malfunction. Please report to me if any failures occur.

Backstory time

When CentOS 8 was finally released (September 24), I downloaded it right away and updated my kickstart process for it (future post).

Some packages built just fine right away, on the rhel8beta repo. Some failed because they use ImageMagick which wasn’t compiled yet, but has since been added. I use the “convert” utility like a lot of packagers do, for converting an svg to instantiated png files for icons. Anyway, I was considering rewriting my scripts to use GraphicsMagick but thankfully upstream added ImageMagick, which reduced my workload considerably.

Some packages failed because various libraries were unavailable, and were still unavailable. Using one of my preferred upstreams (city-fan) and rebuilding some Fedora packages, I added libraries necessary to compile the rest of my packages.

It is worth noting that CentOS 8 uses dnf modules or “streams.” I don’t fully understand the concept, and personally think it only causes problems. I had to compile curl-7.66.0 and host it myself, because of which repositories I had to enable and disable to get the right perl modules to compile it. Libcurl is required to compile FreeFileSync, and various unimportant perl modules are required to compile libcurl. However, due to the modules in dnf/yum, there is a conflict between certain latest perl packages in that stream, with other repositories, and I was unable to configure the COPR to take any old version of the perl modules.

Windows: Map network drives from csv

Even back in my olden days of using a non-free operating system, I was automating my tasks. The non-persistent sessions at the computer science lab required that I script my tasks. This is what I came up with for mapping network drives.

You can set a csv file with the following contents:


So it’s not a real csv file; it’s got headers delineated by “SERVER” and a server name. The script will operate on the following lines, until the next “SERVER” line. It will mount the drive letter, from the following CIFS share, using a username and password or prompting if blank, and a pretty name. It will only mount those entries, if the SERVER actually is reachable. So it fails safely if you are on a different network than the requested server at the time.

The script is available on my gitlab. And that example csv is also there.

I eventually scrapped this script when I deployed an Active Directory domain and I used group policy to define a number of mounts to define.

Devuan freeipa domain users control local devices

The Debian method of granting access to devices like the network cards, audio output, printers, etc., is to add a user to the appropriate system group. For domain users, however, do I have to add every single domain user to the local group? I have sought an answer to this problem for a long time. After a lot of research, and coming back to the problem, I finally have a solution I find acceptable for general use and for sharing.


You have to adjust pam, nsswitch, and the local groups themselves. However, no additional packages should be needed!


I did this with lightdm display manager, which calls pam. During my research, I read on one of those pages somewhere that not all DMs use pam. Just make sure yours does.
You have domain groups named netdev, plugdev, audio, etc. Making extra groups in the directory, with either nested groups or direct members, is a small price to pay for this goal!

The steps

Configure pam

You have to configure pam to include the pam_group library.

sudo touch "${tf}" ; sudo chmod 0644 "${tf}" ; sudo chown root.root "${tf}"
cat <<EOF | sudo tee "${tf}" 1>/dev/null
Name: activate /etc/security/group.conf
Default: yes
Priority: 900
Auth-Type: Primary
        required                        pam_group.so use_first_pass

And run the debian pam-auth-update program. Obviously there is not a EL equivalent, but then you can’t have this problem on a EL derivative.


And select the option that we just wrote, “Activate /etc/security/group.conf”

Configure nsswitch.conf

Change the group: line in nsswitch.conf to the following:

group:      compat [SUCCESS=merge] sss

You can accomplish that with a sed oneliner:

sed -i -r -e '/^\s*group:/s/(compat|files) sss/\1 [SUCCESS=merge] sss/;' /etc/nsswitch.conf

Change the local groups

To take advantage of the glibc group merging, you have to be using glibc 2.24 or higher, and Devuan Ceres has 2.28 so we’re good. Also, the GIDs have to match exactly. Of course your GID range will be different from mine, but I wrote a general solution.

test -z "${LOGFILE}" && LOGFILE=/root/deploy.log
for word in netdev video audio dip ;
      tgid="$( getent group -s  sss  "${word}" | awk -F':' '{print $3}' )"
      ogid="$( getent group -s files "${word}" | awk -F':' '{print $3}' )"
   } 2>/dev/null
   # if group exists locally and in domain
   test -n "${ogid}" && test -n "${tgid}" && test ${ogid} -ne ${tgid} && {
      # use sed because groupmod fails because the new GID already exists
      sed -i -r -e "/^${word}:/s/:${ogid}:/:${tgid}:/;" /etc/group
      # log to stdout and logfile
      printf '%s %s\n' "$( date -u "+%FT%TZ" )" "Change ${word} from gid ${ogid} to ${tgid}" | tee -a "${LOGFILE}"

This snippet changes the gid of the requested local groups, to match the gid of the netgroups. A reboot is required to get the updated permissions on the device special files.


Web searches

pam_group add domain user to netdev


  1. pam – Add all network users to local group for specific hosts in CentOS7 – Server Fault
  2. OpenLDAP/SSSD Automatically Add User to Local Group – Server Fault
  3. LDAPClientAuthentication – Community Help Wiki [help.ubuntu.com]
  4. Proposals/GroupMerging – glibc wiki
  5. SystemGroups – Debian Wiki
  6. My question from a few months ago Grant domain user access like he is in netdev group [linuxquestions.org]

Devuan join freeipa domain

FreeIPA is a great identity management domain for GNU/Linux systems. This post explains how to join a Devuan installation as a client to FreeIPA so that you can use centralized users, sudo policies, certificates, and everything else that is managed by freeipa.


Running Devuan Ceres

You must be running Devuan ceres (unstable) to make the freeipa packages available. To get there, you need these exact apt sources:

deb http://packages.devuan.org/merged ceres main contrib non-free
deb-src http://packages.devuan.org/merged ceres main contrib non-free

To use the packages from these repos, you should do the normal update, upgrade, and dist-upgrade. Here is my full command for an unattended upgrade.

mkdir -p ~/log ; sudo apt-get update ;
_myact() {
   sudo DEBIAN_FRONTEND=noninteractive apt-get -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-overwrite" upgrade ;
   sudo DEBIAN_FRONTEND=noninteractive apt-get -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-overwrite" dist-upgrade ;
} ;
time _myact 2>&1 | tee -a ~/log/apt-get.upgrade.$( date "+%F" ).log

After a reboot, you are ready for the next steps.

Building custom oddjob-mkhomedir

You need a custom package, because in Devuan package oddjob is banned (because of systemd dependencies). I built a dummy package, which you can install from my OBS account.
I will briefly describe the build process so you can do this in your environment. My build resources are in version control on my gitlab in two directories.

  1. Build a dummy source tarball
    mkdir -p ~/deb/oddjob-mkhomedir-0.0.1/ ; cd ~/deb/oddjob-mkhomedir ; echo "Dummy package" >> README-oddjob-mkhomedir.md
  2. Build a debian/ directory

    I modifed the debian control files to make it an all-architecture deb so I didn’t have to recompile for i686 and x86_64, but for a one-off package for yourself, don’t bother.

  3. Compile the package
    debuild -us -uc

    In the parent directory, which in my example is ~/deb, there should be the oddjob-mkhomedir_0.0.1-1_amd64.deb
    Loading it into an apt repository is beyond the scope of this conversation.

  4. Install the package
    apt-get install ~/deb/oddjob-mkhomedir_0.0.1-1_amd64.deb

Because of this fake mkhomedir package, we will have to take steps to enable the mkhomedir behavior farther ahead.

Building custom python3-ipalib

Devuan bans python-ipalib because it depends on systemd. You can get around this by changing the deb Requires: statements.

Download the released dpkg from http://ftp.us.debian.org/debian/pool/main/f/freeipa/python-ipalib_4.7.1-3_all.deb or whichever the latest is.

cd ~/Downloads
wget http://ftp.us.debian.org/debian/pool/main/f/freeipa/python-ipalib_4.7.1-3_all.deb
mkdir temp
dpkg-deb -R python-ipalib_4.7.1-3_all.deb temp

Manually fix DEBIAN/control file as needed. I used

#Depends: freeipa-common (= 4.7.1-3), gnupg2, gnupg-agent, keyutils, python-cffi, python-cryptography (>= 1.6), python-dbus, python-dnspython, python-gssapi, python-jwcrypto, python-ldap, python-libipa-hbac, python-lxml, python-netaddr, python-netifaces (>= 0.10.4), python-nss (>= 0.16.0), python-pyasn1, python-qrcode (>= 5.0.0), python-requests, python-setuptools, python-six, python-usb (>= 1.0.0~b2), python-yubico, python-pyasn1-modules, python:any (<< 2.8), python:any (>= 2.7~)
Depends: python-netaddr, python-netifaces (>= 0.10.4), python-dbus

I also customized the release number.
Reassemble the dpkg.

dpkg-deb -b temp python-ipalib_4.7.1-3+stackrpms_all.deb

Install packages and files

Install the client software.

sudo apt-get -y install freeipa-client

You will need to have a dummy file for systemctl and for hostnamectl. Some components of freeipa are hardcoded to use that. Maybe we should recompile the freeipa package for Devuan instead of just using the debian one. But that sounds way beyond my capacity. So let’s just keep hacking.

sudo touch "${tf}" ; sudo chmod 0755 "${tf}"
sudo tee "${tf}" <<EOF /dev/null

sudo touch "${tf}" ; sudo chmod 0755 "${tf}"
sudo tee "${tf}" <<EOF /dev/null

Configure freeipa client

Now we are ready to do the main work! I found that I had to disable ntp so the script could do its thing, which recently has been installing chronyd. I guess I don’t care; I just don’t want drift. I picked my battles, and ntp clients is not the battle I will fight today.

sudo service ntp stop

The script does not make a few important directories, so just make these yourself, and then run the install script.

sudo mkdir -p /etc/ipa /var/lib/ipa-client/pki
sudo ipa-client-install --hostname="$( hostname --fqdn )" --mkhomedir --configure-firefox

Of course if you don’t want those options, remove them. I think the configure-firefox step is broken anyway. I forget what it’s supposed to do; maybe load the ipa CA cert into the nss database.
I found that I always have to restart sssd after my initial client configuration. It’s a small price to pay for domain user resolution, so just do it. In this case, actually stop it and then start it.

sudo service sssd stop ; sudo service sssd start

That should be the bare minimum to get freeipa domain user auth working.

Followup and extra goodies

For the quality-of-life improvements, you need a few extra steps.

Add mkhomedir

Now is the time to add pam_mkhomedir to the pam stack.

# add pam_mkhomedir
tf=/etc/pam.d/common-session ; ! grep -q 'mkhomedir' "${tf}" && { thisline="$(( $( grep -nE 'session\s+optional' "${tf}" | head -n1 | awk -F':' '{print $1}' ) - 0 ))" ; awk -v thisline="$thisline" 'NR == (thisline) {print "session optional        pam_mkhomedir.so"; } {print;}' "${tf}" > "${tf}.2" ; test -f "${tf}.2" && mv "${tf}.2" "${tf}" ; }

This one-liner checks for the existence of the string “mkhomedir” in the common-session file and then adds the pam_mkhomedir.so lib to the pam session stack if it was absent. It cleverly sticks it at the beginning of the “session optional” section, because the order of pam statements is important. So if you have heavily customized your pam configuration, you need to be careful. This line works with a bog-standard pam config straight from the ISO. If you want to stick it in there yourself, you need this line:

session optional        pam_mkhomedir.so

Kerberos trust dns

If you want to just use short hostnames to access other systems, you need to tell kerberos to trust dns.
If you have bgscripts package installed, you can use the updateval command in a oneliner.

sudo updateval -a /etc/krb5.conf -s '[libdefaults]' '^(\s*dns_canonicalize_hostname\s*=\s*).*' '  dns_canonicalize_hostname = true'

Basically, in /etc/krb5.conf change dns_canonicalize_hostname to true.


If the install fails for any reason, before you reinstall it, you have to run ipa-client-install –uninstall. And in order for that second command to succeed, you probably have to run “certmonger” first. I don’t really know why running that allows it to uninstall, but just take it under advisement.


Original research


  1. package management – Easily unpack DEB, edit postinst, and repack DEB – Unix & Linux Stack Exchange
  2. http://ftp.us.debian.org/debian/pool/main/f/freeipa/

Run init script as SELinux type other than initrc_t

To run a custom init script as SELinux context other than initrc_t, you can use an SELinux policy that adds a new type for you to use.

# Filename: general-local.te
# License: CC-BY-SA 4.0
# Author: bgstack15
# Startdate: 2019-09-19 16:45
# Title: SELinux Policy for Custom Process Types from Init Scripts
# Purpose: SELinux policy to allow an init script to run a process as a selinux type other than initrc_t
# History:
# Usage:
#    When installed, you can run the following command to have the daemon process transition to type unconfined_t:
#    chcon -t 'local_initrc_exec_t' /etc/init.d/myscript
# Reference:
#    liberal use of tail -n45000 /var/log/audit/audit.log | audit2allow
#    https://selinuxproject.org/page/ObjectClassesPerms#filesystem
#    http://www.cse.psu.edu/~trj1/cse543-f07/slides/03-PolicyConcepts.pdf
#    http://www.billauer.co.il/selinux-policy-module-howto.html
#    https://fedoraproject.org/wiki/PackagingDrafts/SELinux#Creating_new_types
#    https://wiki.centos.org/HowTos/SELinux
#    https://bgstack15.wordpress.com/2018/02/13/logrotate-audit-log-selinux-cron-and-ansible/
# Improve:
# Documentation:
#    Change an init script to context local_initrc_exec_t and then the process will transition to unconfined_t which of course is insecure, but it satisfies the scan that is looking for daemons running as initrc_t.
module general-local 1.0;

require {
        type fs_t;
        type initrc_exec_t;
        type init_t;
        type unconfined_t;
        class file { append create entrypoint execmod execute execute_no_trans getattr ioctl link lock mounton open quotaon read relabelfrom relabelto rename setattr swapon unlink write };
        class filesystem associate;
        class process { unconfined transition };
        class service { start status };

type local_initrc_exec_t;
type_transition init_t local_initrc_exec_t:process unconfined_t ;

#============= init_t ==============
allow init_t local_initrc_exec_t:file *;
allow init_t unconfined_t:process transition;
#============= local_initrc_exec_t ==============
allow local_initrc_exec_t fs_t:filesystem associate;
#============= unconfined_t ==============
allow unconfined_t local_initrc_exec_t:file *;
allow unconfined_t local_initrc_exec_t:service { start status };

To compile and install this module, you can run the following oneliner.

checkmodule -M -m -o general_local.mod general_local.te && semodule_package -m general_local.mod -o general_local.pp && semodule -v -i general_local.pp

Should you run daemons as unconfined_t? Of course not. But it’s different than running it as initrc_t.



  1. ObjectClassesPerms – SELinux Wiki
  2. SELinux Policy Concepts and Overview: Security Policy Development Primer for Security Enhanced Linux
  3. Writing a targeted policy module for SELinux (howto tutorial slides)
  4. PackagingDrafts/SELinux – Fedora Project Wiki#Creating_new_types
  5. HowTos/SELinux – CentOS Wiki
  6. Logrotate, audit.log, selinux, cron, and ansible | Knowledge Base