Release v0.2.0
This commit is contained in:
parent
f0e29d38a4
commit
c24af42fc0
9 changed files with 153 additions and 6 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -4,6 +4,16 @@
|
|||
|
||||
Changes yet to be released are documented here.
|
||||
|
||||
## v0.2.0
|
||||
|
||||
- Improve config discovery for server workflows:
|
||||
- honor `$NIX_CACHE_LOGIN_CONFIG` when `--config` is not set
|
||||
- fall back to `/etc/nix-cache-login/config.toml` when per-user config is absent
|
||||
- Update `--config` help text to document config path resolution order
|
||||
- Set `NIX_CACHE_LOGIN_CONFIG` in the NixOS server module so interactive commands (like `status`) use the same config as the timer service
|
||||
- Install `/etc/nix-cache-login/config.toml` via the NixOS server module from `services.nix-cache-login-server.configFile`
|
||||
- Add a NixOS server module VM test and wire it into flake checks
|
||||
|
||||
## v0.1.3
|
||||
|
||||
- Improve `status` for server use by detecting service-account mode from config
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -68,6 +68,16 @@ nix-cache-login status # show token expiry info
|
|||
nix-cache-login logout # revoke tokens and clean up
|
||||
```
|
||||
|
||||
Config path resolution order:
|
||||
|
||||
1. `--config`
|
||||
2. `$NIX_CACHE_LOGIN_CONFIG`
|
||||
3. `$XDG_CONFIG_HOME/nix-cache-login/config.toml`
|
||||
4. `/etc/nix-cache-login/config.toml` (server fallback)
|
||||
|
||||
The NixOS server module exports `NIX_CACHE_LOGIN_CONFIG` and installs
|
||||
`/etc/nix-cache-login/config.toml` from `services.nix-cache-login-server.configFile`.
|
||||
|
||||
## Maintenance
|
||||
|
||||
This tool is actively maintained by [Guardian Project](https://guardianproject.info).
|
||||
|
|
|
|||
|
|
@ -42,5 +42,5 @@ func Execute() {
|
|||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringVar(&cfgPath, "config", "", "path to config file (default: $XDG_CONFIG_HOME/nix-cache-login/config.toml)")
|
||||
rootCmd.PersistentFlags().StringVar(&cfgPath, "config", "", "path to config file (default resolution: --config, $NIX_CACHE_LOGIN_CONFIG, $XDG_CONFIG_HOME/nix-cache-login/config.toml, /etc/nix-cache-login/config.toml)")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
}
|
||||
// pkgs.lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||
nixos-module = pkgs.testers.runNixOSTest (import ./nixos-test.nix self);
|
||||
nixos-module-server = pkgs.testers.runNixOSTest (import ./nixos-test-server.nix self);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,23 @@ type Config struct {
|
|||
ClientSecret string `toml:"-"`
|
||||
}
|
||||
|
||||
const configPathEnvVar = "NIX_CACHE_LOGIN_CONFIG"
|
||||
|
||||
var systemConfigPath = "/etc/nix-cache-login/config.toml"
|
||||
|
||||
// Load reads the config from the given path, or from the default XDG location.
|
||||
func Load(path string) (*Config, error) {
|
||||
if path == "" {
|
||||
path = filepath.Join(xdg.ConfigHome, "nix-cache-login", "config.toml")
|
||||
}
|
||||
|
||||
path = resolveConfigPath(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil && path == defaultXDGConfigPath() {
|
||||
// On servers, allow a system-wide fallback when per-user XDG config is absent.
|
||||
if systemData, systemErr := os.ReadFile(systemConfigPath); systemErr == nil {
|
||||
data = systemData
|
||||
err = nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("reading config file: %w", err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading config file: %w", err)
|
||||
}
|
||||
|
|
@ -55,6 +65,20 @@ func Load(path string) (*Config, error) {
|
|||
return &cfg, nil
|
||||
}
|
||||
|
||||
func resolveConfigPath(path string) string {
|
||||
if path != "" {
|
||||
return path
|
||||
}
|
||||
if envPath := strings.TrimSpace(os.Getenv(configPathEnvVar)); envPath != "" {
|
||||
return envPath
|
||||
}
|
||||
return defaultXDGConfigPath()
|
||||
}
|
||||
|
||||
func defaultXDGConfigPath() string {
|
||||
return filepath.Join(xdg.ConfigHome, "nix-cache-login", "config.toml")
|
||||
}
|
||||
|
||||
func (c *Config) validate() error {
|
||||
if c.Issuer == "" {
|
||||
return fmt.Errorf("config: issuer is required")
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
)
|
||||
|
||||
func TestLoadValidConfig(t *testing.T) {
|
||||
|
|
@ -192,6 +194,65 @@ func TestMissingRequiredFields(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestLoadUsesNixCacheLoginConfigEnvWhenPathEmpty(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
cfgFile := filepath.Join(dir, "custom-config.toml")
|
||||
|
||||
content := `
|
||||
issuer = "https://id.example.com/realms/test"
|
||||
client_id = "nix-cache-server"
|
||||
cache_host = "cache.example.com"
|
||||
netrc_path = "/tmp/netrc"
|
||||
`
|
||||
if err := os.WriteFile(cfgFile, []byte(content), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Setenv(configPathEnvVar, cfgFile)
|
||||
cfg, err := Load("")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if cfg.ClientID != "nix-cache-server" {
|
||||
t.Fatalf("client_id = %q, want %q", cfg.ClientID, "nix-cache-server")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFallsBackToSystemConfigPath(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
systemCfg := filepath.Join(dir, "system-config.toml")
|
||||
systemConfigPathOrig := systemConfigPath
|
||||
systemConfigPath = systemCfg
|
||||
defer func() {
|
||||
systemConfigPath = systemConfigPathOrig
|
||||
}()
|
||||
|
||||
content := `
|
||||
issuer = "https://id.example.com/realms/test"
|
||||
client_id = "nix-cache-server"
|
||||
cache_host = "cache.example.com"
|
||||
netrc_path = "/tmp/netrc"
|
||||
`
|
||||
if err := os.WriteFile(systemCfg, []byte(content), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Setenv(configPathEnvVar, "")
|
||||
origConfigHome := xdg.ConfigHome
|
||||
xdg.ConfigHome = filepath.Join(dir, "xdg-missing")
|
||||
defer func() {
|
||||
xdg.ConfigHome = origConfigHome
|
||||
}()
|
||||
|
||||
cfg, err := Load("")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if cfg.ClientID != "nix-cache-server" {
|
||||
t.Fatalf("client_id = %q, want %q", cfg.ClientID, "nix-cache-server")
|
||||
}
|
||||
}
|
||||
|
||||
func contains(s, substr string) bool {
|
||||
return len(s) >= len(substr) && searchString(s, substr)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ in
|
|||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
environment.variables.NIX_CACHE_LOGIN_CONFIG = toString cfg.configFile;
|
||||
environment.etc."nix-cache-login/config.toml".source = cfg.configFile;
|
||||
systemd.services.nix-cache-login = {
|
||||
description = "Nix cache login - service account token refresh";
|
||||
serviceConfig = {
|
||||
|
|
|
|||
39
nixos-test-server.nix
Normal file
39
nixos-test-server.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
self: {
|
||||
name = "nix-cache-login-nixos-module-server";
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [ self.nixosModules.server ];
|
||||
services.nix-cache-login-server = {
|
||||
enable = true;
|
||||
configFile = pkgs.writeText "nix-cache-login-server-config.toml" ''
|
||||
issuer = "https://id.example.com/realms/test"
|
||||
client_id = "nix-cache-server"
|
||||
client_secret_file = "/run/secrets/nix-cache-client-secret"
|
||||
cache_host = "cache.example.com"
|
||||
netrc_path = "/var/lib/nix-cache-login/netrc"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
# Module should install system service and timer unit files.
|
||||
machine.succeed("test -f /etc/systemd/system/nix-cache-login.timer")
|
||||
machine.succeed("test -f /etc/systemd/system/nix-cache-login.service")
|
||||
|
||||
# wantedBy = ["timers.target"] should create this symlink.
|
||||
machine.succeed("test -L /etc/systemd/system/timers.target.wants/nix-cache-login.timer")
|
||||
|
||||
# Config should be available at a standard path for interactive commands.
|
||||
machine.succeed("test -f /etc/nix-cache-login/config.toml")
|
||||
|
||||
# Service unit should invoke service-account mode with explicit --config.
|
||||
unit = machine.succeed("cat /etc/systemd/system/nix-cache-login.service")
|
||||
assert "nix-cache-login --config" in unit and "service-account" in unit, (
|
||||
f"ExecStart not found in service unit:\n{unit}"
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
buildGoModule {
|
||||
pname = "nix-cache-login";
|
||||
version = "0.1.3";
|
||||
version = "0.2.0";
|
||||
src = ./.;
|
||||
# src = fetchgit {
|
||||
# url = "https://guardianproject.dev/ops/nix-cache-login.git";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue