grim/hgkeeper
Clone
Summary
Browse
Changes
Graph
Add support for specifying which mercurial executable to use
14 months ago, Gary Kramlich
8275959b76f0
Add support for specifying which mercurial executable to use
package
access
import
(
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
log
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
)
const
(
keysDir
=
"keys"
)
var
(
usernames
map
[
string
]
string
keys
map
[
string
]
ssh
.
PublicKey
keysLock
sync
.
Mutex
)
func
refreshKeys
()
error
{
keysLock
.
Lock
()
defer
keysLock
.
Unlock
()
keys
=
map
[
string
]
ssh
.
PublicKey
{}
usernames
=
map
[
string
]
string
{}
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
{
return
err
}
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
}
counter
:=
0
// 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
{
if
!
strings
.
HasSuffix
(
err
.
Error
(),
"ssh: no key found"
)
{
log
.
Warnf
(
"failed to parse key file for user %s: %v"
,
username
,
err
)
}
continue
}
fingerprint
:=
ssh
.
FingerprintSHA256
(
pubkey
)
if
duppedname
,
found
:=
usernames
[
fingerprint
];
found
{
log
.
Warnf
(
"duplicate key found for user %s. existing key was for %s."
,
username
,
duppedname
,
)
}
usernames
[
fingerprint
]
=
username
keys
[
fingerprint
]
=
pubkey
counter
++
}
log
.
Infof
(
"loaded %d keys for user %q"
,
counter
,
username
)
}
// UsernameFromFingerprint looks up a username from an SSH key's fingerprint
// and returns the username if found, or err if not found.
func
UsernameFromFingerprint
(
fingerprint
string
)
(
string
,
error
)
{
keysLock
.
Lock
()
defer
keysLock
.
Unlock
()
username
,
found
:=
usernames
[
fingerprint
]
if
!
found
{
return
""
,
fmt
.
Errorf
(
"user not found"
)
}
return
username
,
nil
}
func
UsernameFromPubkey
(
pubkey
ssh
.
PublicKey
)
(
string
,
error
)
{
return
UsernameFromFingerprint
(
ssh
.
FingerprintSHA256
(
pubkey
))
}
func
PubkeyFromFingerprint
(
fingerprint
string
)
(
string
,
error
)
{
pubkey
,
found
:=
keys
[
fingerprint
]
if
!
found
{
return
""
,
fmt
.
Errorf
(
"PubKey not found"
)
}
str
:=
string
(
ssh
.
MarshalAuthorizedKey
(
pubkey
))
return
str
,
nil
}