gitreef

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 9f3f15945e86a5e246d106c31cc51b613a3fc2d5
parent 6032076cd9074451a0ec0c061d9e9e81911932cc
Author: Matthias Jaros <jaros@mailbox.org>
Date:   Mon, 20 Oct 2025 12:23:03 +0200

Security hardening

Diffstat:
MDockerfile | 6++++--
Mdocker-compose.yml | 2++
Asrc/env | 4++++
Msrc/init | 14+++++++++-----
Msrc/run | 32++++++++++++++++++++++----------
Msrc/ssh.conf | 9++++++++-
Msrc/sudo-git | 1-
7 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/Dockerfile b/Dockerfile @@ -9,9 +9,11 @@ COPY src/ssh.conf /etc/ssh/sshd_config.d/ COPY src/sudo-git /etc/sudoers.d/ # copy scrips -COPY src/run /usr/local/bin/ +COPY src/env /usr/local/bin/ COPY src/init /usr/local/bin/ -RUN chmod 755 /usr/local/bin/run +COPY src/run /usr/local/bin/ +RUN chmod 755 /usr/local/bin/env RUN chmod 755 /usr/local/bin/init +RUN chmod 755 /usr/local/bin/run ENTRYPOINT ["/usr/local/bin/init"] diff --git a/docker-compose.yml b/docker-compose.yml @@ -10,7 +10,9 @@ services: environment: - GIT_UID=1000 - USER_handy=handy:ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPsl91WPAT8aWwZ6y5WAfXU9PoHzxJ3YG9uFgSmlGQr2HwV+gL/XaTBJ4Brj+pa+R7tfYEBMi+7Navx/ZsEmr9E= mj@xps15 + - USER_yolo=yolo:ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPsl91WPAT8aWwZ6y5WAfXU9PoHzxJ3YG9uFgSmlGQr2HwV+gL/XaTBJ4Brj+pa+R7tfYEBMi+7Navx/ZsEmr9E= mj@xps15 - REPO_pass=/pass.git:handy volumes: - ./donotsync/ssh:/var/ssh - ./donotsync/repos:/srv/repos + - ./donotsync/log:/var/log diff --git a/src/env b/src/env @@ -0,0 +1,4 @@ +set _REPO_PERMISSIONS_FILE /etc/repo-permissions +set _REPO_VALIDATION_REGEX "((?:\/[a-zA-Z0-9_-]+)+.git)" +set _GIT_VALIDATION_REGEX "^(git-(?:upload-pack|receive-pack|upload-archive)) '$_REPO_VALIDATION_REGEX'\$" +set LOG /var/log/error.txt diff --git a/src/init b/src/init @@ -1,14 +1,14 @@ #!/usr/bin/env fish +# load environment +source (dirname (status --current-filename))/env + # # # function definitions # # -set _REPO_PERMISSIONS_FILE /etc/repo-permissions -set _REPO_VALIDATION_REGEX "^((?:\/[a-zA-Z-]+)+.git)\$" - function createUser set -l userConfig (string split ':' $argv[1]) set -l user $userConfig[1] @@ -37,9 +37,9 @@ function setupRepo set -l repo $parsedConfig[1] # check repo name - set -l matcher (string match -r -g $_REPO_VALIDATION_REGEX $repo) + set -l matcher (string match -r -g "^$_REPO_VALIDATION_REGEX\$" $repo) if test -z $matcher[1] - echo "Invalid repo name $repo" + echo "Failed to setup repo, invalid path/name: $repo" return 1 end @@ -102,6 +102,7 @@ end # git user has read/write access to all repos, set git-shell # and no password login allowed -> no ssh login possible adduser git -u $GIT_UID -D --shell "/usr/bin/git-shell" +passwd -l git for userConfig in $users createUser "$userConfig" end @@ -112,6 +113,9 @@ for repoConfig in $repos setupRepo "$repoConfig" end +# create writable log file +touch $LOG && chmod 777 $LOG + echo "Setting up server" # generate host keys in case mkdir -p /var/ssh/etc/ssh/ && ssh-keygen -A -f /var/ssh diff --git a/src/run b/src/run @@ -1,25 +1,37 @@ #!/usr/bin/env fish -set _REPO_PERMISSIONS_FILE /etc/repo-permissions -# unify repo regex somehow -set _GIT_VALIDATION_REGEX "^(git-(?:upload-pack|receive-pack|upload-archive)) '((?:\/[a-zA-Z-]+)+.git)'\$" +# load environment +source (dirname (status --current-filename))/env # check given git command -set -l matcher (string match -r -g $_GIT_VALIDATION_REGEX "$argv") +set -l currentUser (whoami) +set -l matcher (string match -r -g $_GIT_VALIDATION_REGEX -- "$argv") if test (count $matcher) -ne 2 # there should be two groups otherwise something is wrong + echo "$(date -Is): DENY bad_format user=$currentUser ip=$SSH_CONNECTION argv=$argv" &>$LOG exit 1 end -# echo check for permissions -set -l checkUser (whoami) +# extract variables from git command set -l gitCommand $matcher[1] set -l repo $matcher[2] + # adjust repo path to /srv/repos -set -l repoDir srv repos -set -l repoDir /(string join -n '/' $repoDir (string split '/' $repo)) -cat $_REPO_PERMISSIONS_FILE | grep -q -E "^$repoDir:$checkUser\$" -or exit 1; +set -l repoDir /(string join -n '/' srv repos (string split '/' $repo)) + +# check repo jail in /srv/repos +if not string match -r -q -- "/srv/repos/.*" "(realpath $repoDir)" + # something is for sure wrong here + echo "$(date -Is): DENY jail_escape user=$currentUser ip=$SSH_CONNECTION argv=$argv" &>$LOG + exit 2 +end + +# check for permissions +if not cat $_REPO_PERMISSIONS_FILE | grep -q -E "^$repoDir:$currentUser\$" + # something is for sure wrong here + echo "$(date -Is): DENY no_permissions user=$currentUser ip=$SSH_CONNECTION argv=$argv" &>$LOG + exit 1 +end # execute parsed git command /usr/bin/sudo -u git /usr/bin/git-shell -c "$gitCommand '$repoDir'" diff --git a/src/ssh.conf b/src/ssh.conf @@ -1,6 +1,10 @@ -# Security, do not allow any access to the git repos outside of allowed users +# Security, we only want public key login for users and NOT for users root,git PermitRootLogin no PasswordAuthentication no +PubkeyAuthentication yes +AuthenticationMethods publickey +KbdInteractiveAuthentication no +ChallengeResponseAuthentication no PermitTTY no AllowAgentForwarding no @@ -15,3 +19,6 @@ LogLevel INFO # Force run script that checks for permissions and runs sudo ForceCommand /usr/local/bin/run "$SSH_ORIGINAL_COMMAND" + +# git user has access to EVERYTHING. no login should be possible +DenyUsers git diff --git a/src/sudo-git b/src/sudo-git @@ -1,2 +1 @@ -Defaults:pass !requiretty ALL ALL=(git) NOPASSWD: /usr/bin/git-shell