Swap relation of symlinks

This commit is contained in:
Drew DeVault 2018-12-31 11:24:45 -05:00
parent 240c0f64e8
commit acf9751e05
12 changed files with 279 additions and 279 deletions

View File

@ -1,67 +0,0 @@
#!/usr/bin/env python3
# AuthorizedKeysCommand=/usr/bin/git-srht-dispatch "%u" "%h" "%t" "%k"
# AuthorizedKeysUser=root
import sys
import os
try:
f = open("/var/log/git-srht-dispatch", "a")
os.close(sys.stderr.fileno())
os.dup2(f.fileno(), sys.stderr.fileno())
except Exception as ex:
sys.stderr.write("Unable to open log for writing\n")
sys.stderr.write(str(ex) + "\n")
from collections import namedtuple
from datetime import datetime
from pwd import getpwnam
from grp import getgrnam
from srht.config import cfg, cfgkeys
def log(s, *args):
sys.stderr.write("{} {}\n".format(datetime.now().isoformat(),
s.format(*args) if isinstance(s, str) else str(s)))
sys.stderr.flush()
log("Running git-srht-dispatch")
def auth_keys_error():
log("This command should be run by sshd's AuthorizedKeysCommand")
log('AuthorizedKeysCommand={} "%u" "%h" "%t" "%k"\nAuthorizedKeysUser=root',
os.path.abspath(sys.argv[0]))
sys.exit(1)
Dispatcher = namedtuple("Dispatcher", ["cmd", "uid", "gid"])
dispatchers = list()
for cmd in cfgkeys("git.sr.ht::dispatch"):
user = cfg("git.sr.ht::dispatch", cmd).split(":")
uid, gid = getpwnam(user[0]).pw_uid, getgrnam(user[-1]).gr_gid
dispatchers.append(Dispatcher(cmd=cmd, uid=uid, gid=gid))
log("registered dispatcher for {}:{}: {}", uid, gid, cmd)
if len(sys.argv) != 5:
auth_keys_error()
user = sys.argv[1]
uid = getpwnam(user).pw_uid
homedir = sys.argv[2]
key_type = sys.argv[3]
b64key = sys.argv[4]
authorized_keys_file = "{}/.ssh/authorized_keys".format(homedir)
log("authorizing user={} ({}) home={} b64key={} key_type={}",
user, uid, homedir, b64key, key_type)
for dispatch in dispatchers:
if dispatch.uid == uid:
log("dispatching to {} with uid={}, gid={}",
dispatch.cmd, dispatch.uid, dispatch.gid)
os.setgid(dispatch.gid)
os.setuid(dispatch.uid)
os.execl(dispatch.cmd, *([dispatch.cmd] + sys.argv[1:]))
log("Falling back to existing authorized keys file")
if not os.path.exists(authorized_keys_file):
sys.exit(0)
with open(authorized_keys_file, "r") as f:
authorized_keys = f.read()
print(authorized_keys)
sys.exit(0)

1
git-srht-dispatch Symbolic link
View File

@ -0,0 +1 @@
gitsrht-dispatch

View File

@ -1,33 +0,0 @@
#!/usr/bin/env python3
import os
import sys
import requests
from srht.config import cfg
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import User
db.init()
sys.stderr.write(str(sys.argv) + "\n")
key_type = sys.argv[3]
b64key = sys.argv[4]
r = requests.get("{}/api/ssh-key/{}".format(
cfg("meta.sr.ht", "origin"), b64key))
if r.status_code != 200:
sys.stderr.write("meta.sr.ht returned 404 for this key\n")
sys.exit(0)
j = r.json()
username = j["owner"]["name"]
u = User.query.filter(User.username == username).first()
if not u:
sys.stderr.write("Unknown user {}\n", username)
sys.exit(1)
default_shell = os.path.join(os.path.dirname(sys.argv[0]), "git-srht-shell")
shell = cfg("git.sr.ht", "shell", default=default_shell)
keys = "command=\"{} '{}' '{}'\",".format(shell, u.id, b64key) + \
"no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty " + \
"{} {} {}".format(key_type, b64key, username) + "\n"
print(keys)
sys.stderr.write(keys)
sys.exit(0)

