Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 8 additions & 1 deletion config/k3s/activate-client.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ fi

mkdir -p "$HOME/.kube"

SCP_ERR=$(mktemp)
trap 'rm -f "$SCP_ERR"' EXIT

if scp -o ConnectTimeout=5 -o BatchMode=yes \
"${REMOTE_HOST}:${REMOTE_KUBECONFIG_PATH}" "$LOCAL_KUBECONFIG" 2>/dev/null; then
"${REMOTE_HOST}:${REMOTE_KUBECONFIG_PATH}" "$LOCAL_KUBECONFIG" 2>"$SCP_ERR"; then
chmod 600 "$LOCAL_KUBECONFIG"
echo "k3s-client: kubeconfig synced from ${REMOTE_HOST}"
else
echo "k3s-client: failed to fetch kubeconfig from ${REMOTE_HOST}" >&2
sed 's/^/k3s-client: /' "$SCP_ERR" >&2
fi
29 changes: 29 additions & 0 deletions config/k3s/activate.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail

GALACTICA_AUTHORIZED_KEY="@galacticaAuthorizedKey@"

ensure_authorized_key() {
local key="$1"
local ssh_dir="$HOME/.ssh"
local auth_file="$ssh_dir/authorized_keys"

if [ -z "$key" ] || [[ $key == "@"*"@" ]]; then
return 0
fi

mkdir -p "$ssh_dir"
chmod 700 "$ssh_dir"
touch "$auth_file"
chmod 600 "$auth_file"

if grep -qxF "$key" "$auth_file"; then
return 0
fi

if [ -s "$auth_file" ] && [ "$(tail -c1 "$auth_file" | wc -l)" -eq 0 ]; then
printf '\n' >>"$auth_file"
fi
printf '%s\n' "$key" >>"$auth_file"
echo "k3s-server: authorized galactica SSH key for kubeconfig sync"
}

ensure_authorized_key "$GALACTICA_AUTHORIZED_KEY"

