Perl Net::SSH::Any with Key Exchange - perl

I need to be able to use Perl to determine the version of python running on remote servers which I have key exchanges with. To try to accomplish this, I've been using Net::SSH::Any but want to use a key exchange instead of specifying the password in the script. I've looked at cpan's example which specifies the password.
The following is a snippet from my Perl code, which I'm trying to determine if python 2.6 is installed on the remote server.
my $ssh = Net::SSH::Any->new( $curIP, 'root' );
my #out = $ssh->capture("python -V");
my $outSize = #out;
my $ver26 = 0;
for ( my $j = 0; $j < $outSize; $j++ ) {
if ( index( $out[$j], "2.6." ) != -1 ) {
$ver26 = 1;
}
}
When I run this, it complains and says a host needs to be specified:
mandatory parameter host missing at ./GenerateConfig.pl line 162
I modified the code to look similar to how this is done in a different post (How can I FTP a file with an SSH key instead of a password, in Perl?) but it also fails:
my $ssh = Net::SSH::Any->new( $curIP, {'root'} );
my #out = $ssh->capture("python -V");
my $outSize = #out;
my $ver26 = 0;
for ( my $j = 0; $j < $outSize; $j++ ) {
if ( index( $out[$j], "2.6." ) != -1 ) {
$ver26 = 1;
}
}
How can I do this, or is there an alternative to accomplish the same thing?

According to the documentation for Net::SSH::Any, you need to pass it the hostname and pairs of options:
my $ssh = Net::SSH::Any->new($curIP, user => 'root');

Related

How can I handle multiple outlook accounts using Perl

I have task to read mails from secondary mail account from outlook using perl.
Please check the following it may help you.But you should install respective modules.Reference from "http://www.perlmonks.org/?node_id=916759"
use Modern::Perl;
use Mail::POP3Client;
use MIME::QuotedPrint;
my $pop_user = 'XXXXXXXXXX';
my $pop_pass = 'XXXXXXXXXX';
my $pop_host = 'exchange3';
#connect to POP3 sever
my $pop = new Mail::POP3Client ( HOST => $pop_host );
$pop->User($pop_user);
$pop->Pass($pop_pass);
$pop->Connect()
or die "Unable to connect to POP3 server: ".$pop->Message()."\n";
#count number of items in POP3 mailbox
my $mailcount = $pop->Count();
for (my $i = 1; $i <= $mailcount ; $i++) {
my $header = $pop->Head($i); #gets the header
my $uni = $pop->Uidl($i); # gets the unquie id
my $body = $pop->Body($i);
$body = decode_qp($body); #decode quoted printable body
say "$uni";
say "$header\n";
say "$body";
}

Authen::PAM login doesn't work after Vintela flush

