func NewAccount(kms security.KMS, password string) (proto.Account, *security.ManagedKey, error) { id, err := snowflake.New() if err != nil { return nil, nil, err } sec, clientKey, err := proto.NewAccountSecurity(kms, password) if err != nil { return nil, nil, err } account := &memAccount{ id: id, sec: *sec, } return account, clientKey, nil }
func (b *AccountManagerBinding) Register( ctx scope.Context, kms security.KMS, namespace, id, password string, agentID string, agentKey *security.ManagedKey) ( proto.Account, *security.ManagedKey, error) { // Generate ID for new account. accountID, err := snowflake.New() if err != nil { return nil, nil, err } // Generate credentials in advance of working in DB transaction. sec, clientKey, err := proto.NewAccountSecurity(kms, password) if err != nil { return nil, nil, err } // Begin transaction to check on identity availability and store new account data. t, err := b.DbMap.Begin() if err != nil { return nil, nil, err } rollback := func() { if err := t.Rollback(); err != nil { backend.Logger(ctx).Printf("rollback error: %s", err) } } // Insert new rows for account. account := &Account{ ID: accountID.String(), Nonce: sec.Nonce, MAC: sec.MAC, EncryptedSystemKey: sec.SystemKey.Ciphertext, EncryptedUserKey: sec.UserKey.Ciphertext, EncryptedPrivateKey: sec.KeyPair.EncryptedPrivateKey, PublicKey: sec.KeyPair.PublicKey, } personalIdentity := &PersonalIdentity{ Namespace: namespace, ID: id, AccountID: accountID.String(), } if err := t.Insert(account); err != nil { rollback() return nil, nil, err } if err := t.Insert(personalIdentity); err != nil { rollback() if strings.HasPrefix(err.Error(), "pq: duplicate key value") { return nil, nil, proto.ErrPersonalIdentityInUse } return nil, nil, err } // Look up the associated agent. atb := &AgentTrackerBinding{b.Backend} agent, err := atb.getFromDB(agentID, t) if err != nil { rollback() return nil, nil, err } if err := agent.SetClientKey(agentKey, clientKey); err != nil { rollback() return nil, nil, err } err = atb.setClientKeyInDB(agentID, accountID.String(), agent.EncryptedClientKey.Ciphertext, t) if err != nil { rollback() return nil, nil, err } // Commit the transaction. if err := t.Commit(); err != nil { return nil, nil, err } backend.Logger(ctx).Printf("registered new account %s for %s:%s", account.ID, namespace, id) ab := account.Bind(b.Backend) ab.identities = []proto.PersonalIdentity{&PersonalIdentityBinding{personalIdentity}} return ab, clientKey, nil }