async def _claim_invitation(config, addr, password): async with backend_invited_cmds_factory(addr=addr) as cmds: try: async with spinner("Retrieving invitation info"): initial_ctx = await claimer_retrieve_info(cmds) except BackendConnectionRefused: raise RuntimeError("Invitation not found") if initial_ctx.greeter_human_handle: display_greeter = click.style(initial_ctx.greeter_human_handle, fg="yellow") else: display_greeter = click.style(initial_ctx.greeter_user_id, fg="yellow") click.echo(f"Invitation greeter: {display_greeter}") while True: try: if isinstance(initial_ctx, DeviceClaimInitialCtx): new_device = await _do_claim_device(initial_ctx) else: assert isinstance(initial_ctx, UserClaimInitialCtx) new_device = await _do_claim_user(initial_ctx) if new_device: break except InviteError as exc: click.secho(str(exc), fg="red") click.secho("Restarting the invitation process", fg="red") device_display = click.style(new_device.slughash, fg="yellow") with operation(f"Saving device {device_display}"): save_device_with_password(config.config_dir, new_device, password)
async def _bootstrap_organization( debug, device_id, organization_bootstrap_addr, config_dir, force, password ): root_signing_key = SigningKey.generate() root_verify_key = root_signing_key.verify_key organization_addr = organization_bootstrap_addr.generate_organization_addr(root_verify_key) device_display = click.style(device_id, fg="yellow") device = generate_new_device(device_id, organization_addr) with operation(f"Creating locally {device_display}"): save_device_with_password(config_dir, device, password, force=force) now = pendulum.now() certified_user = certify_user(None, root_signing_key, device.user_id, device.public_key, now) certified_device = certify_device(None, root_signing_key, device_id, device.verify_key, now) async with spinner(f"Sending {device_display} to server"): async with backend_anonymous_cmds_factory(organization_bootstrap_addr) as cmds: await cmds.organization_bootstrap( organization_bootstrap_addr.organization_id, organization_bootstrap_addr.bootstrap_token, root_verify_key, certified_user, certified_device, ) organization_addr_display = click.style(organization_addr, fg="yellow") click.echo(f"Organization url: {organization_addr_display}")
async def _bootstrap_organization(debug, device_id, organization_bootstrap_addr, config_dir, force, password): root_signing_key = SigningKey.generate() root_verify_key = root_signing_key.verify_key organization_addr = organization_bootstrap_addr.generate_organization_addr( root_verify_key) device_display = click.style(device_id, fg="yellow") device = generate_new_device(device_id, organization_addr, profile=UserProfile.ADMIN) with operation(f"Creating locally {device_display}"): save_device_with_password(config_dir, device, password, force=force) now = pendulum.now() user_certificate = UserCertificateContent( author=None, timestamp=now, user_id=device.user_id, public_key=device.public_key, profile=device.profile, ) redacted_user_certificate = user_certificate.evolve(human_handle=None) device_certificate = DeviceCertificateContent(author=None, timestamp=now, device_id=device_id, verify_key=device.verify_key) redacted_device_certificate = device_certificate.evolve(device_label=None) user_certificate = user_certificate.dump_and_sign(root_signing_key) device_certificate = device_certificate.dump_and_sign(root_signing_key) redacted_user_certificate = redacted_user_certificate.dump_and_sign( root_signing_key) redacted_device_certificate = redacted_device_certificate.dump_and_sign( root_signing_key) async with spinner(f"Sending {device_display} to server"): async with apiv1_backend_anonymous_cmds_factory( organization_bootstrap_addr) as cmds: await cmds.organization_bootstrap( organization_id=organization_bootstrap_addr.organization_id, bootstrap_token=organization_bootstrap_addr.token, root_verify_key=root_verify_key, user_certificate=user_certificate, device_certificate=device_certificate, redacted_user_certificate=redacted_user_certificate, redacted_device_certificate=redacted_device_certificate, ) organization_addr_display = click.style(organization_addr.to_url(), fg="yellow") click.echo(f"Organization url: {organization_addr_display}")
async def _claim_device(config, organization_addr, new_device_id, token, password): async with spinner("Waiting for referee to reply"): device = await actual_claim_device( organization_addr=organization_addr, new_device_id=new_device_id, token=token, keepalive=config.backend_connection_keepalive, ) device_display = click.style(new_device_id, fg="yellow") with operation(f"Saving locally {device_display}"): save_device_with_password(config.config_dir, device, password)
async def _export_recovery_device(config: CoreConfig, original_device: LocalDevice, output: Path) -> None: async with spinner("Creating new recovery device"): recovery_device = await generate_recovery_device(original_device) file_name = get_recovery_device_file_name(recovery_device) file_path = output / file_name file_path_display = click.style(str(file_path.absolute()), fg="yellow") with operation(f"Saving recovery device file in {file_path_display}"): passphrase = await save_recovery_device(file_path, recovery_device) p1 = click.style("Save the recovery passphrase in a safe place:", fg="red") p2 = click.style(passphrase, fg="green") click.echo(f"{p1} {p2}")
async def _claim_user(config, backend_addr, token, new_device_id, password, pkcs11): async with backend_anonymous_cmds_factory(backend_addr) as cmds: async with spinner("Waiting for referee to reply"): device = await actual_claim_user(cmds, new_device_id, token) device_display = click.style(new_device_id, fg="yellow") with operation(f"Saving locally {device_display}"): if pkcs11: token_id = click.prompt("PCKS11 token id", type=int) key_id = click.prompt("PCKS11 key id", type=int) save_device_with_pkcs11(config.config_dir, device, token_id, key_id) else: save_device_with_password(config.config_dir, device, password)
async def _bootstrap_organization(config, addr, password, force): label = await aprompt("User fullname") email = await aprompt("User email") human_handle = HumanHandle(email=email, label=label) device_label = await aprompt("Device label", default=platform.node()) async with apiv1_backend_anonymous_cmds_factory(addr=addr) as cmds: async with spinner("Bootstrapping organization in the backend"): new_device = await do_bootstrap_organization( cmds=cmds, human_handle=human_handle, device_label=device_label) device_display = click.style(new_device.slughash, fg="yellow") with operation(f"Saving device {device_display}"): save_device_with_password(config_dir=config.config_dir, device=new_device, password=password, force=force)
async def _bootstrap_organization(config, addr, password, device_label, human_label, human_email): if not human_label: human_label = await aprompt("User fullname") if not human_email: human_email = await aprompt("User email") human_handle = HumanHandle(email=human_email, label=human_label) if not device_label: device_label = await aprompt("Device label", default=platform.node()) async with apiv1_backend_anonymous_cmds_factory(addr=addr) as cmds: async with spinner("Bootstrapping organization in the backend"): new_device = await do_bootstrap_organization( cmds=cmds, human_handle=human_handle, device_label=device_label ) device_display = click.style(new_device.slughash, fg="yellow") # We don't have to worry about overwritting an existing keyfile # given their names are base on the device's slughash which is intended # to be globally unique. with operation(f"Saving device {device_display}"): save_device_with_password( config_dir=config.config_dir, device=new_device, password=password )