1
git-srht-keys Symbolic link
View File

@ -0,0 +1 @@
gitsrht-keys

View File

@ -1,5 +0,0 @@
#!/usr/bin/env python3
import gitsrht.alembic
from srht.config import cfg
from srht.database import alembic
alembic("git.sr.ht", gitsrht.alembic)

1
git-srht-migrate Symbolic link
View File

@ -0,0 +1 @@
gitsrht-migrate

View File

@ -1,17 +0,0 @@
#!/usr/bin/env python3
from srht.config import cfg
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import Repository, RepoVisibility
db.init()
from datetime import datetime, timedelta
def cleanup_autocreated():
due = datetime.utcnow() - timedelta(minutes=20)
repos = (Repository.query
.filter(Repository.visibility == RepoVisibility.autocreated)
.filter(Repository.created < due)).all()
(db.session.delete(r) for r in repos)
db.session.commit()
cleanup_autocreated()

1
git-srht-periodic Symbolic link
View File

@ -0,0 +1 @@
gitsrht-periodic

View File

@ -1,93 +0,0 @@
#!/usr/bin/env python3
import sys
import os
try:
f = open("/var/log/git-srht-shell", "a")
os.close(sys.stderr.fileno())
os.dup2(f.fileno(), sys.stderr.fileno())
except Exception as ex:
sys.stderr.write("Unable to open log for writing\n")
sys.stderr.write(str(ex) + "\n")
import requests
import shlex
from datetime import datetime
from srht.config import cfg
from srht.validation import Validation
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import User, Repository, RepoVisibility, Redirect
from gitsrht.access import has_access, UserAccess
from gitsrht.repos import create_repo
db.init()
def log(s, *args):
sys.stderr.write("{} {}\n".format(datetime.now().isoformat(),
s.format(*args) if isinstance(s, str) else str(s)))
origin = cfg("git.sr.ht", "origin")
repos = cfg("git.sr.ht", "repos")
_cmd = os.environ.get("SSH_ORIGINAL_COMMAND")
if not _cmd:
_cmd = ""
if len(sys.argv) < 2:
log("Error: expected 2 arguments from SSH")
sys.exit(1)
user_id = sys.argv[1]
ssh_key = sys.argv[2]
user = User.query.filter(User.id == user_id).first()
if not user:
log("Unknown user ID {}", user_id)
sys.exit(1)
log("User: {}", user.username)
cmd = shlex.split(_cmd)
valid_commands = ["git-receive-pack", "git-upload-pack", "git-upload-archive"]
if len(cmd) < 1 or not cmd[0] in valid_commands:
log("Not permitting unacceptable command")
print("Hi {}! You've successfully authenticated, ".format(user.username) +
"but I do not provide an interactive shell. Bye!")
sys.exit(128)
os.chdir(repos)
path = os.path.abspath(cmd[-1])
if not path.startswith(repos):
sys.stderr.write("Access denied")
sys.exit(128)
cmd[-1] = path
repo = Repository.query.filter(Repository.path == path).first()
if not repo:
repo = Redirect.query.filter(Redirect.path == path).first()
if repo:
repo = repo.new_repo
sys.stderr.write("\n\t\033[93mNOTICE\033[0m\n")
sys.stderr.write("\tThis repository has moved:\n")
# TODO: orgs
sys.stderr.write("\t{}/~{}/{}\n".format(
origin, repo.owner.username, repo.name))
sys.stderr.write("\tPlease update your remote.\n\n")
sys.exit(128)
_path, repo_name = os.path.split(path)
owner = os.path.basename(_path)
if "~" + user.username != owner:
sys.exit(128)
valid = Validation({ "name": repo_name })
repo = create_repo(valid, user)
if not valid.ok:
sys.exit(128)
repo.visibility = RepoVisibility.autocreated
db.session.commit()
if cmd[0] == "git-receive-pack":
if not has_access(repo, UserAccess.write, user):
sys.exit(128)
else:
if not has_access(repo, UserAccess.read, user):
sys.exit(128)
log("Executing {}", " ".join(cmd))
sys.stderr.close()
os.execvp(cmd[0], cmd)

