diff --git a/lib/services/oidc.go b/lib/services/oidc.go index e8c6815a2882e..d3d824320be7b 100644 --- a/lib/services/oidc.go +++ b/lib/services/oidc.go @@ -417,6 +417,12 @@ func (o *OIDCConnectorV2) RoleFromTemplate(claims jose.Claims) (Role, error) { roleTemplate.SetName(executedName) roleTemplate.SetLogins(executedLogins) + // check all fields and make sure we have have a valid role + err = roleTemplate.CheckAndSetDefaults() + if err != nil { + return nil, trace.Wrap(err) + } + return roleTemplate, nil } } diff --git a/lib/services/oidc_test.go b/lib/services/oidc_test.go index 7895b3019c71d..35d1e795ad991 100644 --- a/lib/services/oidc_test.go +++ b/lib/services/oidc_test.go @@ -162,6 +162,8 @@ func (s *OIDCSuite) TestUnmarshalInvalid(c *check.C) { c.Assert(err, check.NotNil) } +// TestRoleFromTemplate checks that we can create a valid role from a template. Also +// makes sure missing fields are filled in. func (s *OIDCSuite) TestRoleFromTemplate(c *check.C) { oidcConnector := OIDCConnectorV2{ Kind: KindOIDCConnector, @@ -189,7 +191,6 @@ func (s *OIDCSuite) TestRoleFromTemplate(c *check.C) { Namespace: defaults.Namespace, }, Spec: RoleSpecV2{ - Namespaces: []string{"default"}, MaxSessionTTL: NewDuration(30 * 60 * time.Minute), Logins: []string{`{{index . "nickname"}}`, `root`}, NodeLabels: map[string]string{"*": "*"}, diff --git a/lib/services/role.go b/lib/services/role.go index 3b087d04eb80f..dadba0790cdea 100644 --- a/lib/services/role.go +++ b/lib/services/role.go @@ -262,18 +262,40 @@ func (r *RoleV2) SetForwardAgent(forwardAgent bool) { // Check checks validity of all parameters and sets defaults func (r *RoleV2) CheckAndSetDefaults() error { + // make sure we have defaults for all fields if r.Metadata.Name == "" { return trace.BadParameter("missing parameter Name") } + if r.Metadata.Namespace == "" { + r.Metadata.Namespace = defaults.Namespace + } if r.Spec.MaxSessionTTL.Duration == 0 { r.Spec.MaxSessionTTL.Duration = defaults.MaxCertDuration } if r.Spec.MaxSessionTTL.Duration < defaults.MinCertDuration { return trace.BadParameter("maximum session TTL can not be less than") } + if r.Spec.Namespaces == nil { + r.Spec.Namespaces = []string{defaults.Namespace} + } + if r.Spec.NodeLabels == nil { + r.Spec.NodeLabels = map[string]string{Wildcard: Wildcard} + } + if r.Spec.Resources == nil { + r.Spec.Resources = map[string][]string{ + KindSession: RO(), + KindRole: RO(), + KindNode: RO(), + KindAuthServer: RO(), + KindReverseTunnel: RO(), + KindCertAuthority: RO(), + } + } + + // restrict wildcards for _, login := range r.Spec.Logins { if login == Wildcard { - return trace.BadParameter("wilcard matcher is not allowed in logins") + return trace.BadParameter("wildcard matcher is not allowed in logins") } if !cstrings.IsValidUnixUser(login) { return trace.BadParameter("'%v' is not a valid user name", login) @@ -284,6 +306,7 @@ func (r *RoleV2) CheckAndSetDefaults() error { return trace.BadParameter("selector *: is not supported") } } + return nil }