refactor internal rule representation

This commit is contained in:
Sasha Klizhentas 2017-08-23 19:08:56 -07:00
parent 20a859aa28
commit 0c77c5c0e9
16 changed files with 268 additions and 204 deletions

View file

@ -164,9 +164,9 @@ func createUserAndRoleWithoutRoles(clt clt, username string, allowedLogins []str
}
role := services.RoleForUser(user)
rules := role.GetRules(services.Allow)
delete(rules, services.KindRole)
role.SetRules(services.Allow, rules)
set := services.MakeRuleSet(role.GetRules(services.Allow))
delete(set, services.KindRole)
role.SetRules(services.Allow, set.Slice())
role.SetLogins(services.Allow, []string{user.GetName()})
err = clt.UpsertRole(role, backend.Forever)
if err != nil {

View file

@ -152,8 +152,8 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
services.RoleSpecV3{
Allow: services.RoleConditions{
Namespaces: []string{services.Wildcard},
Rules: map[string][]string{
services.KindAuthServer: services.RW(),
Rules: []services.Rule{
services.NewRule(services.KindAuthServer, services.RW()),
},
},
})
@ -165,17 +165,17 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
services.RoleSpecV3{
Allow: services.RoleConditions{
Namespaces: []string{services.Wildcard},
Rules: map[string][]string{
services.KindNode: services.RW(),
services.KindSession: services.RW(),
services.KindEvent: services.RW(),
services.KindProxy: services.RO(),
services.KindCertAuthority: services.RO(),
services.KindUser: services.RO(),
services.KindNamespace: services.RO(),
services.KindRole: services.RO(),
services.KindAuthServer: services.RO(),
services.KindReverseTunnel: services.RO(),
Rules: []services.Rule{
services.NewRule(services.KindNode, services.RW()),
services.NewRule(services.KindSession, services.RW()),
services.NewRule(services.KindEvent, services.RW()),
services.NewRule(services.KindProxy, services.RO()),
services.NewRule(services.KindCertAuthority, services.RO()),
services.NewRule(services.KindUser, services.RO()),
services.NewRule(services.KindNamespace, services.RO()),
services.NewRule(services.KindRole, services.RO()),
services.NewRule(services.KindAuthServer, services.RO()),
services.NewRule(services.KindReverseTunnel, services.RO()),
},
},
})
@ -185,24 +185,24 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
services.RoleSpecV3{
Allow: services.RoleConditions{
Namespaces: []string{services.Wildcard},
Rules: map[string][]string{
services.KindProxy: services.RW(),
services.KindOIDCRequest: services.RW(),
services.KindSession: services.RW(),
services.KindEvent: services.RW(),
services.KindSAMLRequest: services.RW(),
services.KindOIDC: services.RO(),
services.KindSAML: services.RO(),
services.KindNamespace: services.RO(),
services.KindNode: services.RO(),
services.KindAuthServer: services.RO(),
services.KindReverseTunnel: services.RO(),
services.KindCertAuthority: services.RO(),
services.KindUser: services.RO(),
services.KindRole: services.RO(),
services.KindClusterAuthPreference: services.RO(),
services.KindClusterName: services.RO(),
services.KindStaticTokens: services.RO(),
Rules: []services.Rule{
services.NewRule(services.KindProxy, services.RW()),
services.NewRule(services.KindOIDCRequest, services.RW()),
services.NewRule(services.KindSession, services.RW()),
services.NewRule(services.KindEvent, services.RW()),
services.NewRule(services.KindSAMLRequest, services.RW()),
services.NewRule(services.KindOIDC, services.RO()),
services.NewRule(services.KindSAML, services.RO()),
services.NewRule(services.KindNamespace, services.RO()),
services.NewRule(services.KindNode, services.RO()),
services.NewRule(services.KindAuthServer, services.RO()),
services.NewRule(services.KindReverseTunnel, services.RO()),
services.NewRule(services.KindCertAuthority, services.RO()),
services.NewRule(services.KindUser, services.RO()),
services.NewRule(services.KindRole, services.RO()),
services.NewRule(services.KindClusterAuthPreference, services.RO()),
services.NewRule(services.KindClusterName, services.RO()),
services.NewRule(services.KindStaticTokens, services.RO()),
},
},
})
@ -212,14 +212,14 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
services.RoleSpecV3{
Allow: services.RoleConditions{
Namespaces: []string{services.Wildcard},
Rules: map[string][]string{
services.KindWebSession: services.RW(),
services.KindSession: services.RW(),
services.KindAuthServer: services.RO(),
services.KindUser: services.RO(),
services.KindRole: services.RO(),
services.KindNamespace: services.RO(),
services.KindTrustedCluster: services.RO(),
Rules: []services.Rule{
services.NewRule(services.KindWebSession, services.RW()),
services.NewRule(services.KindSession, services.RW()),
services.NewRule(services.KindAuthServer, services.RO()),
services.NewRule(services.KindUser, services.RO()),
services.NewRule(services.KindRole, services.RO()),
services.NewRule(services.KindNamespace, services.RO()),
services.NewRule(services.KindTrustedCluster, services.RO()),
},
},
})
@ -229,9 +229,9 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
services.RoleSpecV3{
Allow: services.RoleConditions{
Namespaces: []string{services.Wildcard},
Rules: map[string][]string{
services.KindAuthServer: services.RO(),
services.KindClusterAuthPreference: services.RO(),
Rules: []services.Rule{
services.NewRule(services.KindAuthServer, services.RO()),
services.NewRule(services.KindClusterAuthPreference, services.RO()),
},
},
})
@ -246,8 +246,8 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
Namespaces: []string{services.Wildcard},
Logins: []string{},
NodeLabels: map[string]string{services.Wildcard: services.Wildcard},
Rules: map[string][]string{
services.Wildcard: services.RW(),
Rules: []services.Rule{
services.NewRule(services.Wildcard, services.RW()),
},
},
})
@ -257,7 +257,7 @@ func GetCheckerForBuiltinRole(role teleport.Role) (services.AccessChecker, error
services.RoleSpecV3{
Allow: services.RoleConditions{
Namespaces: []string{},
Rules: map[string][]string{},
Rules: []services.Rule{},
},
})
}

