#!/usr/bin/perl

## no critic (CodeLayout::ProhibitParensWithBuiltins) ;

use strict;
use warnings;
use autodie;

use File::Copy;
use File::Slurper ;
use File::Spec ;
use File::Temp ;
use Readonly ;

# Number of spaces to indent
Readonly my $INDENT => 6 ;

my $OSSEC_HOME          = '/var/ossec' ;
my $OSSEC_ETC           = File::Spec->catdir(($OSSEC_HOME, 'etc'));
my $OSSEC_FRAGMENTS_DIR = File::Spec->catdir(($OSSEC_ETC,  'fragments'));
my $OSSEC_CONF          = File::Spec->catfile(($OSSEC_ETC), 'ossec.conf');
my $OSSEC_CONF_TEMPLATE = File::Spec->catfile(($OSSEC_ETC), 'ossec.conf.template');

# Step 1. Concatenate all the fragment files into a single string.
opendir(my $DIR, $OSSEC_FRAGMENTS_DIR) ;
my @fragment_files = readdir($DIR) ;
closedir $DIR ;

my $combined_fragments = q{} ;
foreach my $fragment_file (sort @fragment_files) {
    # Skip the '.' and '..' directories.
    if ($fragment_file !~ m{^[.]{1,2}$}xsm) {
        my $cur_path = File::Spec->catfile(($OSSEC_FRAGMENTS_DIR, $fragment_file)) ;
        $combined_fragments .= File::Slurper::read_text($cur_path) ;
    }
}

# Step 2. Indent the fragments
my $spacer         = q{ } x $INDENT ;
my @lines          = split(/\n/xsm, $combined_fragments) ;
my @lines_indented = map { $spacer . $_ } @lines ;

my $combined_fragments_indented = join("\n", @lines_indented) ;

# Step 3. Insert this string into the ossec.conf template file.
my $new_ossec = File::Temp->new()->filename ;

open(my $INFH,  q{<}, $OSSEC_CONF_TEMPLATE) ;
open(my $OUTFH, q{>}, $new_ossec) ;

while (my $line = <$INFH>) {
  $line =~ s{%%COMBINED_CONF_FILE%%}{$combined_fragments_indented}xsm ;
  print {$OUTFH} $line ;
}
close($INFH) ;
close($OUTFH) ;

# Step 4. Copy the new ossec.conf into place.
File::Copy::copy($new_ossec, $OSSEC_CONF) ;

# Step 5. Clean up
unlink $new_ossec ;

exit 0 ;

__END__

=head1 NAME

merge-ossec-fragments - Merge the OSSEC configuration file with syscheck fragments

=head1 USAGE

merge-ossec-fragments

=head1 DESCRIPTION

B<merge-ossec-fragments> merges all the OSSEC syscheck fragments in
F</var/ossec/etc/fragments/> with the template file
F</var/ossec/etc/ossec.conf.template> and writes the output to
F</var/ossec/etc/ossec.conf>.

This script is meant to be used along with the Puppet module B<su_ossec> which
manages the OSSEC syscheck fragments and the ossec.conf template file.

=head1 REQUIRED ARGUMENTS

None.

=head1 OPTIONS

None.

=head1 EXIT STATUS

The script will exit with 0 if the script completes and there were no
failures, 1 for any other reason.

=head1 DEPENDENCIES

L<File::Copy|File::Copy>,
L<File::Slurper|File::Slurper>,
L<File::Spec|File::Spec>,
L<File::Temp|File::Temp>,
L<Readonly|Readonly>

=head1 INCOMPATIBILITIES

No known incompatibilities.

=head1 BUGS AND LIMITATIONS

None known.

=head1 DIAGNOSTICS

None.

=head1 CONFIGURATION

No configuration.

=head1 AUTHOR

Adam Lewenberg <adamhl@stanford.edu>

=head1 LICENSE AND COPYRIGHT

Copyright 2019 The Board of Trustees of the Leland Stanford Junior
University.  All rights reserved.

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Stanford University not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission.  Stanford University makes no
representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.

THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

=cut

#############################################################################
#############################################################################
