예제 #1
0
파일: user.go 프로젝트: jimmiebtlr/juju
// AddUser adds a user to the state.
func (st *State) AddUser(username, displayName, password, creator string) (*User, error) {
	if !names.IsValidUser(username) {
		return nil, errors.Errorf("invalid user name %q", username)
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return nil, err
	}
	timestamp := time.Now().Round(time.Second).UTC()
	u := &User{
		st: st,
		doc: userDoc{
			Name:         username,
			DisplayName:  displayName,
			PasswordHash: utils.UserPasswordHash(password, salt),
			PasswordSalt: salt,
			CreatedBy:    creator,
			DateCreated:  timestamp,
		},
	}
	ops := []txn.Op{{
		C:      usersC,
		Id:     username,
		Assert: txn.DocMissing,
		Insert: &u.doc,
	}}
	err = st.runTransaction(ops)
	if err == txn.ErrAborted {
		err = errors.New("user already exists")
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	return u, nil
}
예제 #2
0
파일: identity.go 프로젝트: jimmiebtlr/juju
// SetPassword sets the password associated with the Identity.
func (i *Identity) SetPassword(password string) error {
	salt, err := utils.RandomSalt()
	if err != nil {
		return err
	}
	return i.setPasswordHash(utils.UserPasswordHash(password, salt), salt)
}
예제 #3
0
파일: user.go 프로젝트: jimmiebtlr/juju
// SetPassword sets the password associated with the user.
func (u *User) SetPassword(password string) error {
	salt, err := utils.RandomSalt()
	if err != nil {
		return err
	}
	return u.SetPasswordHash(utils.UserPasswordHash(password, salt), salt)
}
예제 #4
0
func (*passwordSuite) TestRandomSalt(c *gc.C) {
	salt, err := utils.RandomSalt()
	c.Assert(err, gc.IsNil)
	if len(salt) < 12 {
		c.Errorf("salt too short: %q", salt)
	}
	// check we're not adding base64 padding.
	c.Assert(salt, gc.Matches, base64Chars)
}
예제 #5
0
파일: user.go 프로젝트: bac/juju
// SetPassword sets the password associated with the User.
func (u *User) SetPassword(password string) error {
	if err := u.ensureNotDeleted(); err != nil {
		return errors.Annotate(err, "cannot set password")
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return err
	}
	return u.SetPasswordHash(utils.UserPasswordHash(password, salt), salt)
}
예제 #6
0
파일: user.go 프로젝트: bac/juju
func (st *State) addUser(name, displayName, password, creator string, secretKey []byte) (*User, error) {
	if !names.IsValidUserName(name) {
		return nil, errors.Errorf("invalid user name %q", name)
	}
	nameToLower := strings.ToLower(name)

	dateCreated := st.NowToTheSecond()
	user := &User{
		st: st,
		doc: userDoc{
			DocID:       nameToLower,
			Name:        name,
			DisplayName: displayName,
			SecretKey:   secretKey,
			CreatedBy:   creator,
			DateCreated: dateCreated,
		},
	}

	if password != "" {
		salt, err := utils.RandomSalt()
		if err != nil {
			return nil, err
		}
		user.doc.PasswordHash = utils.UserPasswordHash(password, salt)
		user.doc.PasswordSalt = salt
	}

	ops := []txn.Op{{
		C:      usersC,
		Id:     nameToLower,
		Assert: txn.DocMissing,
		Insert: &user.doc,
	}}
	controllerUserOps := createControllerUserOps(st.ControllerUUID(),
		names.NewUserTag(name),
		names.NewUserTag(creator),
		displayName,
		dateCreated,
		defaultControllerPermission)
	ops = append(ops, controllerUserOps...)

	err := st.runTransaction(ops)
	if err == txn.ErrAborted {
		err = errors.AlreadyExistsf("user")
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	return user, nil
}
예제 #7
0
파일: user_test.go 프로젝트: kat-co/juju
func (s *UserSuite) TestSetPasswordHash(c *gc.C) {
	user := s.Factory.MakeUser(c, nil)

	salt, err := utils.RandomSalt()
	c.Assert(err, jc.ErrorIsNil)
	err = user.SetPasswordHash(utils.UserPasswordHash("foo", salt), salt)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(user.PasswordValid("foo"), jc.IsTrue)
	c.Assert(user.PasswordValid("bar"), jc.IsFalse)

	// User passwords should *not* use the fast PasswordHash function
	hash := utils.AgentPasswordHash("foo-12345678901234567890")
	c.Assert(err, jc.ErrorIsNil)
	err = user.SetPasswordHash(hash, "")
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(user.PasswordValid("foo-12345678901234567890"), jc.IsFalse)
}
예제 #8
0
파일: identity.go 프로젝트: jimmiebtlr/juju
// AddIdentity adds an identity to the database.
func (st *State) AddIdentity(name, displayName, password, creator string) (*Identity, error) {
	// The name of the identity happens to match the regex we use to confirm user names.
	// Identities do not have tags, so there is no special function for identities. Given
	// the relationships between users and identities it seems reasonable to use the same
	// validation check.
	if !names.IsValidUser(name) {
		return nil, errors.Errorf("invalid identity name %q", name)
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return nil, err
	}
	identity := &Identity{
		st: st,
		doc: identityDoc{
			Name:         name,
			DisplayName:  displayName,
			PasswordHash: utils.UserPasswordHash(password, salt),
			PasswordSalt: salt,
			CreatedBy:    creator,
			DateCreated:  nowToTheSecond(),
		},
	}
	ops := []txn.Op{{
		C:      identityCollectionName,
		Id:     name,
		Assert: txn.DocMissing,
		Insert: &identity.doc,
	}}
	err = st.runTransaction(ops)
	if err == txn.ErrAborted {
		err = errors.New("identity already exists")
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	return identity, nil
}
예제 #9
0
파일: user.go 프로젝트: imoapps/juju
// AddUser adds a user to the database.
func (st *State) AddUser(name, displayName, password, creator string) (*User, error) {
	if !names.IsValidUserName(name) {
		return nil, errors.Errorf("invalid user name %q", name)
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return nil, err
	}
	nameToLower := strings.ToLower(name)
	user := &User{
		st: st,
		doc: userDoc{
			DocID:        nameToLower,
			Name:         name,
			DisplayName:  displayName,
			PasswordHash: utils.UserPasswordHash(password, salt),
			PasswordSalt: salt,
			CreatedBy:    creator,
			DateCreated:  nowToTheSecond(),
		},
	}
	ops := []txn.Op{{
		C:      usersC,
		Id:     nameToLower,
		Assert: txn.DocMissing,
		Insert: &user.doc,
	}}
	err = st.runTransaction(ops)
	if err == txn.ErrAborted {
		err = errors.AlreadyExistsf("user")
	}
	if err != nil {
		return nil, errors.Trace(err)
	}
	return user, nil
}
예제 #10
0
파일: open.go 프로젝트: bac/juju
// Initialize sets up an initial empty state and returns it.
// This needs to be performed only once for the initial controller model.
// It returns unauthorizedError if access is unauthorized.
func Initialize(args InitializeParams) (_ *State, err error) {
	if err := args.Validate(); err != nil {
		return nil, errors.Annotate(err, "validating initialization args")
	}

	// When creating the controller model, the new model
	// UUID is also used as the controller UUID.
	modelTag := names.NewModelTag(args.ControllerModelArgs.Config.UUID())
	st, err := open(modelTag, args.MongoInfo, args.MongoDialOpts, args.NewPolicy, args.Clock)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer func() {
		if err != nil {
			if closeErr := st.Close(); closeErr != nil {
				logger.Errorf("error closing state while aborting Initialize: %v", closeErr)
			}
		}
	}()
	st.controllerModelTag = modelTag

	// A valid model is used as a signal that the
	// state has already been initalized. If this is the case
	// do nothing.
	if _, err := st.Model(); err == nil {
		return nil, errors.New("already initialized")
	} else if !errors.IsNotFound(err) {
		return nil, errors.Trace(err)
	}

	logger.Infof("initializing controller model %s", modelTag.Id())

	modelOps, err := st.modelSetupOps(
		args.ControllerConfig.ControllerUUID(),
		args.ControllerModelArgs,
		&lineage{
			ControllerConfig: args.ControllerInheritedConfig,
			RegionConfig:     args.RegionInheritedConfig,
		})
	if err != nil {
		return nil, errors.Trace(err)
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return nil, err
	}

	dateCreated := st.NowToTheSecond()
	ops := createInitialUserOps(
		args.ControllerConfig.ControllerUUID(),
		args.ControllerModelArgs.Owner,
		args.MongoInfo.Password,
		salt,
		dateCreated,
	)
	ops = append(ops,

		txn.Op{
			C:      controllersC,
			Id:     modelGlobalKey,
			Assert: txn.DocMissing,
			Insert: &controllersDoc{
				CloudName: args.CloudName,
				ModelUUID: st.ModelUUID(),
			},
		},
		createCloudOp(args.Cloud, args.CloudName),
		txn.Op{
			C:      controllersC,
			Id:     apiHostPortsKey,
			Assert: txn.DocMissing,
			Insert: &apiHostPortsDoc{},
		},
		txn.Op{
			C:      controllersC,
			Id:     stateServingInfoKey,
			Assert: txn.DocMissing,
			Insert: &StateServingInfo{},
		},
		txn.Op{
			C:      controllersC,
			Id:     hostedModelCountKey,
			Assert: txn.DocMissing,
			Insert: &hostedModelCountDoc{},
		},
		createSettingsOp(controllersC, controllerSettingsGlobalKey, args.ControllerConfig),
		createSettingsOp(globalSettingsC, controllerInheritedSettingsGlobalKey, args.ControllerInheritedConfig),
	)
	for k, v := range args.Cloud.RegionConfig {
		// Create an entry keyed on cloudname#<key>, value for each region in
		// region-config. The values here are themselves
		// map[string]interface{}.
		ops = append(ops, createSettingsOp(globalSettingsC, regionSettingsGlobalKey(args.CloudName, k), v))
	}

	for tag, cred := range args.CloudCredentials {
		ops = append(ops, createCloudCredentialOp(tag, cred))
	}
	ops = append(ops, modelOps...)

	if err := st.runTransaction(ops); err != nil {
		return nil, errors.Trace(err)
	}
	controllerTag := names.NewControllerTag(args.ControllerConfig.ControllerUUID())
	if err := st.start(controllerTag); err != nil {
		return nil, errors.Trace(err)
	}
	return st, nil
}
예제 #11
0
파일: open.go 프로젝트: makyo/juju
// Initialize sets up an initial empty state and returns it.
// This needs to be performed only once for the initial controller model.
// It returns unauthorizedError if access is unauthorized.
func Initialize(owner names.UserTag, info *mongo.MongoInfo, cfg *config.Config, opts mongo.DialOpts, policy Policy) (_ *State, err error) {
	uuid := cfg.UUID()
	modelTag := names.NewModelTag(uuid)
	st, err := open(modelTag, info, opts, policy)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer func() {
		if err != nil {
			if closeErr := st.Close(); closeErr != nil {
				logger.Errorf("error closing state while aborting Initialize: %v", closeErr)
			}
		}
	}()

	// A valid model is used as a signal that the
	// state has already been initalized. If this is the case
	// do nothing.
	if _, err := st.Model(); err == nil {
		return nil, errors.New("already initialized")
	} else if !errors.IsNotFound(err) {
		return nil, errors.Trace(err)
	}

	// When creating the controller model, the new model
	// UUID is also used as the controller UUID.
	logger.Infof("initializing controller model %s", uuid)
	modelOps, err := st.modelSetupOps(cfg, uuid, uuid, owner, MigrationModeActive)
	if err != nil {
		return nil, errors.Trace(err)
	}
	salt, err := utils.RandomSalt()
	if err != nil {
		return nil, err
	}
	ops := []txn.Op{
		createInitialUserOp(st, owner, info.Password, salt),
		txn.Op{
			C:      controllersC,
			Id:     modelGlobalKey,
			Assert: txn.DocMissing,
			Insert: &controllersDoc{
				ModelUUID: st.ModelUUID(),
			},
		},
		txn.Op{
			C:      controllersC,
			Id:     apiHostPortsKey,
			Assert: txn.DocMissing,
			Insert: &apiHostPortsDoc{},
		},
		txn.Op{
			C:      controllersC,
			Id:     stateServingInfoKey,
			Assert: txn.DocMissing,
			Insert: &StateServingInfo{},
		},
		txn.Op{
			C:      controllersC,
			Id:     hostedModelCountKey,
			Assert: txn.DocMissing,
			Insert: &hostedModelCountDoc{},
		},
	}
	ops = append(ops, modelOps...)

	if err := st.runTransaction(ops); err != nil {
		return nil, errors.Trace(err)
	}
	if err := st.start(modelTag); err != nil {
		return nil, errors.Trace(err)
	}
	return st, nil
}