[pve-devel] [PATCH v2 http-server 2/2] api-server: extract, set and handle API token header
Fabian Grünbichler
f.gruenbichler at proxmox.com
Thu Nov 21 15:43:43 CET 2019
Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
---
Notes:
versioned breaks/depends with pve-manager and part of PMG?
PVE/APIServer/AnyEvent.pm | 25 ++++++++++++++++++-------
PVE/APIServer/Formatter.pm | 9 +++++++++
PVE/APIServer/Formatter/Bootstrap.pm | 1 +
3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/PVE/APIServer/AnyEvent.pm b/PVE/APIServer/AnyEvent.pm
index 1e5c180..3ce948f 100644
--- a/PVE/APIServer/AnyEvent.pm
+++ b/PVE/APIServer/AnyEvent.pm
@@ -544,7 +544,7 @@ sub websocket_proxy {
}
sub proxy_request {
- my ($self, $reqstate, $clientip, $host, $node, $method, $uri, $ticket, $token, $params) = @_;
+ my ($self, $reqstate, $clientip, $host, $node, $method, $uri, $auth, $params) = @_;
eval {
my $target;
@@ -564,8 +564,12 @@ sub proxy_request {
PVEClientIP => $clientip,
};
- $headers->{'cookie'} = PVE::APIServer::Formatter::create_auth_cookie($ticket, $self->{cookie_name}) if $ticket;
- $headers->{'CSRFPreventionToken'} = $token if $token;
+ $headers->{'cookie'} = PVE::APIServer::Formatter::create_auth_cookie($auth->{ticket}, $self->{cookie_name})
+ if $auth->{ticket};
+ $headers->{'Authorization'} = PVE::APIServer::Formatter::create_auth_header($auth->{api_token}, $self->{apitoken_name})
+ if $auth->{api_token};
+ $headers->{'CSRFPreventionToken'} = $auth->{token}
+ if $auth->{token};
$headers->{'Accept-Encoding'} = 'gzip' if ($reqstate->{accept_gzip} && $self->{compression});
if (defined(my $host = $reqstate->{request}->header('Host'))) {
@@ -744,7 +748,7 @@ sub handle_api2_request {
$res->{proxy_params}->{tmpfilename} = $reqstate->{tmpfilename} if $upload_state;
$self->proxy_request($reqstate, $clientip, $host, $res->{proxynode}, $method,
- $r->uri, $auth->{ticket}, $auth->{token}, $res->{proxy_params});
+ $r->uri, $auth, $res->{proxy_params});
return;
} elsif ($upgrade && ($method eq 'GET') && ($path =~ m|websocket$|)) {
@@ -1238,6 +1242,11 @@ sub unshift_read_header {
$ticket = PVE::APIServer::Formatter::extract_auth_value($auth_header, $self->{cookie_name})
if !$ticket;
+ # finally, fallback to API token if no ticket has been provided so far
+ my $api_token;
+ $api_token = PVE::APIServer::Formatter::extract_auth_value($auth_header, $self->{apitoken_name})
+ if !$ticket;
+
my ($rel_uri, $format) = &$split_abs_uri($path, $self->{base_uri});
if (!$format) {
$self->error($reqstate, HTTP_NOT_IMPLEMENTED, "no such uri");
@@ -1245,7 +1254,7 @@ sub unshift_read_header {
}
eval {
- $auth = $self->auth_handler($method, $rel_uri, $ticket, $token,
+ $auth = $self->auth_handler($method, $rel_uri, $ticket, $token, $api_token,
$reqstate->{peer_host});
};
if (my $err = $@) {
@@ -1639,6 +1648,7 @@ sub new {
my $self = bless { %args }, $class;
$self->{cookie_name} //= 'PVEAuthCookie';
+ $self->{apitoken_name} //= 'PVEAPIToken';
$self->{base_uri} //= "/api2";
$self->{dirs} //= {};
$self->{title} //= 'API Inspector';
@@ -1646,7 +1656,7 @@ sub new {
# formatter_config: we pass some configuration values to the Formatter
$self->{formatter_config} = {};
- foreach my $p (qw(cookie_name base_uri title)) {
+ foreach my $p (qw(apitoken_name cookie_name base_uri title)) {
$self->{formatter_config}->{$p} = $self->{$p};
}
$self->{formatter_config}->{csrfgen_func} =
@@ -1781,7 +1791,7 @@ sub generate_csrf_prevention_token {
}
sub auth_handler {
- my ($self, $method, $rel_uri, $ticket, $token, $peer_host) = @_;
+ my ($self, $method, $rel_uri, $ticket, $token, $api_token, $peer_host) = @_;
die "implement me";
@@ -1791,6 +1801,7 @@ sub auth_handler {
# userid => $username,
# age => $age,
# isUpload => $isUpload,
+ # api_token => $api_token,
#};
}
diff --git a/PVE/APIServer/Formatter.pm b/PVE/APIServer/Formatter.pm
index def1932..20455a0 100644
--- a/PVE/APIServer/Formatter.pm
+++ b/PVE/APIServer/Formatter.pm
@@ -95,4 +95,13 @@ sub create_auth_cookie {
return "${cookie_name}=$encticket; path=/; secure;";
}
+sub create_auth_header {
+ my ($value, $key) = @_;
+
+ return undef if !$key;
+
+ my $encoded = uri_escape($value);
+ return "${key} ${encoded}";
+}
+
1;
diff --git a/PVE/APIServer/Formatter/Bootstrap.pm b/PVE/APIServer/Formatter/Bootstrap.pm
index d61f982..e67554a 100644
--- a/PVE/APIServer/Formatter/Bootstrap.pm
+++ b/PVE/APIServer/Formatter/Bootstrap.pm
@@ -65,6 +65,7 @@ sub new {
url => $url,
title => $config->{title},
cookie_name => $config->{cookie_name},
+ apitoken_name => $config->{apitoken_name},
js => '',
};
--
2.20.1
More information about the pve-devel
mailing list