Compare commits

...

35 Commits

Author SHA1 Message Date
3a4773ebce Revert "feat: pass private key as env variable SSH_KEY"
This reverts commit 73f25ab8d2.
2025-05-23 15:15:45 +00:00
b88313f598 Revert "feat: remove key mounts"
This reverts commit b41097d23d.
2025-05-23 15:15:41 +00:00
8375989fd2 feat: add command to update secre key 2025-05-23 12:36:55 +00:00
b41097d23d feat: remove key mounts 2025-05-23 12:25:35 +00:00
73f25ab8d2 feat: pass private key as env variable SSH_KEY 2025-05-23 12:22:25 +00:00
c84f7ec54f Revert "feat: pass private key as argument to start.sh"
This reverts commit 5a2cab497c.
2025-05-23 12:19:28 +00:00
0e53249507 feat: add command to update start.sh 2025-05-23 09:40:23 +00:00
5a2cab497c feat: pass private key as argument to start.sh 2025-05-23 09:07:25 +00:00
1cbc443b70 feat: update path of workspaces project to /app/private 2025-05-23 09:02:21 +00:00
63fa06ee66 feat: change name from analytics-backend-workspace to workspaces 2025-05-22 17:12:02 +00:00
cae2b53209 feat: map host uid:gid to 1000:1000 inside container 2025-05-22 16:45:34 +00:00
4f61a71d12 feat: apply host group permissions inside the container 2025-05-22 16:05:18 +00:00
dd0cefd6c9 feat: split data into public and private
enable working with shared podman socket
2025-05-21 11:23:51 +00:00
79e3e0fe3f fix: correct event name mkdir -> create 2025-05-21 10:54:10 +00:00
c9c334c244 refactor: rename setgit -> setgid 2025-05-21 10:50:14 +00:00
0b3473b9c4 feat: add files to setgid on folders inside user public repos 2025-05-21 10:45:23 +00:00
3396a4360a revert: partial reverse of c333b45b (previous commit) 2025-05-20 21:20:35 +00:00
4c7171dc9b feat: add update podman_access command to gitops pipeline 2025-05-20 20:23:27 +00:00
c333b45b76 chore: remove redundant access file 2025-05-20 19:56:02 +00:00
d414a61c62 Revert "feat: add CONTAINER_CONNECTION=my_remote environment variable"
This reverts commit bd9559ad79.
2025-05-20 19:00:05 +00:00
bd9559ad79 feat: add CONTAINER_CONNECTION=my_remote environment variable 2025-05-20 18:52:07 +00:00
fa06fbb9dd fix: update save path of authorized_keys 2025-05-20 14:47:35 +00:00
4f0e173ce2 chore: add -r to yq to return quated strings 2025-05-20 14:46:57 +00:00
aebb5eab85 feat: update logic to connect to start and attach tmux 2025-05-20 14:45:33 +00:00
e298ee43c2 feat: change permissions on home.tar.gz to read only (600) 2025-05-20 09:27:15 +00:00
791165b415 fix: correct the build workspace command 2025-05-20 08:47:11 +00:00
b330636d08 feat: change the update home_tar command to directly copy from the container 2025-05-20 08:28:57 +00:00
acc0bfd748 Revert "feat: mount podman socket of user mypodmanuser"
This reverts commit 99aac09f75.
2025-05-17 19:25:31 +00:00
c1cbaffe42 fix: correct filename for update authorized_keys command 2025-05-17 18:56:40 +00:00
99aac09f75 feat: mount podman socket of user mypodmanuser 2025-05-17 18:55:02 +00:00
1f2d81984b refactor: replace $PERSON with local $ws in generate_gitconfig 2025-05-17 17:23:09 +00:00
5cf7a35311 fix: update generate_gitconfig to use go-yq without -r flag 2025-05-17 17:22:13 +00:00
0a76fb12d8 test: update command validation test with new cases 2025-05-17 17:08:20 +00:00
aa6d5ebbfb feat: add gitops command to remove podman images 2025-05-17 16:58:36 +00:00
d83040478e feat: add validation for commands with arbitrary arguments 2025-05-17 16:58:07 +00:00
7 changed files with 87 additions and 41 deletions

View File

@ -1,13 +0,0 @@
pallav:
fixedArgsCommands:
build:
- base
- workspace
- all
clean:
status:
multiArgsCommands:
remove:
- palak
- param
- darshan

View File

