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

cockpit: 330 -> 331 #368886

Merged
merged 3 commits into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 2 additions & 165 deletions nixos/modules/services/monitoring/cockpit.nix
Original file line number Diff line number Diff line change
Expand Up @@ -53,171 +53,8 @@ in {

networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];

# units are in reverse sort order if you ls $out/lib/systemd/system
# all these units are basically verbatim translated from upstream

# Translation from $out/lib/systemd/system/systemd-cockpithttps.slice
systemd.slices.system-cockpithttps = {
description = "Resource limits for all [email protected] instances";
sliceConfig = {
TasksMax = 200;
MemoryHigh = "75%";
MemoryMax = "90%";
};
};

# Translation from $out/lib/systemd/system/[email protected]
systemd.sockets."cockpit-wsinstance-https@" = {
unitConfig = {
Description = "Socket for Cockpit Web Service https instance %I";
BindsTo = [ "cockpit.service" "cockpit-wsinstance-https@%i.service" ];
# clean up the socket after the service exits, to prevent fd leak
# this also effectively prevents a DoS by starting arbitrarily many sockets, as
# the services are resource-limited by system-cockpithttps.slice
Documentation = "man:cockpit-ws(8)";
};
socketConfig = {
ListenStream = "/run/cockpit/wsinstance/https@%i.sock";
SocketUser = "root";
SocketMode = "0600";
};
};

# Translation from $out/lib/systemd/system/[email protected]
systemd.services."cockpit-wsinstance-https@" = {
description = "Cockpit Web Service https instance %I";
bindsTo = [ "cockpit.service"];
path = [ cfg.package ];
documentation = [ "man:cockpit-ws(8)" ];
serviceConfig = {
Slice = "system-cockpithttps.slice";
ExecStart = "${cfg.package}/libexec/cockpit-ws --for-tls-proxy --port=0";
User = "root";
Group = "";
};
};

# Translation from $out/lib/systemd/system/cockpit-wsinstance-http.socket
systemd.sockets.cockpit-wsinstance-http = {
unitConfig = {
Description = "Socket for Cockpit Web Service http instance";
BindsTo = "cockpit.service";
Documentation = "man:cockpit-ws(8)";
};
socketConfig = {
ListenStream = "/run/cockpit/wsinstance/http.sock";
SocketUser = "root";
SocketMode = "0600";
};
};

# Translation from $out/lib/systemd/system/cockpit-wsinstance-https-factory.socket
systemd.sockets.cockpit-wsinstance-https-factory = {
unitConfig = {
Description = "Socket for Cockpit Web Service https instance factory";
BindsTo = "cockpit.service";
Documentation = "man:cockpit-ws(8)";
};
socketConfig = {
ListenStream = "/run/cockpit/wsinstance/https-factory.sock";
Accept = true;
SocketUser = "root";
SocketMode = "0600";
};
};

# Translation from $out/lib/systemd/system/[email protected]
systemd.services."cockpit-wsinstance-https-factory@" = {
description = "Cockpit Web Service https instance factory";
documentation = [ "man:cockpit-ws(8)" ];
path = [ cfg.package ];
serviceConfig = {
ExecStart = "${cfg.package}/libexec/cockpit-wsinstance-factory";
User = "root";
};
};

# Translation from $out/lib/systemd/system/cockpit-wsinstance-http.service
systemd.services."cockpit-wsinstance-http" = {
description = "Cockpit Web Service http instance";
bindsTo = [ "cockpit.service" ];
path = [ cfg.package ];
documentation = [ "man:cockpit-ws(8)" ];
serviceConfig = {
ExecStart = "${cfg.package}/libexec/cockpit-ws --no-tls --port=0";
User = "root";
Group = "";
};
};

# Translation from $out/lib/systemd/system/cockpit.socket
systemd.sockets."cockpit" = {
unitConfig = {
Description = "Cockpit Web Service Socket";
Documentation = "man:cockpit-ws(8)";
Wants = "cockpit-motd.service";
};
socketConfig = {
ListenStream = cfg.port;
ExecStartPost = [
"-${cfg.package}/share/cockpit/motd/update-motd \"\" localhost"
"-${pkgs.coreutils}/bin/ln -snf active.motd /run/cockpit/motd"
];
ExecStopPost = "-${pkgs.coreutils}/bin/ln -snf inactive.motd /run/cockpit/motd";
};
wantedBy = [ "sockets.target" ];
};

