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

Add Store::isTrustedClient() #7515

Merged
merged 1 commit into from
Apr 7, 2023

Conversation

MatthewCroughan
Copy link
Contributor

@MatthewCroughan MatthewCroughan commented Dec 26, 2022

This PR extends the worker protocol in worker-protocol-hh by adding a new operation (47) which permits a client to check if they are trusted. I have needed this for some scripts I'm trying to write which use Nix, that need to check.

In addition, it also adds a new command nix store check-trusted which will make use of this addition. It will return exit code 0 if trusted, 1 if not trusted or 2 if an unexpected error occurs.

I have also added a new checkInfo function to doctor.cc which will print an inconsequential blue [INFO] telling the user whether they are trusted. This does not change the exit status of the nix doctor command.

image

The following Bash function is an example of a fallback mechanism I've implemented in Bash but do not have the skills to implement in C++.

function isTrustedUser {
  function writeDummyBuildLog {
    {
      echo 0x6378696e 0x00000000; # WORKER_MAGIC_1
      echo 0x0a010000 0x00000000; # PROTOCOL_VERSION
      echo 0x2d000000 0x00000000; # wopAddBuildlog (45)
      echo 0x26000000 0x00000000; # Length of Store Path (38)
      echo -n "$(echo -n aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-a.drv | xxd -p -c0)00000000000000000000"; # Store Path
    } \
    | xxd -p -r \
    | socat - UNIX-CONNECT:/nix/var/nix/daemon-socket/socket \
    | tr -d '\0'
  }
  x=$(writeDummyBuildLog)
  if (grep -aq "error:" <<< "$x") && (grep -aq "not privileged" <<< "$x")
  then
    echo "You are not a trusted user"
    return 1
  elif (grep -aq "error:" <<< "$x")
    echo "An unknown error occurred whilst checking if you are a trusted user"
    return 2
  else
    :
    return 0
  fi
}
isTrustedUser

Thanks a lot to @roberth who introduced me to the C++ codebase and answering a lot of questions. And thanks to @tomberek + @pkharvey + @helicalbytes for helping me understand the daemon protocol.

@NobbZ
Copy link
Contributor

NobbZ commented Dec 27, 2022

This is a good first step into a solution for #6752/#6672.

Can't say much codewise though.

@MatthewCroughan
Copy link
Contributor Author

This PR will also improve #7461

src/libstore/dummy-store.cc Outdated Show resolved Hide resolved
src/libstore/remote-store.cc Outdated Show resolved Hide resolved
src/nix/doctor.cc Outdated Show resolved Hide resolved
@MatthewCroughan
Copy link
Contributor Author

MatthewCroughan commented Dec 27, 2022

I somehow accidentally removed the review request for @edolstra @fricklerhandwerk and @thufschmitt just by requesting a re-review from @max-privatevoid, this seems to be a bug in the way reviews are handled on GitHub. I am unable to add new reviewers, or add these reviewers back.

@MatthewCroughan MatthewCroughan marked this pull request as draft December 27, 2022 20:09
@MatthewCroughan MatthewCroughan marked this pull request as ready for review December 27, 2022 20:09
@MatthewCroughan
Copy link
Contributor Author

I marked the PR as a draft, then unmarked it as a draft. It seems that the GitHub review bug is still in effect.

@MatthewCroughan
Copy link
Contributor Author

Just pushed to resolve conflicts with the release notes.

src/libstore/daemon.cc Outdated Show resolved Hide resolved
src/libstore/build/local-derivation-goal.cc Outdated Show resolved Hide resolved
@MatthewCroughan MatthewCroughan changed the title Add Store::checkTrustedUser() and nix store check-trusted Add Store::isTrustedUser() and nix store check-trusted Dec 30, 2022
Copy link
Member

@thufschmitt thufschmitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that's a useful command to have I think.

Left some suggestions on the code and docs, but that looks good overall.

(That also makes me realize with horror that we don't have any test for the "non-trusted-user" case 😬 )

@@ -635,6 +635,9 @@ public:
return 0;
};

/* Check if the user making the connection is a trusted-user. */
virtual bool isTrustedUser() = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to define this to unsupported by default like we do for a bunch of other methods and remove all the custom implementations for the stores that don't support it:

Suggested change
virtual bool isTrustedUser() = 0;
virtual bool isTrustedUser()
{ unsupported("isTrustedUser"); }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That definitely makes it a smaller diff too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I've left the implementation for legacy ssh though, since it's more helpful to print it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thufschmitt This pattern is counterproductive for discovering such functionality as recursive nix store is not trusted early. Perhaps not a great example, but who knows what else we might have missed because of the bad default?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roberth since the default behaviour is to fail loudly, I think it's OK because it's a conservative approach, and we can always refine the implementation after the fact if we realize that we've been missing one

