async def fetch_info_by_username(request): username = request.json.get("id") conn = request.app.config.DB_CONN result = ( await r.table("auth") .get_all(username, index="username") .limit(1) .coerce_to("array") .run(conn) ) if result: return result[0] result = ( await r.table("users") .get_all(username, index="username") .limit(1) .coerce_to("array") .run(conn) ) if not result: raise ApiNotFound("No user with username '{}' exists.".format(username)) result = result[0] user_key = Key() encrypted_private_key = encrypt_private_key( request.app.config.AES_KEY, user_key.public_key, user_key.private_key_bytes ) auth_entry = { "user_id": result.get("user_id"), "username": result.get("username"), "email": result.get("email"), "encrypted_private_key": encrypted_private_key, } insert_result = await r.table("auth").insert(auth_entry).run(conn) # TODO: execute USER_ADD_KEY message return auth_entry
def test_encrypt_private_key(self): """Test that we can encrypt an AES key using a keypair""" aes_key = self.test_generate_aes_key() user_key = Key() next_id = user_key.public_key encrypted = encrypt_private_key(aes_key=aes_key, next_id=next_id, private_key=user_key.private_key) return encrypted, aes_key, user_key, next_id
def test_encrypt_private_key(self): self.assertTrue(callable(encrypt_private_key)) aes_key = self.test_generate_aes_key() user_key = Key() user_id = user_key.public_key encrypted = encrypt_private_key(aes_key=aes_key, user_id=user_id, private_key=user_key.private_key) return encrypted, aes_key, user_key, user_id
async def create_new_user(request): required_fields = ["name", "username", "password", "email"] utils.validate_fields(required_fields, request.json) # Generate keys txn_key = Key() txn_user_id = rbac.user.unique_id() encrypted_private_key = encrypt_private_key(request.app.config.AES_KEY, txn_key.public_key, txn_key.private_key_bytes) # Build create user transaction batch_list = rbac.user.batch_list( signer_keypair=txn_key, signer_user_id=txn_user_id, user_id=txn_user_id, name=request.json.get("name"), username=request.json.get("username"), email=request.json.get("email"), metadata=request.json.get("metadata"), manager=request.json.get("manager"), key=txn_key.public_key, ) # Submit transaction and wait for complete await utils.send(request.app.config.VAL_CONN, batch_list, request.app.config.TIMEOUT) # Save new user in auth table hashed_password = hashlib.sha256( request.json.get("password").encode("utf-8")).hexdigest() auth_entry = { "user_id": txn_user_id, "hashed_password": hashed_password, "encrypted_private_key": encrypted_private_key, "username": request.json.get("username"), "email": request.json.get("email"), } conn = await db_utils.create_connection( request.app.config.DB_HOST, request.app.config.DB_PORT, request.app.config.DB_NAME, ) await auth_query.create_auth_entry(conn, auth_entry) conn.close() # Send back success response return create_user_response(request, txn_user_id)
async def fetch_info_by_username(request): username = request.json.get("id") conn = await db_utils.create_connection( request.app.config.DB_HOST, request.app.config.DB_PORT, request.app.config.DB_NAME, ) result = (await r.table("auth").get_all( username, index="username").limit(1).coerce_to("array").run(conn)) if result: return result[0] # Auth record not found, check if the username exists result = (await r.table("users").get_all( username, index="username").limit(1).coerce_to("array").run(conn)) if not result: raise ApiNotFound( "No user with username '{}' exists.".format(username)) result = result[0] # Generate and store key and auth record first time a user logs in user_id = result.get("user_id") user_key = Key() batch_list = rbac.key.batch_list( signer_keypair=user_key, signer_user_id=user_id, user_id=user_id, key_id=user_key.public_key, ) await utils.send(request.app.config.VAL_CONN, batch_list, request.app.config.TIMEOUT) encrypted_private_key = encrypt_private_key(request.app.config.AES_KEY, user_key.public_key, user_key.private_key_bytes) auth_entry = { "user_id": user_id, "username": result.get("username"), "email": result.get("email"), "encrypted_private_key": encrypted_private_key, } await r.table("auth").insert(auth_entry).run(conn) conn.close() return auth_entry
async def create_new_user(request): required_fields = ["name", "username", "password"] utils.validate_fields(required_fields, request.json) # Generate keys private_key = Secp256k1PrivateKey.new_random() txn_key = Key(private_key.as_hex()) encrypted_private_key = encrypt_private_key( request.app.config.AES_KEY, txn_key.public_key, private_key.as_bytes() ) # Build create user transaction batch_list = create_user( txn_key, request.app.config.BATCHER_KEY_PAIR, request.json.get("name"), request.json.get("username"), txn_key.public_key, request.json.get("metadata"), request.json.get("manager"), ) # Submit transaction and wait for complete await utils.send( request.app.config.VAL_CONN, batch_list[0], request.app.config.TIMEOUT ) # Save new user in auth table hashed_password = hashlib.sha256( request.json.get("password").encode("utf-8") ).hexdigest() auth_entry = { "user_id": txn_key.public_key, "hashed_password": hashed_password, "encrypted_private_key": encrypted_private_key, "user_name": request.json.get("username"), "email": request.json.get("email"), } await auth_query.create_auth_entry(request.app.config.DB_CONN, auth_entry) # Send back success response return create_user_response(request, txn_key.public_key)
async def create_new_user(request): """Create a new user.""" required_fields = ["name", "username", "password", "email"] utils.validate_fields(required_fields, request.json) username_created = request.json.get("username") conn = await db_utils.create_connection( request.app.config.DB_HOST, request.app.config.DB_PORT, request.app.config.DB_NAME, ) # Check if username already exists if await users_query.fetch_username_match_count(conn, username_created) > 0: # Throw Error response to Next_UI raise ApiBadRequest( "Username already exists. Please give a different Username.") conn.close() # Generate keys key_pair = Key() next_id = str(uuid4()) encrypted_private_key = encrypt_private_key(AES_KEY, key_pair.public_key, key_pair.private_key_bytes) # Build create user transaction batch_list = User().batch_list( signer_keypair=key_pair, signer_user_id=next_id, next_id=next_id, name=request.json.get("name"), username=request.json.get("username"), email=request.json.get("email"), metadata=request.json.get("metadata"), manager=request.json.get("manager"), key=key_pair.public_key, ) # Submit transaction and wait for complete await utils.send(request.app.config.VAL_CONN, batch_list, request.app.config.TIMEOUT) # Save new user in auth table hashed_password = hashlib.sha256( request.json.get("password").encode("utf-8")).hexdigest() auth_entry = { "next_id": next_id, "hashed_password": hashed_password, "encrypted_private_key": encrypted_private_key, "username": request.json.get("username"), "email": request.json.get("email"), } mapping_data = { "next_id": next_id, "provider_id": None, "remote_id": None, "public_key": key_pair.public_key, "encrypted_key": encrypted_private_key, "active": True, } # Insert to user_mapping and close conn = await db_utils.create_connection( request.app.config.DB_HOST, request.app.config.DB_PORT, request.app.config.DB_NAME, ) await auth_query.create_auth_entry(conn, auth_entry) await users_query.create_user_map_entry(conn, mapping_data) conn.close() # Send back success response return create_user_response(request, next_id)
def add_transaction(inbound_entry): """ Adds transactional entries onto inbound_entry """ try: set_metadata_flag = {} data = inbound_entry["data"] key_pair = Key() encrypted_private_key = encrypt_private_key(AES_KEY, key_pair.public_key, key_pair.private_key_bytes) inbound_entry["public_key"] = key_pair.public_key inbound_entry["private_key"] = encrypted_private_key set_metadata_flag["sync_direction"] = "INBOUND" data["metadata"] = set_metadata_flag data["provider_id"] = inbound_entry["provider_id"] if inbound_entry["data_type"] == "user": next_user = get_next_object("user_mapping", data["remote_id"], inbound_entry["provider_id"]) # Generate Ids if next_user: next_id = next_user[0]["next_id"] else: next_id = str(uuid4()) inbound_entry = add_sawtooth_prereqs(entry_id=next_id, inbound_entry=inbound_entry, data_type="user") message = User().imports.make(signer_keypair=key_pair, next_id=next_id, **data) batch = User().imports.batch( signer_keypair=key_pair, signer_user_id=key_pair.public_key, message=message, ) inbound_entry["batch"] = batch.SerializeToString() add_metadata(inbound_entry, message) elif inbound_entry["data_type"] == "group": next_role = get_next_object("roles", data["remote_id"], inbound_entry["provider_id"]) # Generate Ids if next_role: next_id = next_role[0]["role_id"] else: next_id = str(uuid4()) inbound_entry = add_sawtooth_prereqs(entry_id=next_id, inbound_entry=inbound_entry, data_type="group") message = Role().imports.make(signer_keypair=key_pair, role_id=next_id, **data) batch = Role().imports.batch( signer_keypair=key_pair, signer_user_id=key_pair.public_key, message=message, ) inbound_entry["batch"] = batch.SerializeToString() add_metadata(inbound_entry, message) elif inbound_entry["data_type"] == "user_deleted": LOGGER.info("User deletion detected in inbound_queue: %s", data["remote_id"]) # Find user to be deleted deleted_user = data["remote_id"] conn = connect_to_db() user_in_db = (r.table("users").filter({ "remote_id": deleted_user }).coerce_to("array").run(conn)) conn.close() # Process if the user exists if user_in_db: delete_user_transaction(inbound_entry, user_in_db, key_pair) elif inbound_entry["data_type"] == "group_deleted": LOGGER.info("Group deletion detected in inbound_queue: %s", data["remote_id"]) deleted_group = data["remote_id"] conn = connect_to_db() group_in_db = (r.table("roles").filter({ "remote_id": deleted_group }).coerce_to("array").run(conn)) if group_in_db: role_delete = DeleteRole() role_id = group_in_db[0]["role_id"] role_relationships = fetch_role_relationships(role_id=role_id, conn=conn) if role_relationships: data = {**data, **role_relationships} inbound_entry = add_sawtooth_prereqs( entry_id=role_id, inbound_entry=inbound_entry, data_type="group") message = role_delete.make(signer_keypair=key_pair, role_id=role_id, **data) batch = role_delete.batch( signer_keypair=key_pair, signer_user_id=key_pair.public_key, message=message, ) inbound_entry["batch"] = batch.SerializeToString() conn.close() except Exception as err: # pylint: disable=broad-except LOGGER.exception("Unable to create transaction for inbound data:\n%s", inbound_entry) LOGGER.exception(err)
async def create_new_user(request): """Create a new user. Must be an adminsitrator. Args: request: obj: incoming request object """ log_request(request, True) # Validate that we have all fields required_fields = ["name", "username", "password", "email"] validate_fields(required_fields, request.json) # Check if username already exists conn = await create_connection() username = request.json.get("username") if await users_query.fetch_username_match_count(conn, username) > 0: # Throw Error response to Next_UI return await handle_errors( request, ApiTargetConflict("Username already exists.")) conn.close() # Check to see if they are trying to create the NEXT admin env = Env() next_admin = { "name": env("NEXT_ADMIN_NAME"), "username": env("NEXT_ADMIN_USER"), "email": env("NEXT_ADMIN_EMAIL"), "password": env("NEXT_ADMIN_PASS"), } if request.json != next_admin: # Try to see if they are in NEXT if not env.int("ENABLE_NEXT_BASE_USE"): raise ApiDisabled("Not a valid action. Source not enabled.") txn_key, txn_user_id, next_id, key_pair = await non_admin_creation( request) else: txn_key, txn_user_id, next_id, key_pair = await next_admin_creation( request) if request.json.get("metadata") is None: set_metadata = {} else: set_metadata = request.json.get("metadata") set_metadata["sync_direction"] = "OUTBOUND" # Build create user transaction batch_list = User().batch_list( signer_keypair=txn_key, signer_user_id=txn_user_id, next_id=next_id, name=request.json.get("name"), username=request.json.get("username"), email=request.json.get("email"), metadata=set_metadata, manager_id=request.json.get("manager"), key=key_pair.public_key, ) # Submit transaction and wait for complete sawtooth_response = await send(request.app.config.VAL_CONN, batch_list, request.app.config.TIMEOUT) if not sawtooth_response: return await handle_errors( request, ApiInternalError( "There was an error submitting the sawtooth transaction."), ) # Save new user in auth table salt = hashlib.sha256(os.urandom(60)).hexdigest().encode("utf-8") password = request.json.get("password").encode("utf-8") hashed_password = hashlib.pbkdf2_hmac("sha256", password, salt, 100000).hex() encrypted_private_key = encrypt_private_key(AES_KEY, key_pair.public_key, key_pair.private_key_bytes) auth_entry = { "next_id": next_id, "salt": salt, "hashed_password": hashed_password, "encrypted_private_key": encrypted_private_key, "username": request.json.get("username"), "email": request.json.get("email"), } mapping_data = { "next_id": next_id, "provider_id": "NEXT-created", "remote_id": None, "public_key": key_pair.public_key, "encrypted_key": encrypted_private_key, "active": True, } # Insert to user_mapping and close await auth_query.create_auth_entry(auth_entry) conn = await create_connection() await users_query.create_user_map_entry(conn, mapping_data) conn.close() # Send back success response return json({"data": {"user": {"id": next_id}}})
async def create_new_user(request): """Create a new user.""" env = Env() admin_role = { "name": env("NEXT_ADMIN_NAME"), "username": env("NEXT_ADMIN_USER"), "email": env("NEXT_ADMIN_EMAIL"), "password": env("NEXT_ADMIN_PASS"), } if request.json != admin_role: if not env.int("ENABLE_NEXT_BASE_USE"): raise ApiBadRequest("Not a valid action. Source not enabled") required_fields = ["name", "username", "password", "email"] utils.validate_fields(required_fields, request.json) username_created = request.json.get("username") conn = await create_connection() # Check if username already exists if await users_query.fetch_username_match_count(conn, username_created) > 0: # Throw Error response to Next_UI raise ApiBadRequest( "Username already exists. Please give a different Username.") conn.close() # Generate keys key_pair = Key() next_id = str(uuid4()) encrypted_private_key = encrypt_private_key(AES_KEY, key_pair.public_key, key_pair.private_key_bytes) if request.json.get("metadata") is None or request.json.get( "metadata") == {}: set_metadata = {} else: set_metadata = request.json.get("metadata") set_metadata["sync_direction"] = "OUTBOUND" # Build create user transaction batch_list = User().batch_list( signer_keypair=key_pair, signer_user_id=next_id, next_id=next_id, name=request.json.get("name"), username=request.json.get("username"), email=request.json.get("email"), metadata=set_metadata, manager_id=request.json.get("manager"), key=key_pair.public_key, ) # Submit transaction and wait for complete await utils.send(request.app.config.VAL_CONN, batch_list, request.app.config.TIMEOUT) # Save new user in auth table hashed_password = hashlib.sha256( request.json.get("password").encode("utf-8")).hexdigest() auth_entry = { "next_id": next_id, "hashed_password": hashed_password, "encrypted_private_key": encrypted_private_key, "username": request.json.get("username"), "email": request.json.get("email"), } mapping_data = { "next_id": next_id, "provider_id": None, "remote_id": None, "public_key": key_pair.public_key, "encrypted_key": encrypted_private_key, "active": True, } # Insert to user_mapping and close conn = await create_connection() await auth_query.create_auth_entry(auth_entry) await users_query.create_user_map_entry(conn, mapping_data) conn.close() # Send back success response return create_user_response(request, next_id)
def add_transaction(inbound_entry): """ Adds transactional entries onto inbound_entry """ try: data = inbound_entry["data"] key_pair = Key() encrypted_private_key = encrypt_private_key(AES_KEY, key_pair.public_key, key_pair.private_key_bytes) inbound_entry["public_key"] = key_pair.public_key inbound_entry["private_key"] = encrypted_private_key if inbound_entry["data_type"] == "user": next_user = get_next_id("user_mapping", data["remote_id"], inbound_entry["provider_id"]) # Generate Ids if next_user: next_id = next_user[0]["next_id"] else: next_id = str(uuid4()) object_id = User().hash(next_id) address = User().address(object_id=object_id) inbound_entry["next_id"] = next_id inbound_entry["address"] = bytes_from_hex(address) inbound_entry["object_id"] = bytes_from_hex(object_id) inbound_entry["object_type"] = addresser.ObjectType.USER.value message = User().imports.make(signer_keypair=key_pair, next_id=next_id, **data) batch = User().imports.batch( signer_keypair=key_pair, signer_user_id=key_pair.public_key, message=message, ) inbound_entry["batch"] = batch.SerializeToString() add_metadata(inbound_entry, message) elif inbound_entry["data_type"] == "group": next_id = str(uuid4()) object_id = Role().hash(next_id) address = Role().address(object_id=object_id) inbound_entry["address"] = bytes_from_hex(address) inbound_entry["object_id"] = bytes_from_hex(object_id) inbound_entry["object_type"] = addresser.ObjectType.ROLE.value message = Role().imports.make(signer_keypair=key_pair, role_id=next_id, **data) batch = Role().imports.batch( signer_keypair=key_pair, signer_user_id=key_pair.public_key, message=message, ) inbound_entry["batch"] = batch.SerializeToString() add_metadata(inbound_entry, message) except Exception as err: # pylint: disable=broad-except LOGGER.exception("Unable to create transaction for inbound data:\n%s", inbound_entry) LOGGER.exception(err)