grim/hgkeeper

Parents f82b7c397849
Children f3041eb60173
Update setup for new auth. Init and read auth work, but read also grants write at the moment
--- a/.hgignore Mon Sep 09 05:04:32 2019 -0500
+++ b/.hgignore Mon Sep 09 22:58:35 2019 -0500
@@ -1,4 +1,5 @@
syntax: regexp
^host-keys\/
^hgkeeper$
+^setup\/resources\.go$
--- a/access/access.go Mon Sep 09 05:04:32 2019 -0500
+++ b/access/access.go Mon Sep 09 22:58:35 2019 -0500
@@ -16,15 +16,15 @@
// Refresh will try to reload the casbin model and policies followed by SSH
// keys. If there is an error it's possible that the casbin model and polcies
// could have been updated but the ssh keys were not.
-func Refresh(repoPath string) error {
+func Refresh(adminRepoPath string) error {
accessLock.Lock()
defer accessLock.Unlock()
- if err := refreshEnforcer(repoPath); err != nil {
+ if err := refreshEnforcer(adminRepoPath); err != nil {
return err
}
- if err := refreshKeys(repoPath); err != nil {
+ if err := refreshKeys(adminRepoPath); err != nil {
return err
}
--- a/access/enforcer.go Mon Sep 09 05:04:32 2019 -0500
+++ b/access/enforcer.go Mon Sep 09 22:58:35 2019 -0500
@@ -5,6 +5,7 @@
"sync"
"github.com/casbin/casbin"
+ log "github.com/sirupsen/logrus"
)
var (
@@ -14,8 +15,6 @@
func accessMatch(key1, key2 string) bool {
switch key2 {
- case "deny":
- return false
case "init":
return key1 == "init" || key1 == "write" || key1 == "read"
case "write":
@@ -34,12 +33,15 @@
return (bool)(accessMatch(key1, key2)), nil
}
-func refreshEnforcer(repoPath string) error {
+func refreshEnforcer(adminRepoPath string) error {
enforcerLock.Lock()
defer enforcerLock.Unlock()
- modelFile := filepath.Join(repoPath, modelFilename)
- policyFile := filepath.Join(repoPath, policyFilename)
+ modelFile := filepath.Join(adminRepoPath, modelFilename)
+ policyFile := filepath.Join(adminRepoPath, policyFilename)
+
+ log.Debugf("reading model from %q", modelFile)
+ log.Debugf("reading policy from %q", policyFile)
e := casbin.NewEnforcer(modelFile, policyFile)
--- a/access/users.go Mon Sep 09 05:04:32 2019 -0500
+++ b/access/users.go Mon Sep 09 22:58:35 2019 -0500
@@ -3,6 +3,7 @@
import (
"fmt"
"io/ioutil"
+ "os"
"path/filepath"
"sync"
@@ -19,13 +20,20 @@
keysLock sync.Mutex
)
-func refreshKeys(repoPath string) error {
+func refreshKeys(adminRepoPath string) error {
keysLock.Lock()
defer keysLock.Unlock()
keys = map[string]string{}
- keysPath := filepath.Join(repoPath, keysDir)
+ keysPath := filepath.Join(adminRepoPath, keysDir)
+
+ if _, err := os.Stat(keysPath); err != nil {
+ if os.IsNotExist(err) {
+ log.Error("keys directory not found, no one will be to access hgkeeper")
+ return nil
+ }
+ }
entries, err := ioutil.ReadDir(keysPath)
if err != nil {
--- a/commands/init.go Mon Sep 09 05:04:32 2019 -0500
+++ b/commands/init.go Mon Sep 09 22:58:35 2019 -0500
@@ -23,7 +23,7 @@
}
func (i *Init) Run(conn ssh.Channel, serverConn *ssh.ServerConn, username string, req *ssh.Request) error {
- if !access.CanInit(username, i.repoName) {
+ if !access.CanInit(username, "/"+i.repoName) {
return fmt.Errorf("access denied")
}
--- a/commands/serve.go Mon Sep 09 05:04:32 2019 -0500
+++ b/commands/serve.go Mon Sep 09 22:58:35 2019 -0500
@@ -23,11 +23,11 @@
}
func (s *Serve) Run(conn ssh.Channel, serverConn *ssh.ServerConn, username string, req *ssh.Request) error {
- if !access.CanRead(username, s.repoName) {
+ if !access.CanRead(username, "/"+s.repoName) {
return fmt.Errorf("repository %q not found", s.repoName)
}
- writeable := access.CanWrite(username, s.repoName)
+ writeable := access.CanWrite(username, "/"+s.repoName)
return run(hg.Serve(s.repoPath, writeable), conn, serverConn, req)
}
--- a/hg/hg.go Mon Sep 09 05:04:32 2019 -0500
+++ b/hg/hg.go Mon Sep 09 22:58:35 2019 -0500
@@ -6,7 +6,8 @@
)
func common(cmd *exec.Cmd) *exec.Cmd {
- cmd.Env = append(os.Environ(), "HGRCPATH=/dev/null")
+ cmd.Env = append(cmd.Env, os.Environ()...)
+ cmd.Env = append(cmd.Env, "HGRCPATH=/dev/null")
return cmd
}
@@ -22,10 +23,6 @@
"--stdio",
}
- if !writeable {
- args = append(args, "--config", "hooks.pretxnchangegroup=/bin/false")
- }
-
return common(exec.Command("hg", args...))
}
--- a/serve/command.go Mon Sep 09 05:04:32 2019 -0500
+++ b/serve/command.go Mon Sep 09 22:58:35 2019 -0500
@@ -1,6 +1,8 @@
package serve
import (
+ "path/filepath"
+
"bitbucket.org/rw_grim/hgkeeper/access"
"bitbucket.org/rw_grim/hgkeeper/globals"
"bitbucket.org/rw_grim/hgkeeper/ssh"
@@ -12,7 +14,8 @@
}
func (c *Command) Run(g *globals.Globals) error {
- if err := access.Refresh(g.AdminRepo); err != nil {
+ adminRepoPath := filepath.Join(g.ReposPath, g.AdminRepo)
+ if err := access.Refresh(adminRepoPath); err != nil {
return err
}
--- a/setup/command.go Mon Sep 09 05:04:32 2019 -0500
+++ b/setup/command.go Mon Sep 09 22:58:35 2019 -0500
@@ -1,12 +1,13 @@
+//go:generate esc -o resources.go -pkg setup -include resources\/.+ -prefix resources/ .
package setup
import (
"fmt"
"io/ioutil"
+ "os"
"os/exec"
"path/filepath"
-
- log "github.com/sirupsen/logrus"
+ "strings"
"bitbucket.org/rw_grim/hgkeeper/globals"
"bitbucket.org/rw_grim/hgkeeper/hg"
@@ -15,49 +16,9 @@
type Command struct{}
var (
- accessYmlFilename = "access.yml"
- accessYmlData = `---
-global:
- init:
- - admins
- read:
- - public
-groups:
- admins:
-patterns:
- hgkeeper:
- read:
- - admins
- write:
- - admins
-`
-
- readmeMdFilename = "README.md"
- readmeMdData = `# hgkeeper
-
-This repository is used to manage keys for hgkeeper. This is done by
-organizing ssh public keys in the keys directory.
-
-# keys/
-
-Files in the keys directory should be named after the user the belong to and
-contain the ssh public keys for that user. The name of the file is used in
-access.yaml as the users/group name.
-`
-
hgUsername = "hgkeeper"
commitMessage = "initial revision"
-
- hgrcData = `# this file was created by hgkeeper, do not modify
-[extensions]
-hgext.purge =
-
-[hooks]
-changegroup.aaba = hg update -C default > /dev/null
-changegroup.aaca = hg purge --all > /dev/null
-changegroup.aada = hgkeeper refresh-auth
-`
)
func runCmd(cmd *exec.Cmd) error {
@@ -70,36 +31,54 @@
}
func (c *Command) createAdminRepo(reposPath, adminRepo string) error {
- log.Errorf("reposPath: %q", reposPath)
- log.Errorf("adminRepo: %q", adminRepo)
path := filepath.Join(reposPath, adminRepo)
- log.Infof("creating %q", path)
// create the admin repo
if err := runCmd(hg.Init(path)); err != nil {
return err
}
- // create our hgrc
- hgrcPath := filepath.Join(path, ".hg", "hgrc")
- if err := ioutil.WriteFile(hgrcPath, []byte(hgrcData), 0644); err != nil {
- return err
- }
+ filenames := []string{}
+
+ // walk through the embeded resources and dump them into the directory
+ for name, data := range _escData {
+ // skip directories as we only add the ones were we have files
+ if data.isDir {
+ continue
+ }
+
+ // we're copying a regular file now, so figure out the paths so we can
+ // create them if necessary.
+ absname := filepath.Join(path, name)
+ dirname := filepath.Dir(absname)
- // create our access.yml
- accessYmlPath := filepath.Join(path, accessYmlFilename)
- if err := ioutil.WriteFile(accessYmlPath, []byte(accessYmlData), 0644); err != nil {
- return err
- }
+ // if we don't have the directory create it
+ if _, err := os.Stat(dirname); err != nil {
+ if os.IsNotExist(err) {
+ if err := os.MkdirAll(dirname, 0755); err != nil {
+ return err
+ }
+ } else {
+ return err
+ }
+ }
- // create our readme.md
- readmeMdPath := filepath.Join(path, readmeMdFilename)
- if err := ioutil.WriteFile(readmeMdPath, []byte(readmeMdData), 0644); err != nil {
- return err
+ if err := ioutil.WriteFile(absname, FSMustByte(false, name), 0644); err != nil {
+ return err
+ }
+
+ rel, err := filepath.Rel(path, absname)
+ if err != nil {
+ return err
+ }
+
+ if !strings.HasPrefix(rel, ".hg/") {
+ filenames = append(filenames, rel)
+ }
}
// add our files
- if err := runCmd(hg.Add(path, accessYmlFilename, readmeMdFilename)); err != nil {
+ if err := runCmd(hg.Add(path, filenames...)); err != nil {
return err
}