I have a perl script that gets the username and password from an external process and then does user authentication using Vintela. Everything works perfectly until someone forces Vintela to flush it's cache. After the cache is flushed, the Authen::PAM module returns code 10, which means that it couldn't find the username.
If I run the "id $username" command in the shell and then run the script then everything returns to normal for that user. Or if the user SSH's into the system then Authen::PAM works perfectly.
On the production server user's don't SSH into the server and hence after Vintela flush, user's can't login anymore. I don't want to run the "id" command for every user before I authenticate them. Is there a way I can force the script or PAM module to look for user and then authenticate them ?
Script --
BEGIN {
unshift(#INC, "..", "/usr/local/staf/bin", "/usr/local/staf/lib", "C:/STAF/Bin");
}
use strict;
use PLSTAF;
require Authen::PAM;
my $GlobalUserName = <STDIN>;
my $GlobalPasswd = <STDIN>;
my $result = -1;
$GlobalPasswd = STAF::RemovePrivacyDelimiters($GlobalPasswd);
my $pamHandle = Authen::PAM->new("login", $GlobalUserName, \&conversionFunction);
$result = $pamHandle->pam_authenticate();
# force the destructor execution for PAM
$pamHandle = 0;
# When $result is 0 then user has been authenticated
if ($result == 0) {
print $result;
exit $result;
}
else {
exit $result;
}
sub conversionFunction {
my #response = ();
# PAM constants
my $pamEchoOn = Authen::PAM->PAM_PROMPT_ECHO_ON();
my $pamEchoOff = Authen::PAM->PAM_PROMPT_ECHO_OFF();
my $pamSuccess = Authen::PAM->PAM_SUCCESS();
while ( #_ ) {
my $code = shift;
my $msg = shift;
my $answer = "";
if ($code == $pamEchoOn) {
$answer = $GlobalUserName;
}
if ($code == $pamEchoOff) {
$answer = $GlobalPasswd;
}
# response is always in pairs, response code and the actual answer
push(#response, $pamSuccess, $answer);
}
push(#response, $pamSuccess);
return #response;
}

Use in-memory file as argument in SFTP

I need to open an SFTP connection in Perl and I need to use a dsa key file but I can't actually store the file on the hard disk for security reasons. I am trying to use Net::SFTP.
my $sftp = Net::SFTP->new(
$host, user=>"$userid",
ssh_args => {
identity_files => [ $pathToInMemoryKeyFile ]
}
);
I think I know how to get a string represented as an in memory file handle but I don't know how to get the path of that file handle such that I can pass it in as one of the ssh_args. Does anybody have any suggestions?
Thanks!
I've looked through the various options of doing SFTP (Net::SFTP hasn't been updated since 2005, Net::SFTP::Foreign is more up to date) and they all do key authentication via a file.
Net::SFTP is backed by Net::SSH::Perl which is a pure Perl SSH implementation. You can do some patching to make it do what you want. I'm going to sketch it out for you.
Patch or put a wrapper around Net::SSH::Perl::Auth::PublicKey->authenticate to look for a new configuration key. Let's call it identity_keys.
sub authenticate {
my $auth = shift;
my $ssh = $auth->{ssh};
my $sent = 0;
if (my $agent = $auth->mgr->agent) {
do {
$sent = $auth->_auth_agent;
} until $sent || $agent->num_left <= 0;
}
return $sent if $sent;
##### This is the new bit which tries any keys passed in. ######
my $ik = $ssh->config->get('identity_keys') || [];
for my $key (#$ik) {
return 1 if $auth->_auth_key($key);
}
my $if = $ssh->config->get('identity_files') || [];
my $idx = $auth->{_identity_idx} || 0;
for my $f (#$if[$idx..$#$if]) {
$auth->{_identity_idx}++;
return 1 if $auth->_auth_identity($f);
}
}
auth_key would be a copy of _auth_identity but calling Net::SSH::Perl::Key->read_private_key which would be the guts of Net::SSH::Perl::Key->read_private_pem minus opening and reading the key from a file. read_private_pem would then be gutted to use read_private_key.
Alternatively, use an ssh-agent. It holds the decrypted private key in memory, so you can immediately wipe it from the disk.

Does any one have a working script of LoadRunner Automation API?

Currently I am writing Perl script that creates LoadRunner scenario, execute the test, collect the result, recover the environment and repeat the cycle again with different scenario variables.
I don't have a problem creating new scenario, adding generator, adding 2 groups + script + the run-time settings. But I am having a problem with:
Setting scenario schedule from "Scenario" to "Group".
Setting schedule per group
This the snippet of the code:
use strict;
use v5.10;
use Win32::OLE;
use Win32::OLE::Enum;
use Win32::OLE::Variant;
use Data::Dumper;
use Win32::OLE::Const 'LoadRunner Automation Library';
use constant False => Variant(VT_BOOL,'');
use constant True => Variant(VT_BOOL,1);
my $lrEngine = Win32::OLE->new('wlrun.LrEngine') or die "oops\n";
my $lrScenario = $lrEngine->Scenario();
my $rc = $lrScenario->new(0, 1); # do not save previous, Regular vusers based scenario
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->new(0, 1):rc: $rc\n";
}
# snip-snipped - add generator
# snip-snipped - add #groups definition
foreach my $group (#groups) {
print "scriptName: $group->{scriptName}\n";
my $scriptLocation = $group->{scriptLocation};
my $scriptName = Variant(VT_BSTR|VT_BYREF, $group->{scriptName});
{ # add $group->{scriptName} script
$rc = $lrScenario->Scripts->Add($scriptLocation, $scriptName);
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->Scripts->Add($scriptLocation, $scriptName):rc: $rc\n";
}
}
#############################################################################
my $groupName = Variant(VT_BSTR|VT_BYREF, $group->{groupName});
{ # add $group->{groupName} group
$rc = $lrScenario->Groups->Add($groupName);
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->Groups->Add:rc: $rc\n";
}
$rc = $lrScenario->Groups->Item($groupName)->AddVusers($scriptName, $hostname, 3);
if ($rc != 0) {
print "Win32::OLE::LastError: ".Win32::OLE::LastError()."\n";
print "lrScenario->Groups->Item($groupName)->AddVusers:rc: $rc\n";
}
}
#############################################################################
# snip-snipped - change group script run time setting
}
my $scheduleName = Variant(VT_BSTR|VT_BYREF, 'Schedule123');
my $lrManualScheduleData = $lrScenario->ManualScheduler->AddSchedule($scheduleName, lrGroupSchedule); # Scenario schedule mode
if (!$lrManualScheduleData) {
say "Win32::OLE::LastError: ".Win32::OLE::LastError();
say "lrScenario->ManualScheduler->AddSchedule:rc: $rc";
}
$rc = $lrScenario->ManualScheduler->SetCurrentSchedule($scheduleName);
if ($rc != 0) {
say "Win32::OLE::LastError: ".Win32::OLE::LastError();
say "lrScenario->ManualScheduler->SetCurrentSchedule:rc: $rc";
}
print "\$lrScenario->ManualScheduler->SetScheduleMode($scheduleName, lrGroupSchedule):";
$lrScenario->ManualScheduler->SetScheduleMode($scheduleName, lrGroupSchedule);
#LrManualScheduleMode -> lrGroupSchedule = 1, lrScenarioSchedule = 0
say "Win32::OLE::LastError: ".Win32::OLE::LastError();
$lrManualScheduleData->{'InitAllBeforeRun'} = 'True';
$lrManualScheduleData->{'DurationMode'} = 1;
$lrManualScheduleData->{'Duration'} = 60 * 60;
$lrManualScheduleData->{'RampupBatchSize'} = 1;
$lrManualScheduleData->{'RampupMode'} = lrRampupByGroupBatches;
$lrManualScheduleData->{'RampupTimeInterval'} = 5;
$lrManualScheduleData->{'RampdownBatchSize'} = 1;
$lrManualScheduleData->{'RampdownMode'} = lrRampupByGroupBatches;
$lrManualScheduleData->{'RampdownTimeInterval'} = 5;
$rc = $lrScenario->ManualScheduler->{'ScenarioStartTimeMode'} = 0; # Start scenario without delay
#test
say "$scheduleName: ".$lrScenario->ManualScheduler->Schedule($scheduleName)->{'Duration'}; # returns 300
I have the same problem. Setting those properties and then calling either setschedulemode or setcurrentschedule doesn't seem to work. The only workaround I have found is to use the setscheduledata method passing in xml. You will need to get the current xml for the scheduledata and then change the xml, passing in the modified xml to the setscheduledata method. Hopefully this helps
lrManualScheduleData data = engine.Scenario.ManualScheduler.get_Schedule("Schedule 1");
String scheduleXML,errStr;
int returncode = data.getScheduleData(out scheduleXML, out errStr);
// Manipulate the XML to set whatever schedule you want
data.SetScheduleData(scheduleXML, out errStr);

How can I get the date of an email using Perl's Mail::MboxParser::Mail?

This is a simple question. I have a little program here that reads
a list of emails in a specific inbox of a user account specified by the program.
I can access an account using its username, password and host. The only problem is I don't know how to get the date on each of these mails.
Here's some part of my code:
my $pop = new Mail::POP3Client(
USER => $user, #some user,password & host assigned
PASSWORD => $pass,
HOST => $host );
for( $i = 1; $i <= $pop->Count(); $i++ ) {
#header = $pop->Head($i);
#body = $pop->Body($i);
$mail = new Mail::MboxParser::Mail(\#header, \#body);
$user_email = $mail->from()->{email
print "Email:".$user_email; #this prints out right
foreach( $pop->Head( $i ) ) {
/^(Date):\s+/i && print $_, "\n";
$date = $_;
}
}
Now what i need is to get the only one date for each email,
but that loop gives me all.. but when remove the loop, it
returns an error. I'm using Perl.
Kindly help me? :)
According to MboxParser::Email doc, you should be able to do:
$date = $mail->header->{'date'}; #Keys are all lowercase
If you have more than one date returned, $date will be an array ref and you can access the first occurence of the Date with:
$date->[0];
So you shouldn't need to loop through the header and use a regular expression.