Compare commits

..

No commits in common. "main" and "v0.2.0" have entirely different histories.
main ... v0.2.0

9 changed files with 28 additions and 188 deletions

View file

@ -4,22 +4,6 @@
Changes yet to be released are documented here.
## v0.3.0
- Stop setting `nix.settings.netrc-file` from the Home Manager module
- Document `netrc_path` in `config.toml` as the path operators should wire into their daemon configuration
- Add a module evaluation check to prevent the Home Manager module from reintroducing `nix.settings.netrc-file`
These changes are made to support both cppnix and detsysnix. The latter has [special requirements][additionalnetrcsources] around the `netrc` files.
[additionalnetrcsources]: https://docs.determinate.systems/determinate-nix/#additionalnetrcsources
## v0.2.1
- Fix netrc parsing for one-line entries such as `machine ... login ... password ...`
- Always write netrc entries as one line with a non-empty login (`dummy`)
- Add regression tests for one-line netrc parsing and write format
## v0.2.0
- Improve config discovery for server workflows:

View file

@ -58,14 +58,6 @@ netrc_path = "$XDG_CONFIG_HOME/nix/netrc"
Path values support environment variable expansion (`$VAR` and `${VAR}`).
`netrc_path` is the path this tool writes tokens to.
Configure Nix to read that same path.
This supports both cppnix and detsysnix. The latter has [special
requirements][additionalnetrcsources] around `netrc` files, so set
`additionalNetrcSources` to include the configured `netrc_path`.
## Usage
```bash
@ -86,15 +78,6 @@ Config path resolution order:
The NixOS server module exports `NIX_CACHE_LOGIN_CONFIG` and installs
`/etc/nix-cache-login/config.toml` from `services.nix-cache-login-server.configFile`.
## Module Integration
The Home Manager and NixOS modules in this repo install the package and refresh
services.
Nix and detsysnix daemon configuration stays outside these modules.
Set your daemon to read the `netrc_path` configured in `config.toml`.
## Maintenance
This tool is actively maintained by [Guardian Project](https://guardianproject.info).
@ -109,7 +92,6 @@ For security-related issues, please contact us through our [security policy][sec
[issues]: https://guardianproject.dev/ops/nix-cache-login/issues
[sec]: https://guardianproject.info/contact/
[additionalnetrcsources]: https://docs.determinate.systems/determinate-nix/#additionalnetrcsources
## License

10
flake.lock generated
View file

@ -2,12 +2,12 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1775423009,
"narHash": "sha256-vPKLpjhIVWdDrfiUM8atW6YkIggCEKdSAlJPzzhkQlw=",
"rev": "68d8aa3d661f0e6bd5862291b5bb263b2a6595c9",
"revCount": 975402,
"lastModified": 1771848320,
"narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=",
"rev": "2fc6539b481e1d2569f25f8799236694180c0993",
"revCount": 953160,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.975402%2Brev-68d8aa3d661f0e6bd5862291b5bb263b2a6595c9/019d657b-b3b7-7288-b3c0-42d420df206b/source.tar.gz"
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.953160%2Brev-2fc6539b481e1d2569f25f8799236694180c0993/019c8e05-d2f6-7c7e-9ead-612154b18bfb/source.tar.gz"
},
"original": {
"type": "tarball",

View file

@ -36,7 +36,6 @@
'';
doCheck = true;
});
module-checks = import ./module-checks.nix { inherit self pkgs; };
devShell = self.devShells.${pkgs.stdenv.hostPlatform.system}.default;
}
// pkgs.lib.optionalAttrs pkgs.stdenv.isLinux {

View file

@ -26,6 +26,7 @@ in
};
config = lib.mkIf cfg.enable {
nix.settings.netrc-file = "${config.xdg.configHome}/nix/netrc";
home.packages = [ cfg.package ];
systemd.user.services.nix-cache-login = {
Unit.Description = "Nix cache login - refresh access token";

View file

@ -93,34 +93,23 @@ func parse(path string) ([]entry, error) {
}
fields := strings.Fields(line)
for i := 0; i < len(fields); {
switch fields[i] {
case "machine":
if i+1 >= len(fields) {
i++
if len(fields) < 2 {
continue
}
switch fields[0] {
case "machine":
if current != nil {
entries = append(entries, *current)
}
current = &entry{machine: fields[i+1]}
i += 2
current = &entry{machine: fields[1]}
case "login":
if current != nil && i+1 < len(fields) {
current.login = fields[i+1]
i += 2
continue
if current != nil {
current.login = fields[1]
}
i++
case "password":
if current != nil && i+1 < len(fields) {
current.password = fields[i+1]
i += 2
continue
}
i++
default:
i++
if current != nil {
current.password = fields[1]
}
}
}
@ -141,12 +130,11 @@ func write(path string, entries []entry) error {
}
var b strings.Builder
for _, e := range entries {
login := e.login
if login == "" {
login = "dummy"
for i, e := range entries {
if i > 0 {
b.WriteString("\n")
}
fmt.Fprintf(&b, "machine %s login %s password %s\n", e.machine, login, e.password)
fmt.Fprintf(&b, "machine %s\nlogin %s\npassword %s\n", e.machine, e.login, e.password)
}
if err := os.WriteFile(path, []byte(b.String()), 0600); err != nil {

View file

@ -3,7 +3,6 @@ package netrc
import (
"os"
"path/filepath"
"strings"
"testing"
)
@ -56,28 +55,6 @@ func TestUpsertUpdateExisting(t *testing.T) {
}
}
func TestUpsertUpdateExistingOneLineEntry(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "netrc")
initial := "machine other.host login dummy password otherpass\nmachine cache.example.com login dummy password oldtoken\n"
if err := os.WriteFile(path, []byte(initial), 0600); err != nil {
t.Fatal(err)
}
if err := Upsert(path, "cache.example.com", "newtoken"); err != nil {
t.Fatalf("unexpected error: %v", err)
}
pw, err := GetPassword(path, "cache.example.com")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if pw != "newtoken" {
t.Errorf("password = %q, want %q", pw, "newtoken")
}
}
func TestUpsertAppend(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "netrc")
@ -220,29 +197,3 @@ func TestFilePermissionsCorrected(t *testing.T) {
t.Errorf("file permissions = %o, want 0600", perm)
}
}
func TestWriteUsesOneLineFormatAndDummyLoginFallback(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "netrc")
// Existing one-line entry with missing login should be normalized.
if err := os.WriteFile(path, []byte("machine cache.example.com password oldtoken\n"), 0600); err != nil {
t.Fatal(err)
}
if err := Upsert(path, "cache.example.com", "newtoken"); err != nil {
t.Fatalf("unexpected error: %v", err)
}
content, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read error: %v", err)
}
text := string(content)
if !strings.Contains(text, "machine cache.example.com login dummy password newtoken\n") {
t.Fatalf("unexpected netrc content: %q", text)
}
if strings.Contains(text, "\nlogin ") || strings.Contains(text, "\npassword ") {
t.Fatalf("netrc entry should be written on one line: %q", text)
}
}

View file

@ -1,65 +0,0 @@
{ self, pkgs }:
let
lib = pkgs.lib;
fakePackage = pkgs.runCommand "nix-cache-login-fake-package" { } ''
mkdir -p "$out/bin"
touch "$out/bin/nix-cache-login"
chmod +x "$out/bin/nix-cache-login"
'';
hmStubModule =
{ lib, ... }:
{
options = {
home.packages = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = [ ];
};
home.homeDirectory = lib.mkOption {
type = lib.types.str;
default = "/home/tester";
};
xdg.configHome = lib.mkOption {
type = lib.types.str;
default = "/home/tester/.config";
};
nix.settings = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = { };
};
systemd.user.services = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = { };
};
systemd.user.timers = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = { };
};
launchd.agents = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = { };
};
};
};
evalHome =
extraConfig:
lib.evalModules {
modules = [
hmStubModule
./home-module.nix
{
services.nix-cache-login.enable = true;
services.nix-cache-login.package = fakePackage;
}
extraConfig
];
};
homeDefault = evalHome { };
in
pkgs.runCommand "nix-cache-login-module-checks" { } ''
test ${lib.escapeShellArg (builtins.toJSON (builtins.hasAttr "netrc-file" homeDefault.config.nix.settings))} = ${lib.escapeShellArg "false"}
test ${lib.escapeShellArg homeDefault.config.systemd.user.services.nix-cache-login.Service.ExecStart} = ${lib.escapeShellArg "${fakePackage}/bin/nix-cache-login refresh"}
touch "$out"
''

View file

@ -6,7 +6,7 @@
buildGoModule {
pname = "nix-cache-login";
version = "0.3.0";
version = "0.2.0";
src = ./.;
# src = fetchgit {
# url = "https://guardianproject.dev/ops/nix-cache-login.git";