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

yubikey-agent: init at 0.1.3 #92936

Merged
merged 1 commit into from Jul 23, 2020
Merged

Conversation

philandstuff
Copy link
Contributor

Motivation for this change

This adds yubikey-agent as a package and a nixos module.

The yubikey-agent is impure in how it calls pinentry; I tried patching
gopass to point at a particular pinentry but this changes the value of
vendorSha256 depending on the particular choice of pinentry program,
which felt frustratingly difficult. Instead, we use wrapProgram to
set a default pinentry in PATH, and use a systemd override to prefix
PATH to select a chosen pinentry program if specified.

On linux, we need libnotify to provide the notify-send utility for
desktop notifications (such as "Waiting for Yubikey touch...").

The systemd unit a copy of the one in the upstream repo, in systemd.md:
https://github.com/FiloSottile/yubikey-agent/blob/master/systemd.md

This might work on other flavors of unix, but I haven't tested.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

Copy link
Contributor

@flokli flokli left a comment

Choose a reason for hiding this comment

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

Thanks for the code! I don't think we should reinvent yet another pinentry selection, so we should just reuse the one from the gnupg module for the time being.

nixos/modules/services/security/yubikey-agent.nix Outdated Show resolved Hide resolved
nixos/modules/services/security/yubikey-agent.nix Outdated Show resolved Hide resolved
nixos/modules/services/security/yubikey-agent.nix Outdated Show resolved Hide resolved
nixos/modules/services/security/yubikey-agent.nix Outdated Show resolved Hide resolved
nixos/modules/services/security/yubikey-agent.nix Outdated Show resolved Hide resolved
pkgs/tools/security/yubikey-agent/yubikey-agent.service Outdated Show resolved Hide resolved
pkgs/top-level/all-packages.nix Outdated Show resolved Hide resolved
pkgs/tools/security/yubikey-agent/default.nix Outdated Show resolved Hide resolved
pkgs/tools/security/yubikey-agent/default.nix Outdated Show resolved Hide resolved
pkgs/tools/security/yubikey-agent/default.nix Outdated Show resolved Hide resolved
@flokli
Copy link
Contributor

flokli commented Jul 12, 2020

Is there any context/docs on why yubikey-agent is fine to discover pinentry from $PATH, whereas gpg-agent.conf insists on absoulte paths?

I did some digging in #90214 (comment), so would be nice to hear @FiloSottile's opinion on that as well :-)

@philandstuff
Copy link
Contributor Author

@flokli thank you for your thorough review! I agree with most of your points and will update the PR.

Yes, the way pinentry is configured is weird and idiosyncratic.

The gnupg nix package sets a hardcoded absolute path to pinentry. This works ok because programs like gpg-agent have a --pinentry-program command-line option to choose a different pinentry at runtime, as well as config file options and suchlike. This means that the gnupg nixos module can allow the user to configure their choice of pinentry program easily, even if the underlying gnupg package has a hardcoded pinentry path as a default value.

