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
build)
case "${args[0]}" in
base) podman build --target base -t analytics-backend-base . ;;
workspace) podman build --target base -t analytics-backend-base . ;;
all) podman build -t analytics-backend-workspace . ;;
base) podman build --target base -t workspaces-base . ;;
workspace) podman build --target workspace -t workspaces . ;;
all) podman build -t workspaces . ;;
*) log ERROR "build: invalid arg '${args[0]}'" ;;
esac
;;
@ -159,18 +159,28 @@ update)
case "${args[0]}" in
containerfile) update 0 Containerfile . 500 ;;
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 ;;
gitops_router) update 1 gitops_router.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 ;;
start.sh) update 0 start.sh . 500 ;;
*) log ERROR "update: invalid arg '${args[0]}'" ;;
esac
;;
clean) clean_images ;;
status) podman images ;;
remove) remove_containers "${args[@]}" ;;
rmi) podman rmi "${args[@]}" ;;
*)
log ERROR "Unknown command: '$cmd'"
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>}"
WORKSPACE="${SSH_ORIGINAL_COMMAND:-}"
IMAGE="localhost/analytics-backend-workspace:latest"
IMAGE="localhost/workspaces:latest"
DEV_USER="devuser"
XDG_RUNTIME_DIR="/run/user/$(id -u)"
LOG_FILE="/tmp/.ssh-router-${PERSON}.log"
@ -45,7 +45,7 @@ if [[ -z "$WORKSPACE" ]]; then
WORKSPACE="$PERSON"
log INFO "Defaulted WORKSPACE → $WORKSPACE"
fi
TMUX_SESSION="${WORKSPACE}|analytics-backend"
TMUX_SESSION="${WORKSPACE}|workspace"
# ─────────────────────────────────────────────
# Ensure Podman socket is up
@ -92,16 +92,17 @@ esac
# ─────────────────────────────────────────────
# Generate per-user gitconfig
generate_gitconfig() {
local ws="$1"
local access="$HOME/access.yml"
local template="$HOME/gitconfig.template"
local userdir="$HOME/secrets/$PERSON"
local userdir="$HOME/secrets/$ws"
local name email
name=$(yq -r ".\"$PERSON\".name" "$access" 2>/dev/null || echo)
email=$(yq -r ".\"$PERSON\".email" "$access" 2>/dev/null || echo)
name=$(yq -r ".\"$ws\".name" "$access" 2>/dev/null || echo)
email=$(yq -r ".\"$ws\".email" "$access" 2>/dev/null || echo)
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
fi
@ -116,14 +117,16 @@ generate_gitconfig() {
start_container_if_needed() {
if ! podman container exists "$WORKSPACE"; then
log INFO "Creating container '$WORKSPACE'"
generate_gitconfig
generate_gitconfig "$PERSON"
podman run -dit \
--name "$WORKSPACE" \
--userns=keep-id \
--userns=keep-id:uid=1000,gid=1000 \
--group-add keep-groups \
--user "$DEV_USER" \
--hostname "$WORKSPACE" \
--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/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" \
@ -177,16 +180,21 @@ case "$MODE" in
rw)
start_container_if_needed
# Ensure tmux session exists
if ! podman exec -it --user "$DEV_USER" "$WORKSPACE" tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
podman exec -it --user "$DEV_USER" "$WORKSPACE" \
tmux new-session -d -s "$TMUX_SESSION"
fi
log INFO "$PERSON attaching to workspace '$WORKSPACE'"
# 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" \
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
log INFO "$PERSON detached from '$WORKSPACE'"
check_devuser_attached
;;
ro)

View File

@ -8,13 +8,18 @@ pallav:
- base
- workspace
- all
update:
- access
clean:
status:
multiArgsCommands:
remove:
- pallav
- palak
- param
- darshan
arbitArgsCommands:
- rmi
EOF
source ./validate_command_access.sh
@ -29,19 +34,33 @@ testcase() {
fi
}
# ----- Fixed Args Commands -----
testcase "build base (valid)" build base
testcase "build all (valid)" build all
testcase "build base workspace (invalid)" build base workspace || true
testcase "build (no arg, invalid)" build || true
testcase "update access (valid)" update access
testcase "clean (zero-arg, valid)" clean
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 param palak (valid, any order)" remove param palak
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 foo (invalid)" remove foo || true
testcase "remove palak palak (duplicate, invalid)" remove palak palak || true
testcase "status (zero-arg, valid)" status
testcase "status foo (invalid)" status foo || true
# ----- Arbitrary Args Commands -----
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 yaml="access.yml"
# Check if fixedArgsCommands.<cmd> exists
local is_fixed
# Check for fixed, multi, or arbitrary args commands
local is_fixed is_multi is_arbit
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_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
return 1
fi
# Exclude flags from positional args
# Exclude flags from positional args for fixed/multi; pass all for arbit
local args=()
for tok in "${tokens[@]}"; do
[[ "$tok" == -* ]] && continue
@ -80,4 +79,9 @@ validate_command() {
done
return 0
fi
if [[ "$is_arbit" == "true" ]]; then
# Arbitrary arguments allowed, always valid
return 0
fi
}