From: Chris Sharp Date: Mon, 30 Jan 2023 21:38:54 +0000 (-0500) Subject: first changes to acq EDI SFTP implementation X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=34851a8b526f7e1b89504f09ed6eef876e8bd57d;p=working%2FEvergreen.git first changes to acq EDI SFTP implementation --- diff --git a/Open-ILS/src/extras/install/Makefile.debian-bullseye b/Open-ILS/src/extras/install/Makefile.debian-bullseye index b8da0991ac..490e759b6d 100644 --- a/Open-ILS/src/extras/install/Makefile.debian-bullseye +++ b/Open-ILS/src/extras/install/Makefile.debian-bullseye @@ -52,7 +52,7 @@ export DEBS = \ libnet-ip-perl\ libnet-ldap-perl \ libnet-server-perl\ - libnet-ssh2-perl\ + libnet-sftp-foreign-perl\ libnet-z3950-simple2zoom-perl\ libnet-z3950-simpleserver-perl\ libnet-z3950-zoom-perl \ diff --git a/Open-ILS/src/extras/install/Makefile.debian-buster b/Open-ILS/src/extras/install/Makefile.debian-buster index 719eefdfc9..2373b009fd 100644 --- a/Open-ILS/src/extras/install/Makefile.debian-buster +++ b/Open-ILS/src/extras/install/Makefile.debian-buster @@ -53,7 +53,7 @@ export DEBS = \ libnet-ip-perl\ libnet-ldap-perl \ libnet-server-perl\ - libnet-ssh2-perl\ + libnet-sftp-foreign-perl\ libnet-z3950-simple2zoom-perl\ libnet-z3950-simpleserver-perl\ libnet-z3950-zoom-perl \ diff --git a/Open-ILS/src/extras/install/Makefile.ubuntu-focal b/Open-ILS/src/extras/install/Makefile.ubuntu-focal index 85da870669..1b8738524a 100644 --- a/Open-ILS/src/extras/install/Makefile.ubuntu-focal +++ b/Open-ILS/src/extras/install/Makefile.ubuntu-focal @@ -50,7 +50,7 @@ export DEBS = \ libnet-ip-perl\ libnet-ldap-perl \ libnet-server-perl\ - libnet-ssh2-perl\ + libnet-sftp-foreign-perl\ libnet-z3950-simpleserver-perl\ libnet-z3950-zoom-perl \ libnspr4-dev\ diff --git a/Open-ILS/src/extras/install/Makefile.ubuntu-jammy b/Open-ILS/src/extras/install/Makefile.ubuntu-jammy index 0e1014ac3e..752535198c 100644 --- a/Open-ILS/src/extras/install/Makefile.ubuntu-jammy +++ b/Open-ILS/src/extras/install/Makefile.ubuntu-jammy @@ -52,7 +52,7 @@ export DEBS = \ libnet-ip-perl\ libnet-ldap-perl \ libnet-server-perl\ - libnet-ssh2-perl\ + libnet-sftp-foreign-perl\ libnet-z3950-simpleserver-perl\ libnet-z3950-zoom-perl \ libnet-z3950-simple2zoom-perl \ diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm index b4a8f1ecf1..0b3e0cd1ae 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm @@ -4,8 +4,9 @@ package OpenILS::Utils::RemoteAccount; use OpenSRF::Utils::Logger qw/:logger/; use Data::Dumper; +use IO::Pty; use Net::FTP; -use Net::SSH2; +use Net::SFTP::Foreign; use File::Temp; use File::Basename; use File::Spec; @@ -340,8 +341,8 @@ sub delete { if ($self->type eq "FTP") { return $self->delete_ftp($file); } else { - my %keys = $self->key_check($params); - return $self->delete_ssh2(\%keys, $file); + my %keys = $self->key_check($params); + return $self->delete_ssh2(\%keys, $file); } } @@ -364,172 +365,173 @@ sub glob_parse { # Internal Mechanics -sub _ssh2 { - my $self = shift; - $self->{ssh2} and return $self->{ssh2}; # caching - my $keys = shift; - - my $ssh2 = Net::SSH2->new(); - unless($ssh2->connect($self->remote_host)) { - $logger->warn($self->error("SSH2 connect FAILED: $! " . join(" ", $ssh2->error))); - return; # we cannot connect - } - - my $success = 0; - my @privates = keys %$keys; - my $count = scalar @privates; - - if ($count) { - foreach (@privates) { - if ($self->auth_ssh2($ssh2,$self->auth_ssh2_args($_,$keys->{$_}))) { - $success++; - last; - } - } - unless ($success) { - $logger->error( - $self->error( - "All ($count) keypair(s) FAILED for " . $self->remote_host - ) - ); - return; - } - } else { - $logger->error( - $self->error("Login FAILED for " . $self->remote_host) - ) unless $self->auth_ssh2($ssh2, $self->auth_ssh2_args); - } - return $self->{ssh2} = $ssh2; -} - -sub auth_ssh2 { - my $self = shift; - my $ssh2 = shift; - my %auth_args = @_; - $ssh2 or return; - - my $host = $auth_args{hostname} || 'UNKNOWN'; - my $key = $auth_args{privatekey} || 'UNKNOWN'; - my $msg = "ssh2->auth by keypair for $host using $key"; - if ($ssh2->auth(%auth_args)) { - $logger->info("Successful $msg"); - return 1; - } - - if ($self->specific) { - $logger->error($self->error("Aborting. FAILED $msg: " . ($ssh2->error || ''))); - } else { - $logger->warn($self->error("Unsuccessful keypair: FAILED $msg: " . ($ssh2->error || ''))); - } - return; -} - -sub auth_ssh2_args { - my $self = shift; - my %auth_args = ( - privatekey => shift, - publickey => shift, - rank => [qw/ publickey hostbased password /], - ); - $self->remote_user and $auth_args{username} = $self->remote_user ; - $self->remote_password and $auth_args{password} = $self->remote_password; - $self->remote_host and $auth_args{hostname} = $self->remote_host ; - return %auth_args; -} - -sub put_ssh2 { - my $self = shift; - my $keys = shift; # could have many keypairs here - unless (@_) { - $logger->error($self->_error("put_ssh2 called without target: nothing to put!")); - return; - } - - $logger->info("*** attempting put (" . join(", ", @_) . ") with ssh keys"); - my $ssh2 = $self->_ssh2($keys) or return; - my $res; - if ($res = $ssh2->scp_put( @_ )) { - $logger->info(_pkg("successfully sent", $self->remote_host, join(' --> ', @_ ))); - return $res; - } - $logger->error($self->_error(sprintf "put with keys to %s failed with error: $!", $self->remote_host)); - return; -} - -sub get_ssh2 { - my $self = shift; - my $keys = shift; # could have many keypairs here - unless (@_) { - $logger->error($self->_error("get_ssh2 called without target: nothing to get!")); - return; - } - - $logger->info("*** get args: " . Dumper(\@_)); - $logger->info("*** attempting get (" . join(", ", map {$_ =~ /\S/ ? $_ : '*Object'} map {defined($_) ? $_ : '*Object'} @_) . ") with ssh keys"); - my $ssh2 = $self->_ssh2($keys) or return; - my $res; - if ($res = $ssh2->scp_get( @_ )) { - $logger->info(_pkg("successfully got", $self->remote_host, join(' --> ', @_ ))); - return $res; - } - $logger->error($self->_error(sprintf "get with keys from %s failed with error: $!", $self->remote_host)); - return; -} -sub ls_ssh2 { - my $self = shift; - my @list = $self->ls_ssh2_full(@_); - @list and return sort map {$_->{slash_path}} @list; -# @list and return sort grep {$_->{name} !~ /./ and {$_->{name} !~ /./ } map {$_->{slash_path}} @list; -} - -sub ls_ssh2_full { - my $self = shift; - my $keys = shift; # could have many keypairs here - my @targets = grep {defined} @_; - - $logger->info("*** attempting ls ('" . join("', '", @targets) . "') with ssh keys"); - my $ssh2 = $self->_ssh2($keys) or return; - my $sftp = $ssh2->sftp or return; - - my @list = (); - foreach my $target (@targets) { - my ($dir, $file); - my ($dirpath, $regex) = $self->glob_parse($target); - $dir = $sftp->opendir($dirpath || $target); # Try to open it like a directory - unless ($dir) { - $file = $sftp->stat($target); # Otherwise, check it like a file - if ($file) { - $file->{slash_path} = $self->_slash_path($target, $file->{name}); # it was a file, not a dir. That's OK. - push @list, $file; - } else { - $logger->warn($self->_error("sftp->opendir($target) failed: " . $sftp->error)); - } - next; - } - my @pool = (); - while ($file = $dir->read()) { - $file->{slash_path} = $self->_slash_path($target, $file->{name}); - push @pool, $file; - } - if ($regex) { - my $count = scalar(@pool); - @pool = grep {$_->{name} =~ /$regex/} @pool; - $logger->info("SSH ls: Glob regex($regex) matches " . scalar(@pool) . " of $count files"); - } # else { $logger->info("SSH ls: No Glob regex in '$target'. Just a regular ls"); } - push @list, @pool; - } - return @list; - -} - -sub delete_ssh2 { - my $self = shift; - my $keys = shift; - my $file = shift; - my $sftp = $self->_ssh2($keys)->sftp; - return $sftp->unlink($file); -} +#sub _ssh2 { +# my $self = shift; +# $self->{ssh2} and return $self->{ssh2}; # caching +# my $keys = shift; +# +# my $ssh2 = Net::SSH2->new(); +# unless($ssh2->connect($self->remote_host)) { +# $logger->warn($self->error("SSH2 connect FAILED: $! " . join(" ", $ssh2->error))); +# return; # we cannot connect +# } +# +# my $success = 0; +# my @privates = keys %$keys; +# my $count = scalar @privates; +# +# if ($count) { +# foreach (@privates) { +# if ($self->auth_ssh2($ssh2,$self->auth_ssh2_args($_,$keys->{$_}))) { +# $success++; +# last; +# } +# } +# unless ($success) { +# $logger->error( +# $self->error( +# "All ($count) keypair(s) FAILED for " . $self->remote_host +# ) +# ); +# return; +# } +# } else { +# $logger->error( +# $self->error("Login FAILED for " . $self->remote_host) +# ) unless $self->auth_ssh2($ssh2, $self->auth_ssh2_args); +# } +# return $self->{ssh2} = $ssh2; +#} +# +#sub auth_ssh2 { +# my $self = shift; +# my $ssh2 = shift; +# my %auth_args = @_; +# $ssh2 or return; +# +# my $host = $auth_args{hostname} || 'UNKNOWN'; +# my $key = $auth_args{privatekey} || 'UNKNOWN'; +# my $msg = "ssh2->auth by keypair for $host using $key"; +# if ($ssh2->auth(%auth_args)) { +# $logger->info("Successful $msg"); +# return 1; +# } +# +# if ($self->specific) { +# $logger->error($self->error("Aborting. FAILED $msg: " . ($ssh2->error || ''))); +# } else { +# $logger->warn($self->error("Unsuccessful keypair: FAILED $msg: " . ($ssh2->error || ''))); +# } +# return; +#} +# +#sub auth_ssh2_args { +# my $self = shift; +# my %auth_args = ( +# privatekey => shift, +# publickey => shift, +# rank => [qw/ publickey hostbased password /], +# ); +# $self->remote_user and $auth_args{username} = $self->remote_user ; +# $self->remote_password and $auth_args{password} = $self->remote_password; +# $self->remote_host and $auth_args{hostname} = $self->remote_host ; +# return %auth_args; +#} +# +#sub put_ssh2 { +# my $self = shift; +# my $keys = shift; # could have many keypairs here +# unless (@_) { +# $logger->error($self->_error("put_ssh2 called without target: nothing to put!")); +# return; +# } +# +# $logger->info("*** attempting put (" . join(", ", @_) . ") with ssh keys"); +# my $ssh2 = $self->_ssh2($keys) or return; +# my $res; +# if ($res = $ssh2->scp_put( @_ )) { +# $logger->info(_pkg("successfully sent", $self->remote_host, join(' --> ', @_ ))); +# return $res; +# } +# $logger->error($self->_error(sprintf "put with keys to %s failed with error: $!", $self->remote_host)); +# return; +#} +# +#sub get_ssh2 { +# my $self = shift; +# my $keys = shift; # could have many keypairs here +# unless (@_) { +# $logger->error($self->_error("get_ssh2 called without target: nothing to get!")); +# return; +# } +# +# $logger->info("*** get args: " . Dumper(\@_)); +# $logger->info("*** attempting get (" . join(", ", map {$_ =~ /\S/ ? $_ : '*Object'} map {defined($_) ? $_ : '*Object'} @_) . ") with ssh keys"); +# my $ssh2 = $self->_ssh2($keys) or return; +# my $res; +# if ($res = $ssh2->scp_get( @_ )) { +# $logger->info(_pkg("successfully got", $self->remote_host, join(' --> ', @_ ))); +# return $res; +# } +# $logger->error($self->_error(sprintf "get with keys from %s failed with error: $!", $self->remote_host)); +# return; +#} +# +#sub ls_ssh2 { +# my $self = shift; +# my @list = $self->ls_ssh2_full(@_); +# @list and return sort map {$_->{slash_path}} @list; +## @list and return sort grep {$_->{name} !~ /./ and {$_->{name} !~ /./ } map {$_->{slash_path}} @list; +#} +# +#sub ls_ssh2_full { +# my $self = shift; +# my $keys = shift; # could have many keypairs here +# my @targets = grep {defined} @_; +# +# $logger->info("*** attempting ls ('" . join("', '", @targets) . "') with ssh keys"); +# my $ssh2 = $self->_ssh2($keys) or return; +# my $sftp = $ssh2->sftp or return; +# +# my @list = (); +# foreach my $target (@targets) { +# my ($dir, $file); +# my ($dirpath, $regex) = $self->glob_parse($target); +# $dir = $sftp->opendir($dirpath || $target); # Try to open it like a directory +# unless ($dir) { +# $file = $sftp->stat($target); # Otherwise, check it like a file +# if ($file) { +# $file->{slash_path} = $self->_slash_path($target, $file->{name}); # it was a file, not a dir. That's OK. +# push @list, $file; +# } else { +# $logger->warn($self->_error("sftp->opendir($target) failed: " . $sftp->error)); +# } +# next; +# } +# my @pool = (); +# while ($file = $dir->read()) { +# $file->{slash_path} = $self->_slash_path($target, $file->{name}); +# push @pool, $file; +# } +# if ($regex) { +# my $count = scalar(@pool); +# @pool = grep {$_->{name} =~ /$regex/} @pool; +# $logger->info("SSH ls: Glob regex($regex) matches " . scalar(@pool) . " of $count files"); +# } # else { $logger->info("SSH ls: No Glob regex in '$target'. Just a regular ls"); } +# push @list, @pool; +# } +# return @list; +# +#} +# +#sub delete_ssh2 { +# my $self = shift; +# my $keys = shift; +# my $file = shift; +# my $sftp = $self->_ssh2($keys)->sftp; +# return $sftp->unlink($file); +#} sub _slash_path { my $self = shift; @@ -732,7 +734,7 @@ sub new { sub DESTROY { # in order to create, we must first ... my $self = shift; - $self->{ssh2} and $self->{ssh2}->disconnect(); # let the other end know we're done. + $self->{sftp} and $self->{sftp}->disconnect; # let the other end know we're done. $self->{ftp} and $self->{ftp}->quit(); # let the other end know we're done. }