grim/hgkeeper
Clone
Summary
Browse
Changes
Graph
Remove the explicit write access of admins to the hgkeeper repo.
23 months ago, Gary Kramlich
5389b17b4002
Remove the explicit write access of admins to the hgkeeper repo.
Fixes HGKEEPER-21
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
)
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
}