1
git-srht-shell Symbolic link
View File

@ -0,0 +1 @@
gitsrht-shell

View File

@ -1,58 +0,0 @@
#!/usr/bin/env python3
from srht.config import cfg, cfgi
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import User, Repository, RepoVisibility
db.init()
from configparser import ConfigParser
from datetime import datetime
from pygit2 import Repository as GitRepository
import shlex
import subprocess
import sys
import re
op = sys.argv[0]
builds_sr_ht = cfg("builds.sr.ht", "origin", default=None)
origin = cfg("git.sr.ht", "origin")
if op == "hooks/post-update":
refs = sys.argv[1:]
config = ConfigParser()
with open("config") as f:
config.read_file(f)
repo_id = config.get("srht", "repo-id")
if not repo_id:
sys.exit(0)
repo_id = int(repo_id)
repo = Repository.query.get(repo_id)
if not repo:
sys.exit(0)
if repo.visibility == RepoVisibility.autocreated:
print("\n\t\033[93mNOTICE\033[0m")
print("\tWe saved your changes, but this repository does not exist.")
print("\tClick here to create it:")
print("\t{}/create?name={}".format(origin, repo.name))
print("\tYour changes will be discarded in 20 minutes.\n")
repo.updated = datetime.utcnow()
db.session.commit()
git_repo = GitRepository(repo.path)
for ref in refs:
try:
if re.match(r"^[0-9a-z]{40}$", ref): # commit
ref = git_repo.get(ref)
elif ref.startswith("refs/"): # ref
ref = git_repo.lookup_reference(ref).target
else:
continue
except:
continue
if builds_sr_ht:
from gitsrht.worker import do_post_update
do_post_update(repo, git_repo, ref)

1
git-srht-update-hook Symbolic link
View File

@ -0,0 +1 @@
gitsrht-update-hook

View File

@ -1 +0,0 @@
git-srht-dispatch

67
gitsrht-dispatch Executable file
View File

@ -0,0 +1,67 @@
#!/usr/bin/env python3
# AuthorizedKeysCommand=/usr/bin/git-srht-dispatch "%u" "%h" "%t" "%k"
# AuthorizedKeysUser=root
import sys
import os
try:
f = open("/var/log/git-srht-dispatch", "a")
os.close(sys.stderr.fileno())
os.dup2(f.fileno(), sys.stderr.fileno())
except Exception as ex:
sys.stderr.write("Unable to open log for writing\n")
sys.stderr.write(str(ex) + "\n")
from collections import namedtuple
from datetime import datetime
from pwd import getpwnam
from grp import getgrnam
from srht.config import cfg, cfgkeys
def log(s, *args):
sys.stderr.write("{} {}\n".format(datetime.now().isoformat(),
s.format(*args) if isinstance(s, str) else str(s)))
sys.stderr.flush()
log("Running git-srht-dispatch")
def auth_keys_error():
log("This command should be run by sshd's AuthorizedKeysCommand")
log('AuthorizedKeysCommand={} "%u" "%h" "%t" "%k"\nAuthorizedKeysUser=root',
os.path.abspath(sys.argv[0]))
sys.exit(1)
Dispatcher = namedtuple("Dispatcher", ["cmd", "uid", "gid"])
dispatchers = list()
for cmd in cfgkeys("git.sr.ht::dispatch"):
user = cfg("git.sr.ht::dispatch", cmd).split(":")
uid, gid = getpwnam(user[0]).pw_uid, getgrnam(user[-1]).gr_gid
dispatchers.append(Dispatcher(cmd=cmd, uid=uid, gid=gid))
log("registered dispatcher for {}:{}: {}", uid, gid, cmd)
if len(sys.argv) != 5:
auth_keys_error()
user = sys.argv[1]
uid = getpwnam(user).pw_uid
homedir = sys.argv[2]
key_type = sys.argv[3]
b64key = sys.argv[4]
authorized_keys_file = "{}/.ssh/authorized_keys".format(homedir)
log("authorizing user={} ({}) home={} b64key={} key_type={}",
user, uid, homedir, b64key, key_type)
for dispatch in dispatchers:
if dispatch.uid == uid:
log("dispatching to {} with uid={}, gid={}",
dispatch.cmd, dispatch.uid, dispatch.gid)
os.setgid(dispatch.gid)
os.setuid(dispatch.uid)
os.execl(dispatch.cmd, *([dispatch.cmd] + sys.argv[1:]))
log("Falling back to existing authorized keys file")
if not os.path.exists(authorized_keys_file):
sys.exit(0)
with open(authorized_keys_file, "r") as f:
authorized_keys = f.read()
print(authorized_keys)
sys.exit(0)

