Hierarchical tokens.
This commit is contained in:
@@ -1781,7 +1781,11 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||||||
if tok.Group != c.group.Name() {
|
if tok.Group != c.group.Name() {
|
||||||
return terror("error", "wrong group in token")
|
return terror("error", "wrong group in token")
|
||||||
}
|
}
|
||||||
|
if tok.IncludeSubgroups {
|
||||||
|
return terror("error",
|
||||||
|
"hierarchical token not allowed",
|
||||||
|
)
|
||||||
|
}
|
||||||
if tok.Expires == nil {
|
if tok.Expires == nil {
|
||||||
return terror("error", "token doesn't expire")
|
return terror("error", "token doesn't expire")
|
||||||
}
|
}
|
||||||
@@ -1837,6 +1841,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||||||
return terror("error", err.Error())
|
return terror("error", err.Error())
|
||||||
}
|
}
|
||||||
if tok.Group != "" || tok.Username != nil ||
|
if tok.Group != "" || tok.Username != nil ||
|
||||||
|
tok.IncludeSubgroups ||
|
||||||
tok.Permissions != nil ||
|
tok.Permissions != nil ||
|
||||||
tok.IssuedBy != nil ||
|
tok.IssuedBy != nil ||
|
||||||
tok.IssuedAt != nil {
|
tok.IssuedAt != nil {
|
||||||
|
|||||||
+33
-17
@@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -16,26 +17,28 @@ var ErrTagMismatch = errors.New("tag mismatch")
|
|||||||
|
|
||||||
// A stateful token
|
// A stateful token
|
||||||
type Stateful struct {
|
type Stateful struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
Group string `json:"group"`
|
Group string `json:"group"`
|
||||||
Username *string `json:"username,omitempty"`
|
IncludeSubgroups bool `json:"includeSubgroups,omitempty"`
|
||||||
Permissions []string `json:"permissions"`
|
Username *string `json:"username,omitempty"`
|
||||||
Expires *time.Time `json:"expires,omitempty"`
|
Permissions []string `json:"permissions"`
|
||||||
NotBefore *time.Time `json:"not-before,omitempty"`
|
Expires *time.Time `json:"expires,omitempty"`
|
||||||
IssuedAt *time.Time `json:"issuedAt,omitempty"`
|
NotBefore *time.Time `json:"not-before,omitempty"`
|
||||||
IssuedBy *string `json:"issuedBy,omitempty"`
|
IssuedAt *time.Time `json:"issuedAt,omitempty"`
|
||||||
|
IssuedBy *string `json:"issuedBy,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (token *Stateful) Clone() *Stateful {
|
func (token *Stateful) Clone() *Stateful {
|
||||||
return &Stateful{
|
return &Stateful{
|
||||||
Token: token.Token,
|
Token: token.Token,
|
||||||
Group: token.Group,
|
Group: token.Group,
|
||||||
Username: token.Username,
|
IncludeSubgroups: token.IncludeSubgroups,
|
||||||
Permissions: append([]string(nil), token.Permissions...),
|
Username: token.Username,
|
||||||
Expires: token.Expires,
|
Permissions: append([]string(nil), token.Permissions...),
|
||||||
NotBefore: token.NotBefore,
|
Expires: token.Expires,
|
||||||
IssuedAt: token.IssuedAt,
|
NotBefore: token.NotBefore,
|
||||||
IssuedBy: token.IssuedBy,
|
IssuedAt: token.IssuedAt,
|
||||||
|
IssuedBy: token.IssuedBy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,8 +86,21 @@ func Get(token string) (*Stateful, string, error) {
|
|||||||
return tokens.Get(token)
|
return tokens.Get(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (token *Stateful) match(group string) bool {
|
||||||
|
if group == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if group == token.Group {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if token.IncludeSubgroups {
|
||||||
|
return strings.HasPrefix(group, token.Group + "/")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (token *Stateful) Check(host, group string, username *string) (string, []string, error) {
|
func (token *Stateful) Check(host, group string, username *string) (string, []string, error) {
|
||||||
if token.Group == "" || group != token.Group {
|
if !token.match(group) {
|
||||||
return "", nil, errors.New("token for bad group")
|
return "", nil, errors.New("token for bad group")
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ func TestStatefulCheck(t *testing.T) {
|
|||||||
Expires: &future,
|
Expires: &future,
|
||||||
NotBefore: &nearFuture,
|
NotBefore: &nearFuture,
|
||||||
}
|
}
|
||||||
|
token5 := &Stateful{
|
||||||
|
Token: "token",
|
||||||
|
Group: "group",
|
||||||
|
IncludeSubgroups: true,
|
||||||
|
Username: &user,
|
||||||
|
Permissions: []string{"present", "message"},
|
||||||
|
Expires: &future,
|
||||||
|
}
|
||||||
|
|
||||||
success := []struct {
|
success := []struct {
|
||||||
token *Stateful
|
token *Stateful
|
||||||
@@ -107,6 +115,20 @@ func TestStatefulCheck(t *testing.T) {
|
|||||||
expUsername: "",
|
expUsername: "",
|
||||||
expPermissions: []string{"present", "message"},
|
expPermissions: []string{"present", "message"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
token: token5,
|
||||||
|
group: "group",
|
||||||
|
username: &user,
|
||||||
|
expUsername: "user",
|
||||||
|
expPermissions: []string{"present", "message"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: token5,
|
||||||
|
group: "group/subgroup",
|
||||||
|
username: &user,
|
||||||
|
expUsername: "user",
|
||||||
|
expPermissions: []string{"present", "message"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, s := range success {
|
for i, s := range success {
|
||||||
@@ -139,6 +161,11 @@ func TestStatefulCheck(t *testing.T) {
|
|||||||
group: "group",
|
group: "group",
|
||||||
username: &user,
|
username: &user,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
token: token5,
|
||||||
|
group: "groups",
|
||||||
|
username: &user,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, s := range failure {
|
for i, s := range failure {
|
||||||
|
|||||||
Reference in New Issue
Block a user