Support for specifying git access-tokens with file paths in nix.conf #526

Open
opened 2024-09-17 05:49:27 +00:00 by lehmanator · 4 comments

To configure Lix / Nix to use an access token for git forges, you currently must specify the option access-tokens = ... in nix.conf, which would add the token to the Nix store, something most people would probably want to keep private.

This is a problem most Nix users will eventually run into, and one without a trivial solution. Misconfiguration can easily result in users exposing plaintext tokens to VCS, global-readable /nix/store, or a public binary cache.

CppNix had issue #6536 filed in 2022, but no action has been taken on a fix for a pretty common papercut (30+ :thumbs-up: reactions)

Describe the solution you'd like

Add a configuration option to nix.conf that allows using access-tokens by specifying files, directories, and/or path globs containing access-tokens to use.

Example nix.conf options:

  access-token-files = /run/secrets/github.token, /run/secrets/gitlab.token`
  access-token-files = /run/secrets/git-*.token
  access-token-dirs = /run/secrets/git

Not particularly partial to any solution, but it would also be nice to specify directories in addition to files.

Describe alternatives you've considered

There are a handful of workarounds for this,
but they are all clunky, add boilerplate just to avoid hitting API rate limits, and don't gracefully handle multiple access tokens.

e.g. the one I use:

{ # Actual token must be prefixed with:  "access-tokens = "
  sops.secrets."github.token" = {};
  nix.extraConfig = ''
    !includes ${sops.secrets."github.token".path}`
  '';
}

Creating .netrc or .git-credentials files has the same problem of writing tokens to the Nix store or embedding the entire config in the encrypted secret.

Setting the environment variable NIX_CONFIG='access-tokens=...' also doesn't play well with encrypted secrets.

## Is your feature request related to a problem? Please describe. To configure Lix / Nix to use an access token for git forges, you currently must specify the option `access-tokens = ...` in `nix.conf`, which would add the token to the Nix store, something most people would probably want to keep private. This is a problem most Nix users will eventually run into, and one without a trivial solution. Misconfiguration can easily result in users exposing plaintext tokens to VCS, global-readable `/nix/store`, or a public binary cache. CppNix had [issue #6536](https://github.com/NixOS/nix/issues/6536) filed in 2022, but no action has been taken on a fix for a pretty common papercut (30+ `:thumbs-up:` reactions) ## Describe the solution you'd like Add a configuration option to `nix.conf` that allows using `access-tokens` by specifying files, directories, and/or path globs containing `access-tokens` to use. Example `nix.conf` options: ```nix access-token-files = /run/secrets/github.token, /run/secrets/gitlab.token` access-token-files = /run/secrets/git-*.token access-token-dirs = /run/secrets/git ``` Not particularly partial to any solution, but it would also be nice to specify directories in addition to files. ## Describe alternatives you've considered There are a handful of workarounds for this, but they are all clunky, add boilerplate just to avoid hitting API rate limits, and don't gracefully handle multiple access tokens. e.g. the one I use: ```nix { # Actual token must be prefixed with: "access-tokens = " sops.secrets."github.token" = {}; nix.extraConfig = '' !includes ${sops.secrets."github.token".path}` ''; } ``` Creating `.netrc` or `.git-credentials` files has the same problem of writing tokens to the Nix store or embedding the entire config in the encrypted secret. Setting the environment variable `NIX_CONFIG='access-tokens=...'` also doesn't play well with encrypted secrets.
Owner

Feels like to me that path globs encompass directories and files, so there's no need for two different options if globs are allowed.

The only left problem is the merging strategy, it's unclear to me which of the option overrides the other and inside multiple files, which file override. Maybe the good thing to do is to say access-tokens have precedence over access-token-files and that no same credential can be declared in two files. If there's collisions, there should be a warning anyway.

Feels like to me that path globs encompass directories and files, so there's no need for two different options if globs are allowed. The only left problem is the merging strategy, it's unclear to me which of the option overrides the other and inside multiple files, which file override. Maybe the good thing to do is to say access-tokens have precedence over access-token-files and that no same credential can be declared in two files. If there's collisions, there should be a warning anyway.
Author

