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 | ||||
|       not allow access to any files outside of the Nix search path (as | ||||
|       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> | ||||
| 
 | ||||
|     </listitem> | ||||
|  | @ -571,6 +572,21 @@ password <replaceable>my-password</replaceable> | |||
|   </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> | ||||
| 
 | ||||
|     <listitem> | ||||
|  |  | |||
|  | @ -418,6 +418,14 @@ configureFlags = "--prefix=${placeholder "out"} --includedir=${placeholder "dev" | |||
|     through the MELPA package repository.</para> | ||||
|   </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> | ||||
| 
 | ||||
| <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) | ||||
| { | ||||
|     Value * v2 = allocValue(); | ||||
|  |  | |||
|  | @ -110,6 +110,8 @@ public: | |||
| 
 | ||||
|     Path checkSourcePath(const Path & path); | ||||
| 
 | ||||
|     void checkURI(const std::string & uri); | ||||
| 
 | ||||
|     /* Parse a Nix expression from the specified file. */ | ||||
|     Expr * parseExprFromFile(const Path & path); | ||||
|     Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv); | ||||
|  |  | |||
|  | @ -1937,8 +1937,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, | |||
|     } else | ||||
|         url = state.forceStringNoCtx(*args[0], pos); | ||||
| 
 | ||||
|     if (state.restricted) | ||||
|         throw Error(format("'%1%' is not allowed in restricted mode") % who); | ||||
|     state.checkURI(url); | ||||
| 
 | ||||
|     Path res = getDownloader()->downloadCached(state.store, url, unpack, name, expectedHash); | ||||
|     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) | ||||
| { | ||||
|     // FIXME: cut&paste from fetch().
 | ||||
|     if (state.restricted) throw Error("'fetchGit' is not allowed in restricted mode"); | ||||
| 
 | ||||
|     std::string url; | ||||
|     std::string ref = "master"; | ||||
|     std::string rev; | ||||
|  | @ -150,6 +147,10 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va | |||
|     } else | ||||
|         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); | ||||
| 
 | ||||
|     state.mkAttrs(v, 8); | ||||
|  |  | |||
|  | @ -225,7 +225,7 @@ public: | |||
| 
 | ||||
|     Setting<bool> restrictEval{this, false, "restrict-eval", | ||||
|         "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", | ||||
|         "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", | ||||
|         "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>' -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