From: Laurent GUERBY <laurent@guerby.net>
To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>
Subject: Re: [pve-devel] New API endpoint to manage snippets / bugzilla 2208 / updated patch but missing something, need help
Date: Fri, 08 Apr 2022 20:25:51 +0200 [thread overview]
Message-ID: <1649442351.6346.25.camel@guerby.net> (raw)
In-Reply-To: <1649408819.6346.22.camel@guerby.net>
> Hi,
>
> I've tried to adapt the patch to current PVE 7.1-12 (see below) but I
> still get
>
> proxmoxer.core.ResourceException: 501 Not Implemented: upload failed
> -
> {'errors': b''}
>
> When I try to upload a snippet.
>
> My proxmoxer setup works for iso, the following succeeds:
>
> proxmox.nodes(h).storage(s).upload.post(content="iso",filename=f)
>
> But the following fails (f being read "rb" from some xxx.yaml)
>
> proxmox.nodes(h).storage(s).upload.post(content="snippets",filename=f
> )
>
> Not having snippet upload makes it impossible to use PVE auth realm
> tokens to control permissions, you have to give a priviledged system
> account to users *just* to be able to do cloud init with a yaml which
> is not great security wise (and not practical).
>
> I'm probably missing a few things to have a patch that works, I'm
> willing to put some time on it if someone gives me directions.
I instrumented some PVE perl code and failure to recognize the upload
API data seems to happen somewhere in the logic of
/usr/share/perl5/PVE/APIServer/AnyEvent.pm:file_upload_multipart
With my patch installed for content=snippet filename=yoyobig.yaml if I
upload a 16137 or more byte files it works, but for 16136 byte and
below it fails with 501 not implemented which is suspicious.
By adding max debug to python http libs I was able to check that the
headers are strictly identical except for Content-Length as expected,
see below.
There's a comment in AnyEvent.pm about "# assume we have single line
headers" and also some complex state handling while parsing the request
but for now I wasn't able to pinpoint what triggers the failure.
Help welcomed :)
Sincerely,
Laurent
Debug logs:
import http.client
http.client.HTTPConnection.debuglevel=5
import logging
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
Works:
INFO:proxmoxer.core:POST https://nuc2:8006/api2/json/nodes/nuc2/storage/element2dir/upload {'content': 'snippets', 'filename': <_io.BufferedReader name='yoyobig.yaml'>}
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): nuc2:8006
send: b'POST /api2/json/nodes/nuc2/storage/element2dir/upload HTTP/1.1\r\nHost: nuc2:8006\r\nUser-Agent: python-requests/2.23.0\r\nAccept-Encoding: gzip, deflate\r\naccept: application/json, application/x-javasc
ript, text/javascript, text/x-javascript, text/x-json\r\nConnection: keep-alive\r\nContent-Length: 16385\r\nContent-Type: multipart/form-data; boundary=790f8b2d9dcdc452863bff66e1d262bc\r\nAuthorization: PVEAPITo
ken=root@pam!testpython1=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r\n\r\n'
send: b'--790f8b2d9dcdc452863bff66e1d262bc\r\nContent-Disposition: form-data; name="content"\r\n\r\nsnippets\r\n--790f8b2d9dcdc452863bff66e1d262bc\r\nContent-Disposition: form-data; name="filename"; filename="yo
yobig.yaml"\r\n\r\n#cloud-config\xhostname: test...
Fails:
INFO:proxmoxer.core:POST https://nuc2:8006/api2/json/nodes/nuc2/storage/element2dir/upload {'content': 'snippets', 'filename': <_io.BufferedReader name='yoyobig.yaml'>}
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): nuc2:8006
send: b'POST /api2/json/nodes/nuc2/storage/element2dir/upload HTTP/1.1\r\nHost: nuc2:8006\r\nUser-Agent: python-requests/2.23.0\r\nAccept-Encoding: gzip, deflate\r\naccept: application/json, application/x-javasc
ript, text/javascript, text/x-javascript, text/x-json\r\nConnection: keep-alive\r\nContent-Length: 16384\r\nContent-Type: multipart/form-data; boundary=1ae9ce4d260e3f514d7c12ec03e4389f\r\nAuthorization: PVEAPITo
ken=root@pam!testpython1=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r\n\r\n'
send: b'--1ae9ce4d260e3f514d7c12ec03e4389f\r\nContent-Disposition: form-data; name="content"\r\n\r\nsnippets\r\n--1ae9ce4d260e3f514d7c12ec03e4389f\r\nContent-Disposition: form-data; name="filename"; filename="yo
yobig.yaml"\r\n\r\n#cloud-config\nhostname: test...
> Thanks!
>
> Sincerely,
>
> Laurent (paying PVE+PBS customer at work)
>
> root@test:/usr/share/perl5# diff -u PVE/Storage.pm{-orig,}
> --- PVE/Storage.pm-orig 2022-04-08 09:15:52.443943197 +0200
> +++ PVE/Storage.pm 2022-04-08 09:17:23.457073570 +0200
> @@ -412,6 +412,15 @@
> return $plugin->get_subdir($scfg, 'iso');
> }
>
> +sub get_snippet_dir {
> + my ($cfg, $storeid) = @_;
> +
> + my $scfg = storage_config($cfg, $storeid);
> + my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
> +
> + return $plugin->get_subdir($scfg, 'snippets');
> +}
> +
> sub get_vztmpl_dir {
> my ($cfg, $storeid) = @_;
>
> root@test:/usr/share/perl5# diff -u ./PVE/API2/Storage/Status.pm{-
> orig,}
> --- ./PVE/API2/Storage/Status.pm-orig 2022-04-08
> 09:15:43.883836880 +0200
> +++ ./PVE/API2/Storage/Status.pm 2022-04-08 10:23:43.914401204
> +0200
> @@ -381,7 +381,7 @@
> content => {
> description => "Content type.",
> type => 'string', format => 'pve-storage-content',
> - enum => ['iso', 'vztmpl'],
> + enum => ['iso', 'vztmpl', 'snippets'],
> },
> filename => {
> description => "The name of the file to create.
> Caution: This will be normalized!",
> @@ -446,8 +446,10 @@
> raise_param_exc({ filename => "wrong file extension"
> });
> }
> $path = PVE::Storage::get_vztmpl_dir($cfg, $param-
> >{storage});
> - } else {
> - raise_param_exc({ content => "upload content type
> '$content' not allowed" });
> + } elsif ($content eq 'snippets') {
> + $path = PVE::Storage::get_snippet_dir($cfg, $param-
> >{storage});
> + } else {
> + raise_param_exc({ content => "upload content type
> '$content' not allowed" });
> }
>
> die "storage '$param->{storage}' does not support '$content'
> content\n"
> @@ -564,7 +566,7 @@
> content => {
> description => "Content type.", # TODO: could be
> optional & detected in most cases
> type => 'string', format => 'pve-storage-content',
> - enum => ['iso', 'vztmpl'],
> + enum => ['iso', 'vztmpl', 'snippets'],
> },
> filename => {
> description => "The name of the file to create.
> Caution: This will be normalized!",
> @@ -627,6 +629,8 @@
> raise_param_exc({ filename => "wrong file extension"
> });
> }
> $path = PVE::Storage::get_vztmpl_dir($cfg, $storage);
> + } elsif ($content eq 'snippets') {
> + $path = PVE::Storage::get_snippet_dir($cfg,
> $storage);
> } else {
> raise_param_exc({ content => "upload content-type
> '$content' is not allowed" });
> }
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2022-04-08 18:25 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-07 10:27 [pve-devel] New API endpoint to manage snippets Patryk Ściborek
2022-04-08 9:06 ` [pve-devel] New API endpoint to manage snippets / bugzilla 2208 / updated patch but missing something, need help Laurent GUERBY
2022-04-08 18:25 ` Laurent GUERBY [this message]
2022-04-11 9:03 ` Matthias Heiserer
2022-04-11 10:00 ` Laurent GUERBY
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1649442351.6346.25.camel@guerby.net \
--to=laurent@guerby.net \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.