Skip to content

Commit

Permalink
Validate node_labels syntax at role creation time
Browse files Browse the repository at this point in the history
Also improve error output and user validation.
Based on missed feedback in #4253 (review)
  • Loading branch information
Andrew Lytvynov authored and awly committed Oct 5, 2020
1 parent 9b59832 commit 63da432
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 6 deletions.
12 changes: 12 additions & 0 deletions lib/services/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,18 @@ func (r *RoleV3) CheckAndSetDefaults() error {
if key == Wildcard && !(len(val) == 1 && val[0] == Wildcard) {
return trace.BadParameter("selector *:<val> is not supported")
}
for _, l := range val {
if _, err := parse.NewMatcher(l); err != nil {
return trace.Wrap(err)
}
}
}
for _, val := range r.Spec.Deny.NodeLabels {
for _, l := range val {
if _, err := parse.NewMatcher(l); err != nil {
return trace.Wrap(err)
}
}
}
for i := range r.Spec.Allow.Rules {
err := r.Spec.Allow.Rules[i].CheckAndSetDefaults()
Expand Down
5 changes: 4 additions & 1 deletion lib/services/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,10 @@ func (u *UserV1) Check() error {
}
for _, login := range u.AllowedLogins {
e, err := parse.NewExpression(login)
if err == nil && e.Namespace() != parse.LiteralNamespace {
if err != nil {
return trace.Wrap(err)
}
if e.Namespace() != parse.LiteralNamespace {
return trace.BadParameter("role variables not allowed in allowed logins")
}
}
Expand Down
14 changes: 9 additions & 5 deletions lib/utils/parse/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,12 @@ type Matcher interface {
//
// These expressions do not support variable interpolation (e.g.
// `{{internal.logins}}`), like Expression does.
func NewMatcher(value string) (Matcher, error) {
func NewMatcher(value string) (m Matcher, err error) {
defer func() {
if err != nil {
err = trace.WrapWithMessage(err, "see supported syntax at https://gravitational.com/teleport/docs/enterprise/ssh-rbac/#rbac-for-hosts")
}
}()
match := reVariable.FindStringSubmatch(value)
if len(match) == 0 {
if strings.Contains(value, "{{") || strings.Contains(value, "}}") {
Expand All @@ -191,7 +196,7 @@ func NewMatcher(value string) (Matcher, error) {
// parse and get the ast of the expression
expr, err := parser.ParseExpr(variable)
if err != nil {
return nil, trace.BadParameter("failed to parse %q: %v", variable, err)
return nil, trace.BadParameter("failed to parse %q: %v", value, err)
}

// walk the ast tree and gather the variable parts
Expand All @@ -204,7 +209,7 @@ func NewMatcher(value string) (Matcher, error) {
// the matching logic. For example
// `{{regexp.match(external.allowed_env_trait)}}`.
if result.transform != nil || len(result.parts) > 0 {
return nil, trace.BadParameter("%q is not a valid matcher expression - no variables and transformations are allowed", variable)
return nil, trace.BadParameter("%q is not a valid matcher expression - no variables and transformations are allowed", value)
}
return newPrefixSuffixMatcher(prefix, suffix, result.match), nil
}
Expand Down Expand Up @@ -345,8 +350,7 @@ func walk(node ast.Node) (*walkResult, error) {
if err != nil {
return nil, trace.Wrap(err)
}
// If this is not_match, wrap the regexpMatcher to invert
// it.
// If this is not_match, wrap the regexpMatcher to invert it.
if fn == RegexpNotMatchFnName {
result.match = notMatcher{result.match}
}
Expand Down

0 comments on commit 63da432

Please sign in to comment.