Add signing constraints

This commit is contained in:
Sasha Klizhentas 2016-12-15 20:08:48 -08:00
parent 791c55548d
commit e513a789c5
3 changed files with 49 additions and 10 deletions

View file

@ -212,9 +212,9 @@ func (s *AuthServer) GenerateHostCert(key []byte, hostID, authDomain string, rol
// GenerateUserCert generates user certificate, it takes pkey as a signing
// private key (user certificate authority)
func (s *AuthServer) GenerateUserCert(
key []byte, username string, ttl time.Duration) ([]byte, error) {
func (s *AuthServer) GenerateUserCert(key []byte, username string, allowedLogins []string, ttl time.Duration) ([]byte, error) {
// here I should map username to appropriate certificate authority
// how do I do that?
ca, err := s.Trust.GetCertAuthority(services.CertAuthID{
Type: services.UserCA,
DomainName: s.DomainName,
@ -226,11 +226,7 @@ func (s *AuthServer) GenerateUserCert(
if err != nil {
return nil, trace.Wrap(err)
}
user, err := s.GetUser(username)
if err != nil {
return nil, trace.Wrap(err)
}
return s.Authority.GenerateUserCert(privateKey, key, username, user.GetAllowedLogins(), ttl)
return s.Authority.GenerateUserCert(privateKey, key, username, allowedLogins, ttl)
}
func (s *AuthServer) SignIn(user string, password []byte) (*Session, error) {

View file

@ -348,7 +348,12 @@ func (a *AuthWithRoles) GenerateUserCert(key []byte, user string, ttl time.Durat
if err := a.currentUserAction(user); err != nil {
return nil, trace.Wrap(err)
}
return a.authServer.GenerateUserCert(key, user, ttl)
// check signing TTL and return a list of allowed logins
allowedLogins, err := a.checker.CheckLogins(ttl)
if err != nil {
return nil, trace.Wrap(err)
}
return a.authServer.GenerateUserCert(key, user, allowedLogins, ttl)
}
func (a *AuthWithRoles) CreateSignupToken(user services.User) (token string, e error) {

View file

@ -25,6 +25,7 @@ import (
"github.com/gravitational/teleport/lib/utils"
log "github.com/Sirupsen/logrus"
"github.com/gravitational/configure/cstrings"
"github.com/gravitational/trace"
)
@ -112,6 +113,14 @@ func (r *RoleResource) CheckAndSetDefaults() error {
if r.Spec.MaxSessionTTL.Duration < defaults.MinCertDuration {
return trace.BadParameter("maximum session TTL can not be less than")
}
for _, login := range r.Spec.Logins {
if login == Wildcard {
return trace.BadParameter("wilcard matcher is not allowed in logins")
}
if !cstrings.IsValidUnixUser(login) {
return trace.BadParameter("'%v' is not a valid user name", login)
}
}
for key, val := range r.Spec.NodeLabels {
if key == Wildcard && val != Wildcard {
return trace.BadParameter("selector *:<val> is not supported")
@ -141,6 +150,9 @@ type AccessChecker interface {
CheckAccessToServer(login string, server Server) error
// CheckResourceAction check access to resource action
CheckResourceAction(resourceNamespace, resourceName, accessType string) error
// CheckLogins checks if role set can login up to given duration
// and returns a combined list of allowed logins
CheckLogins(ttl time.Duration) ([]string, error)
}
// FromSpec returns new RoleSet created from spec
@ -213,7 +225,7 @@ func MatchResourceAction(selector map[string][]string, resourceName, resourceAct
// MatchLogin returns true if attempted login matches any of the logins
func MatchLogin(logins []string, login string) bool {
for _, l := range logins {
if l == login || l == Wildcard {
if l == login {
return true
}
}
@ -249,6 +261,32 @@ func MatchLabels(selector map[string]string, target map[string]string) bool {
return true
}
// CheckLogins checks if role set can login up to given duration
// and returns a combined list of allowed logins
func (set RoleSet) CheckLogins(ttl time.Duration) ([]string, error) {
var logins map[string]bool
var matchedTTL bool
for _, role := range set {
if ttl < role.GetMaxSessionTTL().Duration {
matchedTTL = true
}
for _, login := range role.GetLogins() {
logins[login] = true
}
}
if !matchedTTL {
return nil, trace.AccessDenied("this user can not sign certificate for %v", ttl)
}
if len(logins) == 0 {
return nil, trace.AccessDenied("this user can not create SSH sessions, has no logins")
}
out := make([]string, 0, len(logins))
for login := range logins {
out = append(out, login)
}
return out, nil
}
// CheckAccessToServer checks if role set has access to server based
// on combined role's selector and attempted login
func (set RoleSet) CheckAccessToServer(login string, s Server) error {