# Translation from $out/lib/systemd/system/cockpit.service
systemd.services."cockpit" = {
description = "Cockpit Web Service";
documentation = [ "man:cockpit-ws(8)" ];
restartIfChanged = true;
path = with pkgs; [ coreutils cfg.package ];
requires = [ "cockpit.socket" "cockpit-wsinstance-http.socket" "cockpit-wsinstance-https-factory.socket" ];
after = [ "cockpit-wsinstance-http.socket" "cockpit-wsinstance-https-factory.socket" ];
environment = {
G_MESSAGES_DEBUG = "cockpit-ws,cockpit-bridge";
};
serviceConfig = {
RuntimeDirectory="cockpit/tls";
ExecStartPre = [
# cockpit-tls runs in a more constrained environment, these + means that these commands
# will run with full privilege instead of inside that constrained environment
# See https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart= for details
"+${cfg.package}/libexec/cockpit-certificate-ensure --for-cockpit-tls"
];
ExecStart = "${cfg.package}/libexec/cockpit-tls";
User = "root";
Group = "";
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
ProtectKernelTunables = true;
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
MemoryDenyWriteExecute = true;
};
};

# Translation from $out/lib/systemd/system/cockpit-motd.service
# This part basically implements a motd state machine:
# - If cockpit.socket is enabled then /run/cockpit/motd points to /run/cockpit/active.motd
# - If cockpit.socket is disabled then /run/cockpit/motd points to /run/cockpit/inactive.motd
# - As cockpit.socket is disabled by default, /run/cockpit/motd points to /run/cockpit/inactive.motd
# /run/cockpit/active.motd is generated dynamically by cockpit-motd.service
systemd.services."cockpit-motd" = {
path = with pkgs; [ nettools ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${cfg.package}/share/cockpit/motd/update-motd";
};
description = "Cockpit motd updater service";
documentation = [ "man:cockpit-ws(8)" ];
wants = [ "network.target" ];
after = [ "network.target" "cockpit.socket" ];
};
systemd.packages = [ cfg.package ];
systemd.sockets.cockpit.wantedBy = [ "multi-user.target" ];

