Open andrewrk opened 1 year ago
How would this fit into the framework proposed in #14286? It sounds like the goal in that issue is to make it safer to run un-audited build.zig
files from dependencies by sandboxing them with WASM, but this proposal would also allow arbitrary code execution by downloading and running fetch plugins, similarly to running someone else's build.zig
.
As a user of IPFS once in a blue moon, here's my 2 cents.
If you found a package that for some reason exists only on IPFS, you can
This is applicable to practically any other uncommon protocols and are generally straightforward to implement. It is also guaranteed to work with Zig (it would just see it as normal http/tar). For those who frequently use exotic protocols, they likely already have the expertise to employ standard proxy methods. If a proxy for a specific protocol isn't available, developing a general-purpose proxy could be more beneficial than creating a plugin specifically for the Zig package manager.
Even without considering security implications - this just seems like a feature creep.
Given that the package manager is still in its early development phase, focusing on foundational stability and functionality might be more prudent. I wouldn't expect this kind of feature to be available even in Zig 1.0, let alone 0.13.0
I'd like to add, this relates to extensible v. composable, and making extensibility features at the right layer. I wouldn't be comfortable with mandated X protocols to ratify counterpart Y protocols declaratively, let alone recursively. Also not sure how indiscriminate you can get with this.
This is applicable to practically any other uncommon protocols and are generally straightforward to implement. It is also guaranteed to work with Zig (it would just see it as normal http/tar). For those who frequently use exotic protocols, they likely already have the expertise to employ standard proxy methods. If a proxy for a specific protocol isn't available, developing a general-purpose proxy could be more beneficial than creating a plugin specifically for the Zig package manager.
Even without considering security implications - this just seems like a feature creep.
Agreed, see also my comment at https://github.com/ziglang/zig/issues/14298#issuecomment-1735162557
So, I decided that I try to tackle this over the last few days, so, here is my rather basic proposal. It may have some flaws which I overlooked, but I think it's fine for what one can get without an implementation. It makes it quite easy to e.g. implement Git over SSH (for a few reason which I mentioned in that issue #14295).
As for security considerations. The way I have formulated this one could end up restricting it in a way to make it run inside of a sandbox (e.g only access to the network and the target directory and maybe some directory for temporary files), but since for example Git over SSH users often use their SSH keys to connect to the server, I am not sure how practical that would end up being.
Anyway, here we go:
A fetch plugin is a directory with the following contents:
fetch-plugin.zon
; this file is a struct with the following fields:
.projectname
: This is the name of the plugin.protocols
: a list of all supported protocols of this plugin.kind
: an enum of two possible values (.Source
and .Executable
) which influence the other expected contents of the plugin.Executable
plugin, the directory contains an executable file (or a symlink to one) which does the fetching. How the interface works is described later. The name of the executable must the Projectname plus possible OS-specific file extensions. This is mostly meant for Fetch Plugins which are scripts (like a bash file or a batch file) or precompiled..Source
plugin, the directory contains a Zig project whose build.zig
file supports zig build run --
with the arguments coming afterwards.The plugin is supposed to behave according to the following interface:
Here an quick'n'dirty example:
Directory with the files fetch-plugin.zon
, git-plugin.sh
and git-plugin.bat
.
content of fetch-plugin.zon
:
.{
.projectname = "git-plugin",
.protocols = .{
"git+http",
"git+https",
"git+ssh",
},
.kind = .Executable,
}
content of git-plugin.sh
:
#!/bin/sh
git clone --depth=1 "$2" "$1" >/dev/null 2>/dev/null
exit $?
content of git-plugin.bat
@echo off
git clone --depth=1 %2 %1 > nul 2> nul
exit %errorlevel%
Extracted from #14265.
Zig will have built-in support for fetching dependencies from some protocols, such as http, https, gzip, tar, and some others. But there will always be new or exotic protocols. One such example would be ipfs. Not really ubiquitous enough to support directly, but could be interesting for some people to use.
For this I propose a "fetch plugin" system.
Fetch plugins would be specified in build.zig.zon like this:
The url fields within
fetch_plugins
must use a built-in URI scheme or a different fetch plugin from the same manifest.Implementing this proposal will lift out this code from the zig compiler:
https://github.com/ziglang/zig/blob/7cb2f9222da38d687e8708dd5d94d3175cc77995/src/main.zig#L4080-L4126
...and move it to a new file
lib/fetch_runner.zig
. This is similar tobuild_runner.zig
andtest_runner.zig
and has the responsibility to fetch the full dependency tree. It will deal with fetch plugins by fetching them, and then rebuilding the fetch runner itself, multiple times if necessary, until everything is fetched.Once everything is fetched, build_runner.zig proceeds as usual. Note that in the case when everything is already fetched, the fetch_runner will not be executed because the open() syscalls on the first-level dependencies based on their hashes all succeeded.