* Add flag ignore_errors to allow uninterrupted fragment deployment
* Other minor updates
This commit is contained in:
parent
813315bc4f
commit
78d2d6aff1
@ -2,9 +2,8 @@
|
||||
|
||||
## What's new
|
||||
|
||||
:loudspeaker: **30/12/2020**:
|
||||
* added support for SELinux (CentOS/RHEL 8.x)
|
||||
* various fixes
|
||||
:loudspeaker: **27/04/2025**:
|
||||
* added the `ignore_errors` flag to allow uninterrupted deployment of fragements.
|
||||
|
||||
## About
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#******************************************************************************
|
||||
# @(#) manage_sudo.sh
|
||||
#******************************************************************************
|
||||
# @(#) Copyright (C) 2014 by KUDOS BVBA (info@kudos.be). All rights reserved.
|
||||
# @(#) Copyright (C) 2014 by KUDOS BV (info@kudos.be). All rights reserved.
|
||||
#
|
||||
# This program is a free software; you can redistribute it and/or modify
|
||||
# it under the same terms of the GNU General Public License as published by
|
||||
@ -42,7 +42,7 @@
|
||||
# or LOCAL_CONFIG_FILE instead
|
||||
|
||||
# define the version (YYYY-MM-DD)
|
||||
typeset -r SCRIPT_VERSION="2021-06-17"
|
||||
typeset -r SCRIPT_VERSION="2025-04-27"
|
||||
# name of the global configuration file (script)
|
||||
typeset -r GLOBAL_CONFIG_FILE="manage_sudo.conf"
|
||||
# name of the local configuration file (script)
|
||||
@ -585,7 +585,7 @@ function display_usage
|
||||
cat << EOT
|
||||
|
||||
**** ${SCRIPT_NAME} ****
|
||||
**** (c) KUDOS BVBA - Patrick Van der Veken ****
|
||||
**** (c) KUDOS BV - Patrick Van der Veken ****
|
||||
|
||||
Performs basic functions for SUDO controls: update SUDOers files locally or
|
||||
remote, validate SUDO syntax or copy/distribute the SUDO controls files
|
||||
|
@ -12,6 +12,9 @@
|
||||
# use short hostnames or FQDN (0=short names; 1=FQDN) [default: 0]
|
||||
use_fqdn=1
|
||||
|
||||
# ignore errors during fragment deployment (0=no; 1=yes [default: 0])
|
||||
ignore_errors=0
|
||||
|
||||
# target directory for sudo fragment files
|
||||
fragments_dir=/etc/sudo_controls/sudoers.d
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#******************************************************************************
|
||||
# @(#) update_sudo.pl
|
||||
#******************************************************************************
|
||||
# @(#) Copyright (C) 2014 by KUDOS BVBA <info@kudos.be>. All rights reserved.
|
||||
# @(#) Copyright (C) 2014 by KUDOS BV <info@kudos.be>. All rights reserved.
|
||||
#
|
||||
# This program is a free software; you can redistribute it and/or modify
|
||||
# it under the same terms of the GNU General Public License as published by
|
||||
@ -44,7 +44,7 @@ use File::Temp qw(tempfile);
|
||||
|
||||
# ------------------------- CONFIGURATION starts here -------------------------
|
||||
# define the version (YYYY-MM-DD)
|
||||
my $script_version = "2020-12-30";
|
||||
my $script_version = "2025-04-27";
|
||||
# name of global configuration file (no path, must be located in the script directory)
|
||||
my $global_config_file = "update_sudo.conf";
|
||||
# name of localized configuration file (no path, must be located in the script directory)
|
||||
@ -55,7 +55,7 @@ my $max_recursion = 5;
|
||||
my $selinux_context = "etc_t";
|
||||
# ------------------------- CONFIGURATION ends here ---------------------------
|
||||
# initialize variables
|
||||
my ($debug, $verbose, $preview, $global, $use_fqdn) = (0,0,0,0,0);
|
||||
my ($debug, $verbose, $preview, $global, $use_fqdn, $ignore_errors) = (0,0,0,0,0,0);
|
||||
my (@config_files, $fragments_dir, $visudo_bin, $immutable_self_file, $immutable_self_cmd);
|
||||
my (%options, @uname, %aliases, %frags, @grants);
|
||||
my ($os, $host, $hostname, $run_dir);
|
||||
@ -89,7 +89,7 @@ sub parse_config_file {
|
||||
my $config_file = shift;
|
||||
|
||||
unless (open (CONF_FD, "<", $config_file)) {
|
||||
do_log ("ERROR: failed to open the configuration file ${config_file} [$! $hostname]")
|
||||
do_log ("ERROR: failed to open the configuration file ${config_file} [$!/$hostname]")
|
||||
and exit (1);
|
||||
}
|
||||
while (<CONF_FD>) {
|
||||
@ -102,6 +102,10 @@ sub parse_config_file {
|
||||
$use_fqdn = $1;
|
||||
do_log ("DEBUG: picking up setting: use_fqdn=${use_fqdn}");
|
||||
}
|
||||
if (/^\s*ignore_errors\s*=\s*(0|1)\s*$/) {
|
||||
$ignore_errors = $1;
|
||||
do_log ("DEBUG: picking up setting: ignore_errors=${ignore_errors}");
|
||||
}
|
||||
if (/^\s*fragments_dir\s*=\s*([0-9A-Za-z_\-\.\/~]+)\s*$/) {
|
||||
$fragments_dir = $1;
|
||||
do_log ("DEBUG: picking up setting: fragments_dir=${fragments_dir}");
|
||||
@ -156,12 +160,24 @@ sub set_file {
|
||||
|
||||
my ($file, $perm, $uid, $gid) = @_;
|
||||
|
||||
chmod ($perm, "$file")
|
||||
or do_log ("ERROR: cannot set permissions on $file [$! $hostname]")
|
||||
and exit (1);
|
||||
chown ($uid, $gid, "$file")
|
||||
or do_log ("ERROR: cannot set ownerships on $file [$! $hostname]")
|
||||
and exit (1);
|
||||
my $rc = chmod ($perm, "$file");
|
||||
if (!$rc) {
|
||||
if ($ignore_errors) {
|
||||
do_log ("ERROR: cannot set permissions on $file [$!/$hostname] -- IGNORED");
|
||||
} else {
|
||||
do_log ("ERROR: cannot set permissions on $file [$!/$hostname]");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
my $rc = chown ($uid, $gid, "$file");
|
||||
if (!$rc) {
|
||||
if ($ignore_errors) {
|
||||
do_log ("ERROR: cannot set ownerships on $file [$!/$hostname] -- IGNORED");
|
||||
} else {
|
||||
do_log ("ERROR: cannot set ownerships on $file [$!/$hostname]");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
@ -182,6 +198,7 @@ if ( @ARGV > 0 ) {
|
||||
debug|d
|
||||
help|h|?
|
||||
global|g
|
||||
ignore|i
|
||||
preview|p
|
||||
verbose|v
|
||||
version|V
|
||||
@ -204,6 +221,10 @@ if ($options{'help'}) {
|
||||
if ($options{'global'}) {
|
||||
$global = 1;
|
||||
}
|
||||
# check ignore parameter
|
||||
if ($options{'ignore'}) {
|
||||
$ignore_errors = 1;
|
||||
}
|
||||
# check preview parameter
|
||||
if ($options{'preview'}) {
|
||||
$preview = 1;
|
||||
@ -292,7 +313,7 @@ do_log ("INFO: runtime info: ".getpwuid ($<)."; ${hostname}\@${run_dir}; Perl v$
|
||||
do_log ("INFO: reading 'alias' file ...");
|
||||
|
||||
open (ALIASES, "<", "${run_dir}/alias")
|
||||
or do_log ("ERROR: cannot read 'alias' file [$! $hostname]") and exit (1);
|
||||
or do_log ("ERROR: cannot read 'alias' file [$!/$hostname]") and exit (1);
|
||||
while (<ALIASES>) {
|
||||
|
||||
my ($key, $value, @values);
|
||||
@ -370,7 +391,7 @@ if (-d "${run_dir}/fragments.d" && -f "${run_dir}/fragments") {
|
||||
if (-d "${run_dir}/fragments.d") {
|
||||
do_log ("INFO: local 'fragments' are stored in a DIRECTORY on $hostname");
|
||||
opendir (FRAGS_DIR, "${run_dir}/fragments.d")
|
||||
or do_log ("ERROR: cannot open 'fragments.d' directory [$! $hostname]")
|
||||
or do_log ("ERROR: cannot open 'fragments.d' directory [$!/$hostname]")
|
||||
and exit (1);
|
||||
while (my $frag_file = readdir (FRAGS_DIR)) {
|
||||
next if ($frag_file =~ /^\./);
|
||||
@ -388,7 +409,7 @@ if (-d "${run_dir}/fragments.d") {
|
||||
# process 'fragments' files
|
||||
foreach my $frag_file (@frag_files) {
|
||||
open (FRAGS, "<", $frag_file)
|
||||
or do_log ("ERROR: cannot read 'fragments' file [$! $hostname]")
|
||||
or do_log ("ERROR: cannot read 'fragments' file [$!/$hostname]")
|
||||
and exit (1);
|
||||
do_log ("INFO: reading SUDO fragments from file: $frag_file");
|
||||
|
||||
@ -482,7 +503,7 @@ if ($? == 0) {
|
||||
do_log ("INFO: reading 'grants' file ...");
|
||||
|
||||
open (GRANTS, "<", "${run_dir}/grants")
|
||||
or do_log ("ERROR: cannot read 'grants' file [$! $hostname]") and exit (1);
|
||||
or do_log ("ERROR: cannot read 'grants' file [$!/$hostname]") and exit (1);
|
||||
while (<GRANTS>) {
|
||||
|
||||
my ($what, $where, @what, @where);
|
||||
@ -523,7 +544,7 @@ print Dumper(\@grants) if $debug;
|
||||
if ($preview && $global) {
|
||||
|
||||
open (GRANTS, "<", "${run_dir}/grants")
|
||||
or do_log ("ERROR: cannot read 'grants' file [$! $hostname]") and exit (1);
|
||||
or do_log ("ERROR: cannot read 'grants' file [$!/$hostname]") and exit (1);
|
||||
while (<GRANTS>) {
|
||||
|
||||
my ($what, $where, @what, @where);
|
||||
@ -574,7 +595,7 @@ unless ($preview) {
|
||||
|
||||
# remove previous fragment files first
|
||||
opendir (FRAGS_DIR, "${fragments_dir}")
|
||||
or do_log ("ERROR: cannot open ${fragments_dir} directory [$! $hostname]")
|
||||
or do_log ("ERROR: cannot open ${fragments_dir} directory [$!/$hostname]")
|
||||
and exit (1);
|
||||
while (my $frag_file = readdir (FRAGS_DIR)) {
|
||||
next if ($frag_file =~ /^\./ or $frag_file eq $immutable_self_file);
|
||||
@ -587,7 +608,7 @@ while (my $frag_file = readdir (FRAGS_DIR)) {
|
||||
if (unlink ($frag_file)) {
|
||||
do_log ("INFO: de-activating fragment file $frag_file on $hostname");
|
||||
} else {
|
||||
do_log ("ERROR: cannot de-activate fragment file(s) [$! $hostname]");
|
||||
do_log ("ERROR: cannot de-activate fragment file(s) [$!/$hostname]");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -604,7 +625,7 @@ foreach my $grant (@grants) {
|
||||
|
||||
unless ($preview) {
|
||||
open (SUDO_FILE, "+>", $sudo_file)
|
||||
or do_log ("ERROR: cannot open file for writing in $fragments_dir [$! $hostname]")
|
||||
or do_log ("ERROR: cannot open file for writing in $fragments_dir [$!/$hostname]")
|
||||
and exit (1);
|
||||
}
|
||||
print SUDO_FILE "$frags{$grant}\n" unless $preview;
|
||||
@ -639,7 +660,7 @@ unless ($preview) {
|
||||
my $self_file = "$fragments_dir/$immutable_self_file";
|
||||
|
||||
open (SELF_FILE, "+>", $self_file)
|
||||
or do_log ("ERROR: cannot open file for writing in $fragments_dir [$! $hostname]")
|
||||
or do_log ("ERROR: cannot open file for writing in $fragments_dir [$!/$hostname]")
|
||||
and exit (1);
|
||||
|
||||
print SELF_FILE "# THIS IS THE IMMUTABLE SELF FRAGMENT OF SUDO CONTROLS\n";
|
||||
@ -682,6 +703,7 @@ update_sudo.pl - distributes SUDO fragments according to a desired state model.
|
||||
|
||||
update_sudo.pl [-d|--debug]
|
||||
[-h|--help]
|
||||
[-i|--ignore]
|
||||
([-p|--preview] [-g|--global])
|
||||
[-v|--verbose]
|
||||
[-V|--version]
|
||||
@ -716,6 +738,8 @@ Following settings must be configured:
|
||||
|
||||
=item * B<use_fqdn> : whether to use short or FQDN host names
|
||||
|
||||
=item * B<ignore_errors> : whether to ignore errors during fragment deployment
|
||||
|
||||
=item * B<fragments_dir> : target directory for SUDO fragments files
|
||||
|
||||
=item * B<visudo_bin> : path to the visudo tool (for sudo rules syntax checking)
|
||||
@ -736,6 +760,10 @@ S< >Be I<very> verbose during execution; show array/hash dumps.
|
||||
|
||||
S< >Show the help page.
|
||||
|
||||
=item -i | --ignore
|
||||
|
||||
S< >Ignore errors during fragment deployment.
|
||||
|
||||
=item -p | --preview
|
||||
|
||||
S< >Do not actually distribute any SUDO fragments, nor update/remove SUDO files.
|
||||
@ -766,4 +794,4 @@ S< >Show version of the script.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
(c) KUDOS BVBA, Patrick Van der Veken
|
||||
(c) KUDOS BV, Patrick Van der Veken
|
||||
|
Loading…
x
Reference in New Issue
Block a user