Add option allowed-uris
This allows network access in restricted eval mode.
This commit is contained in:
		
							parent
							
								
									f1c555cef8
								
							
						
					
					
						commit
						812e027e1d
					
				
					 8 changed files with 67 additions and 7 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue