Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

restrict-eval in niv #145

Closed
nmattia opened this issue Nov 21, 2019 · 5 comments
Closed

restrict-eval in niv #145

nmattia opened this issue Nov 21, 2019 · 5 comments

Comments

@nmattia
Copy link
Owner

nmattia commented Nov 21, 2019

When enabling restrict-eval, with --option restrict-eval true, Nix adds some restrictions to the evaluation:

  • no IFD
  • no files can be accessed outside of the NIX_PATH

(and a few other things irrelevant here). I had to fix naersk to work with restrict-eval and had to hack the build steps to enable restricted evaluation. It amounted to generating a NIX_PATH from sources.json (this is needed to access e.g. nixpkgs):

#!/usr/bin/env bash
# vim: ft=sh

set -euo pipefail

keys=$(cat nix/sources.json | jq -rc 'keys | .[]')
readonly keys

IFS='
'
NIV_PATH=

for key in $keys; do
    spec=$(cat nix/sources.json | jq -c ".\"$key\"")
    owner=$(echo "$spec" | jq -r '.owner')
    repo=$(echo "$spec" | jq -r '.repo')
    rev=$(echo "$spec" | jq -r '.rev')
    cachepath="$HOME/.cache/niv/git/$owner/$repo/$rev"
    echo "$cachepath"
    if ! [ -d  "$cachepath" ]; then
        git clone "git@github.com:$owner/$repo" "$cachepath"
        pushd "$cachepath"
        git checkout "$rev"
        popd
    fi
    if ! [ -z "$NIV_PATH" ]; then
        NIV_PATH=":$NIV_PATH"
    fi
    NIV_PATH="$key=$cachepath$NIV_PATH"
done

echo "final nix path: $NIV_PATH"

NIX_PATH="niv_is_niv_build=.:src=.:$NIV_PATH" \
    NIV_BUILD=1 \
    nix-build  ...

then by tweaking the sources.nix all sources can be access with <source-name>, like <nixpkgs>:

diff --git a/nix/sources.nix b/nix/sources.nix
index 7a9a2ae..4f7bf1d 100644
--- a/nix/sources.nix
+++ b/nix/sources.nix
@@ -1,8 +1,7 @@
 # This file has been generated by Niv.
 
 # A record, from name to path, of the third-party packages
-with rec
-{
+let
   pkgs =
     if hasNixpkgsPath
     then
@@ -74,16 +73,24 @@ with rec
       "file" = pkgs.fetchurl;
       "builtin-url" = builtins_fetchurl;
     };
-};
-# NOTE: spec must _not_ have an "outPath" attribute
-mapAttrs (_: spec:
-  if builtins.hasAttr "outPath" spec
-  then abort
-    "The values in sources.json should not have an 'outPath' attribute"
-  else
-    if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec
-    then
-      spec //
-      { outPath = callFunctionWith spec (getFetcher spec) { }; }
-    else spec
-  ) sources
+  drvs =
+    mapAttrs (_: spec:
+      if builtins.hasAttr "outPath" spec
+      then abort
+        "The values in sources.json should not have an 'outPath' attribute"
+      else
+        if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec
+        then
+          spec //
+          { outPath = callFunctionWith spec (getFetcher spec) { }; }
+        else spec
+      ) sources;
+  fixupDrvs = if ! (builtins.tryEval <niv_is_niv_build>).success then (x: x) else
+    let
+      nixPath = builtins.listToAttrs (map (x: { name = x.prefix; value = x.path; }) builtins.nixPath);
+    in ds:
+      builtins.mapAttrs (k: v:
+      if builtins.hasAttr k nixPath
+      then v // { outPath = nixPath.${k}; } else v) ds;
+in
+  fixupDrvs drvs

this will be trivially solved by flakes, although in the meantime niv could have some support for populating the NIX_PATH.

@michaelpj
Copy link
Contributor

We use niv in restricted evaluation mode (on Hydra) just fine. The main issues are:

  • builtins.fetchTarball is disallowed except for allowed-uris, so if you're using a builtin-tarball fetcher to bootstrap your nixpkgs, you'll need to add the URI for that to allowed-uris.
  • pkgs.fetchzip and co do work in restricted mode, because they're implemented from scratch as fixed-output derivations.
  • I don't think IFD is restricted? We certainly use it.

@nmattia
Copy link
Owner Author

nmattia commented Nov 21, 2019

I don't think IFD is restricted? We certainly use it.

Interesting. I was told by different people that restrict-eval prevents IFD/R(readFile)FD and believed it. My understanding of restrict-eval is nonetheless somewhat shattered now, which I summed up here: NixOS/nix#3234

@michaelpj
Copy link
Contributor

michaelpj commented Nov 22, 2019

My understanding of restrict-eval comes from reading the nix source code 😅 That is to say, there's not much documentation!

It pretty much just affects which files you can put into the nix store. Once you've done that, though, you're fine to import from them.

So the particular common case of "IFD from fixed-output derivation" does work.

@nmattia
Copy link
Owner Author

nmattia commented Nov 22, 2019

Thanks! This is an interesting idea, but no real application then. Closing!

@nmattia nmattia closed this as completed Nov 22, 2019
@nmattia
Copy link
Owner Author

nmattia commented Dec 3, 2019

Actually, I confirm: builtins.fetchTarball and builtins.fetchurl are not available in restrict-eval, according to the manual:


builtins.fetchurl url
Download the specified URL and return the path of the downloaded file. This function is not available if restricted evaluation mode is enabled.

fetchTarball url, builtins.fetchTarball url
Download the specified URL, unpack it and return the path of the unpacked tree. The file must be a tape archive (.tar) compressed with gzip, bzip2 or xz. The top-level path component of the files in the tarball is removed, so it is best if the tarball contains a single directory at top level. The typical use of the function is to obtain external Nix expression dependencies, such as a particular version of Nixpkgs, e.g.

with import (fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz) {};

stdenv.mkDerivation { … }
The fetched tarball is cached for a certain amount of time (1 hour by default) in ~/.cache/nix/tarballs/. You can change the cache timeout either on the command line with --option tarball-ttl number of seconds or in the Nix configuration file with this option: tarball-ttl number of seconds to cache.

Note that when obtaining the hash with nix-prefetch-url the option --unpack is required.

This function can also verify the contents against a hash. In that case, the function takes a set instead of a URL. The set requires the attribute url and the attribute sha256, e.g.

with import (fetchTarball {
url = https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz;
sha256 = "1jppksrfvbk5ypiqdz4cddxdl8z6zyzdb2srq8fcffr327ld5jj2";
}) {};

stdenv.mkDerivation { … }
This function is not available if restricted evaluation mode is enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants