aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alternative-way/config.yaml11
-rwxr-xr-xalternative-way/gitserve61
-rwxr-xr-xcreate-repo6
-rwxr-xr-xgitcmd47
-rw-r--r--readme.txt57
5 files changed, 182 insertions, 0 deletions
diff --git a/alternative-way/config.yaml b/alternative-way/config.yaml
new file mode 100644
index 0000000..1a27a66
--- /dev/null
+++ b/alternative-way/config.yaml
@@ -0,0 +1,11 @@
+username:
+
+ # example of readwrite access
+ reponame: rw
+
+ # public
+ reponame2: ro
+
+username2:
+
+ reponame2: rw
diff --git a/alternative-way/gitserve b/alternative-way/gitserve
new file mode 100755
index 0000000..bfb9ea6
--- /dev/null
+++ b/alternative-way/gitserve
@@ -0,0 +1,61 @@
+#!/usr/bin/python3
+
+import sys
+import os
+import re
+import yaml
+from sys import stderr
+
+repo_regex = re.compile(r'\'([a-zA-Z0-9-]+)(.git)?\'$')
+command_regex = re.compile('^[a-zA-Z0-9-]+')
+
+valid_ro_commands=('git-upload-pack')
+valid_rw_commands=('git-upload-pack', 'git-receive-pack')
+
+#print >>sys.stderr, "command d'org: %s" % os.environ['SSH_ORIGINAL_COMMAND']
+
+if 'SSH_ORIGINAL_COMMAND' not in os.environ:
+ print('You are not authorized to login directly.', file=stderr)
+ sys.exit(1)
+
+ssh_original_command = os.environ['SSH_ORIGINAL_COMMAND']
+user = sys.argv[1]
+
+conf = yaml.load(open('/home/calendros/seele/git/config.yaml', 'r'))
+#print('conf: ', conf)
+
+if user not in conf:
+ print('access not allowed for user {}.'.format(user), file=stderr)
+ sys.exit(1)
+
+if ssh_original_command == 'ls' or ssh_original_command == 'list':
+ print('\n'.join([repo for repo in conf[user].keys()]))
+ sys.exit(0)
+
+repo = repo_regex.findall(ssh_original_command)[0][0]
+if repo.endswith('.git'):
+ repo = repo[:-4]
+
+if repo not in conf[user].keys():
+ print('repository {} not allowed for {}.'.format(repo, user), file=stderr)
+ sys.exit(1)
+
+command = command_regex.findall(ssh_original_command)[0]
+
+if ((conf[user][repo] == 'rw' and command not in valid_rw_commands)
+ or (conf[user][repo] == 'ro' and command not in valid_ro_commands)):
+ print('command {} not allowed for {}.'.format(command, user), file=stderr)
+ sys.exit(1)
+
+os.chdir(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ 'repositories'))
+
+command_map = {
+ 'git-upload-pack': lambda: os.execv('/usr/bin/git-upload-pack',
+ ['/usr/bin/git-upload-pack', '--strict', '--timeout=600', repo]),
+ 'git-receive-pack': lambda: os.execv('/usr/bin/git-receive-pack',
+ ['/usr/bin/git-receive-pack', repo])
+ }
+
+command_map[command]()
diff --git a/create-repo b/create-repo
new file mode 100755
index 0000000..2883b58
--- /dev/null
+++ b/create-repo
@@ -0,0 +1,6 @@
+#!/bin/sh
+if [ -n "$1" ]; then
+ echo "Usage: create-repo <reponame>"
+ exit 1
+fi
+sudo -u git git init --bare "$1"
diff --git a/gitcmd b/gitcmd
new file mode 100755
index 0000000..53cd3d8
--- /dev/null
+++ b/gitcmd
@@ -0,0 +1,47 @@
+#!/usr/bin/python3
+
+import sys
+import os
+
+def printerr(*l, **d): return print(*l, **d, file=sys.stderr)
+def fail(*l, **d): printerr(*l, **d); raise SystemExit(1)
+
+try:
+ user = sys.argv[1]
+except IndexError:
+ fail('Bad adminsys, he forgot to set user associated with this key.')
+
+try:
+ with open(user + '.listro', 'r', encoding='utf8') as f:
+ repositories_ro = f.read().splitlines()
+except FileNotFoundError:
+ repositories_ro = []
+
+try:
+ with open(user + '.listrw', 'r', encoding='utf8') as f:
+ repositories_rw = f.read().splitlines()
+except FileNotFoundError:
+ repositories_rw = []
+
+try:
+ ssh_original_command = os.environ['SSH_ORIGINAL_COMMAND'].split()
+ command = ssh_original_command[0]
+ repository = ssh_original_command[1].split('.git')[0].strip("'")
+except IndexError:
+ if command == 'ls':
+ print('\n'.join(repositories_ro + repositories_rw or ['Empty list']))
+ raise SystemExit(0)
+ fail('Invalid repository name or git usage')
+except KeyError:
+ fail('Bad boy, git only access authorized.')
+
+repositories_ro = repositories_ro + repositories_rw
+if command == 'git-upload-pack' and repository in repositories_ro:
+ os.execv('/usr/bin/git-upload-pack',
+ ['/usr/bin/git-upload-pack', '--strict', '--timeout=600',
+ repository])
+elif command == 'git-receive-pack' and repository in repositories_rw:
+ os.execv('/usr/bin/git-receive-pack',
+ ['/usr/bin/git-receive-pack', repository])
+else:
+ fail('Bad git command or inexistant repository or access denied')
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..27039f5
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,57 @@
+This repository is a quick setup to allow readonly and readwrite access for
+git-only through ssh. It is simple but should be secure. You can review the
+script for security as it is really short.
+
+
+sudo adduser --home /home/git --no-create-home --shell /bin/sh --gecos 'git version control' --disabled-password git
+sudo mkdir /home/git
+sudo chown git:git /home/git
+sudo chmod 2770 /home/git
+sudo cp path/gitcmd /home/git/
+sudo gpasswd -a calendros git
+
+in /etc/ssh/sshd_config:
+
+Match User git
+ X11Forwarding no
+ AllowTcpForwarding no
+ AllowAgentForwarding no
+ PermitTunnel no
+ GatewayPorts no
+ PermitTTY no
+ Banner "Only git access allowed"
+ AuthorizedKeysFile /etc/ssh/git_keys
+
+in /etc/ssh/git_keys
+
+# usage: restrict,command="./gitcmd username" key
+# then create a ~git/username.listro for authorized repositories
+
+username.listro with username replaced with the username given at the gitcmd
+argument at the front of the ssh key contains a list of repositories
+directory for read-only access. username.listrw contains a list of read-write
+access.
+
+git directories are created with git init --bare <reponame>
+
+Example of directory structure:
+
+in /home/git:
+
+$ tree --dirsfirst -L 2
+.
+├── <reponame>
+│   ├── branches
+│   ├── hooks
+│   ├── info
+│   ├── objects
+│   ├── refs
+│   ├── HEAD
+│   ├── config
+│   └── description
+├── <username>.listrw
+├── <username>.listro
+├── create-repo
+└── gitcmd
+
+6 directories, 8 files