systemd.tmpfiles.rules = [ # From $out/lib/tmpfiles.d/cockpit-tmpfiles.conf
"C /run/cockpit/inactive.motd 0640 root root - ${cfg.package}/share/cockpit/motd/inactive.motd"
Expand Down
20 changes: 11 additions & 9 deletions nixos/tests/cockpit.nix
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ import ./make-test-python.nix (
log("Opening homepage")
driver.get("https://server:9090")

wait = WebDriverWait(driver, 60)


def wait_elem(by, query):
def wait_elem(by, query, timeout=10):
wait = WebDriverWait(driver, timeout)
wait.until(EC.presence_of_element_located((by, query)))


def wait_title_contains(title):
def wait_title_contains(title, timeout=10):
wait = WebDriverWait(driver, timeout)
wait.until(EC.title_contains(title))


Expand Down Expand Up @@ -121,6 +121,12 @@ import ./make-test-python.nix (

assert "Web console is running in limited access mode" in driver.page_source

log("Clicking the sudo button")
driver.switch_to.default_content()
driver.find_element(By.CSS_SELECTOR, 'button.ct-locked').click()
log("Checking that /nonexistent is not a thing")
assert '/nonexistent' not in driver.page_source

driver.close()
'';
in
Expand All @@ -136,12 +142,8 @@ import ./make-test-python.nix (
testScript = ''
start_all()

server.wait_for_unit("sockets.target")
server.wait_for_open_port(9090)
server.wait_for_unit("network.target")
server.wait_for_unit("multi-user.target")
server.systemctl("start", "polkit")

client.wait_for_unit("multi-user.target")

client.succeed("curl -k https://server:9090 -o /dev/stderr")
print(client.succeed("whoami"))
Expand Down
55 changes: 21 additions & 34 deletions pkgs/by-name/co/cockpit/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@

stdenv.mkDerivation rec {
lucasew marked this conversation as resolved.
Show resolved Hide resolved
pname = "cockpit";
version = "330";
version = "331";

src = fetchFromGitHub {
owner = "cockpit-project";
repo = "cockpit";
rev = "refs/tags/${version}";
lucasew marked this conversation as resolved.
Show resolved Hide resolved
hash = "sha256-tPoFa9/22WUO+N3Pc/7jdWIOsoImeru6/F+2yUi92iI=";
hash = "sha256-G0L1ZcvjUCSNkDvYoyConymZ4bsEye03t5K15EyI008=";
fetchSubmodules = true;
};

Expand Down Expand Up @@ -104,12 +104,13 @@ stdenv.mkDerivation rec {
test/common/pixel-tests \
test/common/run-tests \
test/common/tap-cdp \
test/static-code \
tools/escape-to-c \
tools/make-compile-commands \
tools/node-modules \
tools/termschutz \
tools/webpack-make.js
tools/webpack-make.js \
tools/test-driver \
test/common/static-code

for f in node_modules/.bin/*; do
patchShebangs $(realpath $f)
Expand All @@ -129,45 +130,32 @@ stdenv.mkDerivation rec {
substituteInPlace src/common/Makefile-common.am \
--replace 'TEST_PROGRAM += test-pipe' "" # skip test-pipe because it hangs the build

substituteInPlace src/ws/Makefile-ws.am \
--replace 'TEST_PROGRAM += test-compat' ""

substituteInPlace test/pytest/*.py \
--replace "'bash" "'${bashInteractive}/bin/bash"
lucasew marked this conversation as resolved.
Show resolved Hide resolved

echo "m4_define(VERSION_NUMBER, [${version}])" > version.m4

# hardcode libexecdir, I am assuming that cockpit only use it to find it's binaries
printf 'def get_libexecdir() -> str:\n\treturn "%s"' "$out/libexec" >> src/cockpit/packages.py
'';

configureFlags = [
"--enable-prefix-only=yes"
"--disable-pcp" # TODO: figure out how to package its dependency
"--with-default-session-path=/run/wrappers/bin:/run/current-system/sw/bin"
"--with-admin-group=root" # TODO: really? Maybe "wheel"?
"--enable-old-bridge=yes"
];

enableParallelBuilding = true;

preBuild = ''
patchShebangs \
tools/test-driver
'';

postBuild = ''
chmod +x \
src/systemd/update-motd \
src/tls/cockpit-certificate-helper \
src/ws/cockpit-desktop

patchShebangs \
src/systemd/update-motd \
src/tls/cockpit-certificate-helper \
src/ws/cockpit-desktop

substituteInPlace src/ws/cockpit-desktop \
--replace ' /bin/bash' ' ${runtimeShell}'
'';

fixupPhase = ''
runHook preFixup

patchShebangs $out/libexec/*

wrapProgram $out/libexec/cockpit-certificate-helper \
--prefix PATH : ${
lib.makeBinPath [
Expand All @@ -177,9 +165,6 @@ stdenv.mkDerivation rec {
} \
--run 'cd $(mktemp -d)'

wrapProgram $out/share/cockpit/motd/update-motd \
--prefix PATH : ${lib.makeBinPath [ gnused ]}

wrapProgram $out/bin/cockpit-bridge \
--prefix PYTHONPATH : $out/${python3Packages.python.sitePackages}

Expand All @@ -189,29 +174,31 @@ stdenv.mkDerivation rec {
substituteInPlace $out/share/polkit-1/actions/org.cockpit-project.cockpit-bridge.policy \
--replace-fail /usr $out

substituteInPlace $out/lib/systemd/*/* \
--replace /bin /run/current-system/sw/bin
lucasew marked this conversation as resolved.
Show resolved Hide resolved

runHook postFixup
'';

doCheck = true;
checkInputs = [
bashInteractive
cacert
dbus
glib-networking
openssh
python3Packages.pytest
python3Packages.pytestCheckHook
lucasew marked this conversation as resolved.
Show resolved Hide resolved
];
checkPhase = ''

preCheck = ''
export GIO_EXTRA_MODULES=$GIO_EXTRA_MODULES:${glib-networking}/lib/gio/modules
export G_DEBUG=fatal-criticals
export G_MESSAGES_DEBUG=cockpit-ws,cockpit-wrapper,cockpit-bridge
export PATH=$PATH:$(pwd)

make pytest -j$NIX_BUILD_CORES || true
# make pytest -j$NIX_BUILD_CORES || true
make check -j$NIX_BUILD_CORES || true
test/static-code
npm run eslint
npm run stylelint || true
npm run stylelint
'';

passthru = {
Expand Down
Loading