func getMachine(st *state.State, tag names.Tag) (*state.Machine, error) { m0, err := st.FindEntity(tag) if err != nil { return nil, err } return m0.(*state.Machine), nil }
// 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 }
// tagToActionReceiver takes a tag string and tries to convert it to an // ActionReceiver. func tagToActionReceiver(st *state.State, tag string) (state.ActionReceiver, error) { receiverTag, err := names.ParseTag(tag) if err != nil { return nil, common.ErrBadId } entity, err := st.FindEntity(receiverTag) if err != nil { return nil, common.ErrBadId } receiver, ok := entity.(state.ActionReceiver) if !ok { return nil, common.ErrBadId } return receiver, nil }
// EnsureAvailabilitySingle applies a single StateServersSpec specification to the current environment. // Exported so it can be called by the legacy client API in the client package. func EnsureAvailabilitySingle(st *state.State, spec params.StateServersSpec) (params.StateServersChanges, error) { if !st.IsStateServer() { return params.StateServersChanges{}, errors.New("unsupported with hosted environments") } // Check if changes are allowed and the command may proceed. blockChecker := common.NewBlockChecker(st) if err := blockChecker.ChangeAllowed(); err != nil { return params.StateServersChanges{}, errors.Trace(err) } // Validate the environment tag if present. if spec.EnvironTag != "" { tag, err := names.ParseEnvironTag(spec.EnvironTag) if err != nil { return params.StateServersChanges{}, errors.Errorf("invalid environment tag: %v", err) } if _, err := st.FindEntity(tag); err != nil { return params.StateServersChanges{}, err } } series := spec.Series if series == "" { ssi, err := st.StateServerInfo() if err != nil { return params.StateServersChanges{}, err } // We should always have at least one voting machine // If we *really* wanted we could just pick whatever series is // in the majority, but really, if we always copy the value of // the first one, then they'll stay in sync. if len(ssi.VotingMachineIds) == 0 { // Better than a panic()? return params.StateServersChanges{}, fmt.Errorf("internal error, failed to find any voting machines") } templateMachine, err := st.Machine(ssi.VotingMachineIds[0]) if err != nil { return params.StateServersChanges{}, err } series = templateMachine.Series() } changes, err := st.EnsureAvailability(spec.NumStateServers, spec.Constraints, series, spec.Placement) if err != nil { return params.StateServersChanges{}, err } return stateServersChanges(changes), nil }
func checkCreds(st *state.State, c params.Creds) (taggedAuthenticator, error) { entity0, err := st.FindEntity(c.AuthTag) if err != nil && !errors.IsNotFound(err) { return nil, 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. entity, ok := entity0.(taggedAuthenticator) if !ok { return nil, common.ErrBadCreds } if err != nil || !entity.PasswordValid(c.Password) { return nil, common.ErrBadCreds } // Check if a machine agent is logging in with the right Nonce if err := checkForValidMachineAgent(entity, c); err != nil { return nil, err } return entity, 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. 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 }
// EnableHASingle applies a single ControllersServersSpec specification to the current environment. // Exported so it can be called by the legacy client API in the client package. func EnableHASingle(st *state.State, spec params.ControllersSpec) (params.ControllersChanges, error) { if !st.IsController() { return params.ControllersChanges{}, errors.New("unsupported with hosted models") } // Check if changes are allowed and the command may proceed. blockChecker := common.NewBlockChecker(st) if err := blockChecker.ChangeAllowed(); err != nil { return params.ControllersChanges{}, errors.Trace(err) } // Validate the environment tag if present. if spec.ModelTag != "" { tag, err := names.ParseModelTag(spec.ModelTag) if err != nil { return params.ControllersChanges{}, errors.Errorf("invalid model tag: %v", err) } if _, err := st.FindEntity(tag); err != nil { return params.ControllersChanges{}, err } } series := spec.Series if series == "" { ssi, err := st.ControllerInfo() if err != nil { return params.ControllersChanges{}, err } // We should always have at least one voting machine // If we *really* wanted we could just pick whatever series is // in the majority, but really, if we always copy the value of // the first one, then they'll stay in sync. if len(ssi.VotingMachineIds) == 0 { // Better than a panic()? return params.ControllersChanges{}, errors.Errorf("internal error, failed to find any voting machines") } templateMachine, err := st.Machine(ssi.VotingMachineIds[0]) if err != nil { return params.ControllersChanges{}, err } series = templateMachine.Series() } if constraints.IsEmpty(&spec.Constraints) { // No constraints specified, so we'll use the constraints off // a running controller. controllerInfo, err := st.ControllerInfo() if err != nil { return params.ControllersChanges{}, err } // We'll sort the controller ids to find the smallest. // This will typically give the initial bootstrap machine. var controllerIds []int for _, id := range controllerInfo.MachineIds { idNum, err := strconv.Atoi(id) if err != nil { logger.Warningf("ignoring non numeric controller id %v", id) continue } controllerIds = append(controllerIds, idNum) } if len(controllerIds) == 0 { errors.Errorf("internal error, failed to find any controllers") } sort.Ints(controllerIds) // Load the controller machine and get its constraints. controllerId := controllerIds[0] controller, err := st.Machine(strconv.Itoa(controllerId)) if err != nil { return params.ControllersChanges{}, errors.Annotatef(err, "reading controller id %v", controllerId) } spec.Constraints, err = controller.Constraints() if err != nil { return params.ControllersChanges{}, errors.Annotatef(err, "reading constraints for controller id %v", controllerId) } } changes, err := st.EnableHA(spec.NumControllers, spec.Constraints, series, spec.Placement) if err != nil { return params.ControllersChanges{}, err } return controllersChanges(changes), nil }