// checkCreds validates the entities credentials in the current environment. // If the entity is a user, and lookForEnvUser is true, an env user must exist // for the environment. In the case of a user logging in to the server, but // not an environment, there is no env user needed. While we have the env // user, if we do have it, update the last login time. func checkCreds(st *state.State, req params.LoginRequest, lookForEnvUser bool) (state.Entity, *time.Time, error) { tag, err := names.ParseTag(req.AuthTag) if err != nil { return nil, nil, err } entity, err := st.FindEntity(tag) if errors.IsNotFound(err) { // We return the same error when an entity does not exist as for a bad // password, so that we don't allow unauthenticated users to find // information about existing entities. logger.Debugf("entity %q not found", tag) return nil, nil, common.ErrBadCreds } if err != nil { return nil, nil, errors.Trace(err) } authenticator, err := authentication.FindEntityAuthenticator(entity) if err != nil { return nil, nil, err } if err = authenticator.Authenticate(entity, req.Credentials, req.Nonce); err != nil { logger.Debugf("bad credentials") return nil, nil, err } // For user logins, update the last login time. // NOTE: this code path is only for local users. When we support remote // user logins with bearer tokens, we will need to make sure that we also // update the last connection times for the environment users there. var lastLogin *time.Time if user, ok := entity.(*state.User); ok { userLastLogin, err := user.LastLogin() if err != nil && !state.IsNeverLoggedInError(err) { return nil, nil, errors.Trace(err) } if lookForEnvUser { envUser, err := st.EnvironmentUser(user.UserTag()) if err != nil { return nil, nil, errors.Wrap(err, common.ErrBadCreds) } // The last connection for the environment takes precedence over // the local user last login time. userLastLogin, err = envUser.LastConnection() if err != nil && !state.IsNeverConnectedError(err) { return nil, nil, errors.Trace(err) } envUser.UpdateLastConnection() } // Only update the user's last login time if it is a successful // login, meaning that if we are logging into an environment, make // sure that there is an environment user in that environment for // this user. user.UpdateLastLogin() lastLogin = &userLastLogin } return entity, lastLogin, nil }
func checkCreds(st *state.State, c params.Creds) (state.Entity, error) { tag, err := names.ParseTag(c.AuthTag) if err != nil { return nil, err } entity, err := st.FindEntity(tag) if errors.IsNotFound(err) { // We return the same error when an entity does not exist as for a bad // password, so that we don't allow unauthenticated users to find // information about existing entities. return nil, common.ErrBadCreds } if err != nil { return nil, errors.Trace(err) } authenticator, err := authentication.FindEntityAuthenticator(entity) if err != nil { return nil, err } if err = authenticator.Authenticate(entity, c.Password, c.Nonce); err != nil { return nil, err } return entity, nil }
func (s *AgentAuthenticatorSuite) TestFindEntityAuthenticator(c *gc.C) { fact := factory.NewFactory(s.State) user := fact.MakeUser(c, &factory.UserParams{Password: "******"}) authenticator, err := authentication.FindEntityAuthenticator(user) c.Assert(err, jc.ErrorIsNil) c.Assert(authenticator, gc.NotNil) err = authenticator.Authenticate(user, "password", "nonce") c.Assert(err, jc.ErrorIsNil) }
func (s *AgentAuthenticatorSuite) TestFindEntityAuthenticatorFails(c *gc.C) { // add relation wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) wordpressEP, err := wordpress.Endpoint("db") c.Assert(err, jc.ErrorIsNil) mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) mysqlEP, err := mysql.Endpoint("server") c.Assert(err, jc.ErrorIsNil) relation, err := s.State.AddRelation(wordpressEP, mysqlEP) c.Assert(err, jc.ErrorIsNil) _, err = authentication.FindEntityAuthenticator(relation) c.Assert(err, gc.ErrorMatches, "invalid request") }
func checkCreds(st *state.State, c params.Creds) (state.Entity, error) { tag, err := names.ParseTag(c.AuthTag) if err != nil { return nil, err } entity, err := st.FindEntity(tag) if errors.IsNotFound(err) { // We return the same error when an entity does not exist as for a bad // password, so that we don't allow unauthenticated users to find // information about existing entities. logger.Debugf("entity %q not found", tag) return nil, common.ErrBadCreds } if err != nil { return nil, errors.Trace(err) } authenticator, err := authentication.FindEntityAuthenticator(entity) if err != nil { return nil, err } if err = authenticator.Authenticate(entity, c.Password, c.Nonce); err != nil { logger.Debugf("bad credentials") return nil, err } // For user logins, ensure the user is allowed to access the environment. if user, ok := entity.Tag().(names.UserTag); ok { _, err := st.EnvironmentUser(user) if err != nil { return nil, errors.Wrap(err, common.ErrBadCreds) } } return entity, nil }