@ -149,9 +149,9 @@ validate_command "$PERSON" "$cmd" "${args[@]}"
case "$cmd" in case "$cmd" in
build) build)
case "${args[0]}" in case "${args[0]}" in
base) podman build --target base -t analytics-backend-base . ;; base) podman build --target base -t workspaces-base . ;;
workspace) podman build --target base -t analytics-backend-base . ;; workspace) podman build --target workspace -t workspaces . ;;
all) podman build -t analytics-backend-workspace . ;; all) podman build -t workspaces . ;;
*) log ERROR "build: invalid arg '${args[0]}'" ;; *) log ERROR "build: invalid arg '${args[0]}'" ;;
esac esac
;; ;;
@ -159,18 +159,28 @@ update)
case "${args[0]}" in case "${args[0]}" in
containerfile) update 0 Containerfile . 500 ;; containerfile) update 0 Containerfile . 500 ;;
access) update 2 access.yml . 400 ;; access) update 2 access.yml . 400 ;;
authorized_keys) update 2 access.yml . 400 ;; authorized_keys) update 2 authorized_keys .ssh 400 ;;
secret_key) update 2 keys/"${args[1]}"/id_ed25519 secrets/"${args[1]}" 400 ;;
podman_access)
update 2 podman_access.keys . 400
scp podman_access.keys mypodmanuser@alps:~/.ssh/authorized_keys
;;
ssh_router) update 1 ssh_router.sh .local/bin 500 ;; ssh_router) update 1 ssh_router.sh .local/bin 500 ;;
gitops_router) update 1 gitops_router.sh .local/bin 500 ;; gitops_router) update 1 gitops_router.sh .local/bin 500 ;;
validate_command) update 1 validate_command_access.sh .local/bin 500 ;; validate_command) update 1 validate_command_access.sh .local/bin 500 ;;
home_tar) update 0 home.tar.gz . 500 media ;; home_tar)
podman cp "$PERSON":/app/private/workspaces/home.tar.gz "$HOME"/
chmod 600 "$HOME"/home.tar.gz
;;
gitconfig) update 0 gitconfig.template . 500 ;; gitconfig) update 0 gitconfig.template . 500 ;;
start.sh) update 0 start.sh . 500 ;;
*) log ERROR "update: invalid arg '${args[0]}'" ;; *) log ERROR "update: invalid arg '${args[0]}'" ;;
esac esac
;; ;;
clean) clean_images ;; clean) clean_images ;;
status) podman images ;; status) podman images ;;
remove) remove_containers "${args[@]}" ;; remove) remove_containers "${args[@]}" ;;
rmi) podman rmi "${args[@]}" ;;
*) *)
log ERROR "Unknown command: '$cmd'" log ERROR "Unknown command: '$cmd'"
exit 127 exit 127

12
setgid-watcher.service Normal file
View File

@ -0,0 +1,12 @@
[Unit]
Description=Ensure setgid bit on all new directories in /mnt/private/workspaces-data/public
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/setgid-watcher.sh
User=root
Restart=on-failure
[Install]
WantedBy=multi-user.target

6
setgid-watcher.sh Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
WATCH_DIR="/mnt/private/workspaces-data/public"
inotifywait -m -r -e create --format '%w%f' "$WATCH_DIR" | while read -r newdir; do
chmod g+s "$newdir"
done

View File