yubikey-agent pulls pinentry from PATH, and it does so in a 3rd party module (it's actually within gopass), which makes it incredibly awkward to patch an absolute path to pinentry instead. yubikey-agent also offers no way to choose a pinentry program at runtime other than by putting the desired one first in PATH. It has some code to dispatch to a different binary name on different OSes (pinentry.exe on windows, pinentry-mac on macOS, pinentry otherwise) but on non-macOS unixes it basically assumes the underlying distribution will provide an appropriate pinentry, in the PATH. In fairness this is the case with most distributions, but with nix it's completely against the philosophy.

I'm not sure I can think of a better alternative.

@flokli
Copy link
Contributor

flokli commented Jul 12, 2020

Doing the dance via the socket-activated gpg-agent.service in each users' systemd session was mostly done to avoid shipping the whole runtime closure of all (also graphical) pinentry flavours, and to provide a way to select the flavour (#71095), but as written in #90214 (comment), discovering from $PATH for gpg as well might help in some usecases.

We might want to open a discussion with the GnuPG people about why pinentry discovery there is the way it is, and why it's not defaulting to looking for it in $PATH if it's neither set in gpg-agent.conf, nor in --pinentry-program.

I'd like to understand the reasoning on why it currently doesn't do that (and if yubikey-agent/pass doing differently is actually a footgun - if it's not, I'm all for adding it to its $PATH as suggested in #92936 (comment)).

@philandstuff
Copy link
Contributor Author

Let’s assume we go with your proposal to just look for pinentry in PATH (for both gnupg and yubikey-agent). What happens if there is no pinentry anywhere on the PATH?

@FiloSottile
Copy link

yubikey-agent intentionally doesn't have a config file. Would a PINENTRY env var work for you? Happy to add it.

@philandstuff philandstuff force-pushed the add-yubikey-agent branch 2 times, most recently from 128ff96 to d883cfa Compare July 12, 2020 20:46
@philandstuff
Copy link
Contributor Author

philandstuff commented Jul 13, 2020

Okay, I've pushed a couple of updates. Key unresolved issues:

  • I agree that I should reuse the gnupg.agent.pinentryFlavor but i get an error
  • We need to decide how, and where, to configure pinentry

To expand on the pinentry discussion: as a starting point, I feel that a nix closure should contain everything it needs to function correctly. This is why, in general, nix packages depend on other packages via absolute store paths and not via PATH. If you have a dependency via PATH, that does not form part of the closure, and when you copy the closure to another system, you won't copy the dependency.

However, I can see how pinentry is a bit of a weird edge case: users might reasonably want to configure different types of pinentry, and they shouldn't have to install all the pinentries in order to use just one of them.

It's also worth noting that the dynamics on macOS are different: on macOS, there is only one pinentry implementation, and I think gnupg and yubikey-agent should just use it without any extra configuration. But on Linux (and probably other unixes) it's useful to be able to dynamically choose a pinentry program.

I must confess I read some of the discussions that @flokli linked to above (such as #90214 (comment)) but it's really hard to get context by jumping partway through a conversation and chasing back through many linked issues so it's mostly going above my head. But my understanding is: 1) gnupg has a baked-in pinentry choice, 2) gnupg allows users to choose a different pinentry at invocation time, 3) there is some desire (I don't know why) that gnupg should be able to use pinentry from PATH. In any case, the design of gnupg sounds like a live issue, so we shouldn't assume the current gnupg packaging is the correct way to go.

Right now my feeling is:

  • on macOS, the built yubikey-agent binary should use pinentry-mac without any extra configuration
  • on Linux, the built yubikey-agent could just get whatever pinentry it finds in PATH, and we don't need to bake in a default.
  • if the gnupg side of the discussion is resolved, I'm happy to try to ensure yubikey-agent is consistent with it.

How does that sound?

@philandstuff
Copy link
Contributor Author

@FiloSottile Thanks for the offer! I think we need to discuss things a bit further here but we may well take you up on this.

@philandstuff
Copy link
Contributor Author

Added @rawkode as a maintainer, ref: #92965 (comment)

@philandstuff
Copy link
Contributor Author

I pushed another update. I've pulled in the systemd unit from FiloSottile/yubikey-agent#43 but the relative path trick gave me the error: Executable "yubikey-agent" not found in path "/nix/store/zzr1p57r1ii6y0gm7kycid0gkw1hskp3-systemd-245.6/bin/" so I still need to substitute the nix store path into it.

I have removed baking in pinentry to PATH, except on macOS where we bake in pinentry_mac since there's no other choice.

I still haven't come up with a solution to reusing the gpg-agent pinentry selection (see #92936 (comment)).

@flokli
Copy link
Contributor

flokli commented Jul 15, 2020

I pushed another update. I've pulled in the systemd unit from FiloSottile/yubikey-agent#43 but the relative path trick gave me the error: Executable "yubikey-agent" not found in path "/nix/store/zzr1p57r1ii6y0gm7kycid0gkw1hskp3-systemd-245.6/bin/" so I still need to substitute the nix store path into it.

Yeah, this is expected.systemd luckily doesn't pick up things from $PATH when setting just a binary name in ExecStart= but looks up from paths baked into systemd.

On NixOS, we set this to $systemd/bin for reproducibility.

I have removed baking in pinentry to PATH, except on macOS where we bake in pinentry_mac since there's no other choice.

Is there not a native pinentry provided in $PATH?

I still haven't come up with a solution to reusing the gpg-agent pinentry selection (see #92936 (comment)).

Yeah, this is still somewhat pending. I'd probably prefer moving pinentry selection into a module both used from the gnupg module and this module over duplicating it…

@philandstuff
Copy link
Contributor Author

Is there not a native pinentry provided in $PATH?

macOS doesn’t provide one, no. The user might have installed one via gpgtools or homebrew, but plain macOS doesn’t have a pinentry.

@philandstuff
Copy link
Contributor Author

@flokli I've just pushed an update. It turns out the magic word I needed was mkMerge https://nixos.org/nixos/manual/#sec-option-definitions-merging

I think this resolves all the issues we had. PTAL 😄

@rawkode
Copy link
Member

rawkode commented Jul 16, 2020

I'm learning a lot from monitoring this, thank you for your persistence @philandstuff

Copy link
Contributor

@flokli flokli left a comment

Choose a reason for hiding this comment

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

Thanks for the persistence too :-) I think the pinentry problem could be solved without the mkMerge, sent another review.

nixos/modules/programs/gnupg.nix Outdated Show resolved Hide resolved
This adds yubikey-agent as a package and a nixos module.

On macOS, we use `wrapProgram` to set pinentry_mac as default in PATH;
on Linux we rely on the user to set their preferred pinentry in PATH.
In particular, we use a systemd override to prefix PATH to select a
chosen pinentry program if specified.

On Linux, we need libnotify to provide the notify-send utility for
desktop notifications (such as "Waiting for Yubikey touch...").

This might work on other flavors of unix, but I haven't tested.

We reuse the programs.gnupg.agent.pinentryFlavor option for
yubikey-agent, but in doing so I hit a problem: pinentryFlavour's
default value is specified in a mkDefault, but only conditionally.  We
ought to be able to pick up the pinentryFlavour whether or not gpg-agent
is running.  As a result, this commit moves the default value to the
definition of programs.gnupg.agent.enable.
@philandstuff
Copy link
Contributor Author

@flokli pushed another update

@flokli
Copy link
Contributor

flokli commented Jul 20, 2020

This LGTM. I poked upstream for a new release containing the unit file in FiloSottile/yubikey-agent#43 (comment), so we could avoid duplicating this.

cc @Ma27 on the pinentry changes.

@flokli
Copy link
Contributor

flokli commented Jul 23, 2020

Okay, let's merge this as-is. We can always move to the upstream-provided systemd unit, once there's a new release. 👍

Thanks for your work!

@flokli flokli merged commit 8f7a623 into NixOS:master Jul 23, 2020
@philandstuff philandstuff mentioned this pull request Jul 24, 2020
10 tasks
philandstuff added a commit to philandstuff/nixpkgs that referenced this pull request Jul 25, 2020
Mea culpa: in NixOS#92936, I did originally test on macOS but I forgot to
retest after adding the piv-go patch.  Unfortunately, the piv-go patch
is broken on macOS (but fortunately it is unnecessary).
philandstuff added a commit to philandstuff/nixpkgs that referenced this pull request Jul 25, 2020
Mea culpa: in NixOS#92936, I did originally test on macOS but I forgot to
retest after adding the piv-go patch.  Unfortunately, the piv-go patch
was broken on macOS.  This pulls in the latest version of
go-piv/piv-go#75 which works on macOS now.
@philandstuff philandstuff mentioned this pull request Jul 25, 2020
10 tasks
@vcunat
Copy link
Member

vcunat commented Jul 26, 2020

Another problematic platform is i686. I expect it would be OK not to build on unusual platforms unless it made default NixOS depend on the package.

I checked it's not fixed by #93850. You can test on x86_64 by building pkgsi686Linux.yubikey-agent. Example failure on Hydra. Almost all i686 NixOS tests are broken now, EDIT: and nixos-unstable channel is blocked by it as well.

@flokli
Copy link
Contributor

flokli commented Jul 26, 2020

@vcunat Uh, somehow I missed this was missing a mkIf cfg.enable, pulling in yubikey-agent unconditionally 🤦

PR at #93892.

@flokli
Copy link
Contributor

flokli commented Jul 26, 2020

The PR was merged, so we can try to fix i686 at a later time. I opened go-piv/piv-go#76 for investigation.

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

Successfully merging this pull request may close these issues.

None yet

6 participants