App-Yabsm
view release on metacpan or search on metacpan
lib/App/Yabsm/Command/Daemon.pm view on Meta::CPAN
sub yabsmd_init {
# Subcommand to allow user to yabsmd's runtime environment without having to
# start yabsmd.
arg_count_or_die(0, 0, @_);
die 'yabsm: error: permission denied'."\n" unless i_am_root();
my $config_ref = parse_config_or_die();
initialize_yabsmd_runtime_environment(0, 0, $config_ref);
say 'all good';
}
####################################
# HELPERS #
####################################
sub initialize_yabsmd_runtime_environment {
# Initialize yabsmd's runtime environment:
#
# * Install the signal handlers that remove the PID file before exiting
# * Create dirs needed for performing snaps, ssh_backups, and local_backups
# * Create the yabsm user and group if they don't already exists
# * If $create_log_file, create /var/log/yabsm if it does not exist and chown it to yabsm:yabsm
# * If $create_pid_file, create the (empty) file /run/yabsmd.pid and chown it to yabsm:yabsm
# * Create the yabsm users SSH keys if they don't already exist
# * Set this processes UID and GID to yabsm:yabsm
arg_count_or_die(3, 3, @_);
my $create_log_file = shift;
my $create_pid_file = shift;
my $config_ref = shift;
i_am_root_or_die();
have_prerequisites_or_die();
install_signal_handlers();
create_yabsmd_runtime_dirs($config_ref);
my ($yabsm_uid, $yabsm_gid) = create_yabsm_user_and_group($config_ref);
open my $sudoer_fh, '>', '/etc/sudoers.d/yabsm-btrfs'
or die "yabsm: error: cannot open '/etc/sudoers.d/yabsm-btrfs' for writing";
my $btrfs_bin = `which btrfs 2>/dev/null`;
print $sudoer_fh "yabsm ALL=(root) NOPASSWD: $btrfs_bin";
close $sudoer_fh;
if ($create_log_file) {
open my $log_fh, '>>', '/var/log/yabsm'
or confess q(yabsm: internal error: cannot open file '/var/log/yabsm' for writing);
close $log_fh;
chown $yabsm_uid, $yabsm_gid, '/var/log/yabsm';
chmod 0644, '/var/log/yabsm';
}
if ($create_pid_file) {
open my $pid_fh, '>', '/run/yabsmd.pid'
or confess q(yabsm: internal error: cannot not open file '/run/yabsmd.pid' for writing);
close $pid_fh;
chown $yabsm_uid, $yabsm_gid, '/run/yabsmd.pid';
chmod 0644, '/run/yabsmd.pid';
}
POSIX::setgid($yabsm_gid);
POSIX::setuid($yabsm_uid);
create_yabsm_user_ssh_key(0, $config_ref);
return 1;
}
sub create_cron_scheduler {
# Return a Schedule::Cron object that schedules every snap, ssh_backup, and
# local_backup that is defined in the users config.
arg_count_or_die(1, 1, @_);
my $config_ref = shift;
my $cron_scheduler = Schedule::Cron->new(
sub { confess("yabsm: internal error: default Schedule::Cron dispatcher was invoked") },
processprefix => 'yabsmd'
);
for my $snap (all_snaps($config_ref)) {
if (snap_wants_timeframe($snap, '5minute', $config_ref)) {
$cron_scheduler->add_entry(
'*/5 * * * *',
sub { with_error_catch_log(\&App::Yabsm::Snap::do_snap, $snap, '5minute', $config_ref) }
);
}
if (snap_wants_timeframe($snap, 'hourly', $config_ref)) {
$cron_scheduler->add_entry(
'0 */1 * * *',
sub { with_error_catch_log(\&App::Yabsm::Snap::do_snap, $snap, 'hourly', $config_ref) }
);
}
if (snap_wants_timeframe($snap, 'daily', $config_ref)) {
for my $time (snap_daily_times($snap, $config_ref)) {
my $hr = time_hour($time);
my $min = time_minute($time);
$cron_scheduler->add_entry(
"$min $hr * * *",
sub { with_error_catch_log(\&App::Yabsm::Snap::do_snap, $snap, 'daily', $config_ref) }
);
}
}
if (snap_wants_timeframe($snap, 'weekly', $config_ref)) {
my $time = snap_weekly_time($snap, $config_ref);
my $hr = time_hour($time);
my $min = time_minute($time);
my $day = weekday_number(snap_weekly_day($snap, $config_ref));
$cron_scheduler->add_entry(
"$min $hr * * $day",
sub { with_error_catch_log(\&App::Yabsm::Snap::do_snap, $snap, 'weekly', $config_ref) }
);
}
if (snap_wants_timeframe($snap, 'monthly', $config_ref)) {
my $time = snap_monthly_time($snap, $config_ref);
my $hr = time_hour($time);
lib/App/Yabsm/Command/Daemon.pm view on Meta::CPAN
$SIG{ABRT} = $cleanup_and_exit;
$SIG{ALRM} = $cleanup_and_exit;
$SIG{BUS} = $cleanup_and_exit;
$SIG{FPE} = $cleanup_and_exit;
$SIG{ILL} = $cleanup_and_exit;
$SIG{INT} = $cleanup_and_exit;
$SIG{IO} = $cleanup_and_exit;
$SIG{KILL} = $cleanup_and_exit;
$SIG{PIPE} = $cleanup_and_exit;
$SIG{PROF} = $cleanup_and_exit;
$SIG{PWR} = $cleanup_and_exit;
$SIG{QUIT} = $cleanup_and_exit;
$SIG{SEGV} = $cleanup_and_exit;
$SIG{STKFLT} = $cleanup_and_exit;
$SIG{SYS} = $cleanup_and_exit;
$SIG{TERM} = $cleanup_and_exit;
$SIG{TRAP} = $cleanup_and_exit;
$SIG{USR1} = $cleanup_and_exit;
$SIG{USR2} = $cleanup_and_exit;
$SIG{VTALRM} = $cleanup_and_exit;
$SIG{XCPU} = $cleanup_and_exit;
$SIG{XFSZ} = $cleanup_and_exit;
}
sub create_yabsm_user_ssh_key {
# Create an SSH key for the yabsm user if one doesn't already exist. This
# function dies unless the processes ruid and rgid are that of the yabsm user
# and group.
#
# If the $force value is false then only create the key if the users
# configuration defines at least one ssh_backup, and if it is true then
# create the key even if no ssh_backup's are defined.
arg_count_or_die(2, 2, @_);
my $force = shift;
my $config_ref = shift;
if ($force || all_ssh_backups($config_ref)) {
my $yabsm_uid = getpwnam('yabsm') or confess(q(yabsm: internal error: cannot find user named 'yabsm'));
my $yabsm_gid = getgrnam('yabsm') or confess(q(yabsm: internal error: cannot find group named 'yabsm'));
unless (POSIX::getuid() == $yabsm_uid && POSIX::getgid() == $yabsm_gid) {
my $username = getpwuid POSIX::getuid();
my $groupname = getgrgid POSIX::getgid();
confess "yabsm: internal error: expected to be running as user and group yabsm but instead running as user '$username' and group '$groupname'";
}
my $yabsm_user_home = yabsm_user_home($config_ref);
my $ssh_dir = "$yabsm_user_home/.ssh";
my $priv_key = "$ssh_dir/id_ed25519";
my $pub_key = "$ssh_dir/id_ed25519.pub";
unless (-f $priv_key && -f $pub_key) {
system_or_die('ssh-keygen', '-t', 'ed25519', '-f', $priv_key, '-N', '');
chown $yabsm_uid, $yabsm_gid, $priv_key, $pub_key;
chmod 0600, $priv_key;
chmod 0644, $pub_key;
}
return 1;
}
return 0;
}
sub add_yabsm_user_btrfs_sudoer_rule {
# Add sudoer rule to '/etc/sudoers.d/yabsm-btrfs' to grant the 'yabsm' user
# sudo access to btrfs-progs.
arg_count_or_die(0, 0, @_);
i_am_root_or_die();
my $file = '/etc/sudoers.d/yabsm-btrfs';
unless (-f $file) {
my $btrfs_bin = `which btrfs 2>/dev/null`
or confess('yabsm: internal error: btrfs-progs not in root users path');
my $sudoer_rule = "yabsm ALL=(root) NOPASSWD $btrfs_bin";
open my $fh, '>', $file
or confess("yabsm: internal error: could not open '$file' for writing");
print $fh $sudoer_rule;
close $fh
}
return $file;
}
sub create_yabsm_user_and_group {
# Create a locked-user and group named 'yabsm' if they do not already exist.
arg_count_or_die(1, 1, @_);
my $config_ref = shift;
i_am_root_or_die();
unless (yabsm_user_exists()) {
system_or_die('useradd', '-m', '-d', yabsm_user_home($config_ref), '-s', '/bin/sh', '-k', '/dev/null', 'yabsm');
system_or_die('passwd', '--lock', 'yabsm');
}
unless (yabsm_group_exists()) {
system_or_die('groupadd', 'yabsm');
}
# The yabsm users home dir must be reinitialized in case the user changed
# their yabsm_dir since the last time we ran the daemon.
system_or_die('usermod', '-m', '-d', yabsm_user_home($config_ref), 'yabsm');
my $yabsm_uid = getpwnam('yabsm');
( run in 0.477 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )