Add nix support for suid/sgid testing
Build and test / check (push) Successful in 1m55s
Build and test / build (push) Successful in 4m1s
Build and test / check-license (push) Successful in 4m55s
Build and test / test (push) Successful in 3m26s
Build and test / docs (push) Successful in 6m18s

This commit is contained in:
2025-12-04 10:54:32 +09:00
parent 4c21d083df
commit b0ae6e563d
5 changed files with 264 additions and 92 deletions
Generated
+9 -9
View File
@@ -2,11 +2,11 @@
"nodes": { "nodes": {
"crane": { "crane": {
"locked": { "locked": {
"lastModified": 1763938834, "lastModified": 1764782380,
"narHash": "sha256-j8iB0Yr4zAvQLueCZ5abxfk6fnG/SJ5JnGUziETjwfg=", "narHash": "sha256-9tpiB/ta9m4fNXAjmgrLOCOHXsqUYq4mTPcBYSUDvqk=",
"owner": "ipetkov", "owner": "ipetkov",
"repo": "crane", "repo": "crane",
"rev": "d9e753122e51cee64eb8d2dddfe11148f339f5a2", "rev": "e09877b775852470808fda69120691647960bcf2",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -17,11 +17,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1762363567, "lastModified": 1764667669,
"narHash": "sha256-YRqMDEtSMbitIMj+JLpheSz0pwEr0Rmy5mC7myl17xs=", "narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ae814fd3904b621d8ab97418f1d0f2eb0d3716f4", "rev": "418468ac9527e799809c900eda37cbff999199b6",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -45,11 +45,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1762655942, "lastModified": 1764729618,
"narHash": "sha256-hOM12KcQNQALrhB9w6KJmV5hPpm3GA763HRe9o7JUiI=", "narHash": "sha256-z4RA80HCWv2los1KD346c+PwNPzMl79qgl7bCVgz8X0=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "6ac961b02d4235572692241e333d0470637f5492", "rev": "52764074a85145d5001bf0aa30cb71936e9ad5b8",
"type": "github" "type": "github"
}, },
"original": { "original": {
+40 -71
View File
@@ -35,15 +35,29 @@
in f system pkgs toolchain); in f system pkgs toolchain);
in { in {
apps = let apps = let
mkApp = program: { type = "app"; program = toString program; }; mkApp = program: description: {
type = "app";
program = toString program;
meta = {
inherit description;
};
};
mkVm = name: mkApp "${self.nixosConfigurations.${name}.config.system.build.vm}/bin/run-nixos-vm";
in forAllSystems (system: pkgs: _: { in forAllSystems (system: pkgs: _: {
muscl = mkApp (lib.getExe self.packages.${system}.muscl); muscl = mkApp (lib.getExe self.packages.${system}.muscl) "Run muscl without any setup";
coverage = mkApp (pkgs.writeShellScript "muscl-coverage" '' coverage = mkApp (pkgs.writeShellScript "muscl-coverage" ''
${lib.getExe pkgs.python3} -m http.server -d "${self.packages.${system}.coverage}/html" ${lib.getExe pkgs.python3} -m http.server -d "${self.packages.${system}.coverage}/html"
''); '') "Serve code coverage report at http://localhost:8000";
vm = mkApp "${self.nixosConfigurations.vm.config.system.build.vm}/bin/run-nixos-vm";
vm = mkVm "vm" "Start a NixOS VM with muscl installed";
vm-suid = mkVm "vm-suid" "Start a NixOS VM with muscl as SUID/SGID installed";
}); });
nixosConfigurations = {
vm = import ./nix/nixos-configurations/vm.nix { inherit self nixpkgs; };
vm-suid = import ./nix/nixos-configurations/vm-suid.nix { inherit self nixpkgs; };
};
devShell = forAllSystems (system: pkgs: toolchain: pkgs.mkShell { devShell = forAllSystems (system: pkgs: toolchain: pkgs.mkShell {
nativeBuildInputs = with pkgs; [ nativeBuildInputs = with pkgs; [
toolchain toolchain
@@ -66,6 +80,12 @@
muscl-crane = final: prev: { muscl-crane = final: prev: {
muscl = self.packages.${prev.stdenv.hostPlatform.system}.muscl-crane; muscl = self.packages.${prev.stdenv.hostPlatform.system}.muscl-crane;
}; };
muscl-suid = final: prev: {
muscl = self.packages.${prev.stdenv.hostPlatform.system}.muscl-suid;
};
muscl-suid-crane = final: prev: {
muscl = self.packages.${prev.stdenv.hostPlatform.system}.muscl-suid-crane;
};
}; };
nixosModules = { nixosModules = {
@@ -87,83 +107,32 @@
}; };
in { in {
default = self.packages.${system}.muscl-crane; default = self.packages.${system}.muscl-crane;
muscl = pkgs.callPackage ./nix/default.nix { inherit cargoToml cargoLock src; }; muscl = pkgs.callPackage ./nix/default.nix { inherit cargoToml cargoLock src; };
muscl-crane = pkgs.callPackage ./nix/default.nix { muscl-crane = pkgs.callPackage ./nix/default.nix {
useCrane = true; useCrane = true;
inherit cargoToml cargoLock src craneLib; inherit cargoToml cargoLock src craneLib;
}; };
muscl-suid = pkgs.callPackage ./nix/default.nix {
suidSgidSupport = true;
inherit cargoToml cargoLock src;
};
muscl-suid-crane = pkgs.callPackage ./nix/default.nix {
useCrane = true;
suidSgidSupport = true;
inherit cargoToml cargoLock src craneLib;
};
coverage = pkgs.callPackage ./nix/coverage.nix { inherit cargoToml cargoLock src; }; coverage = pkgs.callPackage ./nix/coverage.nix { inherit cargoToml cargoLock src; };
filteredSource = pkgs.runCommandLocal "filtered-source" { } '' filteredSource = pkgs.runCommandLocal "filtered-source" { } ''
ln -s ${src} $out ln -s ${src} $out
''; '';
}); });
nixosConfigurations.vm = nixpkgs.lib.nixosSystem { checks = forAllSystems (system: pkgs: _: {
system = "x86_64-linux"; # NOTE: the non-crane build runs tests during checkPhase
pkgs = import nixpkgs { inherit (self.packages.${system}) muscl muscl-suid;
system = "x86_64-linux"; });
overlays = [
self.overlays.muscl-crane
];
};
modules = [
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
"${nixpkgs}/nixos/tests/common/user-account.nix"
self.nixosModules.default
({ config, pkgs, ... }: {
system.stateVersion = config.system.nixos.release;
virtualisation.graphics = false;
users = {
groups = {
a = { };
b = { };
};
users.alice.extraGroups = [
"a"
"b"
"wheel"
"systemd-journal"
];
extraUsers.root.password = "root";
};
services.getty.autologinUser = "alice";
users.motd = ''
=================================
Welcome to the muscl vm!
Try running:
${config.services.muscl.package.meta.mainProgram}
Password for alice is 'foobar'
Password for root is 'root'
To exit, press Ctrl+A, then X
=================================
'';
services.mysql = {
enable = true;
package = pkgs.mariadb;
};
services.muscl = {
enable = true;
logLevel = "trace";
createLocalDatabaseUser = true;
};
programs.vim = {
enable = true;
defaultEditor = true;
};
environment.systemPackages = with pkgs; [ jq ];
})
];
};
}; };
} }
+51 -12
View File
@@ -1,26 +1,63 @@
{ {
lib lib
, rustPlatform , rustPlatform
, stdenv
, installShellFiles
, versionCheckHook
, cargoToml , cargoToml
, cargoLock , cargoLock
, src , src
, installShellFiles
, useCrane ? false , useCrane ? false
, craneLib ? null , craneLib ? null
, suidSgidSupport ? false
}: }:
let let
mainProgram = (lib.head cargoToml.bin).name; mainProgram = (lib.head cargoToml.bin).name;
buildFunction = if useCrane then craneLib.buildPackage else rustPlatform.buildRustPackage; buildFunction = if useCrane then craneLib.buildPackage else rustPlatform.buildRustPackage;
cargoLock' = if useCrane then cargoLock else { lockFile = cargoLock; };
pname = if useCrane then "${cargoToml.package.name}-crane" else cargoToml.package.name;
in
buildFunction {
pname = pname;
version = cargoToml.package.version;
inherit src;
cargoLock = cargoLock'; pnameCraneSuffix = lib.optionalString useCrane "-crane";
pnameSuidSuffix = lib.optionalString suidSgidSupport "-suid";
pname = "${cargoToml.package.name}${pnameSuidSuffix}${pnameCraneSuffix}";
rustPlatformArgs = {
buildFeatures = lib.optional suidSgidSupport "suid-sgid-mode";
cargoLock.lockFile = cargoLock;
doCheck = true;
useNextest = true;
nativeCheckInputs = [
versionCheckHook
];
cargoCheckFeatures = lib.optional suidSgidSupport "suid-sgid-mode";
postCheck = lib.optionalString (stdenv.buildPlatform.system == stdenv.hostPlatform.system && suidSgidSupport) ''
./target/${stdenv.hostPlatform.rust.rustcTarget}/release/muscl --version | grep "SUID/SGID mode: enabled"
'';
};
craneArgs = {
cargoLock = cargoLock;
cargoExtraArgs = lib.escapeShellArgs [ "--features" (lib.concatStringsSep "," (lib.optional suidSgidSupport "suid-sgid-mode")) ];
cargoArtifacts = craneLib.buildDepsOnly {
inherit pname;
inherit (cargoToml.package) version;
src = lib.fileset.toSource {
root = ../.;
fileset = lib.fileset.unions [
(craneLib.fileset.cargoTomlAndLock ../.)
];
};
cargoLock = cargoLock;
};
};
in
buildFunction ({
inherit pname;
inherit (cargoToml.package) version;
inherit src;
nativeBuildInputs = [ installShellFiles ]; nativeBuildInputs = [ installShellFiles ];
postInstall = let postInstall = let
@@ -29,10 +66,9 @@ buildFunction {
export PATH="$out/bin:$PATH" export PATH="$out/bin:$PATH"
export COMPLETE="${shell}" export COMPLETE="${shell}"
"${command}" > "$TMP/${command}.${shell}" "${command}" > "$TMP/${command}.${shell}"
# See https://github.com/clap-rs/clap/issues/1764
sed -i 's/muscl/${command}/g' "$TMP/${command}.${shell}"
) )
# See https://github.com/clap-rs/clap/issues/1764
sed -i 's/muscl/${command}/g' "$TMP/${command}.${shell}"
installShellCompletion "--${shell}" --cmd "${command}" "$TMP/${command}.${shell}" installShellCompletion "--${shell}" --cmd "${command}" "$TMP/${command}.${shell}"
'') { '') {
shell = [ "bash" "zsh" "fish" ]; shell = [ "bash" "zsh" "fish" ];
@@ -56,3 +92,6 @@ buildFunction {
inherit mainProgram; inherit mainProgram;
}; };
} }
//
(if useCrane then craneArgs else rustPlatformArgs)
)
+96
View File
@@ -0,0 +1,96 @@
{ self, nixpkgs, ... }:
let
inherit (nixpkgs) lib;
in
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [
self.overlays.muscl-suid-crane
];
};
modules = [
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
"${nixpkgs}/nixos/tests/common/user-account.nix"
({ config, pkgs, ... }: {
system.stateVersion = config.system.nixos.release;
virtualisation.graphics = false;
users = {
groups = {
a = { };
b = { };
muscl = { };
};
users.muscl = {
isSystemUser = true;
group = "muscl";
};
users.alice.extraGroups = [
"a"
"b"
"wheel"
"systemd-journal"
];
extraUsers.root.password = "root";
};
services.getty.autologinUser = "alice";
users.motd = ''
=================================
Welcome to the muscl SUID/SGID vm!
Try running:
${pkgs.muscl.meta.mainProgram}
Password for alice is 'foobar'
Password for root is 'root'
To exit, press Ctrl+A, then X
=================================
'';
services.mysql = {
enable = true;
package = pkgs.mariadb;
ensureUsers = [
{
name = "muscl";
ensurePermissions = {
"mysql.*" = "SELECT, INSERT, UPDATE, DELETE";
"*.*" = "GRANT OPTION, CREATE, DROP";
};
}
];
};
security.wrappers.muscl = {
owner = "muscl";
group = "muscl";
setuid = true;
source = lib.getExe pkgs.muscl;
};
environment.etc."muscl/config.toml".source = (pkgs.formats.toml { }).generate "muscl-config.toml" {
mysql = {
username = "muscl";
password = "snakeoil";
socket_path = "/run/mysqld/mysqld.sock";
};
};
# TODO: extra setup commands:
# set password for mysql user
programs.vim = {
enable = true;
defaultEditor = true;
};
environment.systemPackages = with pkgs; [ jq ];
})
];
}
+68
View File
@@ -0,0 +1,68 @@
{ self, nixpkgs, ... }:
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [
self.overlays.muscl-crane
];
};
modules = [
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
"${nixpkgs}/nixos/tests/common/user-account.nix"
self.nixosModules.default
({ config, pkgs, ... }: {
system.stateVersion = config.system.nixos.release;
virtualisation.graphics = false;
users = {
groups = {
a = { };
b = { };
};
users.alice.extraGroups = [
"a"
"b"
"wheel"
"systemd-journal"
];
extraUsers.root.password = "root";
};
services.getty.autologinUser = "alice";
users.motd = ''
=================================
Welcome to the muscl vm!
Try running:
${config.services.muscl.package.meta.mainProgram}
Password for alice is 'foobar'
Password for root is 'root'
To exit, press Ctrl+A, then X
=================================
'';
services.mysql = {
enable = true;
package = pkgs.mariadb;
};
services.muscl = {
enable = true;
logLevel = "trace";
createLocalDatabaseUser = true;
};
programs.vim = {
enable = true;
defaultEditor = true;
};
environment.systemPackages = with pkgs; [ jq ];
})
];
}