@ -3,7 +3,7 @@ set -euo pipefail
PERSON="${1:?Usage: $0 <person>}" PERSON="${1:?Usage: $0 <person>}"
WORKSPACE="${SSH_ORIGINAL_COMMAND:-}" WORKSPACE="${SSH_ORIGINAL_COMMAND:-}"
IMAGE="localhost/analytics-backend-workspace:latest" IMAGE="localhost/workspaces:latest"
DEV_USER="devuser" DEV_USER="devuser"
XDG_RUNTIME_DIR="/run/user/$(id -u)" XDG_RUNTIME_DIR="/run/user/$(id -u)"
LOG_FILE="/tmp/.ssh-router-${PERSON}.log" LOG_FILE="/tmp/.ssh-router-${PERSON}.log"
@ -45,7 +45,7 @@ if [[ -z "$WORKSPACE" ]]; then
WORKSPACE="$PERSON" WORKSPACE="$PERSON"
log INFO "Defaulted WORKSPACE → $WORKSPACE" log INFO "Defaulted WORKSPACE → $WORKSPACE"
fi fi
TMUX_SESSION="${WORKSPACE}|analytics-backend" TMUX_SESSION="${WORKSPACE}|workspace"
# ───────────────────────────────────────────── # ─────────────────────────────────────────────
# Ensure Podman socket is up # Ensure Podman socket is up
@ -92,16 +92,17 @@ esac
# ───────────────────────────────────────────── # ─────────────────────────────────────────────
# Generate per-user gitconfig # Generate per-user gitconfig
generate_gitconfig() { generate_gitconfig() {
local ws="$1"
local access="$HOME/access.yml" local access="$HOME/access.yml"
local template="$HOME/gitconfig.template" local template="$HOME/gitconfig.template"
local userdir="$HOME/secrets/$PERSON" local userdir="$HOME/secrets/$ws"
local name email local name email
name=$(yq -r ".\"$PERSON\".name" "$access" 2>/dev/null || echo) name=$(yq -r ".\"$ws\".name" "$access" 2>/dev/null || echo)
email=$(yq -r ".\"$PERSON\".email" "$access" 2>/dev/null || echo) email=$(yq -r ".\"$ws\".email" "$access" 2>/dev/null || echo)
if [[ -z "$name" || -z "$email" ]]; then if [[ -z "$name" || -z "$email" ]]; then
log ERROR "Missing name/email for '$PERSON' in $access" log ERROR "Missing name/email for '$ws' in $access"
exit 1 exit 1
fi fi
@ -116,14 +117,16 @@ generate_gitconfig() {
start_container_if_needed() { start_container_if_needed() {
if ! podman container exists "$WORKSPACE"; then if ! podman container exists "$WORKSPACE"; then
log INFO "Creating container '$WORKSPACE'" log INFO "Creating container '$WORKSPACE'"
generate_gitconfig generate_gitconfig "$PERSON"
podman run -dit \ podman run -dit \
--name "$WORKSPACE" \ --name "$WORKSPACE" \
--userns=keep-id \ --userns=keep-id:uid=1000,gid=1000 \
--group-add keep-groups \
--user "$DEV_USER" \ --user "$DEV_USER" \
--hostname "$WORKSPACE" \ --hostname "$WORKSPACE" \
--label auto-cleanup=true \ --label auto-cleanup=true \
-v "$HOME/data/$WORKSPACE:/app:Z" \ -v "/mnt/private/workspaces-data/public/$WORKSPACE:/app/public" \
-v "/mnt/private/workspaces-data/private/$WORKSPACE:/app/private" \
-v "$HOME/secrets/$WORKSPACE/gitconfig:/home/$DEV_USER/.gitconfig:ro,Z" \ -v "$HOME/secrets/$WORKSPACE/gitconfig:/home/$DEV_USER/.gitconfig:ro,Z" \
-v "$HOME/secrets/$WORKSPACE/id_ed25519:/home/$DEV_USER/.ssh/id_ed25519:ro,Z" \ -v "$HOME/secrets/$WORKSPACE/id_ed25519:/home/$DEV_USER/.ssh/id_ed25519:ro,Z" \
-v "$HOME/secrets/$WORKSPACE/id_ed25519.pub:/home/$DEV_USER/.ssh/id_ed25519.pub:ro,Z" \ -v "$HOME/secrets/$WORKSPACE/id_ed25519.pub:/home/$DEV_USER/.ssh/id_ed25519.pub:ro,Z" \
@ -177,16 +180,21 @@ case "$MODE" in
rw) rw)
start_container_if_needed start_container_if_needed
# Ensure tmux session exists log INFO "$PERSON attaching to workspace '$WORKSPACE'"
if ! podman exec -it --user "$DEV_USER" "$WORKSPACE" tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
# Try to attach to session; if it fails, create and attach
if ! podman exec -it -e TERM="$TERM" --user "$DEV_USER" "$WORKSPACE" \
tmux attach -t "$TMUX_SESSION"; then
log WARN "tmux session not found, creating new session"
podman exec -it --user "$DEV_USER" "$WORKSPACE" \ podman exec -it --user "$DEV_USER" "$WORKSPACE" \
tmux new-session -d -s "$TMUX_SESSION" tmux new-session -d -s "$TMUX_SESSION" 2>/dev/null || true
podman exec -it -e TERM="$TERM" --user "$DEV_USER" "$WORKSPACE" \
tmux attach -t "$TMUX_SESSION"
fi fi
log INFO "$PERSON attaching to workspace '$WORKSPACE'"
podman exec -it -e TERM="$TERM" --user "$DEV_USER" "$WORKSPACE" \
tmux attach -t "$TMUX_SESSION"
log INFO "$PERSON detached from '$WORKSPACE'" log INFO "$PERSON detached from '$WORKSPACE'"
check_devuser_attached check_devuser_attached
;; ;;
ro) ro)

View File

@ -8,13 +8,18 @@ pallav:
- base - base
- workspace - workspace
- all - all
update:
- access
clean: clean:
status: status:
multiArgsCommands: multiArgsCommands:
remove: remove:
- pallav
- palak - palak
- param - param
- darshan - darshan
arbitArgsCommands:
- rmi
EOF EOF
source ./validate_command_access.sh source ./validate_command_access.sh
@ -29,19 +34,33 @@ testcase() {
fi fi
} }
# ----- Fixed Args Commands -----
testcase "build base (valid)" build base testcase "build base (valid)" build base
testcase "build all (valid)" build all testcase "build all (valid)" build all
testcase "build base workspace (invalid)" build base workspace || true testcase "build base workspace (invalid)" build base workspace || true
testcase "build (no arg, invalid)" build || true testcase "build (no arg, invalid)" build || true
testcase "update access (valid)" update access
testcase "clean (zero-arg, valid)" clean testcase "clean (zero-arg, valid)" clean
testcase "clean with arg (invalid)" clean foo || true testcase "clean with arg (invalid)" clean foo || true
testcase "status (zero-arg, valid)" status
testcase "status foo (invalid)" status foo || true
# ----- Multi Args Commands -----
testcase "remove palak (valid)" remove palak testcase "remove palak (valid)" remove palak
testcase "remove param palak (valid, any order)" remove param palak testcase "remove param palak (valid, any order)" remove param palak
testcase "remove palak param darshan (valid, any order)" remove palak param darshan testcase "remove palak param darshan (valid, any order)" remove palak param darshan
testcase "remove pallav (valid)" remove pallav -f
testcase "remove (no arg, invalid)" remove || true testcase "remove (no arg, invalid)" remove || true
testcase "remove foo (invalid)" remove foo || true testcase "remove foo (invalid)" remove foo || true
testcase "remove palak palak (duplicate, invalid)" remove palak palak || true testcase "remove palak palak (duplicate, invalid)" remove palak palak || true
testcase "status (zero-arg, valid)" status # ----- Arbitrary Args Commands -----
testcase "status foo (invalid)" status foo || true testcase "rmi no args (valid)" rmi
testcase "rmi one arg (valid)" rmi image1
testcase "rmi multiple args (valid)" rmi image1 image2 image3
testcase "rmi with flag (valid)" rmi -f image1 image2
testcase "rmi with only flag (valid)" rmi -f
# ----- Disallowed command -----
testcase "foo (invalid command)" foo image1 # should fail

