amt has asked for the wisdom of the Perl Monks concerning the following question:

The saga continues...

Now that the file propagation has be solved from the previous thread, FreeRadius Config Propagation, I now need to provide some sanity checking for the interface.

Although, the application I am developing provides a front end for Free Radius user and client configurations, there may be time when the remote file has been changed directly by a privileged user. Although, not foreseeable, this situation is...well, foreseeable, and reasonable steps must be taken to prevent my boss' quick and dirty changes getting fried by a help desk tech >>eek!<<

Is there a module that provides a simple solution to this? Is there a way that this module does not need to suck the remote file down the wire to get it's {cma}times?

Thanks in advance,
amt.

perlcheat

Replies are listed 'Best First'.
Re: FR Config Sanity Checking
by hsinclai (Deacon) on Oct 04, 2004 at 19:28 UTC
    You could use stat (FUNCTION RETURN LISTS in perlcheat:) remotely through the ssh interface you've already got in place, or md5 checksum the config file(s) every time your app runs, or keep them in a local cvs
      Excellent, time to brush up on commandline perl! The problem would be exporting the information out of exec or system. How would I go about doing that, with > or |?

      system(/usr/bin/ssh HOST_ABC \"perl "open(FILE,\">>file\"; stat(FILE)[ +9] > $local_var"); print $local_var;

      ???
      amt.

      perlcheat
        I think what you need, is best done from your originating server, by sending a command that will execute remotely, to check the last modification time of $remotefile

        #!/usr/bin/perl -w use strict; my $remotefile = '/tmp/yourfile.conf'; my $remotestat = qx! ssh -2 -p 12345 172.16.16.82 'perl -e "print ((stat(qq~$remotef +ile~))[9])" ' !; print "\n$remotestat \n"; print "\n", scalar localtime($remotestat), "\n\n";
        If your ssh setup is working properly, this should return the value you need from the remote server. You might then keep a comparison table locally so if you determine the file was edited by someone other than your script you could then act accordingly..

        I would just like to add though, that planning the whole thing architecturally - diagram it! - before writing the app will ultimately save you time.. then the code writing will become the final task. It will also be easier to document, and explain to users, management, etc

        It also seems to me that to make your app a little closer to bulletproof you should consider keeping versioned backups of the remote files -- having multiple users jumping in to edit a single file at will with no change control or revisioning is kinda crazy.

      hsinclai, this is the beginning of my "taint" function, I think I don't have the same types of scalars for $remotestat and the stat the i get back from the local stat.

      sub is_config_new { my $fn = shift; my %hosts = { '192.168.1.243' => 0 }; my ($host,$taint); # Probe remote hosts for freshness foreach $host (keys %hosts){ my $remotestat = qx! sudo ssh $host 'perl -e "print (( +stat(qq~$fn~))[9]);"'!; if( $remotestat != ((stat(qq~$fn~))[9]) ) { $hosts{$host} = 0; } else { $hosts{$host} = 1; + } } foreach $host (keys %hosts) { if( !$hosts{$host} ) { $taint = +1; } } if( $taint == 1 ) { # print a conflict page } else { return; } # return to proceed with config


      Also when the conflict page is written, it's outputting the memory value for the hash (HASH0x...), that code section is this:

      foreach $host (keys %hosts){ print "<tr><td>$host</td>"; if ( $hosts{$host} ) { print "<td align=center><img src=/nagios/image +s/greendot2.gif border=0></td></tr>"; } else {print "<td align=center><img src=/nagios/image +s/reddot.gif border=0></td></tr>"; } }
      amt.

      perlcheat
        Double check $fn is what you think it is..

        In your second question, the data structure is not what you think it is.. probably you have to dereference it to find out what is in
        hash (HASH0x...)
        Better yet use Data::Dumper here.. it'll show you what you've got.