View File

@ -1 +0,0 @@
git-srht-keys

33
gitsrht-keys Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env python3
import os
import sys
import requests
from srht.config import cfg
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import User
db.init()
sys.stderr.write(str(sys.argv) + "\n")
key_type = sys.argv[3]
b64key = sys.argv[4]
r = requests.get("{}/api/ssh-key/{}".format(
cfg("meta.sr.ht", "origin"), b64key))
if r.status_code != 200:
sys.stderr.write("meta.sr.ht returned 404 for this key\n")
sys.exit(0)
j = r.json()
username = j["owner"]["name"]
u = User.query.filter(User.username == username).first()
if not u:
sys.stderr.write("Unknown user {}\n", username)
sys.exit(1)
default_shell = os.path.join(os.path.dirname(sys.argv[0]), "git-srht-shell")
shell = cfg("git.sr.ht", "shell", default=default_shell)
keys = "command=\"{} '{}' '{}'\",".format(shell, u.id, b64key) + \
"no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty " + \
"{} {} {}".format(key_type, b64key, username) + "\n"
print(keys)
sys.stderr.write(keys)
sys.exit(0)

View File

@ -1 +0,0 @@
git-srht-migrate

5
gitsrht-migrate Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env python3
import gitsrht.alembic
from srht.config import cfg
from srht.database import alembic
alembic("git.sr.ht", gitsrht.alembic)

View File

@ -1 +0,0 @@
git-srht-periodic

17
gitsrht-periodic Executable file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env python3
from srht.config import cfg
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import Repository, RepoVisibility
db.init()
from datetime import datetime, timedelta
def cleanup_autocreated():
due = datetime.utcnow() - timedelta(minutes=20)
repos = (Repository.query
.filter(Repository.visibility == RepoVisibility.autocreated)
.filter(Repository.created < due)).all()
(db.session.delete(r) for r in repos)
db.session.commit()
cleanup_autocreated()

View File

@ -1 +0,0 @@
git-srht-shell

93
gitsrht-shell Executable file
View File

