1
0
Fork 0

Refactor auth checking

master
Philip O'Toole 2 years ago
parent c13574137a
commit d289da5feb

@ -147,6 +147,35 @@ func (c *CredentialsStore) HasAnyPerm(username string, perm ...string) bool {
}(perm)
}
// AA authenticates and checks authorization for the given username and password
// for the given perm. If the credential store is nil, then this function always
// returns true. If AllUsers have the given perm, authentication is not done.
// Only then are the credentials checked, and then the perm checked.
func (c *CredentialsStore) AA(username, password, perm string) bool {
// No credential store? Auth is not even enabled.
if c == nil {
return true
}
// Is the required perm granted to all users, including anonymous users?
if c.HasAnyPerm(AllUsers, perm, PermAll) {
return true
}
// At this point a username needs to have been supplied
if username == "" {
return false
}
// Are the creds good?
if !c.Check(username, password) {
return false
}
// Is the specified user authorized?
return c.HasAnyPerm(username, perm, PermAll)
}
// HasPermRequest returns true if the username returned by b has the givem perm.
// It does not perform any password checking, but if there is no username
// in the request, it returns false.

@ -192,6 +192,75 @@ func Test_AuthPermsLoadSingle(t *testing.T) {
}
}
func Test_AuthPermsAANilStore(t *testing.T) {
var store *CredentialsStore
if !store.AA("username1", "password1", "foo") {
t.Fatalf("nil store didn't authorize")
}
}
func Test_AuthPermsAA(t *testing.T) {
const jsonStream = `
[
{
"username": "username1",
"password": "password1",
"perms": ["foo", "bar"]
},
{
"username": "username2",
"password": "password2",
"perms": ["baz"]
},
{
"username": "*",
"perms": ["qux"]
}
]
`
store := NewCredentialsStore()
if err := store.Load(strings.NewReader(jsonStream)); err != nil {
t.Fatalf("failed to load single credential: %s", err.Error())
}
if store.AA("nonexistent", "password1", "foo") {
t.Fatalf("nonexistent authenticated and authorized for foo")
}
if !store.AA("nonexistent", "password1", "qux") {
t.Fatalf("nonexistent not authenticated and authorized for qux")
}
if !store.AA("username1", "password1", "foo") {
t.Fatalf("username1 not authenticated and authorized for foo")
}
if !store.AA("username1", "password1", "bar") {
t.Fatalf("username1 not authenticated and authorized for bar")
}
if !store.AA("username1", "password1", "qux") {
t.Fatalf("username1 not authenticated and authorized for qux")
}
if store.AA("username1", "password2", "bar") {
t.Fatalf("username1 was authenticated and authorized for bar using wrong password")
}
if store.AA("username1", "password1", "quz") {
t.Fatalf("username1 was authenticated and authorized for quz")
}
if !store.AA("username2", "password2", "baz") {
t.Fatalf("username2 not authenticated and authorized for baz")
}
if !store.AA("username2", "password2", "qux") {
t.Fatalf("username2 not authenticated and authorized for qux")
}
if store.AA("username2", "password2", "bar") {
t.Fatalf("username2 was authenticated and authorized for bar using wrong password")
}
if store.AA("username2", "password2", "quz") {
t.Fatalf("username2 was authenticated and authorized for quz")
}
}
func Test_AuthLoadHashedSingleRequest(t *testing.T) {
const jsonStream = `
[

@ -99,11 +99,8 @@ type Cluster interface {
// CredentialStore is the interface credential stores must support.
type CredentialStore interface {
// Check returns whether username and password are a valid combination.
Check(username, password string) bool
// HasAnyPerm returns whether username has any of the given perms.
HasAnyPerm(username string, perm ...string) bool
// AA authenticates and checks authorization for the given perm.
AA(username, password, perm string) bool
}
// StatusReporter is the interface status providers must implement.
@ -1256,29 +1253,12 @@ func (s *Service) CheckRequestPerm(r *http.Request, perm string) (b bool) {
}
}()
// No credential store? Auth is not even enabled.
if s.credentialStore == nil {
return true
}
// Is the required perm granted to all users, including anonymous users?
if s.credentialStore.HasAnyPerm(auth.AllUsers, perm, auth.PermAll) {
return true
}
// At this point there needs to be BasicAuth information in the request.
username, password, ok := r.BasicAuth()
if !ok {
return false
}
// Are the BasicAuth creds good?
if !s.credentialStore.Check(username, password) {
return false
username = ""
}
// Is the specified user authorized?
return s.credentialStore.HasAnyPerm(username, perm, auth.PermAll)
return s.credentialStore.AA(username, password, perm)
}
// LeaderAPIAddr returns the API address of the leader, as known by this node.

Loading…
Cancel
Save