Skip to content

Commit

Permalink
Improve keyring creation prompts and warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
KPrasch committed Apr 23, 2021
1 parent e96b1d7 commit d6aad3e
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 12 deletions.
5 changes: 3 additions & 2 deletions nucypher/cli/actions/auth.py
Expand Up @@ -77,13 +77,14 @@ def unlock_signer_account(config: CharacterConfiguration, json_ipc: bool) -> Non
config.signer.unlock_account(account=config.checksum_address, password=__password)


def get_nucypher_password(confirm: bool = False, envvar=NUCYPHER_ENVVAR_KEYRING_PASSWORD) -> str:
def get_nucypher_password(emitter, confirm: bool = False, envvar=NUCYPHER_ENVVAR_KEYRING_PASSWORD) -> str:
"""Interactively collect a nucypher password"""
prompt = COLLECT_NUCYPHER_PASSWORD
if confirm:
from nucypher.config.keyring import NucypherKeyring
emitter.message(f"Ursula keys are locked with a password. Please provide a password. Do not forget this password.")
prompt += f" ({NucypherKeyring.MINIMUM_PASSWORD_LENGTH} character minimum)"
keyring_password = get_password_from_prompt(prompt=prompt, confirm=confirm, envvar=envvar)
keyring_password = get_password_from_prompt(prompt=prompt, confirm=confirm, envvar=envvar)
return keyring_password


Expand Down
2 changes: 1 addition & 1 deletion nucypher/cli/commands/alice.py
Expand Up @@ -206,7 +206,7 @@ def generate_config(self, emitter: StdoutEmitter, config_root: str) -> AliceConf
network=opts.domain)

return AliceConfiguration.generate(
password=get_nucypher_password(confirm=True),
password=get_nucypher_password(emitter=emitter, confirm=True),
config_root=config_root,
checksum_address=pay_with,
domain=opts.domain,
Expand Down
2 changes: 1 addition & 1 deletion nucypher/cli/commands/bob.py
Expand Up @@ -141,7 +141,7 @@ def generate_config(self, emitter: StdoutEmitter, config_root: str) -> BobConfig
provider_uri=self.provider_uri) # TODO: See #1888

return BobConfiguration.generate(
password=get_nucypher_password(confirm=True),
password=get_nucypher_password(emitter=emitter, confirm=True),
config_root=config_root,
checksum_address=checksum_address,
domain=self.domain,
Expand Down
8 changes: 4 additions & 4 deletions nucypher/cli/commands/felix.py
Expand Up @@ -16,10 +16,10 @@
"""


import os

import click
import os

from nucypher.characters.control.emitters import StdoutEmitter
from nucypher.cli.actions.auth import (
get_client_password,
get_nucypher_password,
Expand Down Expand Up @@ -116,7 +116,7 @@ def create_config(self, emitter, config_file):

def generate_config(self, config_root, discovery_port):
return FelixConfiguration.generate(
password=get_nucypher_password(confirm=True),
password=get_nucypher_password(emitter=StdoutEmitter(), confirm=True),
config_root=config_root,
rest_host=self.host,
rest_port=discovery_port,
Expand Down Expand Up @@ -163,7 +163,7 @@ def create_character(self, emitter, config_file, debug):
# Authenticate
unlock_nucypher_keyring(emitter,
character_configuration=felix_config,
password=get_nucypher_password(confirm=False))
password=get_nucypher_password(emitter=emitter, confirm=False))

client_password = get_client_password(checksum_address=felix_config.checksum_address,
envvar=NUCYPHER_ENVVAR_WORKER_ETH_PASSWORD)
Expand Down
4 changes: 3 additions & 1 deletion nucypher/cli/commands/ursula.py
Expand Up @@ -179,7 +179,7 @@ def generate_config(self, emitter, config_root, force):
if not self.rest_host:
self.rest_host = collect_worker_ip_address(emitter, network=self.domain, force=force)

return UrsulaConfiguration.generate(password=get_nucypher_password(confirm=True),
return UrsulaConfiguration.generate(password=get_nucypher_password(emitter=emitter, confirm=True),
config_root=config_root,
rest_host=self.rest_host,
rest_port=self.rest_port,
Expand Down Expand Up @@ -301,6 +301,8 @@ def init(general_config, config_options, force, config_root):
_pre_launch_warnings(emitter, dev=None, force=force)
if not config_root:
config_root = general_config.config_root
if not config_options.federated_only and not config_options.provider_uri:
raise click.BadOptionUsage('--provider', message="--provider is required to initialize a new ursula.")
if not config_options.federated_only and not config_options.domain:
config_options.domain = select_network(emitter)
ursula_config = config_options.generate_config(emitter, config_root, force)
Expand Down
13 changes: 12 additions & 1 deletion nucypher/cli/painting/help.py
Expand Up @@ -55,7 +55,18 @@ def paint_new_installation_help(emitter, new_configuration, filepath):
character_config_class = new_configuration.__class__
character_name = character_config_class.NAME.lower()

emitter.message(f"Generated keyring {new_configuration.keyring_root}", color='green')
emitter.message(f"Generated keyring", color='green')
emitter.message(f"""
Public key (stamp): {bytes(new_configuration.keyring.signing_public_key).hex()}
Path to keyring: {new_configuration.keyring_root}
- You can share your public key with anyone. Others need it to interact with you.
- Never share secret keys with anyone! Character keys are required to interact with the network!
- Backup your keyring! Without the keyring you wil not be able to use existing network policies.
- Remember your password! Without the password, it's impossible to decrypt the key!
""")

default_config_filepath = True
if new_configuration.default_filepath() != filepath:
Expand Down
2 changes: 1 addition & 1 deletion nucypher/cli/utils.py
Expand Up @@ -84,7 +84,7 @@ def make_cli_character(character_config,
if unlock_keyring:
unlock_nucypher_keyring(emitter,
character_configuration=character_config,
password=get_nucypher_password(confirm=False))
password=get_nucypher_password(emitter=emitter, confirm=False))

# Handle Signer/Wallet
if unlock_signer:
Expand Down
3 changes: 2 additions & 1 deletion tests/integration/cli/actions/test_auth_actions.py
Expand Up @@ -21,6 +21,7 @@
from nacl.exceptions import CryptoError

from nucypher.blockchain.eth.decorators import InvalidChecksumAddress
from nucypher.characters.control.emitters import StdoutEmitter
from nucypher.cli.actions.auth import (
get_client_password,
get_nucypher_password,
Expand Down Expand Up @@ -90,7 +91,7 @@ def test_get_client_password(mock_stdin, mock_account, confirm, capsys):
@pytest.mark.parametrize('confirm', (True, False))
def test_get_nucypher_password(mock_stdin, mock_account, confirm, capsys):
mock_stdin.password(INSECURE_DEVELOPMENT_PASSWORD, confirm=confirm)
result = get_nucypher_password(confirm=confirm)
result = get_nucypher_password(emitter=StdoutEmitter(), confirm=confirm)
assert result == INSECURE_DEVELOPMENT_PASSWORD
assert mock_stdin.empty()
captured = capsys.readouterr()
Expand Down

0 comments on commit d6aad3e

Please sign in to comment.