Bug 37543: Use CSRF tokens in connexion_import_daemon.pl
Since version 24.05, due to the changes mentioned at
https://wiki.koha-community.org/wiki/Koha_/svc/_HTTP_API#Changes_coming_in_Koha_24.05 ,
the `connexion_import_daemon.pl` stopped working. The reason for this is that
it did not use CSRF tokens.
To test:
1. Get a Koha instance on 24.05, before applying the patch.
2. Create a plain text file somewhere on the server containing a raw MARC
record (not XML). Let's call it `marc.txt`.
3. On the server, create a config file like this:
```
host: 0.0.0.0
port: 5500
koha: http://localhost:82 # Where 82 is the port of the Koha staff interface.
user: foo # A Koha staff user.
password: Fooo1234 # The Koha staff user's password.
import_mode: stage
```
4. Run `./connexion_import_daemon.pl --config the-config-file-path`
5. In another terminal on the same server (or from anywhere that can reach the
port opened by the `connexion_import_daemon.pl` script,
run `nc localhost 5500 < marc.txt`
6. Observe in the stderr of the daemon script: `Response: Unsuccessful request`
7. Stop the daemon script.
8. Apply the patch and repeat steps 4 and 5.
9. Observe in the stderr of the daemon script:
`Response: Success. Batch number ... - biblio record number HASH(...) added to Koha`
10. Check at /cgi-bin/koha/tools/manage-marc-import.pl for a batch named
`(webservice)`. It should contain one record now. This is how we know that
authentication between the daemon and Koha worked, which is what this
patch tries to address.
Thanks-to: David Cook <dcook@prosentient.com.au>
Sponsored-by: Reformational Study Centre <www.refstudycentre.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
(cherry picked from commit 0e9ea3c9f5)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
f66130b020
commit
c850195a67
|
|
@ -104,7 +104,7 @@ use MARC::File::XML;
|
|||
|
||||
use constant CLIENT_READ_TIMEOUT => 5;
|
||||
use constant CLIENT_READ_BUFFER_SIZE => 100000;
|
||||
use constant AUTH_URI => "/cgi-bin/koha/mainpage.pl";
|
||||
use constant AUTH_URI => "/cgi-bin/koha/svc/authentication";
|
||||
use constant IMPORT_SVC_URI => "/cgi-bin/koha/svc/import_bib";
|
||||
|
||||
sub new {
|
||||
|
|
@ -239,6 +239,32 @@ sub _ua {
|
|||
return $ua;
|
||||
}
|
||||
|
||||
sub get_current_csrf_token {
|
||||
my $self = shift;
|
||||
my $ua = $self->{ua};
|
||||
my $url = $self->{koha} . AUTH_URI;
|
||||
return $ua->get($url)->header('CSRF-TOKEN');
|
||||
}
|
||||
|
||||
sub authenticate {
|
||||
my $self = shift;
|
||||
my $ua = $self->{ua};
|
||||
my $url = $self->{koha} . AUTH_URI;
|
||||
my $resp = $ua->post(
|
||||
$url,
|
||||
{
|
||||
login_userid => $self->{user},
|
||||
login_password => $self->{password},
|
||||
csrf_token => $self->get_current_csrf_token,
|
||||
}
|
||||
);
|
||||
if ( !$resp->is_success ) {
|
||||
$self->log("Authentication failed", $resp->request->as_string, $resp->as_string);
|
||||
return;
|
||||
}
|
||||
return $resp->header('CSRF-TOKEN');
|
||||
}
|
||||
|
||||
sub read_request {
|
||||
my ( $self, $io ) = @_;
|
||||
|
||||
|
|
@ -355,38 +381,34 @@ sub handle_request {
|
|||
}
|
||||
|
||||
my $base_url = $self->{koha};
|
||||
my $post_body = {
|
||||
'nomatch_action' => $self->{params}->{nomatch_action},
|
||||
'overlay_action' => $self->{params}->{overlay_action},
|
||||
'match' => $self->{params}->{match},
|
||||
'import_mode' => $self->{params}->{import_mode},
|
||||
'framework' => $self->{params}->{framework},
|
||||
'overlay_framework' => $self->{params}->{overlay_framework},
|
||||
'item_action' => $self->{params}->{item_action},
|
||||
'xml' => $data
|
||||
};
|
||||
|
||||
# If we have a token, try it, else, authenticate for the first time.
|
||||
$self->{csrf_token} = $self->authenticate unless $self->{csrf_token};
|
||||
my $resp = $ua->post(
|
||||
$base_url . IMPORT_SVC_URI,
|
||||
{
|
||||
'nomatch_action' => $self->{params}->{nomatch_action},
|
||||
'overlay_action' => $self->{params}->{overlay_action},
|
||||
'match' => $self->{params}->{match},
|
||||
'import_mode' => $self->{params}->{import_mode},
|
||||
'framework' => $self->{params}->{framework},
|
||||
'overlay_framework' => $self->{params}->{overlay_framework},
|
||||
'item_action' => $self->{params}->{item_action},
|
||||
'xml' => $data
|
||||
}
|
||||
$post_body,
|
||||
csrf_token => $self->{csrf_token},
|
||||
);
|
||||
|
||||
my $status = $resp->code;
|
||||
if ( $status == HTTP_UNAUTHORIZED || $status == HTTP_FORBIDDEN ) {
|
||||
my $user = $self->{user};
|
||||
my $password = $self->{password};
|
||||
$resp = $ua->post( $base_url . AUTH_URI, { userid => $user, password => $password } );
|
||||
# Our token might have expired. Re-authenticate and post again.
|
||||
$self->{csrf_token} = $self->authenticate;
|
||||
$resp = $ua->post(
|
||||
$base_url . IMPORT_SVC_URI,
|
||||
{
|
||||
'nomatch_action' => $self->{params}->{nomatch_action},
|
||||
'overlay_action' => $self->{params}->{overlay_action},
|
||||
'match' => $self->{params}->{match},
|
||||
'import_mode' => $self->{params}->{import_mode},
|
||||
'framework' => $self->{params}->{framework},
|
||||
'overlay_framework' => $self->{params}->{overlay_framework},
|
||||
'item_action' => $self->{params}->{item_action},
|
||||
'xml' => $data
|
||||
}
|
||||
) if $resp->is_success;
|
||||
$post_body,
|
||||
csrf_token => $self->{csrf_token},
|
||||
)
|
||||
}
|
||||
unless ($resp->is_success) {
|
||||
$self->log("Unsuccessful request", $resp->request->as_string, $resp->as_string);
|
||||
|
|
|
|||
Loading…
Reference in New Issue