there's no need for two different options if globs are allowed.

Yeah, I wasn't necessarily suggesting that we implement all of these options and string semantics. My example was more to show a couple of potentially viable implementation ideas.

I would like to have a way of specifying both directories and files simultaneously, but that makes handling precedence less trivial.

If these options were to coexist, it would probably be best to make the more explicit/specific entries take precedence over the less specific ones. So something like: access-tokens > access-token-files > access-token-dirs

Supporting globbing would implement both files and directories under the same option, but would also require some uncommon parsing semantics with the <myhost.tld>=<tokenData> format. Not sure if globs are used in any other nix.conf options, but that might add more complexity than otherwise desired, especially if any other external tooling reads nix.conf.

The simplest MVP implementation would probably be:

  • just add the option: access-token-files
  • prefer entries from access-tokens to those of access-token-files when hostname conflicts arise.
  • only use lower-priority entries when the access token in a higher-priority entry fails.

Then the only major implementation decision left would be whether to specify them as:

# Like access-tokens, but with the token string replaced with the path containing the string.
access-token-files = github.com=/run/secrets/git/github.token git.lix.systems=/run/secrets/git/lix-systems.token

OR

# Files that directly specify entire entries in the key-value format.
access-token-files = /run/secrets/git/github.token /run/secrets/git/lix-systems.token

Copying the semantics of the existing access-tokens option as closely as possible would be easier to implement and less surprising to users.

Conflict warnings would be nice, and seems like a common sense behavior to avoid silently overriding user expectations.

Not sure if this is out-of-scope or too opinionated, but I think if we implement this feature, having access-tokens specified should generate a warning about potentially adding plaintext secrets to the Nix store.

> there's no need for two different options if globs are allowed. Yeah, I wasn't necessarily suggesting that we implement *all* of these options and string semantics. My example was more to show a couple of potentially viable implementation ideas. I would *like* to have a way of specifying both directories and files simultaneously, but that makes handling precedence less trivial. If these options were to coexist, it would probably be best to make the more explicit/specific entries take precedence over the less specific ones. So something like: `access-tokens` > `access-token-files` > `access-token-dirs` Supporting globbing *would* implement both files and directories under the same option, but would also require some uncommon parsing semantics with the `<myhost.tld>=<tokenData>` format. Not sure if globs are used in any other `nix.conf` options, but that might add more complexity than otherwise desired, especially if any other external tooling reads `nix.conf`. The simplest MVP implementation would probably be: - just add the option: `access-token-files` - prefer entries from `access-tokens` to those of `access-token-files` when hostname conflicts arise. - only use lower-priority entries when the access token in a higher-priority entry fails. Then the only major implementation decision left would be whether to specify them as: ```ini # Like access-tokens, but with the token string replaced with the path containing the string. access-token-files = github.com=/run/secrets/git/github.token git.lix.systems=/run/secrets/git/lix-systems.token ``` *OR* ```ini # Files that directly specify entire entries in the key-value format. access-token-files = /run/secrets/git/github.token /run/secrets/git/lix-systems.token ``` Copying the semantics of the existing `access-tokens` option as closely as possible would be easier to implement and less surprising to users. Conflict warnings would be nice, and seems like a common sense behavior to avoid silently overriding user expectations. *Not sure if this is out-of-scope or too opinionated*, but I think if we implement this feature, having `access-tokens` specified should generate a warning about potentially adding plaintext secrets to the Nix store.
Owner

I think parsing complexity for external consumers is not an explicit goal for us. But options which have complicated override semantics are in scope for the design and they add more complexity IMHO.

I think parsing complexity for external consumers is not an explicit goal for us. But options which have complicated override semantics are in scope for the design and they add more complexity IMHO.
jade added the
Area/fetching
label 2024-10-20 01:04:19 +00:00
Owner

@lehmanator if you can propose a patch, I can take time with you to look through it. :)

@lehmanator if you can propose a patch, I can take time with you to look through it. :)
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lix-project/lix#526
No description provided.