{"id":19388347,"url":"https://github.com/mk-fg/gitolite-ssh-user-proxy","last_synced_at":"2025-04-23T23:31:36.718Z","repository":{"id":144996062,"uuid":"80334197","full_name":"mk-fg/gitolite-ssh-user-proxy","owner":"mk-fg","description":"Custom shell+trigger to proxy ssh connection to gitolite user@host through a proxy/bastion host securely and transparently","archived":false,"fork":false,"pushed_at":"2024-01-10T14:09:05.000Z","size":24,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T22:23:22.196Z","etag":null,"topics":["access","authentication","bastion-host","git","gitolite","keys","network","proxy","python","ssh"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mk-fg.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-29T07:29:09.000Z","updated_at":"2023-01-20T05:46:15.000Z","dependencies_parsed_at":"2024-11-10T10:12:41.589Z","dependency_job_id":"0fd14567-6982-48aa-93b7-b6cfa35eb8fd","html_url":"https://github.com/mk-fg/gitolite-ssh-user-proxy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgitolite-ssh-user-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgitolite-ssh-user-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgitolite-ssh-user-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mk-fg%2Fgitolite-ssh-user-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mk-fg","download_url":"https://codeload.github.com/mk-fg/gitolite-ssh-user-proxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250532051,"owners_count":21446107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["access","authentication","bastion-host","git","gitolite","keys","network","proxy","python","ssh"],"created_at":"2024-11-10T10:12:30.524Z","updated_at":"2025-04-23T23:31:36.346Z","avatar_url":"https://github.com/mk-fg.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"=======================\ngitolite-ssh-user-proxy\n=======================\n\nCustom shell+trigger to proxy ssh connection to gitolite_\nuser\\@host through a proxy/bastion host securely and\ntransparently.\n\n.. _gitolite: https://gitolite.com/\n\n.. contents::\n  :backlinks: none\n\nRepository URLs:\n\n- https://github.com/mk-fg/gitolite-ssh-user-proxy\n- https://codeberg.org/mk-fg/gitolite-ssh-user-proxy\n- https://fraggod.net/code/git/gitolite-ssh-user-proxy\n\n\nWhat it does\n------------\n\nIn a setup like this one::\n\n  +---------------+\n  |               |   git@myhost.net:myrepo\n  |  dev-machine  ---------------------------+\n  |               |                          |\n  +---------------+                          |\n                                +------------v------+\n        git@gitolite:myrepo     |                   |\n    +----------------------------  myhost.net (gw)  |\n    |                           |                   |\n  +-v-------------------+       +-------------------+\n  |                     |\n  |    gitolite (gl)    |\n  |  host/container/vm  |\n  |                     |\n  +---------------------+\n\n...where \"dev-machine\" can't access \"gl\" (gitolite) host directly, allows\nfully-transparent access to gitolite via specific ssh user on a \"gw\" host\n(\"git\\@myhost.net\" in this example).\n\nE.g. simply do ``git add remote origin git@myhost.net:myrepo`` and all the\nthings gitolite will work, without any extra ssh or forwarding configuration\nfor custom ports and such on a dev machine (git client).\n\n\nHow it works\n------------\n\n- gitolite on gl machine has POST_COMPILE \"push-authkeys\" trigger installed, which\n  sends public keys from gitolite-admin keydir to gw host (via simple ``ssh git@gw \u003c keys``).\n\n- git\\@gw, upon receiving keys (to ``gitolite-proxy --auth-update`` command),\n  builds authorized_keys in same exact way as gitolite's ssh-authkeys trigger\n  does, only instead of command=\"gitolite-shell \u003ckey-id\u003e\" it has\n  command=\"gitolite-proxy \u003ckey-id\u003e\", allowing for same gitolite ssh auth to\n  happen on gw host instead.\n\n  Also has one extra key there for access from git\\@gl hook, that runs this\n  ``gitolite-proxy --auth-update`` command.\n\n- Aforementioned push-authkeys trigger (from first step), after sending keys to\n  git\\@gw, makes sure that git\\@gw key is in ~/.ssh/authorized_keys, which will\n  be used for all proxied connections.\n\n  (in addition to all gitolite-admin keys, if ssh-authkeys is enabled)\n\n  git\\@gw -\u003e git\\@gl access a forces 3-liner command=\"gw-proxy\" script,\n  which will then run ``gitolite-shell \u003ckey-id\u003e`` (reading \"key-id\" for it\n  from command passed by gitolite-proxy), same as gitolite will do normally\n  with direct access.\n\nSo every access to git\\@gw (using client key) then ends up working like this:\n\n- Runs gitolite-proxy with key-id argument for that specific key - same key-id\n  arg as gitolite-shell normally gets from command= (when accessed directly).\n\n- Which does straightforward ``os.execlp(ssh -qT gl_host_login key-id git-cmd...)``.\n\n- Which then runs \"gw-proxy\" 3-liner script from above on gl host.\n\n- Which puts \"git-cmd\" into SSH_ORIGINAL_COMMAND and does\n  ``exec gitolite-shell key-id``, i.e. runs gitolite-shell in the same way\n  as direct ssh to gitolite host would do it.\n\n- Which then does whatever gitolite is supposed to do for that key and git command.\n\n\nInstallation / setup\n--------------------\n\n- Install/setup gitolite on git\\@gl destination as usual.\n\n- Install `gitolite-proxy.py`_ to ``/usr/local/bin/gitolite-proxy`` on a gw host,\n  updating gl_host_login line in there, run ``useradd -m git`` to create git\\@gw\n  user account for sshd.\n\n- Run ``ssh-keygen -t ed25519`` as both git\\@gw and git\\@gl, add each host to\n  ~/.ssh/known_hosts on the other one.\n\n- Put following line to ~git/.ssh/authorized_keys.base on gw host, replacing\n  pubkey with ~/.ssh/id_ed25519.pub from git\\@gl::\n\n    command=\"/usr/local/bin/gitolite-proxy --auth-update\",restrict ssh-ed25519 AAA...4u3FI git@gl\n\n  Copy that file to a normal ``authorized_keys`` file as well, allow write\n  access for git\\@gw to it and ``authorized_keys.old`` backup-file next to it\n  (--auth-update from git\\@gl will be updating them). Write-access is only\n  needed to those two files.\n\n- As git\\@gl, run ``ssh -qT git@gw \u003c ~/.ssh/authorized_keys`` to do an initial\n  push of gitolite authorized-keys list to git\\@gw, and test that gitolite-proxy\n  script and all required access permissions work.\n\n- Add this to ~git/.gitolite.rc on gl host right before ENABLE line::\n\n    LOCAL_CODE =\u003e \"$rc{GL_ADMIN_BASE}/local\",\n    POST_COMPILE =\u003e ['push-authkeys'],\n\n- Commit/push `push-authkeys.sh`_ trigger into gitolite-admin repo as\n  ``local/triggers/push-authkeys``, updating gw_proxy_login line in there.\n\n- Done!\n\nBit more info on the setup can found in an old blog entry at one of these URLs:\n\n- http://blog.fraggod.net/2017/01/29/proxying-ssh-user-connections-to-gitolite-host-transparently.html\n- https://github.com/mk-fg/blog/blob/master/content/2017-01-29.proxying_ssh_user_connections_to_gitolite_host.rst\n\n.. _gitolite-proxy.py: gitolite-proxy\n.. _push-authkeys.sh: push-authkeys.sh\n\n\nNotes\n-----\n\n- With this setup in place, \"ssh-authkeys\" trigger can be disabled in gitolite,\n  which will make it only accessible through git\\@gw host, and not directly.\n\n- \"push-authkeys\" trigger can also be installed on gitolite host, without the\n  need to have it in gitolite-admin repo - see `docs on gitolite triggers\n  \u003chttp://gitolite.com/gitolite/gitolite.html#triggers\u003e`_ for more details.\n\n- \"gitolite-proxy --auth-update\" can accept (to stdin) either ssh\n  authorized_keys built by gitolite's \"ssh-authkeys\" or simpler format\n  (just keys without ssh-specific cruft) that push-authkeys sends to it.\n\n- gateway-proxy.py needs python3, push-authkeys.sh uses bash and gawk (GNU awk).\n  Both also use ssh, of course.\n\n- Paths and some other options can be tweaked in the vars at the top of the scripts.\n\n\nOther options\n-------------\n\nAssuming setup from \"What it does\" section above:\n\n- Use separate public host/IP for gitolite, e.g. git.myhost.net (!= myhost.net).\n\n- TCP port forwarding or similar tricks.\n\n  Forward ssh port connections in a \"gw:22 -\u003e gl:22\" fashion, and have\n  gw-specific sshd listen on some other port, if necessary.\n\n  This can be fairly easy to use with something like this for odd-port sshd\n  in ~/.ssh/config::\n\n    Host myhost.net\n      Port 1234\n    Host git.myhost.net\n      Port 1235\n\n  Can also be configured in git via remote urls like\n  ``ssh://git@myhost.net:1235/myrepo``.\n\n- Use ssh port forwarding to essentially do same thing as above, but with\n  resulting git port accessible on localhost.\n\n- Configure ssh to use ProxyCommand, which will login to gw host and setup\n  forwarding through it.\n\nOne advantage of using lower-level port-forwarding is that ssh authentication\nto gitolite is only handled on gitolite host/container/vm itself, all in one place,\ninstead of exposing it in on/to a gw host, adding one extra place where it\ncan potentially be vulnerable, broken, monitored, or tampered with.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmk-fg%2Fgitolite-ssh-user-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmk-fg%2Fgitolite-ssh-user-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmk-fg%2Fgitolite-ssh-user-proxy/lists"}