Files
wlan-lanforge-scripts/adjust_apache.pl
Jed Reynolds 2be72140c9 adjust_apache.pl: fixes printing more than one copy of the current management hostname
This was happening when a unit was getting moved between networks and a totally different IP was found for it

Signed-off-by: Jed Reynolds <jed@candelatech.com>
2021-04-05 17:02:48 -07:00

517 lines
18 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Carp;
use Data::Dumper;
use File::Temp qw(tempfile tempdir);
use Getopt::Long;
my $Q='"';
my $q="'";
my @idhunks = split(' ', `id`);
my @hunks = grep { /uid=/ } @idhunks;
die ("Must be root to use this")
unless( $hunks[0] eq "uid=0(root)" );
@idhunks = undef;
@hunks = undef;
my $start_time = `date +%Y%m%d-%H%M%S`;
chomp($start_time);
my $do_help = 0;
my $do_automatic = ( -t STDIN ) ? 0 : 1; # test for terminal stdin
my $debug = $ENV{'DEBUG'};
my $usage = "$0 :
Use this to update /etc/hosts and /etc/httpd/http.conf for
LANforge server operations. By default this script will backup
your /etc/hosts file to /etc/.hosts.\$date and write a new copy
to /tmp/t_hosts_\$random. It will show you the difference between
the files and prompt you to continue. When you approve it will
copy /tmp/t_hosts_\$random to /etc/hosts.
-d --debug enable debug (or use \$ set DEBUG=1)
-a --auto automatic operation mode, no prompts
-h --help this message
";
GetOptions(
"h|help" => \$do_help,
"d|debug" => \$debug,
"a|auto|automatic" => \$do_automatic,
) || die($usage);
if ($do_help) {
print $usage;
exit(0);
}
sub syslogg {
my $msg = join('\n', @_);
$msg =~ s/\r*\n/ /;
`logger -t adjust_apache "$msg"`
}
sub err {
my $msg = "[error] ".join("\n", @_);
print STDERR $msg, "\n";
syslogg($msg) if ($do_automatic);
}
sub die_err {
my $msg = "[fatal] ".join("\n", @_);
syslogg($msg) if ($do_automatic);
die($msg);
}
sub warning {
my $msg = "[warning] ".join("\n", @_);
print STDOUT $msg, "\n";
syslogg($msg) if ($do_automatic);
}
sub info {
my $msg = "[inf] ".join("\n", @_);
print STDOUT $msg, "\n";
syslogg($msg) if ($do_automatic);
}
my $MgrHostname = `cat /etc/hostname`;
chomp($MgrHostname);
info("Will be setting hostname to $MgrHostname");
sleep 3 if ($debug);
my $config_v = "/home/lanforge/config.values";
# grab the config.values file
die_err("Unable to find $config_v" )
unless ( -f $config_v);
my @configv_lines = `cat $config_v`;
die_err("Probably too little data in config.values")
unless (@configv_lines > 5);
my %configv = ();
foreach my $line (@configv_lines) {
my ($key, $val) = $line =~ /^(\S+)\s+(.*)$/;
$configv{$key} = $val;
}
die_err("Unable to parse config.values")
unless ((keys %configv) > 5);
die_err("no mgt_dev in config.values")
unless defined $configv{'mgt_dev'};
info("LANforge config states mgt_dev $configv{'mgt_dev'}");
if ( ! -d "/sys/class/net/$configv{'mgt_dev'}") {
die_err( "Please run lfconfig again with your updated mgt_port value.");
}
my $ipline = `ip -o a show $configv{"mgt_dev"}`;
my ($ip) = $ipline =~ / inet ([0-9.]+)(\/\d+)? /g;
die_err("No ip found for mgt_dev; your config.values file is out of date: $!")
unless ((defined $ip) && ($ip ne ""));
print "ip: $ip\n" if ($debug);
# This must be kept in sync with similar code in lf_kinstall.
my $found_localhost = 0;
my $fname = "/etc/hosts";
my $backup = "/etc/.hosts.$start_time";
`cp $fname $backup`;
die_err("Unable to create backup of /etc/hosts at $backup") if ( ! -f $backup );
my ($fh, $editfile) = tempfile( "t_hosts_XXXX", DIR=>'/tmp', SUFFIX=>'.txt');
if (-f "$fname") {
my @lines = `cat $fname`;
#open(FILE, ">$fname") or die "Couldn't open file: $fname for writing: $!\n\n";
my $foundit = 0;
my $i;
# chomp is way to simplistic if we need to weed out \r\n characters as well
#chomp(@lines);
for (my $i = 0; $i < @lines; $i++) {
($lines[$i]) = $lines[$i] =~ /^([^\r\n]+)\r?\n$/;
}
# we want to consolidate the $ip $hostname entry for MgrHostname
my @newlines = ();
my %more_hostnames = ();
my $new_entry = "$ip ";
#my $blank = 0;
#my $was_blank = 0;
my $counter = 0;
if ((exists $ENV{"DEBUG"}) && ($ENV{"DEBUG"} eq "1")) {
$debug = 1;
}
my %host_map = (
"localhost.localdomain" => "127.0.0.1",
"localhost" => "127.0.0.1",
"localhost4.localdomain4" => "127.0.0.1",
"localhost4" => "127.0.0.1",
"localhost.localdomain" => "::1",
"localhost" => "::1",
"localhost6.loaldomain6" => "::1",
"localhost6" => "::1",
$MgrHostname => $ip,
"lanforge.localnet" => "192.168.1.101",
"lanforge.localdomain" => "192.168.1.101",
);
my %comment_map = ();
my %address_marker_map = ();
my %address_map = (
"127.0.0.1" => "localhost.localdomain localhost localhost4.localdomain4 localhost4",
"::1" => "localhost.localdomain localhost localhost6.loaldomain6 localhost6",
$ip => $MgrHostname,
"192.168.1.101" => "lanforge.localnet lanforge.localdomain",
);
if ($debug) {
print Dumper(\%address_map);
print Dumper(\%host_map);
}
my $prevname = "";
my $previp = "";
for my $ln (@lines) {
next if (!(defined $ln));
# print "\nLN[$ln]\n" if ($debug);
next if ($ln =~ /^\s*$/);
next if ($ln =~ /^\s*#/);
next if ($ln =~ /LF-HOSTAME-NEXT/); # old typo
next if ($ln =~ /LF-HOSTNAME-NEXT/);
my $comment = undef;
# print "PARSING IPv4 ln[$ln]\n" if ($debug);
if ($ln =~ /#/) {
($comment) = $ln =~ /^[^#]+(#.*)$/;
($ln) = $ln =~ /^([^#]+)\s*#/;
print "line with comment becomes [$ln]\n" if ($debug);
}
@hunks = split(/\s+/, $ln);
my $middleip = 0;
my $counter2 = -1;
my $linehasip = 0;
my $lfhostname = 0;
if ((defined $comment) && ($comment ne "")) {
$comment_map{$hunks[0]} = $comment;
}
for my $hunk (@hunks) {
# print "\n HUNK",$counter2,"-:$hunk:- " if ($debug);
$counter2++;
next if ($hunk =~ /^localhost/);
next if ($hunk =~ /^lanforge-srv$/);
next if ($hunk =~ /^lanforge\.local(domain|net)$/);
next if ($hunk =~ /^extra6?-\d+/);
if ($hunk =~ /^\s*$/) {
next;
}
if ($hunk =~ /^$ip$/) {
$linehasip++;
$lfhostname++;
}
elsif ($hunk =~ /^$MgrHostname$/) {
$lfhostname++;
$prevname = $hunk;
}
$previp = "" if (!defined($previp));
if (($hunk =~ /^127\.0\.0\.1/)
|| ($hunk =~ /^192\.168\.1\.101/)
|| ($hunk =~ /^::1$/)) {
$previp = $hunk;
$linehasip++;
}
elsif ($hunk =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
$linehasip++;
# print " IP4($hunk)" if ($debug);
if ($counter2 > 0) { # we're not first item on line
$middleip++ if ($counter2 > 0);
# print "middle" if ($debug);
}
if (!(defined $address_map{$hunk})) {
$address_map{$hunk} = "";
}
# print "+IP4" if ($debug);
if (("" ne $prevname) && ($counter2 > 0)) {
# print " hunk($hunk)prev($prevname)" if ($debug);
$address_map{$hunk} .= " $prevname"
if ($address_map{$hunk} !~ /\s*$prevname\s*/);
# $host_map{$prevname} .= " $hunk";
if ($host_map{$prevname} !~ /\b$hunk\b/) {
$host_map{$prevname} .= " $hunk";
}
}
$previp = $hunk;
}
elsif (($hunk =~ /[G-Zg-z]+\.?/) || ($hunk =~ /^[^:A-Fa-f0-9]+/)) {
# print " notIP($hunk)" if ($debug);
$prevname = $hunk;
if ($middleip) {
# print " middle($previp)" if ($debug);
$address_map{$previp} .= " $hunk"
if ($address_map{$previp} !~ /\b$hunk\b/);
$prevname = $hunk;
if ($host_map{$prevname} !~ /\b$hunk\b/) {
$host_map{$prevname} .= " $previp";
}
}
elsif ($linehasip) {
# print " prev($previp) hunk($hunk)" if ($debug);
$address_map{$previp} .= " $hunk"
if ($address_map{$previp} !~ /\s*$hunk\s*/);
if ((defined $prevname) && (exists $host_map{$prevname}) && ($host_map{$prevname} !~ /\b$hunk\b/)) {
$host_map{$hunk} .= " $previp";
}
}
elsif ($lfhostname) {
$more_hostnames{$hunk} = 1;
if ($host_map{$prevname} !~ /\b$hunk\b/) {
$host_map{$hunk} .= " $previp";
}
}
else { # strange word
if ("" eq $previp) {
print " hunk($hunk) has no IP***" if ($debug);
$more_hostnames{$hunk} = 1;
}
elsif ($address_map{$previp} !~ /\s*$hunk\s*/) {
$address_map{$previp} .= " $hunk";
if ($host_map{$prevname} !~ /\b$hunk\b/) {
$host_map{$hunk} .= " $previp";
}
}
}
}
elsif (($hunk =~ /::/)
|| ($hunk =~ /[0-9A-Fa-f]+:/)) {
# print " hunk6($hunk)" if ($debug);
$linehasip++;
if (!(defined $address_map{$hunk})) {
$address_map{$hunk} = "";
}
$previp = $hunk;
}
elsif ($address_map{$previp} !~ /\s*$hunk\s*/) {
# is hostname and not an ip
$address_map{$previp} .= " $hunk";
if ($host_map{$prevname} !~ /\b$hunk\b/) {
$host_map{$hunk} .= " $previp";
}
}
} # ~foreach hunk
} # ~foreach line
if (($host_map{$MgrHostname} !~ /^\s*$/) && ($host_map{$MgrHostname} =~ /\S+\s+\S+/)) {
print("Multiple IPs for this hostname: " . $host_map{$MgrHostname} . "\n") if ($debug);
my @iphunks = split(/\s+/, $host_map{$MgrHostname});
print "Changing $MgrHostname to $ip; hostmap: <<$host_map{$MgrHostname}>> addrmap: <<$address_map{$ip}>>\n"
if ($debug);
$host_map{$MgrHostname} = $ip;
}
for my $name (sort keys %more_hostnames) {
$address_map{$ip} .= " $name";
print "updated address_map entry: $ip -> $address_map{$ip}\n" if ($debug);
}
# this might be premature
unshift(@newlines, "192.168.1.101 " . $address_map{"192.168.1.101"});
unshift(@newlines, "127.0.0.1 " . $address_map{"127.0.0.1"});
unshift(@newlines, "::1 " . $address_map{"::1"});
my %used_addresses = ();
delete($address_map{"192.168.1.101"});
$used_addresses{"192.168.1.101"} = 1;
delete($address_map{"127.0.0.1"});
$used_addresses{"127.0.0.1"} = 1;
delete($address_map{"::1"});
$used_addresses{"::1"} = 1;
if ($debug) {
print "# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n";
print "\nAddress map\n";
print Dumper(\%address_map);
print "\nHost map\n";
print Dumper(\%host_map);
print "# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n";
sleep 2;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
# we want to maintain the original line ordering as faithfully as possible
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
for my $ln (@lines) {
$ln = "" if (!(defined $ln));
print "old[$ln]\n" if ($debug);
# if we are comments or blank lines, preserve them
next if ($ln =~ /LF-HOSTNAME-NEXT/);
next if ($ln =~ /\b$MgrHostname\b/); # skip our mgt hostname
next if ($ln =~ /^$host_map{$MgrHostname}\s+/); # line starts with present IP addr
if (($ln =~ /^\s*$/) || ($ln =~ /^\s*#/)) {
push(@newlines, $ln);
next;
}
@hunks = split(/\s+/, $ln);
if (exists $address_map{$hunks[0]}) {
if ((exists $address_marker_map{$hunks[0]})
|| (exists $used_addresses{$hunks[0]})) {
print "already printed $hunks[0]\n" if ($debug);
next;
}
my $comment = "";
if (exists $comment_map{$hunks[0]}) {
$comment = " $comment_map{$hunks[0]}";
}
push(@newlines, "$hunks[0] $address_map{$hunks[0]}$comment");
$address_marker_map{$hunks[0]} = 1;
next;
}
if (!(exists $used_addresses{$hunks[0]})) {
warning("untracked IP <<$hunks[0]>> Used addresses:");
print Dumper(\%address_marker_map) if ($debug);
print Dumper(\%used_addresses) if ($debug);
}
}
push(@newlines, "###-LF-HOSTNAME-NEXT-###");
push(@newlines, $ip . " " . $address_map{$ip});
if ($debug) {
print "# ----- new /etc/hosts ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n";
for my $ln (@newlines) {
print "$ln\n";
}
print "# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n";
sleep 5;
}
# write to /tmp/t_hosts_$random
for my $ln (@newlines) {
print $fh "$ln\n";
}
close $fh;
my $wc_edit_file = `wc -l < $editfile`;
chomp($wc_edit_file);
my $wc_orig_file = `wc -l < $backup`;
if ($wc_edit_file == 0) {
die_err("Abandoning $editfile, it was blank.");
exit(1);
}
my $there_are_diffs = `/bin/diff /etc/hosts $editfile > /dev/null && echo 0 || echo 1`;
chomp($there_are_diffs);
$there_are_diffs = int($there_are_diffs);
if (! $there_are_diffs) {
info("No difference in hosts file.");
sleep(1) if (!$do_automatic);
}
elsif (!$do_automatic) {
my $msg = "Original /etc/hosts file backed up to $backup\n"
. "The hosts file differs by " . ($wc_orig_file - $wc_edit_file) . "lines, at: $editfile\n"
. "Displaying difference...\n";
info($msg);
sleep(2);
my $diffcmd = "diff -y /etc/hosts $editfile";
if ( -x "/usr/bin/colordiff" ) {
$diffcmd = "colordiff -y /etc/hosts $editfile";
}
open(my $diff_in, "-|", $diffcmd);
my ($diff_out, $diff_file) = tempfile( "diff_hosts_XXXX", DIR=>"/tmp" );
my @diff_lines = <$diff_in>;
close($diff_in);
print $diff_out join("", @diff_lines);
close($diff_out);
system("/bin/less -Nr $diff_file");
print "/bin/less -dNr $diff_file\n" if ($debug);
# prompt to exit
print "Press Enter to continue, [ctrl-c] to quit >";
my $i = <STDIN>;
}
if ($there_are_diffs) {
warning("Line comparison: $backup\: $wc_orig_file, $editfile\: $wc_edit_file");
warning("Installing new hosts file from $editfile, backup at $backup");
system("cp $editfile /etc/hosts");
}
} # ~if found hosts file
my $local_crt ="";
my $local_key ="";
my $hostname_crt ="";
my $hostname_key ="";
# check for hostname shaped cert files
if (-f "/etc/pki/tls/certs/localhost.crt") {
$local_crt = "/etc/pki/tls/certs/localhost.crt";
}
if (-f "/etc/pki/tls/private/localhost.key") {
$local_key = "/etc/pki/tls/private/localhost.key";
}
if (-f "/etc/pki/tls/certs/$MgrHostname.crt") {
$hostname_crt = "/etc/pki/tls/certs/$MgrHostname.crt";
}
if (-f "/etc/pki/tls/private/$MgrHostname.key") {
$hostname_key = "/etc/pki/tls/private/$MgrHostname.key";
}
# grab the 0000-default.conf file
my @places_to_check = (
"/etc/apache2/apache2.conf",
"/etc/apache2/ports.conf",
"/etc/apache2/sites-available/000-default.conf",
"/etc/apache2/sites-available/0000-default.conf",
"/etc/httpd/conf/http.conf",
"/etc/httpd/conf/httpd.conf",
"/etc/httpd/conf.d/ssl.conf",
"/etc/httpd/conf.d/00-ServerName.conf",
);
foreach my $file (@places_to_check) {
if (-f $file) {
print "Checking $file...\n";
my @lines = `cat $file`;
chomp @lines;
# we want to match Listen 80$ or Listen 443 https$
# we want to replace with Listen lanforge-mgr:80$ or Listen lanforge-mgr:443 https$
@hunks = grep {/^\s*(Listen|SSLCertificate)/} @lines;
if (@hunks) {
my $edited = 0;
my @newlines = ();
@hunks = (@hunks, "\n");
print "Something to change in $file\n";
print "These lines are interesting:\n";
print join("\n", @hunks);
foreach my $confline (@lines) {
if ($confline =~ /^\s*Listen\s+(?:80|443) */) {
$confline =~ s/Listen /Listen ${MgrHostname}:/;
print "$confline\n";
}
elsif ($confline =~ /^\s*Listen\s+(?:[^:]+:(80|443)) */) {
$confline =~ s/Listen [^:]+:/Listen ${MgrHostname}:/;
print "$confline\n";
}
if ($confline =~ /^\s*SSLCertificateFile /) {
$confline = "SSLCertificateFile $hostname_crt" if ("" ne $hostname_crt);
}
if ($confline =~ /^\s*SSLCertificateKeyFile /) {
$confline = "SSLCertificateKeyFile $hostname_key" if ("" ne $hostname_key);
}
push @newlines, $confline;
$edited++ if ($confline =~ /# modified by lanforge/);
}
push(@newlines, "# modified by lanforge\n") if ($edited == 0);
my $fh;
die($!) unless open($fh, ">", $file);
print $fh join("\n", @newlines);
close $fh;
}
else {
print "Nothing looking like [Listen 80|443] in $file\n";
}
}
} # ~for places_to_check
if (-d "/etc/httpd/conf.d") {
die($!) unless open(FILE, ">", "/etc/httpd/conf.d/00-ServerName.conf");
print FILE "ServerName $MgrHostname\n";
#print FILE "Listen $MgrHostname:80\n";
#print FILE "Listen $MgrHostname:443\n";
close FILE;
}
#