if [ ! -f "$HOME/.config/k3s/config.yaml" ]; then
exit 0
fi
Expand Down
8 changes: 7 additions & 1 deletion config/k3s/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
let
inherit (inputs.host) isKyber isGalactica;
kubeconfig = "${config.home.homeDirectory}/.kube/config-kyber";
# Authorize galactica on kyber so the client activation can scp the
# kubeconfig over Tailscale.
galacticaAuthorizedKey = (import ../../named-hosts/pubkeys.nix).galactica;
serverActivateScript = pkgs.replaceVars ./activate.sh {
galacticaAuthorizedKey = galacticaAuthorizedKey;
};
in
{
home.file.".config/k3s/config.yaml" = lib.mkIf isKyber {
Expand Down Expand Up @@ -40,7 +46,7 @@ in

home.activation.k3s-server = lib.mkIf isKyber (
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
$DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}"
$DRY_RUN_CMD ${pkgs.bash}/bin/bash "${serverActivateScript}"
''
);

Expand Down
7 changes: 1 addition & 6 deletions named-hosts/galactica/secrets.nix
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
let
# Galactica's SSH public key
galactica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com";
# Kyber's SSH public key
kyber = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0IZtP3KSzY6GVSZ+R+VQYYfu3sEOVaQGDblQxAtwNM ubuntu@kyber";
# Matic's SSH public key
matic = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEeknNbHasmT+43PgO9oy0mutoe+V2R2ZNRa5SPOLmLN skakinoki@matic";
inherit (import ../pubkeys.nix) galactica kyber matic;
# All machines that can decrypt shared secrets
allMachines = [
galactica
Expand Down
5 changes: 1 addition & 4 deletions named-hosts/kyber/secrets.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
# 1. Add the secret definition here
# 2. Run: make encrypt-key-kyber KEY_FILE=/path/to/secret
let
# Galactica's SSH public key
galactica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com";
# Kyber's SSH public key
kyber = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0IZtP3KSzY6GVSZ+R+VQYYfu3sEOVaQGDblQxAtwNM ubuntu@kyber";
inherit (import ../pubkeys.nix) galactica kyber;
# All machines that can decrypt shared secrets
allMachines = [
galactica
Expand Down
3 changes: 1 addition & 2 deletions named-hosts/matic/secrets.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Matic secrets - synced from galactica via agenix
let
galactica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com";
matic = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEeknNbHasmT+43PgO9oy0mutoe+V2R2ZNRa5SPOLmLN skakinoki@matic";
inherit (import ../pubkeys.nix) galactica matic;
allMachines = [
galactica
matic
Expand Down
8 changes: 8 additions & 0 deletions named-hosts/pubkeys.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SSH public keys for all machines.
# Single source of truth shared by per-host secrets.nix files and any
# activation script that needs to authorize cross-host access.
{
galactica = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com";
kyber = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0IZtP3KSzY6GVSZ+R+VQYYfu3sEOVaQGDblQxAtwNM ubuntu@kyber";
matic = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEeknNbHasmT+43PgO9oy0mutoe+V2R2ZNRa5SPOLmLN skakinoki@matic";
}
12 changes: 12 additions & 0 deletions spec/activate_k3s_client_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,16 @@ When run bash -c "grep 'chmod 600' '$SCRIPT'"
The output should include 'chmod 600'
End
End

Describe 'failure visibility'
It 'does not silently discard scp stderr'
When run bash -c "grep 'scp ' '$SCRIPT'"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test 'does not silently discard scp stderr' is currently ineffective. Because grep 'scp ' only returns the first line of the multi-line scp command, it does not see the redirection (which was on the following line due to the backslash). Consequently, this test would pass even if 2>/dev/null were still present in the script. Using grep -A 1 ensures the redirection line is included in the check.

Suggested change
When run bash -c "grep 'scp ' '$SCRIPT'"
When run bash -c "grep -A 1 'scp ' '$SCRIPT'"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This regression test only greps the first line of the multi-line scp invocation, so it can miss a reintroduced 2>/dev/null on the continuation line. Include the following line (or scan the whole script) before asserting stderr is not discarded.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At spec/activate_k3s_client_spec.sh, line 50:

<comment>This regression test only greps the first line of the multi-line `scp` invocation, so it can miss a reintroduced `2>/dev/null` on the continuation line. Include the following line (or scan the whole script) before asserting stderr is not discarded.</comment>

<file context>
@@ -44,4 +44,16 @@ When run bash -c "grep 'chmod 600' '$SCRIPT'"
+
+Describe 'failure visibility'
+It 'does not silently discard scp stderr'
+When run bash -c "grep 'scp ' '$SCRIPT'"
+The output should not include '2>/dev/null'
+End
</file context>
Suggested change
When run bash -c "grep 'scp ' '$SCRIPT'"
When run bash -c "grep -A 1 'scp ' '$SCRIPT'"

The output should not include '2>/dev/null'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regression test is too narrow to catch a recurrence: this assertion only looks at lines containing scp (the if scp ... line), but the original 2>/dev/null was on the continuation line "${REMOTE_HOST}:..." "$LOCAL_KUBECONFIG" 2>/dev/null; then — which has no scp token. Reintroducing the bug in the same shape would leave this grep output unchanged and the test would still pass.

Consider checking the whole script instead, e.g.:

It 'does not silently discard scp stderr'
When run bash -c "! grep -n '2>/dev/null' '$SCRIPT'"
The status should be success
End

or a multi-line grep that spans the scp invocation (grep -Pzo 'scp[^;]*2>/dev/null').

End

It 'logs scp failures to stderr'
When run bash -c "grep 'failed to fetch kubeconfig' '$SCRIPT'"
The output should include 'failed to fetch kubeconfig'
End
End
End
98 changes: 97 additions & 1 deletion spec/activate_k3s_spec.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# shellcheck disable=SC2329
# shellcheck disable=SC2329,SC2016

Describe 'config/k3s/activate.sh'
SCRIPT="$PWD/config/k3s/activate.sh"
Expand Down Expand Up @@ -49,4 +49,100 @@ When run bash -c "grep -A 1 '! -f' '$SCRIPT'"
The output should include 'exit 0'
End
End

Describe 'authorized_keys management'
It 'declares a placeholder for galactica authorized key'
When run bash -c "grep 'GALACTICA_AUTHORIZED_KEY' '$SCRIPT'"
The output should include '@galacticaAuthorizedKey@'
End

It 'defines an idempotent ensure_authorized_key helper'
When run bash -c "grep 'ensure_authorized_key' '$SCRIPT'"
The output should include 'ensure_authorized_key'
End

It 'guards against unsubstituted placeholder'
When run bash -c "grep -E '\\\"@\\\"\\*\\\"@\\\"' '$SCRIPT'"
The output should include '@'
End

It 'uses fixed-string match against authorized_keys'
When run bash -c "grep 'grep -qxF' '$SCRIPT'"
The output should include 'grep -qxF'
End

ensure_authorized_key_function() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Behavioral checks run a duplicated helper in the spec instead of the real ensure_authorized_key implementation, which can hide regressions in config/k3s/activate.sh.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At spec/activate_k3s_spec.sh, line 74:

<comment>Behavioral checks run a duplicated helper in the spec instead of the real `ensure_authorized_key` implementation, which can hide regressions in `config/k3s/activate.sh`.</comment>

<file context>
@@ -49,4 +49,100 @@ When run bash -c "grep -A 1 '! -f' '$SCRIPT'"
+The output should include 'grep -qxF'
+End
+
+ensure_authorized_key_function() {
+  cat <<'BASH'
+ensure_authorized_key() {
</file context>

cat <<'BASH'
ensure_authorized_key() {
local key="$1"
local ssh_dir="$HOME/.ssh"
local auth_file="$ssh_dir/authorized_keys"
if [ -z "$key" ] || [[ "$key" == "@"*"@" ]]; then
return 0
fi
mkdir -p "$ssh_dir"
chmod 700 "$ssh_dir"
touch "$auth_file"
chmod 600 "$auth_file"
if grep -qxF "$key" "$auth_file"; then
return 0
fi
if [ -s "$auth_file" ] && [ "$(tail -c1 "$auth_file" | wc -l)" -eq 0 ]; then
printf '\n' >>"$auth_file"
fi
printf '%s\n' "$key" >>"$auth_file"
}
BASH
}

It 'appends the key when authorized_keys does not exist'
When run bash -c '
tmp=$(mktemp -d)
HOME="$tmp"
'"$(ensure_authorized_key_function)"'
ensure_authorized_key "ssh-ed25519 AAAATEST test@example"
grep -qxF "ssh-ed25519 AAAATEST test@example" "$tmp/.ssh/authorized_keys"
'
The status should be success
End

It 'is idempotent on repeated runs'
When run bash -c '
tmp=$(mktemp -d)
HOME="$tmp"
'"$(ensure_authorized_key_function)"'
ensure_authorized_key "ssh-ed25519 AAAATEST test@example"
ensure_authorized_key "ssh-ed25519 AAAATEST test@example"
ensure_authorized_key "ssh-ed25519 AAAATEST test@example"
count=$(grep -cxF "ssh-ed25519 AAAATEST test@example" "$tmp/.ssh/authorized_keys")
test "$count" = "1"
'
The status should be success
End

It 'preserves existing keys when appending'
When run bash -c '
tmp=$(mktemp -d)
HOME="$tmp"
mkdir -p "$tmp/.ssh"
printf "ssh-ed25519 AAAAEXISTING old@example\n" >"$tmp/.ssh/authorized_keys"
'"$(ensure_authorized_key_function)"'
ensure_authorized_key "ssh-ed25519 AAAANEW new@example"
grep -qxF "ssh-ed25519 AAAAEXISTING old@example" "$tmp/.ssh/authorized_keys" &&
grep -qxF "ssh-ed25519 AAAANEW new@example" "$tmp/.ssh/authorized_keys"
'
The status should be success
End

It 'no-ops when given an unsubstituted placeholder'
When run bash -c '
tmp=$(mktemp -d)
HOME="$tmp"
'"$(ensure_authorized_key_function)"'
ensure_authorized_key "@galacticaAuthorizedKey@"
test ! -e "$tmp/.ssh/authorized_keys"
'
The status should be success
End
End
End
Loading