grim/hgkeeper

7dd7f9cf8e7b
Parents 8098dd6d3587
Children f82b7c397849
rework the ssh keyloading to *NOT* be a method
--- a/access/access.go Sun Sep 08 05:11:49 2019 -0500
+++ b/access/access.go Sun Sep 08 05:44:05 2019 -0500
@@ -77,50 +77,6 @@
return nil
}
-func (a *Access) findUsers() []string {
- users := map[string]bool{}
-
- for _, name := range a.Global.Users() {
- // don't add groups to the users list
- if _, found := a.groups[name]; found {
- continue
- }
-
- users[name] = true
- }
-
- for _, groupUsers := range a.groups {
- for _, name := range groupUsers {
- // don't add groups to the users list
- if _, found := a.groups[name]; found {
- continue
- }
-
- users[name] = true
- }
- }
-
- for _, acl := range a.patterns {
- for _, name := range acl.Users() {
- // don't add groups to the users list
- if _, found := a.groups[name]; found {
- continue
- }
-
- users[name] = true
- }
- }
-
- slice := make([]string, len(users))
- idx := 0
- for name, _ := range users {
- slice[idx] = name
- idx++
- }
-
- return slice
-}
-
// load will load the access from file and reindex everything.
func (a *Access) load(r io.Reader) error {
a.lock.Lock()
@@ -130,11 +86,9 @@
return err
}
- users := a.findUsers()
+ RefreshKeys(a.repoPath)
- a.loadSshKeys(users)
-
- log.Infof("keys: %#v", a.fingerprintIndex)
+ log.Infof("keys: %#v", keys)
return nil
}
--- a/access/users.go Sun Sep 08 05:11:49 2019 -0500
+++ b/access/users.go Sun Sep 08 05:44:05 2019 -0500
@@ -3,8 +3,8 @@
import (
"fmt"
"io/ioutil"
- "os"
"path/filepath"
+ "sync"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
@@ -14,44 +14,63 @@
keysDir = "keys"
)
-func (a *Access) loadSshKeys(users []string) error {
-USERS:
- for _, username := range users {
- keyfile := filepath.Join(a.repoPath, keysDir, username)
- if _, err := os.Stat(keyfile); os.IsNotExist(err) {
- log.Warnf("no keys found for user %s", username)
- continue
- }
+var (
+ keys map[string]string
+ keysLock sync.Mutex
+)
+
+func RefreshKeys(repoPath string) error {
+ keysLock.Lock()
+ defer keysLock.Unlock()
+
+ keys = map[string]string{}
- buffer, err := ioutil.ReadFile(keyfile)
- if err != nil {
- log.Warnf("failed to read keyfile for user %s: %v", username, err)
- continue
- }
+ keysPath := filepath.Join(repoPath, keysDir)
- for len(buffer) > 0 {
- var pubkey ssh.PublicKey
- pubkey, _, _, buffer, err = ssh.ParseAuthorizedKey(buffer)
- if err != nil {
- log.Warnf("failed to parse key file for user %s: %v", username, err)
- continue USERS
- }
+ entries, err := ioutil.ReadDir(keysPath)
+ if err != nil {
+ return err
+ }
- fingerprint := ssh.FingerprintSHA256(pubkey)
- a.fingerprintIndex[fingerprint] = username
+ for _, entry := range entries {
+ if entry.Mode().IsRegular() {
+ filename := filepath.Join(keysPath, entry.Name())
+ loadSshKey(filename, entry.Name())
}
}
return nil
}
+func loadSshKey(filename, username string) {
+ buffer, err := ioutil.ReadFile(filename)
+ if err != nil {
+ log.Warnf("failed to read keyfile for user %s: %v", username, err)
+ return
+ }
+
+ // iterate through the file reading one ssh public key at a time
+ for len(buffer) > 0 {
+ var pubkey ssh.PublicKey
+ pubkey, _, _, buffer, err = ssh.ParseAuthorizedKey(buffer)
+ if err != nil {
+ log.Warnf("failed to parse key file for user %s: %v", username, err)
+ return
+ }
+
+ fingerprint := ssh.FingerprintSHA256(pubkey)
+ keys[fingerprint] = username
+ }
+
+}
+
// UsernameFromFingerprint looks up a username from an SSH key's fingerprint
// and returns the username if found, or err if not found.
-func (a *Access) UsernameFromFingerprint(fingerprint string) (string, error) {
- a.lock.Lock()
- defer a.lock.Unlock()
+func UsernameFromFingerprint(fingerprint string) (string, error) {
+ keysLock.Lock()
+ defer keysLock.Unlock()
- username, found := a.fingerprintIndex[fingerprint]
+ username, found := keys[fingerprint]
if !found {
return "", fmt.Errorf("user not found")
}
@@ -59,6 +78,6 @@
return username, nil
}
-func (a *Access) UsernameFromPubkey(pubkey ssh.PublicKey) (string, error) {
- return a.UsernameFromFingerprint(ssh.FingerprintSHA256(pubkey))
+func UsernameFromPubkey(pubkey ssh.PublicKey) (string, error) {
+ return UsernameFromFingerprint(ssh.FingerprintSHA256(pubkey))
}
--- a/ssh/server.go Sun Sep 08 05:11:49 2019 -0500
+++ b/ssh/server.go Sun Sep 08 05:44:05 2019 -0500
@@ -74,7 +74,7 @@
}
func (s *Server) publicKeyCallback(meta ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
- username, err := s.a.UsernameFromPubkey(key)
+ username, err := access.UsernameFromPubkey(key)
log.Infof("username: %q; err %v", username, err)
if err != nil {
if s.a.Global.CanRead(access.Public) {