code: func (a *AuthWithRoles) filterNodes(nodes []services.Server) ([]services.Server, error) {
  	// For certain built-in roles, continue to allow full access and return
  	// the full set of nodes to not break existing clusters during migration.
  	//
  	// In addition, allow proxy (and remote proxy) to access all nodes for it's
  	// smart resolution address resolution. Once the smart resolution logic is
  	// moved to the auth server, this logic can be removed.
  	if a.hasBuiltinRole(string(teleport.RoleAdmin)) ||
  		a.hasBuiltinRole(string(teleport.RoleProxy)) ||
  		a.hasRemoteBuiltinRole(string(teleport.RoleRemoteProxy)) {
  		return nodes, nil
  	}
  
  	// Fetch services.RoleSet for the identity of the logged in user.
  	roles, err := services.FetchRoles(a.user.GetRoles(), a.authServer, a.user.GetTraits())
  	if err != nil {
  		return nil, trace.Wrap(err)
  	}
  
  	// Extract all unique allowed logins across all roles.
  	allowedLogins := make(map[string]bool)
  	for _, role := range roles {
  		for _, login := range role.GetLogins(services.Allow) {
  			allowedLogins[login] = true
  		}
  	}
  
  	// Loop over all nodes and check if the caller has access.
  	filteredNodes := make([]services.Server, 0, len(nodes))
  NextNode:
  	for _, node := range nodes {
  		for login, _ := range allowedLogins {
  			err := roles.CheckAccessToServer(login, node)
  			if err == nil {
  				filteredNodes = append(filteredNodes, node)
  				continue NextNode
  			}
  		}
  	}
  
  	return filteredNodes, nil
  }
docs: // filterNodes filters nodes based off the role of the logged in user.