src/libstore/remote-store.cc Outdated Show resolved Hide resolved
src/nix/doctor.cc Outdated Show resolved Hide resolved
src/nix/store-check-trusted.cc Outdated Show resolved Hide resolved
src/nix/store-check-trusted.cc Outdated Show resolved Hide resolved
src/nix/store-check-trusted.cc Outdated Show resolved Hide resolved
src/nix/store-check-trusted.cc Outdated Show resolved Hide resolved
@MatthewCroughan
Copy link
Contributor Author

I've rebased this PR on 2.14 after the Nix 2.13 release yesterday.

tests/remote-store.sh Outdated Show resolved Hide resolved
@tomberek
Copy link
Contributor

From Nix meeting:

  • instead of a new subcommand, implement nix store ping to return these results explicitly when available
  • In a new PR add --json to nix store ping to allow for easier scripting.
  • include the trusted status into the daemon handshake, this is mediated in the area of the below.
if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 33) {
            conn.to.flush();
            conn.daemonNixVersion = readString(conn.from);
        } 

@yorickvP yorickvP mentioned this pull request Jan 31, 2023
7 tasks
@Ericson2314
Copy link
Member

@MatthewCroughan Do note with #7723 merged the nix store ping changes will be less work!

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2023-01-20-nix-team-meeting-minutes-25/25432/1

@MatthewCroughan
Copy link
Contributor Author

Have dropped the ball on this temporarily, I'm a bit ill after FOSDEM, will pick this up when I am better, anyone else feel free to contribute by making a PR to this PR!

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2023-01-23-nix-team-meeting-minutes-26/25433/1

@fricklerhandwerk fricklerhandwerk added feature Feature request or proposal UX The way in which users interact with Nix. Higher level than UI. store Issues and pull requests concerning the Nix store labels Mar 3, 2023
@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label Apr 3, 2023
@MatthewCroughan MatthewCroughan changed the title Add Store::isTrustedUser() and nix store check-trusted Add Store::isTrustedClient() Apr 3, 2023
@Ericson2314 Ericson2314 added the idea approved The given proposal has been discussed and approved by the Nix team. An implementation is welcome. label Apr 3, 2023
@fricklerhandwerk
Copy link
Contributor

Discussed in the Nix team meeting 2023-04-03:

  • @Ericson2314 rewrote the PR based on the team's requested changes, needs a different reviewer
  • assigned to @thufschmitt

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2023-04-03-nix-team-meeting-minutes-46/27008/1

@domenkozar
Copy link
Member

Would be great to have this in for 2.15.

Copy link
Member

@thufschmitt thufschmitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is good overall, but the wire encoding/decoding logic is a bit too smart imho. Let's keep things simple as much as we can.

doc/manual/src/release-notes/rl-next.md Outdated Show resolved Hide resolved
src/libstore/remote-store.cc Outdated Show resolved Hide resolved
src/libstore/daemon.cc Outdated Show resolved Hide resolved
This function returns true or false depending on whether the Nix client
is trusted or not. Mostly relevant when speaking to a remote store with
a daemon.

We include this information in `nix ping store` and `nix doctor`

Co-Authored-By: John Ericson <John.Ericson@Obsidian.Systems>
@Ericson2314
Copy link
Member

Good point, I did sort of forget about that mechanism! 😳

Copy link
Member

@thufschmitt thufschmitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay!

Just a small suggestion, but fairly minor and not blocking. So let's merge

case 2:
return { NotTrusted };
default:
throw Error("Invalid trusted status from remote");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving it for a potential follow-up (and fairly low-prio), but it could be nicer to just warn and return std::nullopt in that case. Just to make potential future evolutions of the protocol nicer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had thought about that, but I think it's just better to bunl the protocol version on that case? Maybe I'm forgetting, but I couldn't think of another time we tried to do this sort of week forward compat before.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently have more or less one forward compat mechanism, which is the protocol version handshake.
If we're going to improve the forward compat mechanism, it would make more sense to do it structurally, with a self-describing or schema based serialization where we can add fields as we please.

@thufschmitt thufschmitt merged commit 81dfc2b into NixOS:master Apr 7, 2023
@MatthewCroughan MatthewCroughan deleted the mc/check-trusted-user branch April 7, 2023 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Feature request or proposal idea approved The given proposal has been discussed and approved by the Nix team. An implementation is welcome. store Issues and pull requests concerning the Nix store UX The way in which users interact with Nix. Higher level than UI. with-tests Issues related to testing. PRs with tests have some priority
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

10 participants