View File

@ -7,19 +7,18 @@ validate_command() {
local tokens=("$@") local tokens=("$@")
local yaml="access.yml" local yaml="access.yml"
# Check if fixedArgsCommands.<cmd> exists # Check for fixed, multi, or arbitrary args commands
local is_fixed local is_fixed is_multi is_arbit
is_fixed="$(yq e ".\"$PERSON\".fixedArgsCommands | has(\"$cmd\")" "$yaml")" is_fixed="$(yq e ".\"$PERSON\".fixedArgsCommands | has(\"$cmd\")" "$yaml")"
# Check if multiArgsCommands.<cmd> exists
local is_multi
is_multi="$(yq e ".\"$PERSON\".multiArgsCommands | has(\"$cmd\")" "$yaml")" is_multi="$(yq e ".\"$PERSON\".multiArgsCommands | has(\"$cmd\")" "$yaml")"
is_arbit="$(yq e ".\"$PERSON\".arbitArgsCommands[]" "$yaml" | grep -qx "$cmd" && echo true || echo false)"
if [[ "$is_fixed" != "true" && "$is_multi" != "true" ]]; then if [[ "$is_fixed" != "true" && "$is_multi" != "true" && "$is_arbit" != "true" ]]; then
echo "ERROR: Command '$cmd' not allowed for $PERSON" >&2 echo "ERROR: Command '$cmd' not allowed for $PERSON" >&2
return 1 return 1
fi fi
# Exclude flags from positional args # Exclude flags from positional args for fixed/multi; pass all for arbit
local args=() local args=()
for tok in "${tokens[@]}"; do for tok in "${tokens[@]}"; do
[[ "$tok" == -* ]] && continue [[ "$tok" == -* ]] && continue
@ -80,4 +79,9 @@ validate_command() {
done done
return 0 return 0
fi fi
if [[ "$is_arbit" == "true" ]]; then
# Arbitrary arguments allowed, always valid
return 0
fi
} }