summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2019-02-14 15:03:46 -0500
committerDrew DeVault <sir@cmpwn.com>2019-02-14 15:03:46 -0500
commitc1f95e2a03b5b3264ac3d029cc4efb4d0b152dd0 (patch)
treeae71a67548efe99f95b6ef1eacfa9e17719fa5aa
parent8c828abeb29a81c9f3406d7d1a8e6a9a5b1d7a80 (diff)
Rewrite gitsrht-dispatch in Go
-rwxr-xr-xgitsrht-dispatch67
-rw-r--r--gitsrht-dispatch/.gitignore1
-rw-r--r--gitsrht-dispatch/go.mod3
-rw-r--r--gitsrht-dispatch/go.sum2
-rw-r--r--gitsrht-dispatch/main.go111
-rw-r--r--gitsrht/service.py2
-rwxr-xr-xsetup.py1
7 files changed, 118 insertions, 69 deletions
diff --git a/gitsrht-dispatch b/gitsrht-dispatch
deleted file mode 100755
index 39e8609..0000000
--- a/gitsrht-dispatch
+++ /dev/null
@@ -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)
diff --git a/gitsrht-dispatch/.gitignore b/gitsrht-dispatch/.gitignore
new file mode 100644
index 0000000..4644fc2
--- /dev/null
+++ b/gitsrht-dispatch/.gitignore
@@ -0,0 +1 @@
+gitsrht-dispatch
diff --git a/gitsrht-dispatch/go.mod b/gitsrht-dispatch/go.mod
new file mode 100644
index 0000000..bc3195a
--- /dev/null
+++ b/gitsrht-dispatch/go.mod
@@ -0,0 +1,3 @@
+module git.sr.ht/~sircmpwn/git.sr.ht/gitsrht-dispatch
+
+require github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec
diff --git a/gitsrht-dispatch/go.sum b/gitsrht-dispatch/go.sum
new file mode 100644
index 0000000..bac961c
--- /dev/null
+++ b/gitsrht-dispatch/go.sum
@@ -0,0 +1,2 @@
+github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec h1:DGmKwyZwEB8dI7tbLt/I/gQuP559o/0FrAkHKlQM/Ks=
+github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec/go.mod h1:owBmyHYMLkxyrugmfwE/DLJyW8Ro9mkphwuVErQ0iUw=
diff --git a/gitsrht-dispatch/main.go b/gitsrht-dispatch/main.go
new file mode 100644
index 0000000..d7aee14
--- /dev/null
+++ b/gitsrht-dispatch/main.go
@@ -0,0 +1,111 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "io"
+ "os"
+ osuser "os/user"
+ "strconv"
+ "strings"
+ "syscall"
+
+ "github.com/vaughan0/go-ini"
+)
+
+type Dispatcher struct {
+ cmd string
+ uid int
+ gid int
+}
+
+func main() {
+ var (
+ config ini.File
+ err error
+ logger *log.Logger
+ )
+
+ logf, err := os.OpenFile("/var/log/gitsrht-dispatch",
+ os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
+ if err != nil {
+ log.Printf("Warning: unable to open log file: %v " +
+ "(using stderr instead)", err)
+ logger = log.New(os.Stderr, "", log.LstdFlags)
+ } else {
+ logger = log.New(logf, "", log.LstdFlags)
+ }
+
+ logger.Println("Running git.sr.ht dispatch")
+
+ for _, path := range []string{"../config.ini", "/etc/sr.ht/config.ini"} {
+ config, err = ini.LoadFile(path)
+ if err == nil {
+ break
+ }
+ }
+ if err != nil {
+ logger.Fatalf("Failed to load config file: %v", err)
+ }
+
+ if len(os.Args) != 5 {
+ logger.Fatalf(`Error: This command should be run by sshd's AuthorizedKeysCommand:
+
+AuthorizedKeysCommand=%s "%%u" "%%h" "%%t" "%%k"
+AuthorizedKeysUser=root`, os.Args[0])
+ }
+
+ // Map uid -> dispatcher
+ dispatchers := make(map[int]Dispatcher)
+ for cmd, value := range config.Section("git.sr.ht::dispatch") {
+ spec := strings.Split(value, ":")
+ if len(spec) != 2 {
+ logger.Fatalf("Expected %s=user:group", cmd)
+ }
+ user, err := osuser.Lookup(spec[0])
+ if err != nil {
+ logger.Fatalf("Error looking up user %s: %v", spec[0], err)
+ }
+ group, err := osuser.LookupGroup(spec[1])
+ if err != nil {
+ logger.Fatalf("Error looking up group %s: %v", spec[1], err)
+ }
+ uid, _ := strconv.Atoi(user.Uid)
+ gid, _ := strconv.Atoi(group.Gid)
+ dispatchers[uid] = Dispatcher{cmd, uid, gid}
+ logger.Printf("Registered dispatcher for %s(%d):%s(%d): %s",
+ spec[0], uid, spec[1], gid, cmd)
+ }
+
+ var user *osuser.User
+ username := os.Args[1]
+ if user, err = osuser.Lookup(username); err != nil {
+ logger.Fatalf("Unknown user %s", username)
+ }
+ homedir := os.Args[2]
+ key_type := os.Args[3]
+ b64key := os.Args[4]
+ authorized_keys_file := fmt.Sprintf("%s/.ssh/authorized_keys", homedir)
+ uid, _ := strconv.Atoi(user.Uid)
+
+ logger.Printf("Authorizing user %s (%d); home=%s; b64key=%s; key_type=%s",
+ username, uid, homedir, b64key, key_type)
+
+ if dispatcher, ok := dispatchers[uid]; ok {
+ logger.Printf("Dispatching to %s", dispatcher.cmd)
+ syscall.Setgid(dispatcher.gid)
+ syscall.Setuid(dispatcher.uid)
+ if err := syscall.Exec(dispatcher.cmd, append([]string{
+ dispatcher.cmd,
+ }, os.Args[1:]...), os.Environ()); err != nil {
+ logger.Fatalf("Error exec'ing into %s: %v", dispatcher.cmd, err)
+ }
+ }
+
+ logger.Println("Falling back to authorized_keys file")
+ akf, err := os.Open(authorized_keys_file)
+ if err != nil {
+ logger.Fatalf("Error opening authorized_keys: %v", err)
+ }
+ io.Copy(os.Stdout, akf)
+}
diff --git a/gitsrht/service.py b/gitsrht/service.py
index e7e0cda..9e0ed86 100644
--- a/gitsrht/service.py
+++ b/gitsrht/service.py
@@ -46,7 +46,7 @@ class GitOAuthService(AbstractOAuthService):
webhooks.update({
webhook_url: ["ssh-key:add", "ssh-key:remove"]
})
- super().ensure_meta_webhooks(user, webhooks)
+ return super().ensure_meta_webhooks(user, webhooks)
def lookup_or_register(self, token, token_expires, scopes):
user = super().lookup_or_register(token, token_expires, scopes)
diff --git a/setup.py b/setup.py
index c2d7172..76a9a78 100755
--- a/setup.py
+++ b/setup.py
@@ -60,7 +60,6 @@ setup(
]
},
scripts = [
- 'gitsrht-dispatch',
'gitsrht-keys',
'gitsrht-migrate',
'gitsrht-periodic',