Add option allowed-uris
This allows network access in restricted eval mode.
This commit is contained in:
parent
f1c555cef8
commit
812e027e1d
|
@ -563,7 +563,8 @@ password <replaceable>my-password</replaceable>
|
||||||
<para>If set to <literal>true</literal>, the Nix evaluator will
|
<para>If set to <literal>true</literal>, the Nix evaluator will
|
||||||
not allow access to any files outside of the Nix search path (as
|
not allow access to any files outside of the Nix search path (as
|
||||||
set via the <envar>NIX_PATH</envar> environment variable or the
|
set via the <envar>NIX_PATH</envar> environment variable or the
|
||||||
<option>-I</option> option). The default is
|
<option>-I</option> option), or to URIs outside of
|
||||||
|
<option>allowed-uri</option>. The default is
|
||||||
<literal>false</literal>.</para>
|
<literal>false</literal>.</para>
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
|
@ -571,6 +572,21 @@ password <replaceable>my-password</replaceable>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry xml:id="conf-allowed-uris"><term><literal>allowed-uris</literal></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
|
||||||
|
<para>A list of URI prefixes to which access is allowed in
|
||||||
|
restricted evaluation mode. For example, when set to
|
||||||
|
<literal>https://github.com/NixOS</literal>, builtin functions
|
||||||
|
such as <function>fetchGit</function> are allowed to access
|
||||||
|
<literal>https://github.com/NixOS/patchelf.git</literal>.</para>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
<varlistentry xml:id="conf-pre-build-hook"><term><literal>pre-build-hook</literal></term>
|
<varlistentry xml:id="conf-pre-build-hook"><term><literal>pre-build-hook</literal></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -418,6 +418,14 @@ configureFlags = "--prefix=${placeholder "out"} --includedir=${placeholder "dev"
|
||||||
through the MELPA package repository.</para>
|
through the MELPA package repository.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>In restricted evaluation mode
|
||||||
|
(<option>--restrict-eval</option>), builtin functions that
|
||||||
|
download from the network (such as <function>fetchGit</function>)
|
||||||
|
are permitted to fetch underneath the list of URI prefixes
|
||||||
|
specified in the option <option>allowed-uris</option>.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
<para>This release has contributions from TBD.</para>
|
<para>This release has contributions from TBD.</para>
|
||||||
|
|
|
@ -355,6 +355,26 @@ Path EvalState::checkSourcePath(const Path & path_)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EvalState::checkURI(const std::string & uri)
|
||||||
|
{
|
||||||
|
if (!restricted) return;
|
||||||
|
|
||||||
|
/* 'uri' should be equal to a prefix, or in a subdirectory of a
|
||||||
|
prefix. Thus, the prefix https://github.co does not permit
|
||||||
|
access to https://github.com. Note: this allows 'http://' and
|
||||||
|
'https://' as prefixes for any http/https URI. */
|
||||||
|
for (auto & prefix : settings.allowedUris.get())
|
||||||
|
if (uri == prefix ||
|
||||||
|
(uri.size() > prefix.size()
|
||||||
|
&& prefix.size() > 0
|
||||||
|
&& hasPrefix(uri, prefix)
|
||||||
|
&& (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw RestrictedPathError("access to URI '%s' is forbidden in restricted mode", uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EvalState::addConstant(const string & name, Value & v)
|
void EvalState::addConstant(const string & name, Value & v)
|
||||||
{
|
{
|
||||||
Value * v2 = allocValue();
|
Value * v2 = allocValue();
|
||||||
|
|
|
@ -110,6 +110,8 @@ public:
|
||||||
|
|
||||||
Path checkSourcePath(const Path & path);
|
Path checkSourcePath(const Path & path);
|
||||||
|
|
||||||
|
void checkURI(const std::string & uri);
|
||||||
|
|
||||||
/* Parse a Nix expression from the specified file. */
|
/* Parse a Nix expression from the specified file. */
|
||||||
Expr * parseExprFromFile(const Path & path);
|
Expr * parseExprFromFile(const Path & path);
|
||||||
Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv);
|
Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv);
|
||||||
|
|
|
@ -1937,8 +1937,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
||||||
} else
|
} else
|
||||||
url = state.forceStringNoCtx(*args[0], pos);
|
url = state.forceStringNoCtx(*args[0], pos);
|
||||||
|
|
||||||
if (state.restricted)
|
state.checkURI(url);
|
||||||
throw Error(format("'%1%' is not allowed in restricted mode") % who);
|
|
||||||
|
|
||||||
Path res = getDownloader()->downloadCached(state.store, url, unpack, name, expectedHash);
|
Path res = getDownloader()->downloadCached(state.store, url, unpack, name, expectedHash);
|
||||||
mkString(v, res, PathSet({res}));
|
mkString(v, res, PathSet({res}));
|
||||||
|
|
|
@ -113,9 +113,6 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
|
||||||
|
|
||||||
static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
// FIXME: cut&paste from fetch().
|
|
||||||
if (state.restricted) throw Error("'fetchGit' is not allowed in restricted mode");
|
|
||||||
|
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string ref = "master";
|
std::string ref = "master";
|
||||||
std::string rev;
|
std::string rev;
|
||||||
|
@ -150,6 +147,10 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
} else
|
} else
|
||||||
url = state.forceStringNoCtx(*args[0], pos);
|
url = state.forceStringNoCtx(*args[0], pos);
|
||||||
|
|
||||||
|
// FIXME: git externals probably can be used to bypass the URI
|
||||||
|
// whitelist. Ah well.
|
||||||
|
state.checkURI(url);
|
||||||
|
|
||||||
auto gitInfo = exportGit(state.store, url, ref, rev, name);
|
auto gitInfo = exportGit(state.store, url, ref, rev, name);
|
||||||
|
|
||||||
state.mkAttrs(v, 8);
|
state.mkAttrs(v, 8);
|
||||||
|
|
|
@ -225,7 +225,7 @@ public:
|
||||||
|
|
||||||
Setting<bool> restrictEval{this, false, "restrict-eval",
|
Setting<bool> restrictEval{this, false, "restrict-eval",
|
||||||
"Whether to restrict file system access to paths in $NIX_PATH, "
|
"Whether to restrict file system access to paths in $NIX_PATH, "
|
||||||
"and to disallow fetching files from the network."};
|
"and network access to the URI prefixes listed in 'allowed-uris'."};
|
||||||
|
|
||||||
Setting<size_t> buildRepeat{this, 0, "repeat",
|
Setting<size_t> buildRepeat{this, 0, "repeat",
|
||||||
"The number of times to repeat a build in order to verify determinism.",
|
"The number of times to repeat a build in order to verify determinism.",
|
||||||
|
@ -353,6 +353,8 @@ public:
|
||||||
Setting<uint64_t> maxFree{this, std::numeric_limits<uint64_t>::max(), "max-free",
|
Setting<uint64_t> maxFree{this, std::numeric_limits<uint64_t>::max(), "max-free",
|
||||||
"Stop deleting garbage when free disk space is above the specified amount."};
|
"Stop deleting garbage when free disk space is above the specified amount."};
|
||||||
|
|
||||||
|
Setting<Strings> allowedUris{this, {}, "allowed-uris",
|
||||||
|
"Prefixes of URIs that builtin functions such as fetchurl and fetchGit are allowed to fetch."};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,15 @@ nix-instantiate --option restrict-eval true --eval -E 'builtins.readDir ../src/b
|
||||||
(! nix-instantiate --option restrict-eval true --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>')
|
(! nix-instantiate --option restrict-eval true --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>')
|
||||||
nix-instantiate --option restrict-eval true --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>' -I src=.
|
nix-instantiate --option restrict-eval true --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>' -I src=.
|
||||||
|
|
||||||
|
p=$(nix eval --raw "(builtins.fetchurl file://$(pwd)/restricted.sh)" --restrict-eval --allowed-uris "file://$(pwd)")
|
||||||
|
cmp $p restricted.sh
|
||||||
|
|
||||||
|
(! nix eval --raw "(builtins.fetchurl file://$(pwd)/restricted.sh)" --restrict-eval)
|
||||||
|
|
||||||
|
(! nix eval --raw "(builtins.fetchurl file://$(pwd)/restricted.sh)" --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh/")
|
||||||
|
|
||||||
|
nix eval --raw "(builtins.fetchurl file://$(pwd)/restricted.sh)" --restrict-eval --allowed-uris "file://$(pwd)/restricted.sh"
|
||||||
|
|
||||||
|
(! nix eval --raw "(builtins.fetchurl https://github.com/NixOS/patchelf/archive/master.tar.gz)" --restrict-eval)
|
||||||
|
(! nix eval --raw "(builtins.fetchTarball https://github.com/NixOS/patchelf/archive/master.tar.gz)" --restrict-eval)
|
||||||
|
(! nix eval --raw "(fetchGit git://github.com/NixOS/patchelf.git)" --restrict-eval)
|
||||||
|
|
Loading…
Reference in a new issue