View file

@ -157,7 +157,7 @@ func (s *TunSuite) TestUnixServerClient(c *C) {
user, role := createUserAndRole(s.a, userName, []string{userName})
rules := role.GetRules(services.Allow)
rules[services.KindNode] = services.RW()
rules = append(rules, services.NewRule(services.KindNode, services.RW()))
role.SetRules(services.Allow, rules)
err = s.a.UpsertRole(role, backend.Forever)
c.Assert(err, IsNil)

View file

@ -45,6 +45,7 @@ import (
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/session"
"github.com/gravitational/teleport/lib/shell"
"github.com/gravitational/teleport/lib/state"
"github.com/gravitational/teleport/lib/utils"
@ -1364,7 +1365,7 @@ func runLocalCommand(command []string) error {
if err != nil {
return trace.Wrap(err)
}
shell, err := utils.GetLoginShell(user.Username)
shell, err := shell.GetLoginShell(user.Username)
if err != nil {
return trace.Wrap(err)
}

View file

@ -280,8 +280,8 @@ func (s *MigrationsSuite) TestMigrateRoles(c *C) {
Logins: []string{"foo"},
NodeLabels: map[string]string{"a": "b"},
Namespaces: []string{"system", "default"},
Rules: map[string][]string{
KindRole: RW(),
Rules: []Rule{
NewRule(KindRole, RW()),
},
},
},

View file

@ -36,31 +36,31 @@ import (
// DefaultUserRules provides access to the default set of rules assigned to
// all users.
var DefaultUserRules = map[string][]string{
KindRole: RO(),
KindOIDC: RO(),
KindSAML: RO(),
KindSession: RO(),
KindTrustedCluster: RW(),
var DefaultUserRules = []Rule{
NewRule(KindRole, RO()),
NewRule(KindOIDC, RO()),
NewRule(KindSAML, RO()),
NewRule(KindSession, RO()),
NewRule(KindTrustedCluster, RW()),
}
// DefaultImplicitRules provides access to the default set of implicit rules
// assigned to all roles.
var DefaultImplicitRules = map[string][]string{
KindNode: RO(),
KindAuthServer: RO(),
KindReverseTunnel: RO(),
KindCertAuthority: RO(),
var DefaultImplicitRules = []Rule{
NewRule(KindNode, RO()),
NewRule(KindAuthServer, RO()),
NewRule(KindReverseTunnel, RO()),
NewRule(KindCertAuthority, RO()),
}
// DefaultCertAuthorityRules provides access the minimal set of resources
// needed for a certificate authority to function.
var DefaultCertAuthorityRules = map[string][]string{
KindSession: RO(),
KindNode: RO(),
KindAuthServer: RO(),
KindReverseTunnel: RO(),
KindCertAuthority: RO(),
var DefaultCertAuthorityRules = []Rule{
NewRule(KindSession, RO()),
NewRule(KindNode, RO()),
NewRule(KindAuthServer, RO()),
NewRule(KindReverseTunnel, RO()),
NewRule(KindCertAuthority, RO()),
}
// RoleNameForUser returns role name associated with a user.
@ -92,7 +92,7 @@ func NewDefaultRole() Role {
Namespaces: []string{defaults.Namespace},
Logins: []string{teleport.TraitInternalRoleVariable},
NodeLabels: map[string]string{Wildcard: Wildcard},
Rules: utils.CopyStringMapSlices(DefaultUserRules),
Rules: CopyRulesSlice(DefaultUserRules),
},
},
}
@ -116,7 +116,7 @@ func NewImplicitRole() Role {
Namespaces: []string{defaults.Namespace},
Logins: []string{teleport.TraitInternalRoleVariable},
NodeLabels: map[string]string{Wildcard: Wildcard},
Rules: utils.CopyStringMapSlices(DefaultImplicitRules),
Rules: CopyRulesSlice(DefaultImplicitRules),
},
},
}
@ -138,7 +138,7 @@ func RoleForUser(u User) Role {
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
NodeLabels: map[string]string{Wildcard: Wildcard},
Rules: utils.CopyStringMapSlices(DefaultUserRules),
Rules: CopyRulesSlice(DefaultUserRules),
},
},
}
@ -160,7 +160,7 @@ func RoleForCertAuthority(ca CertAuthority) Role {
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
NodeLabels: map[string]string{Wildcard: Wildcard},
Rules: utils.CopyStringMapSlices(DefaultCertAuthorityRules),
Rules: CopyRulesSlice(DefaultCertAuthorityRules),
},
},
}
@ -248,9 +248,9 @@ type Role interface {
SetNodeLabels(RoleConditionType, map[string]string)
// GetRules gets all allow or deny rules.
GetRules(rct RoleConditionType) map[string][]string
GetRules(rct RoleConditionType) []Rule
// SetRules sets an allow or deny rule.
SetRules(rct RoleConditionType, rrs map[string][]string)
SetRules(rct RoleConditionType, rules []Rule)
}
// RoleV3 represents role resource specification
@ -285,8 +285,7 @@ func (r *RoleV3) Equals(other Role) bool {
if !utils.StringMapsEqual(r.GetNodeLabels(condition), other.GetNodeLabels(condition)) {
return false
}
if !utils.StringMapSlicesEqual(r.GetRules(condition), other.GetRules(condition)) {
if !RuleSlicesEqual(r.GetRules(condition), other.GetRules(condition)) {
return false
}
}
@ -439,7 +438,7 @@ func (r *RoleV3) SetNodeLabels(rct RoleConditionType, labels map[string]string)
}
// GetRules gets all allow or deny rules.
func (r *RoleV3) GetRules(rct RoleConditionType) map[string][]string {
func (r *RoleV3) GetRules(rct RoleConditionType) []Rule {
if rct == Allow {
return r.Spec.Allow.Rules
}
@ -447,8 +446,8 @@ func (r *RoleV3) GetRules(rct RoleConditionType) map[string][]string {
}
// SetRules sets an allow or deny rule.
func (r *RoleV3) SetRules(rct RoleConditionType, rrs map[string][]string) {
rcopy := utils.CopyStringMapSlices(rrs)
func (r *RoleV3) SetRules(rct RoleConditionType, in []Rule) {
rcopy := CopyRulesSlice(in)
if rct == Allow {
r.Spec.Allow.Rules = rcopy
@ -478,7 +477,7 @@ func (r *RoleV3) CheckAndSetDefaults() error {
r.Spec.Allow.NodeLabels = map[string]string{Wildcard: Wildcard}
}
if r.Spec.Allow.Rules == nil {
r.Spec.Allow.Rules = utils.CopyStringMapSlices(DefaultUserRules)
r.Spec.Allow.Rules = CopyRulesSlice(DefaultUserRules)
}
// if we find {{ or }} but the syntax is invalid, the role is invalid
@ -647,7 +646,7 @@ type RoleConditions struct {
// Rules is a list of rules and their access levels. Rules are a high level
// construct used for access control.
Rules RoleRules `json:"rules,omitempty" yaml:"rules,omitempty"`
Rules []Rule `json:"rules,omitempty" yaml:"rules,omitempty"`
}
// Equals returns true if the role conditions (logins, namespaces, labels,
@ -662,51 +661,134 @@ func (r *RoleConditions) Equals(o RoleConditions) bool {
if !utils.StringMapsEqual(r.NodeLabels, o.NodeLabels) {
return false
}
if !utils.StringMapSlicesEqual(r.Rules, o.Rules) {
if len(r.Rules) != len(o.Rules) {
return false
}
for i := range r.Rules {
if !r.Rules[i].Equals(o.Rules[i]) {
return false
}
}
return true
}
// RoleRules is a map of resources and their verbs. Role rules can be used
// to allow or deny access to resources.
type RoleRules map[string][]string
// NewRule creates a rule based on a resource name and a list of verbs
func NewRule(resource string, verbs []string) Rule {
return Rule{
Resources: []string{resource},
Verbs: verbs,
}
}
type rules struct {
// Rule represents allow or deny rule that is executed to check
// if user or service have access to resource
type Rule struct {
// Resources is a list of
Resources []string `json:"resources"`
Verbs []string `json:"verbs"`
Where string `json:"where,omitempty"`
Actions []string `json:"actions,omitempty"`
}
// MarshalJSON is used to convert between the internal representation of
// rules and the format defined in RoleSpecV3.
func (rrs *RoleRules) MarshalJSON() ([]byte, error) {
var r []rules
for resource, verbs := range *rrs {
r = append(r, rules{Resources: []string{resource}, Verbs: verbs})
// HasVerb returns true if the rule has verb,
// this method also matches wildcard
func (r *Rule) HasVerb(verb string) bool {
for _, v := range r.Verbs {
if v == verb {
return true
}
}
return json.Marshal(r)
return false
}
// UnmarshalJSON is used to convert between the internal representation of
// rules and the format defined in RoleSpecV3.
func (rrs *RoleRules) UnmarshalJSON(data []byte) error {
var r []rules
err := json.Unmarshal(data, &r)
if err != nil {
return err
// Equals returns true if the rule equals to another
func (r *Rule) Equals(other Rule) bool {
if !utils.StringSlicesEqual(r.Resources, other.Resources) {
return false
}
if !utils.StringSlicesEqual(r.Verbs, other.Verbs) {
return false
}
if !utils.StringSlicesEqual(r.Actions, other.Actions) {
return false
}
if r.Where != other.Where {
return false
}
return true
}
// RuleSet maps resource to a set of rules defined for it
type RuleSet map[string][]Rule
// MatchRule tests if the resource name and verb are in a given list of rules.
func (set RuleSet) Match(resource string, verb string) bool {
// empty set matches nothing
if len(set) == 0 {
return false
}
rmap := make(map[string][]string)
for _, rule := range r {
for _, resource := range rule.Resources {
rmap[resource] = rule.Verbs
// check for wildcard resource matcher
for _, rule := range set[Wildcard] {
if rule.HasVerb(Wildcard) || rule.HasVerb(verb) {
return true
}
}
*rrs = rmap
return nil
// check for matching resource by name
for _, rule := range set[resource] {
if rule.HasVerb(Wildcard) || rule.HasVerb(verb) {
return true
}
}
return false
}
// Slice returns slice from a set
func (set RuleSet) Slice() []Rule {
var out []Rule
for _, rules := range set {
out = append(out, rules...)
}
return out
}
// MakeRuleSet converts slice of rules to the set of rules
func MakeRuleSet(rules []Rule) RuleSet {
set := make(RuleSet)
for _, rule := range rules {
for _, resource := range rule.Resources {
rules, ok := set[resource]
if !ok {
set[resource] = []Rule{rule}
} else {
rules = append(rules, rule)
set[resource] = rules
}
}
}
return set
}
// CopyRulesSlice copies input slice of Rules and returns the copy
func CopyRulesSlice(in []Rule) []Rule {
out := make([]Rule, len(in))
copy(out, in)
return out
}
// RuleSlicesEqual returns true if two rule slices are equal
func RuleSlicesEqual(a, b []Rule) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if !a[i].Equals(b[i]) {
return false
}
}
return true
}
// RoleV2 represents role resource specification
@ -900,7 +982,7 @@ func (r *RoleV2) V3() *RoleV3 {
}
// translate old v2 resources to v3 rules
rules := make(map[string][]string)
rules := []Rule{}
for resource, actions := range r.GetResources() {
var verbs []string
@ -916,7 +998,7 @@ func (r *RoleV2) V3() *RoleV3 {
verbs = []string{VerbReadSecrets, VerbCreate, VerbUpdate, VerbDelete}
}
rules[resource] = utils.Deduplicate(verbs)
rules = append(rules, NewRule(resource, verbs))
}
role.Spec.Allow.Rules = rules
@ -1036,30 +1118,6 @@ func NewRoleSet(roles ...Role) RoleSet {
// RoleSet is a set of roles that implements access control functionality
type RoleSet []Role
// MatchRule tests if the resource name and verb are in a given list of rules.
func MatchRule(rules map[string][]string, resource string, verb string) bool {
// empty selector matches nothing
if len(rules) == 0 {
return false
}
// check for wildcard resource matcher
for _, action := range rules[Wildcard] {
if action == Wildcard || action == verb {
return true
}
}
// check for matching resource by name
for _, action := range rules[resource] {
if action == Wildcard || action == verb {
return true
}
}
return false
}
// MatchLogin returns true if attempted login matches any of the logins
func MatchLogin(logins []string, login string) bool {
for _, l := range logins {
@ -1235,8 +1293,7 @@ func (set RoleSet) CheckAccessToRule(namespace string, resource string, verb str
// check deny: a single match on a deny rule prohibits access
for _, role := range set {
matchNamespace := MatchNamespace(role.GetNamespaces(Deny), ProcessNamespace(namespace))
matchRule := MatchRule(role.GetRules(Deny), resource, verb)
if matchNamespace && matchRule {
if matchNamespace && MakeRuleSet(role.GetRules(Deny)).Match(resource, verb) {
return trace.AccessDenied("%v access to %v in namespace %v is denied for %v: deny rule matched", verb, resource, namespace, role)
}
}
@ -1244,8 +1301,7 @@ func (set RoleSet) CheckAccessToRule(namespace string, resource string, verb str
// check allow: if rule matches, grant access to resource
for _, role := range set {
matchNamespace := MatchNamespace(role.GetNamespaces(Allow), ProcessNamespace(namespace))
matchRule := MatchRule(role.GetRules(Allow), resource, verb)
if matchNamespace && matchRule {
if matchNamespace && MakeRuleSet(role.GetRules(Allow)).Match(resource, verb) {
return nil
}
}

View file

@ -134,8 +134,8 @@ func (s *RoleSuite) TestRoleParse(c *C) {
Allow: RoleConditions{
NodeLabels: map[string]string{"a": "b"},
Namespaces: []string{"system", "default"},
Rules: map[string][]string{
KindRole: []string{VerbRead, VerbList},
Rules: []Rule{
NewRule(KindRole, []string{VerbRead, VerbList}),
},
},
Deny: RoleConditions{
@ -342,8 +342,8 @@ func (s *RoleSuite) TestCheckRuleAccess(c *C) {
Spec: RoleSpecV3{
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
Rules: map[string][]string{
KindSession: []string{VerbRead},
Rules: []Rule{
NewRule(KindSession, []string{VerbRead}),
},
},
},
@ -365,8 +365,8 @@ func (s *RoleSuite) TestCheckRuleAccess(c *C) {
Spec: RoleSpecV3{
Allow: RoleConditions{
Namespaces: []string{"system"},
Rules: map[string][]string{
KindSession: []string{VerbRead},
Rules: []Rule{
NewRule(KindSession, []string{VerbRead}),
},
},
},
@ -379,8 +379,8 @@ func (s *RoleSuite) TestCheckRuleAccess(c *C) {
Spec: RoleSpecV3{
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
Rules: map[string][]string{
KindSession: []string{VerbCreate, VerbRead},
Rules: []Rule{
NewRule(KindSession, []string{VerbCreate, VerbRead}),
},
},
},
@ -404,14 +404,14 @@ func (s *RoleSuite) TestCheckRuleAccess(c *C) {
Spec: RoleSpecV3{
Deny: RoleConditions{
Namespaces: []string{defaults.Namespace},
Rules: map[string][]string{
KindSession: []string{VerbCreate},
Rules: []Rule{
NewRule(KindSession, []string{VerbCreate}),
},
},
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
Rules: map[string][]string{
KindSession: []string{VerbCreate},
Rules: []Rule{
NewRule(KindSession, []string{VerbCreate}),
},
},
},

View file

@ -393,8 +393,8 @@ func (s *ServicesTestSuite) RolesCRUD(c *C) {
Logins: []string{"root", "bob"},
NodeLabels: map[string]string{services.Wildcard: services.Wildcard},
Namespaces: []string{"default", "system"},
Rules: map[string][]string{
services.KindRole: services.RO(),
Rules: []services.Rule{
services.NewRule(services.KindRole, services.RO()),
},
},
},

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package utils
package shell
/*
#cgo solaris CFLAGS: -D_POSIX_PTHREAD_SEMANTICS

43
lib/shell/shell_test.go Normal file
View file

@ -0,0 +1,43 @@
/*
Copyright 2015 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package shell
import (
"gopkg.in/check.v1"
)
type ShellSuite struct {
}
var _ = check.Suite(&ShellSuite{})
func (s *ShellSuite) TestGetShell(c *check.C) {
shell, err := GetLoginShell("root")
c.Assert(err, check.IsNil)
c.Assert(shell == "/bin/bash" || shell == "/bin/sh", check.Equals, true)
shell, err = GetLoginShell("non-existent-user")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Matches, "user: unknown user non-existent-user")
shell, err = GetLoginShell("daemon")
c.Assert(err, check.IsNil)
c.Assert(shell == "/usr/sbin/nologin" ||
shell == "/sbin/nologin" ||
shell == "/usr/bin/nologin" ||
shell == "/usr/bin/false", check.Equals, true)
}

View file

@ -34,10 +34,10 @@ import (
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/shell"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
"github.com/kardianos/osext"
log "github.com/sirupsen/logrus"
)
@ -118,7 +118,7 @@ func prepInteractiveCommand(ctx *ctx) (*exec.Cmd, error) {
// determine shell for the given OS user:
if ctx.exec.cmdName == "" {
runShell = true
ctx.exec.cmdName, err = utils.GetLoginShell(ctx.login)
ctx.exec.cmdName, err = shell.GetLoginShell(ctx.login)
if err != nil {
log.Error(err)
return nil, trace.Wrap(err)
@ -167,7 +167,7 @@ func prepareCommand(ctx *ctx) (*exec.Cmd, error) {
}
// get user's shell:
shell, err := utils.GetLoginShell(ctx.login)
shell, err := shell.GetLoginShell(ctx.login)
if err != nil {
log.Warn(err)
}

View file

@ -935,7 +935,7 @@ func newUpack(username string, allowedLogins []string, a *auth.AuthServer) (*upa
}
role := services.RoleForUser(user)
rules := role.GetRules(services.Allow)
rules[services.Wildcard] = services.RW()
rules = append(rules, services.NewRule(services.Wildcard, services.RW()))
role.SetRules(services.Allow, rules)
role.SetLogins(services.Allow, allowedLogins)
err = a.UpsertRole(role, backend.Forever)

View file

@ -72,20 +72,3 @@ func (s *UtilsSuite) TestMiscFunctions(c *check.C) {
c.Assert(Deduplicate([]string{"a", "b"}), check.DeepEquals, []string{"a", "b"})
c.Assert(Deduplicate([]string{"a", "b", "b", "a", "c"}), check.DeepEquals, []string{"a", "b", "c"})
}
func (s *UtilsSuite) TestGetShell(c *check.C) {
shell, err := GetLoginShell("root")
c.Assert(err, check.IsNil)
c.Assert(shell == "/bin/bash" || shell == "/bin/sh", check.Equals, true)
shell, err = GetLoginShell("non-existent-user")
c.Assert(err, check.NotNil)
c.Assert(err.Error(), check.Matches, "user: unknown user non-existent-user")
shell, err = GetLoginShell("daemon")
c.Assert(err, check.IsNil)
c.Assert(shell == "/usr/sbin/nologin" ||
shell == "/sbin/nologin" ||
shell == "/usr/bin/nologin" ||
shell == "/usr/bin/false", check.Equals, true)
}

View file

@ -209,7 +209,7 @@ func (s *WebSuite) SetUpTest(c *C) {
role := services.RoleForUser(teleUser)
role.SetLogins(services.Allow, []string{s.user})
rules := role.GetRules(services.Allow)
rules[services.Wildcard] = services.RW()
rules = append(rules, services.NewRule(services.Wildcard, services.RW()))
role.SetRules(services.Allow, rules)
err = s.authServer.UpsertRole(role, backend.Forever)
c.Assert(err, IsNil)
@ -457,8 +457,8 @@ func (s *WebSuite) TestSAMLSuccess(c *C) {
Allow: services.RoleConditions{
NodeLabels: map[string]string{services.Wildcard: services.Wildcard},
Namespaces: []string{defaults.Namespace},
Rules: map[string][]string{
services.Wildcard: services.RW(),
Rules: []services.Rule{
services.NewRule(services.Wildcard, services.RW()),
},
},
})

View file

@ -109,15 +109,6 @@ func (a *RoleAccess) initAdmin(teleRole services.Role) {
}
func (a *RoleAccess) applyAdmin(role services.Role) {
if a.Admin.Enabled {
allowAllNamespaces(role)
applyResourceAccess(role, adminRules, services.RW())
} else {
rules := role.GetRules(services.Allow)
delete(rules, services.Wildcard)
role.SetRules(services.Allow, rules)
applyResourceAccess(role, adminRules, services.RO())
}
}
func (a *RoleAccess) applySSH(teleRole services.Role) {
@ -147,10 +138,11 @@ func none() []string {
return nil
}
func hasFullAccess(rules map[string][]string, resources []string) bool {
func hasFullAccess(rules []services.Rule, resources []string) bool {
set := services.MakeRuleSet(rules)
for _, resource := range resources {
hasRead := services.MatchRule(rules, resource, services.ActionRead)
hasWrite := services.MatchRule(rules, resource, services.ActionWrite)
hasRead := set.Match(resource, services.ActionRead)
hasWrite := set.Match(resource, services.ActionWrite)
if !(hasRead && hasWrite) {
return false
@ -159,11 +151,3 @@ func hasFullAccess(rules map[string][]string, resources []string) bool {
return true
}
func applyResourceAccess(role services.Role, rules []string, verbs []string) {
rs := role.GetRules(services.Allow)
for _, rule := range rules {
rs[rule] = verbs
}
role.SetRules(services.Allow, rs)
}

View file

@ -127,13 +127,10 @@ func (n *namespaceCollection) writeYAML(w io.Writer) error {
return trace.Wrap(err)
}
func printActions(resources map[string][]string) string {
func printActions(rules []services.Rule) string {
pairs := []string{}
for key, actions := range resources {
if key == services.Wildcard {
return fmt.Sprintf("<all resources>: %v", strings.Join(actions, ","))
}
pairs = append(pairs, fmt.Sprintf("%v:%v", key, strings.Join(actions, ",")))
for _, rule := range rules {
pairs = append(pairs, fmt.Sprintf("%v:%v", strings.Join(rule.Resources, ","), strings.Join(rule.Verbs, ",")))
}
return strings.Join(pairs, ",")
}