func (s *Server) groupByGID(args []string) string { gid, err := parseID(args) if err != nil { logger.Errorf("Invalid GID for group: %v.", err) return "400" } logger.Infof("Getting group by GID: %v.", gid) group, err := s.Provider.GroupByGID(gid) if err != nil { return marshalError(err) } return fmt.Sprintf("200\n%v", marshalGroup(group)) }
func (s *Server) groupByName(args []string) string { name, err := parseName(args) if err != nil { logger.Errorf("Invalid name for group: %v.", err) return "400" } logger.Infof("Getting group by name: %v.", name) group, err := s.Provider.GroupByName(name) if err != nil { return marshalError(err) } return fmt.Sprintf("200\n%v", marshalGroup(group)) }
func (s *Server) userByUID(args []string) string { uid, err := parseID(args) if err != nil { logger.Errorf("Invalid UID for user: %v.", err) return "400" } logger.Infof("Getting user by UID: %v.", uid) user, err := s.Provider.UserByUID(uid) if err != nil { return marshalError(err) } return fmt.Sprintf("200\n%v", marshalUser(user)) }
func (s *Server) userByName(args []string) string { name, err := parseName(args) if err != nil { logger.Errorf("Invalid name for user: %v.", err) return "400" } logger.Infof("Getting user by name: %v.", name) user, err := s.Provider.UserByName(name) if err != nil { return marshalError(err) } return fmt.Sprintf("200\n%v", marshalUser(user)) }
// AuthorizedKeys satisfies AccountProvider. func (s *cachingStore) AuthorizedKeys(username string) ([]string, error) { cu, ok := s.userByNameImpl(username) if !ok { return nil, accounts.UsernameNotFound(username) } else if !nowOutsideTimespan(cu.keyRefreshTime, s.config.KeyRefreshCooldown) { logger.Infof("Returning cached keys for %v due to cooldown.", username) return cu.keys, nil } view, err := s.apiClient.AuthorizedKeys(username) if err != nil { return cu.keys, nil } go s.updateCachedKeys(username, view.Keys, view.Sudoer, timeNow()) return view.Keys, nil }
// UserByName satisfies AccountProvider. func (s *cachingStore) UserByName(name string) (*accounts.User, error) { cu, ok := s.userByNameImpl(name) if ok { return cu.user, nil } ch := make(chan struct{}) logger.Infof("Triggering refresh due to missing user %v.", name) s.updateWaiters <- ch // Block on update. <-ch cu, ok = s.userByNameImpl(name) if ok { return cu.user, nil } return nil, accounts.UsernameNotFound(name) }
func (s *Server) isName(args []string) string { name, err := parseName(args) if err != nil { logger.Errorf("Invalid name: %v.", err) return "400" } logger.Infof("Checking name: %v.", name) is, err := s.Provider.IsName(name) if err != nil { return marshalError(err) } else if is { logger.Info("Valid name.") return "200" } else { logger.Info("Invalid name.") return "404" } }
func (s *Server) authorizedKeys(args []string) string { username, err := parseName(args) if err != nil { logger.Errorf("Invalid username for keys: %v.", err) return "400" } logger.Infof("Getting keys for user: %v.", username) keys, err := s.Provider.AuthorizedKeys(username) if err != nil { return marshalError(err) } var buf bytes.Buffer buf.WriteString("200") for _, k := range keys { buf.WriteString("\n") buf.WriteString(k) } return buf.String() }
// Serve begins serving accounts information through a socket forever. func (s *Server) Serve() error { os.Remove(socketPath) sock, err := net.ListenUnix("unix", &net.UnixAddr{socketPath, "unix"}) if err != nil { return err } // Make the socket readable and writeable by all. os.Chmod(socketPath, os.ModePerm) listeningCallback() logger.Infof("Listening for connections at %v.", socketPath) for { conn, err := sock.Accept() if err != nil { logger.Errorf("Failed to accept connection: %v.", err) continue } logger.Info("Accepted connection.") go s.handle(conn) } }
func updateKeys(s *cachingStore) { type update struct { name string view *cua.AuthorizedKeysView err error time time.Time } ch := make(chan update) workers := 0 for _, name := range keysRequiringRefresh(s) { go func(n string) { view, err := s.apiClient.AuthorizedKeys(n) ch <- update{n, view, err, timeNow()} }(name) workers += 1 } refreshedKeys := make([]update, workers) for workers != 0 { up := <-ch workers -= 1 if up.err != nil { logger.Errorf("Failed key refresh for %v: %v.", up.name, up.err) continue } logger.Infof("Refreshed keys for %v.", up.name) refreshedKeys = append(refreshedKeys, up) } s.Lock() defer s.Unlock() for _, rk := range refreshedKeys { if cu, ok := s.usersByName[rk.name]; ok { cu.keys = rk.view.Keys cu.sudoer = rk.view.Sudoer cu.keyRefreshTime = rk.time } } refreshCallback(s.config) }
// AuthorizedKeys satisfies APIClient. func (c *googleAPIClient) AuthorizedKeys(username string) (*cua.AuthorizedKeysView, error) { logger.Infof("Fetching authorized keys for %v.", username) p, z, i, err := c.instanceInfo() if err != nil { return nil, err } view, err := c.service.Linux.GetAuthorizedKeysView(p, z, username, i).Do() switch e := err.(type) { case nil: if view.Resource == nil { return nil, fmt.Errorf("Invalid authorized keys returned for %v.", username) } return view.Resource, nil case *googleapi.Error: if e.Code == 404 { logger.Noticef("User %v does not exist.", username) return nil, nil } return nil, err default: return nil, err } }