@ -0,0 +1,93 @@
#!/usr/bin/env python3
import sys
import os
try:
f = open("/var/log/git-srht-shell", "a")
os.close(sys.stderr.fileno())
os.dup2(f.fileno(), sys.stderr.fileno())
except Exception as ex:
sys.stderr.write("Unable to open log for writing\n")
sys.stderr.write(str(ex) + "\n")
import requests
import shlex
from datetime import datetime
from srht.config import cfg
from srht.validation import Validation
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import User, Repository, RepoVisibility, Redirect
from gitsrht.access import has_access, UserAccess
from gitsrht.repos import create_repo
db.init()
def log(s, *args):
sys.stderr.write("{} {}\n".format(datetime.now().isoformat(),
s.format(*args) if isinstance(s, str) else str(s)))
origin = cfg("git.sr.ht", "origin")
repos = cfg("git.sr.ht", "repos")
_cmd = os.environ.get("SSH_ORIGINAL_COMMAND")
if not _cmd:
_cmd = ""
if len(sys.argv) < 2:
log("Error: expected 2 arguments from SSH")
sys.exit(1)
user_id = sys.argv[1]
ssh_key = sys.argv[2]
user = User.query.filter(User.id == user_id).first()
if not user:
log("Unknown user ID {}", user_id)
sys.exit(1)
log("User: {}", user.username)
cmd = shlex.split(_cmd)
valid_commands = ["git-receive-pack", "git-upload-pack", "git-upload-archive"]
if len(cmd) < 1 or not cmd[0] in valid_commands:
log("Not permitting unacceptable command")
print("Hi {}! You've successfully authenticated, ".format(user.username) +
"but I do not provide an interactive shell. Bye!")
sys.exit(128)
os.chdir(repos)
path = os.path.abspath(cmd[-1])
if not path.startswith(repos):
sys.stderr.write("Access denied")
sys.exit(128)
cmd[-1] = path
repo = Repository.query.filter(Repository.path == path).first()
if not repo:
repo = Redirect.query.filter(Redirect.path == path).first()
if repo:
repo = repo.new_repo
sys.stderr.write("\n\t\033[93mNOTICE\033[0m\n")
sys.stderr.write("\tThis repository has moved:\n")
# TODO: orgs
sys.stderr.write("\t{}/~{}/{}\n".format(
origin, repo.owner.username, repo.name))
sys.stderr.write("\tPlease update your remote.\n\n")
sys.exit(128)
_path, repo_name = os.path.split(path)
owner = os.path.basename(_path)
if "~" + user.username != owner:
sys.exit(128)
valid = Validation({ "name": repo_name })
repo = create_repo(valid, user)
if not valid.ok:
sys.exit(128)
repo.visibility = RepoVisibility.autocreated
db.session.commit()
if cmd[0] == "git-receive-pack":
if not has_access(repo, UserAccess.write, user):
sys.exit(128)
else:
if not has_access(repo, UserAccess.read, user):
sys.exit(128)
log("Executing {}", " ".join(cmd))
sys.stderr.close()
os.execvp(cmd[0], cmd)

View File

@ -1 +0,0 @@
git-srht-update-hook

58
gitsrht-update-hook Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
from srht.config import cfg, cfgi
from srht.database import DbSession
db = DbSession(cfg("git.sr.ht", "connection-string"))
from gitsrht.types import User, Repository, RepoVisibility
db.init()
from configparser import ConfigParser
from datetime import datetime
from pygit2 import Repository as GitRepository
import shlex
import subprocess
import sys
import re
op = sys.argv[0]
builds_sr_ht = cfg("builds.sr.ht", "origin", default=None)
origin = cfg("git.sr.ht", "origin")
if op == "hooks/post-update":
refs = sys.argv[1:]
config = ConfigParser()
with open("config") as f:
config.read_file(f)
repo_id = config.get("srht", "repo-id")
if not repo_id:
sys.exit(0)
repo_id = int(repo_id)
repo = Repository.query.get(repo_id)
if not repo:
sys.exit(0)
if repo.visibility == RepoVisibility.autocreated:
print("\n\t\033[93mNOTICE\033[0m")
print("\tWe saved your changes, but this repository does not exist.")
print("\tClick here to create it:")
print("\t{}/create?name={}".format(origin, repo.name))
print("\tYour changes will be discarded in 20 minutes.\n")
repo.updated = datetime.utcnow()
db.session.commit()
git_repo = GitRepository(repo.path)
for ref in refs:
try:
if re.match(r"^[0-9a-z]{40}$", ref): # commit
ref = git_repo.get(ref)
elif ref.startswith("refs/"): # ref
ref = git_repo.lookup_reference(ref).target
else:
continue
except:
continue
if builds_sr_ht:
from gitsrht.worker import do_post_update
do_post_update(repo, git_repo, ref)