diff --git a/src/volttron/client/commands/auth_parser.py b/src/volttron/client/commands/auth_parser.py index 8afe36cd0..c79e64ae6 100644 --- a/src/volttron/client/commands/auth_parser.py +++ b/src/volttron/client/commands/auth_parser.py @@ -45,52 +45,50 @@ _stdout = sys.stdout _stderr = sys.stderr - -def gen_keypair(opts): - keypair = KeyStore.generate_keypair_dict() - _stdout.write("{}\n".format(jsonapi.dumps(keypair, indent=2))) - - -def add_server_key(opts): - store = KnownHostsStore() - store.add(opts.host, opts.serverkey) - _stdout.write("server key written to {}\n".format(store.filename)) - - -def list_known_hosts(opts): - store = KnownHostsStore() - entries = store.load() - if entries: - _print_two_columns(entries, "HOST", "CURVE KEY") - else: - _stdout.write("No entries in {}\n".format(store.filename)) - - -def remove_known_host(opts): - store = KnownHostsStore() - store.remove(opts.host) - _stdout.write('host "{}" removed from {}\n'.format(opts.host, store.filename)) - - -def show_serverkey(opts): - """ - write serverkey to standard out. - - return 0 if success, 1 if false - """ - conn = opts.connection - if not conn: - _stderr.write("VOLTTRON is not running. This command " - "requires VOLTTRON platform to be running\n") - return 1 - q = Query(conn.server.core) - pk = q.query("serverkey").get(timeout=2) - del q - if pk is not None: - _stdout.write("%s\n" % pk) - return 0 - - return 1 +# def gen_keypair(opts): +# keypair = KeyStore.generate_keypair_dict() +# _stdout.write("{}\n".format(jsonapi.dumps(keypair, indent=2))) +# +# +# def add_server_key(opts): +# store = KnownHostsStore() +# store.add(opts.host, opts.serverkey) +# _stdout.write("server key written to {}\n".format(store.filename)) +# +# +# def list_known_hosts(opts): +# store = KnownHostsStore() +# entries = store.load() +# if entries: +# _print_two_columns(entries, "HOST", "CURVE KEY") +# else: +# _stdout.write("No entries in {}\n".format(store.filename)) +# +# +# def remove_known_host(opts): +# store = KnownHostsStore() +# store.remove(opts.host) +# _stdout.write('host "{}" removed from {}\n'.format(opts.host, store.filename)) + +# def show_serverkey(opts): +# """ +# write serverkey to standard out. +# +# return 0 if success, 1 if false +# """ +# conn = opts.connection +# if not conn: +# _stderr.write("VOLTTRON is not running. This command " +# "requires VOLTTRON platform to be running\n") +# return 1 +# q = Query(conn.server.core) +# pk = q.query("serverkey").get(timeout=2) +# del q +# if pk is not None: +# _stdout.write("%s\n" % pk) +# return 0 +# +# return 1 def list_remotes(opts): @@ -126,8 +124,7 @@ def list_remotes(opts): # except TimeoutError: # print("Certs timed out") try: - approved_certs = conn.server.vip.rpc.call(AUTH, - "get_approved_authorizations").get(timeout=4) + approved_certs = conn.server.vip.rpc.call(AUTH, "get_approved_authorizations").get(timeout=4) for value in approved_certs: output_view.append({"entry": value, "status": "APPROVED"}) except TimeoutError: @@ -178,8 +175,7 @@ def list_remotes(opts): address_width = max(5, max(len(str(output["entry"]["address"])) for output in output_view)) status_width = max(5, max(len(str(output["status"])) for output in output_view)) fmt = "{:{}} {:{}} {:{}}\n" - _stderr.write( - fmt.format("USER_ID", userid_width, "ADDRESS", address_width, "STATUS", status_width)) + _stderr.write(fmt.format("USER_ID", userid_width, "ADDRESS", address_width, "STATUS", status_width)) fmt = "{:{}} {:{}} {:{}}\n" for output in output_view: _stdout.write( @@ -235,30 +231,33 @@ def delete_remote(opts): conn.server.vip.rpc.call(AUTH, "delete_authorization", opts.user_id).get(timeout=4) -def get_agent_publickey(opts): - - def get_key(agent): - return opts.aip.get_agent_keystore(agent.uuid).public - - _show_filtered_agents(opts, "PUBLICKEY", get_key) +# def get_agent_publickey(opts): +# +# def get_key(agent): +# return opts.aip.get_agent_keystore(agent.uuid).public +# +# _show_filtered_agents(opts, "PUBLICKEY", get_key) def list_auth(opts, indices=None): - conn = opts.connection - if not conn: - _stderr.write("VOLTTRON is not running. This command " - "requires VOLTTRON platform to be running\n") - return + _stdout.write("This method is under development\n") + return - entries = conn.server.vip.rpc.call(AUTH, "auth_file.read").get()["allow_list"] - print_out = [] - if entries: - for index, entry in enumerate(entries): - if indices is None or index in indices: - _stdout.write("\nINDEX: {}\n".format(index)) - _stdout.write("{}\n".format(jsonapi.dumps(entry, indent=2))) - else: - _stdout.write("No entries in {}\n".format(os.path.join(get_home(), "auth.json"))) + # conn = opts.connection + # if not conn: + # _stderr.write("VOLTTRON is not running. This command " + # "requires VOLTTRON platform to be running\n") + # return + # + # entries = conn.server.vip.rpc.call(AUTH, "auth_file.read").get()["allow_list"] + # print_out = [] + # if entries: + # for index, entry in enumerate(entries): + # if indices is None or index in indices: + # _stdout.write("\nINDEX: {}\n".format(index)) + # _stdout.write("{}\n".format(jsonapi.dumps(entry, indent=2))) + # else: + # _stdout.write("No entries in {}\n".format(os.path.join(get_home(), "auth.json"))) def _ask_for_auth_fields( @@ -407,21 +406,14 @@ def add_auth(opts): fields = { "domain": opts.domain, "address": opts.address, - "mechanism": opts.mechanism, - "credentials": opts.credentials, - "user_id": opts.user_id, - "identity": opts.user_id, - "groups": _comma_split(opts.groups), - "roles": _comma_split(opts.roles), - "capabilities": _parse_capabilities(opts.capabilities), - "rpc_method_authorizations": None, - "comments": opts.comments, + "identity": opts.identity, + #"comments": opts.comments, } if any(fields.values()): # Remove unspecified options so the default parameters are used fields = {k: v for k, v in fields.items() if v} - fields["enabled"] = not opts.disabled + #fields["enabled"] = not opts.disabled entry = fields else: # No options were specified, use interactive wizard @@ -429,48 +421,50 @@ def add_auth(opts): responses["rpc_method_authorizations"] = None entry = responses - if opts.add_known_host: - if entry["address"] is None: - raise ValueError("host (--address) is required when " - "--add-known-host is " - "specified") - if entry["credentials"] is None: - raise ValueError("serverkey (--credentials) is required when " - "--add-known-host is specified") - opts.host = entry["address"] - opts.serverkey = entry["credentials"] - add_server_key(opts) + # if opts.add_known_host: + # if entry["address"] is None: + # raise ValueError("host (--address) is required when " + # "--add-known-host is " + # "specified") + # if entry["credentials"] is None: + # raise ValueError("serverkey (--credentials) is required when " + # "--add-known-host is specified") + # opts.host = entry["address"] + # opts.serverkey = entry["credentials"] + # add_server_key(opts) try: - conn.server.vip.rpc.call(AUTH, "auth_file.add", entry).get(timeout=4) - _stdout.write("added entry {}\n".format(entry)) + # TODO: Add more than just identity maybe. + value = conn.server.vip.rpc.call(AUTH, "create_credentials", identity=opts.identity).get(timeout=4) + if value: + _stdout.write("added credentials for {}\n".format(opts.identity)) + else: + _stdout.write(f"Unable to add credentials for {opts.identity}\n") except AuthException as err: _stderr.write("ERROR: %s\n" % str(err)) def remove_auth(opts): + from volttron.client.commands.control import _ask_yes_no conn = opts.connection if not conn: _stderr.write("VOLTTRON is not running. This command " "requires VOLTTRON platform to be running\n") return - entry_count = len(conn.server.vip.rpc.call(AUTH, "auth_file.read").get()["allow_list"]) - - for i in opts.indices: - if i < 0 or i >= entry_count: - _stderr.write("ERROR: invalid index {}\n".format(i)) - return + # + # entry_count = len(conn.server.vip.rpc.call(AUTH, "auth_file.read").get()["allow_list"]) + # + # for i in opts.indices: + # if i < 0 or i >= entry_count: + # _stderr.write("ERROR: invalid index {}\n".format(i)) + # return + _stdout.write(f"This action will remove the identity {opts.identity}\n") - _stdout.write("This action will delete the following:\n") - list_auth(opts, opts.indices) if not _ask_yes_no("Do you wish to delete?"): return try: - conn.server.vip.rpc.call(AUTH, "auth_file.remove_by_indices", opts.indices) - if len(opts.indices) > 1: - msg = "removed entries at indices {}".format(opts.indices) - else: - msg = msg = "removed entry at index {}".format(opts.indices) + conn.server.vip.rpc.call(AUTH, "remove_credentials", identity=opts.identity) + msg = f"{opts.identity} removed!" _stdout.write(msg + "\n") except AuthException as err: _stderr.write("ERROR: %s\n" % str(err)) @@ -636,8 +630,7 @@ def add_agent_rpc_authorizations(opts): return added_auths = [x for x in opts.pattern[1:]] try: - conn.server.vip.rpc.call(AUTH, "add_rpc_authorizations", agent_id, agent_method, - added_auths).get(timeout=4) + conn.server.vip.rpc.call(AUTH, "add_rpc_authorizations", agent_id, agent_method, added_auths).get(timeout=4) except TimeoutError: _log.error(f"Adding RPC authorizations {added_auths} for {agent_id}'s " f"method {agent_method} timed out") @@ -681,285 +674,289 @@ def remove_agent_rpc_authorizations(opts): def add_auth_parser(add_parser_fn, filterable): - auth_cmds = add_parser_fn("auth", help="manage authorization entries and encryption keys") + """ + This method should only be called if there is an auth service available otherwise + this function will fail. + + :param add_parser_fn: + :param filterable: + :return: + """ + auth_cmds = add_parser_fn("auth", help="manage agent credentials") - auth_subparsers = auth_cmds.add_subparsers(title="subcommands", - metavar="", - dest="store_commands") + auth_subparsers = auth_cmds.add_subparsers(title="subcommands", metavar="", dest="store_commands") - auth_add = add_parser_fn("add", - help="add new authentication record", - subparser=auth_subparsers) + auth_add = add_parser_fn("add", help="add new credentials", subparser=auth_subparsers) + auth_add.add_argument("identity", help="Agent identity to add credentials for.") auth_add.add_argument("--domain", default=None) - auth_add.add_argument("--agent-address", default=None) - auth_add.add_argument("--mechanism", default=None) - auth_add.add_argument("--credentials", default=None) - auth_add.add_argument("--user_id", default=None) - auth_add.add_argument("--identity", default=None) - auth_add.add_argument("--groups", default=None, help="delimit multiple entries with comma") - auth_add.add_argument("--roles", default=None, help="delimit multiple entries with comma") - auth_add.add_argument("--capabilities", - default=None, - help="delimit multiple entries with comma") - auth_add.add_argument("--comments", default=None) - auth_add.add_argument("--disabled", action="store_true") - auth_add.add_argument("--add-known-host", action="store_true", help="adds entry in known host") + # auth_add.add_argument("--agent-address", default=None) + # auth_add.add_argument("--mechanism", default=None) + # auth_add.add_argument("--credentials", default=None) + # auth_add.add_argument("--user_id", default=None) + # auth_add.add_argument("--identity", default=None) + #auth_add.add_argument("--groups", default=None, help="delimit multiple entries with comma") + #auth_add.add_argument("--roles", default=None, help="delimit multiple entries with comma") + # auth_add.add_argument("--capabilities", + # default=None, + # help="delimit multiple entries with comma") + # auth_add.add_argument("--comments", default=None) + # auth_add.add_argument("--disabled", action="store_true") + # auth_add.add_argument("--add-known-host", action="store_true", help="adds entry in known host") auth_add.set_defaults(func=add_auth) - auth_add_group = add_parser_fn( - "add-group", - subparser=auth_subparsers, - help="associate a group name with a set of roles", - ) - auth_add_group.add_argument("group", metavar="GROUP", help="name of group") - auth_add_group.add_argument("roles", - metavar="ROLE", - nargs="*", - help="roles to associate with the group") - auth_add_group.set_defaults(func=add_group) - - auth_add_known_host = add_parser_fn( - "add-known-host", - subparser=auth_subparsers, - help="add server public key to known-hosts file", - ) - auth_add_known_host.add_argument("--host", - required=True, - help="hostname or IP address with optional port") - auth_add_known_host.add_argument("--serverkey", required=True) - auth_add_known_host.set_defaults(func=add_server_key) - - auth_add_role = add_parser_fn( - "add-role", - subparser=auth_subparsers, - help="associate a role name with a set of capabilities", - ) - auth_add_role.add_argument("role", metavar="ROLE", help="name of role") - auth_add_role.add_argument( - "capabilities", - metavar="CAPABILITY", - nargs="*", - help="capabilities to associate with the role", - ) - auth_add_role.set_defaults(func=add_role) - - auth_keypair = add_parser_fn( - "keypair", - subparser=auth_subparsers, - help="generate CurveMQ keys for encrypting VIP connections", - ) - auth_keypair.set_defaults(func=gen_keypair) - - auth_list = add_parser_fn("list", - help="list authentication records", - subparser=auth_subparsers) + # auth_add_group = add_parser_fn( + # "add-group", + # subparser=auth_subparsers, + # help="associate a group name with a set of roles", + # ) + # auth_add_group.add_argument("group", metavar="GROUP", help="name of group") + # auth_add_group.add_argument("roles", + # metavar="ROLE", + # nargs="*", + # help="roles to associate with the group") + # auth_add_group.set_defaults(func=add_group) + # + # auth_add_known_host = add_parser_fn( + # "add-known-host", + # subparser=auth_subparsers, + # help="add server public key to known-hosts file", + # ) + # auth_add_known_host.add_argument("--host", + # required=True, + # help="hostname or IP address with optional port") + # auth_add_known_host.add_argument("--serverkey", required=True) + # auth_add_known_host.set_defaults(func=add_server_key) + # + # auth_add_role = add_parser_fn( + # "add-role", + # subparser=auth_subparsers, + # help="associate a role name with a set of capabilities", + # ) + # auth_add_role.add_argument("role", metavar="ROLE", help="name of role") + # auth_add_role.add_argument( + # "capabilities", + # metavar="CAPABILITY", + # nargs="*", + # help="capabilities to associate with the role", + # ) + # auth_add_role.set_defaults(func=add_role) + # + # auth_keypair = add_parser_fn( + # "keypair", + # subparser=auth_subparsers, + # help="generate CurveMQ keys for encrypting VIP connections", + # ) + # auth_keypair.set_defaults(func=gen_keypair) + + auth_list = add_parser_fn("list", help="list authentication records", subparser=auth_subparsers) auth_list.set_defaults(func=list_auth) - auth_list_groups = add_parser_fn( - "list-groups", - subparser=auth_subparsers, - help="show list of group names and their sets of roles", - ) - auth_list_groups.set_defaults(func=list_groups) - - auth_list_known_host = add_parser_fn( - "list-known-hosts", - subparser=auth_subparsers, - help="list entries from known-hosts file", - ) - auth_list_known_host.set_defaults(func=list_known_hosts) - - auth_list_roles = add_parser_fn( - "list-roles", - subparser=auth_subparsers, - help="show list of role names and their sets of capabilities", - ) - auth_list_roles.set_defaults(func=list_roles) - - auth_publickey = add_parser_fn( - "publickey", - parents=[filterable], - subparser=auth_subparsers, - help="show public key for each agent", - ) - auth_publickey.add_argument("pattern", nargs="*", help="UUID or name of agent") - auth_publickey.add_argument( - "-n", - dest="min_uuid_len", - type=int, - metavar="N", - help="show at least N characters of UUID (0 to show all)", - ) - auth_publickey.set_defaults(func=get_agent_publickey, min_uuid_len=1) + # auth_list_groups = add_parser_fn( + # "list-groups", + # subparser=auth_subparsers, + # help="show list of group names and their sets of roles", + # ) + # auth_list_groups.set_defaults(func=list_groups) + # + # auth_list_known_host = add_parser_fn( + # "list-known-hosts", + # subparser=auth_subparsers, + # help="list entries from known-hosts file", + # ) + # auth_list_known_host.set_defaults(func=list_known_hosts) + + # auth_list_roles = add_parser_fn( + # "list-roles", + # subparser=auth_subparsers, + # help="show list of role names and their sets of capabilities", + # ) + # auth_list_roles.set_defaults(func=list_roles) + # + # auth_publickey = add_parser_fn( + # "publickey", + # parents=[filterable], + # subparser=auth_subparsers, + # help="show public key for each agent", + # ) + # auth_publickey.add_argument("pattern", nargs="*", help="UUID or name of agent") + # auth_publickey.add_argument( + # "-n", + # dest="min_uuid_len", + # type=int, + # metavar="N", + # help="show at least N characters of UUID (0 to show all)", + # ) + # auth_publickey.set_defaults(func=get_agent_publickey, min_uuid_len=1) auth_remove = add_parser_fn( "remove", subparser=auth_subparsers, help="removes one or more authentication records by indices", ) - auth_remove.add_argument("indices", - nargs="+", - type=int, - help="index or indices of record(s) to remove") + auth_remove.add_argument("identity", help="Remove the identity from the credentials store.") + # auth_remove.add_argument("indices", + # nargs="+", + # type=int, + # help="index or indices of record(s) to remove") auth_remove.set_defaults(func=remove_auth) - auth_remove_group = add_parser_fn( - "remove-group", - subparser=auth_subparsers, - help="disassociate a group name from a set of roles", - ) - auth_remove_group.add_argument("group", help="name of group") - auth_remove_group.set_defaults(func=remove_group) - - auth_remove_known_host = add_parser_fn( - "remove-known-host", - subparser=auth_subparsers, - help="remove entry from known-hosts file", - ) - auth_remove_known_host.add_argument("host", - metavar="HOST", - help="hostname or IP address with optional port") - auth_remove_known_host.set_defaults(func=remove_known_host) - - auth_remove_role = add_parser_fn( - "remove-role", - subparser=auth_subparsers, - help="disassociate a role name from a set of capabilities", - ) - auth_remove_role.add_argument("role", help="name of role") - auth_remove_role.set_defaults(func=remove_role) - - auth_serverkey = add_parser_fn( - "serverkey", - subparser=auth_subparsers, - help="show the serverkey for the instance", - ) - auth_serverkey.set_defaults(func=show_serverkey) - - auth_update = add_parser_fn( - "update", - subparser=auth_subparsers, - help="updates one authentication record by index", - ) - auth_update.add_argument("index", type=int, help="index of record to update") - auth_update.set_defaults(func=update_auth) - - auth_update_group = add_parser_fn( - "update-group", - subparser=auth_subparsers, - help="update group to include (or remove) given roles", - ) - auth_update_group.add_argument("group", metavar="GROUP", help="name of group") - auth_update_group.add_argument( - "roles", - nargs="*", - metavar="ROLE", - help="roles to append to (or remove from) the group", - ) - auth_update_group.add_argument("--remove", - action="store_true", - help="remove (rather than append) given roles") - auth_update_group.set_defaults(func=update_group) - - auth_update_role = add_parser_fn( - "update-role", - subparser=auth_subparsers, - help="update role to include (or remove) given capabilities", - ) - auth_update_role.add_argument("role", metavar="ROLE", help="name of role") - auth_update_role.add_argument( - "capabilities", - nargs="*", - metavar="CAPABILITY", - help="capabilities to append to (or remove from) the role", - ) - auth_update_role.add_argument( - "--remove", - action="store_true", - help="remove (rather than append) given capabilities", - ) - auth_update_role.set_defaults(func=update_role) - - auth_remote = add_parser_fn( - "remote", - subparser=auth_subparsers, - help="manage pending RMQ certs and ZMQ credentials", - ) - auth_remote_subparsers = auth_remote.add_subparsers(title="remote subcommands", - metavar="", - dest="store_commands") - - auth_remote_list_cmd = add_parser_fn( - "list", - subparser=auth_remote_subparsers, - help="lists approved, denied, and pending certs and credentials", - ) - auth_remote_list_cmd.add_argument("--status", help="Specify approved, denied, or pending") - auth_remote_list_cmd.set_defaults(func=list_remotes) - - auth_remote_approve_cmd = add_parser_fn( - "approve", - subparser=auth_remote_subparsers, - help="approves pending or denied remote connection", - ) - auth_remote_approve_cmd.add_argument( - "user_id", help="user_id or identity of pending credential or cert to approve") - auth_remote_approve_cmd.set_defaults(func=approve_remote) - - auth_remote_deny_cmd = add_parser_fn( - "deny", - subparser=auth_remote_subparsers, - help="denies pending or denied remote connection", - ) - auth_remote_deny_cmd.add_argument( - "user_id", help="user_id or identity of pending credential or cert to deny") - auth_remote_deny_cmd.set_defaults(func=deny_remote) - - auth_remote_delete_cmd = add_parser_fn( - "delete", - subparser=auth_remote_subparsers, - help="approves pending or denied remote connection", - ) - auth_remote_delete_cmd.add_argument( - "user_id", help="user_id or identity of pending credential or cert to delete") - auth_remote_delete_cmd.set_defaults(func=delete_remote) - - auth_rpc = add_parser_fn("rpc", - subparser=auth_subparsers, - help="Manage rpc method authorizations") - - auth_rpc_subparsers = auth_rpc.add_subparsers(title="subcommands", - metavar="", - dest="store_commands") - auth_rpc_add = add_parser_fn("add", - subparser=auth_rpc_subparsers, - help="adds rpc method authorizations") - - auth_rpc_add.add_argument( - "pattern", - nargs="*", - help="Identity of agent and method, followed " - "by capabilities. " - "Should be in the format: " - "agent_id.method authorized_capability1 " - "authorized_capability2 ...", - ) - auth_rpc_add.set_defaults(func=add_agent_rpc_authorizations, min_uuid_len=1) - - auth_rpc_remove = add_parser_fn( - "remove", - subparser=auth_rpc_subparsers, - help="removes rpc method authorizations", - ) - - auth_rpc_remove.add_argument( - "pattern", - nargs="*", - help="Identity of agent and method, " - "followed by capabilities. " - "Should be in the format: " - "agent_id.method " - "authorized_capability1 " - "authorized_capability2 ...", - ) - auth_rpc_remove.set_defaults(func=remove_agent_rpc_authorizations, min_uuid_len=1) + # auth_remove_group = add_parser_fn( + # "remove-group", + # subparser=auth_subparsers, + # help="disassociate a group name from a set of roles", + # ) + # auth_remove_group.add_argument("group", help="name of group") + # auth_remove_group.set_defaults(func=remove_group) + # + # auth_remove_known_host = add_parser_fn( + # "remove-known-host", + # subparser=auth_subparsers, + # help="remove entry from known-hosts file", + # ) + # auth_remove_known_host.add_argument("host", + # metavar="HOST", + # help="hostname or IP address with optional port") + # auth_remove_known_host.set_defaults(func=remove_known_host) + + # auth_remove_role = add_parser_fn( + # "remove-role", + # subparser=auth_subparsers, + # help="disassociate a role name from a set of capabilities", + # ) + # auth_remove_role.add_argument("role", help="name of role") + # auth_remove_role.set_defaults(func=remove_role) + # + # auth_serverkey = add_parser_fn( + # "serverkey", + # subparser=auth_subparsers, + # help="show the serverkey for the instance", + # ) + # auth_serverkey.set_defaults(func=show_serverkey) + + # auth_update = add_parser_fn( + # "update", + # subparser=auth_subparsers, + # help="updates one authentication record by index", + # ) + # auth_update.add_argument("index", type=int, help="index of record to update") + # auth_update.set_defaults(func=update_auth) + # + # auth_update_group = add_parser_fn( + # "update-group", + # subparser=auth_subparsers, + # help="update group to include (or remove) given roles", + # ) + # auth_update_group.add_argument("group", metavar="GROUP", help="name of group") + # auth_update_group.add_argument( + # "roles", + # nargs="*", + # metavar="ROLE", + # help="roles to append to (or remove from) the group", + # ) + # auth_update_group.add_argument("--remove", + # action="store_true", + # help="remove (rather than append) given roles") + # auth_update_group.set_defaults(func=update_group) + # + # auth_update_role = add_parser_fn( + # "update-role", + # subparser=auth_subparsers, + # help="update role to include (or remove) given capabilities", + # ) + # auth_update_role.add_argument("role", metavar="ROLE", help="name of role") + # auth_update_role.add_argument( + # "capabilities", + # nargs="*", + # metavar="CAPABILITY", + # help="capabilities to append to (or remove from) the role", + # ) + # auth_update_role.add_argument( + # "--remove", + # action="store_true", + # help="remove (rather than append) given capabilities", + # ) + # auth_update_role.set_defaults(func=update_role) + + # auth_remote = add_parser_fn( + # "remote", + # subparser=auth_subparsers, + # help="manage pending RMQ certs and ZMQ credentials", + # ) + # auth_remote_subparsers = auth_remote.add_subparsers(title="remote subcommands", + # metavar="", + # dest="store_commands") + # + # auth_remote_list_cmd = add_parser_fn( + # "list", + # subparser=auth_remote_subparsers, + # help="lists approved, denied, and pending certs and credentials", + # ) + # auth_remote_list_cmd.add_argument("--status", help="Specify approved, denied, or pending") + # auth_remote_list_cmd.set_defaults(func=list_remotes) + # + # auth_remote_approve_cmd = add_parser_fn( + # "approve", + # subparser=auth_remote_subparsers, + # help="approves pending or denied remote connection", + # ) + # auth_remote_approve_cmd.add_argument( + # "user_id", help="user_id or identity of pending credential or cert to approve") + # auth_remote_approve_cmd.set_defaults(func=approve_remote) + # + # auth_remote_deny_cmd = add_parser_fn( + # "deny", + # subparser=auth_remote_subparsers, + # help="denies pending or denied remote connection", + # ) + # auth_remote_deny_cmd.add_argument( + # "user_id", help="user_id or identity of pending credential or cert to deny") + # auth_remote_deny_cmd.set_defaults(func=deny_remote) + # + # auth_remote_delete_cmd = add_parser_fn( + # "delete", + # subparser=auth_remote_subparsers, + # help="approves pending or denied remote connection", + # ) + # auth_remote_delete_cmd.add_argument( + # "user_id", help="user_id or identity of pending credential or cert to delete") + # auth_remote_delete_cmd.set_defaults(func=delete_remote) + + # auth_rpc = add_parser_fn("rpc", + # subparser=auth_subparsers, + # help="Manage rpc method authorizations") + # + # auth_rpc_subparsers = auth_rpc.add_subparsers(title="subcommands", + # metavar="", + # dest="store_commands") + # auth_rpc_add = add_parser_fn("add", + # subparser=auth_rpc_subparsers, + # help="adds rpc method authorizations") + # + # auth_rpc_add.add_argument( + # "pattern", + # nargs="*", + # help="Identity of agent and method, followed " + # "by capabilities. " + # "Should be in the format: " + # "agent_id.method authorized_capability1 " + # "authorized_capability2 ...", + # ) + # auth_rpc_add.set_defaults(func=add_agent_rpc_authorizations, min_uuid_len=1) + # + # auth_rpc_remove = add_parser_fn( + # "remove", + # subparser=auth_rpc_subparsers, + # help="removes rpc method authorizations", + # ) + # + # auth_rpc_remove.add_argument( + # "pattern", + # nargs="*", + # help="Identity of agent and method, " + # "followed by capabilities. " + # "Should be in the format: " + # "agent_id.method " + # "authorized_capability1 " + # "authorized_capability2 ...", + # ) + # auth_rpc_remove.set_defaults(func=remove_agent_rpc_authorizations, min_uuid_len=1) diff --git a/src/volttron/client/commands/control.py b/src/volttron/client/commands/control.py index 3ef98db1d..433db9573 100644 --- a/src/volttron/client/commands/control.py +++ b/src/volttron/client/commands/control.py @@ -144,9 +144,7 @@ def escape(pattern): if len(strings) == 1: return re.escape(pattern), False return ( - "".join( - ".*" if s == "*" else "." if s == "?" else s if s in [r"\?", r"\*"] else re.escape(s) - for s in strings), + "".join(".*" if s == "*" else "." if s == "?" else s if s in [r"\?", r"\*"] else re.escape(s) for s in strings), True, ) @@ -264,8 +262,7 @@ def remove_agent(opts, remove_auth=True): if not match: _stderr.write("{}: error: agent not found: {}\n".format(opts.command, pattern)) elif len(match) > 1 and not opts.force: - _stderr.write("{}: error: pattern returned multiple agents: {}\n".format( - opts.command, pattern)) + _stderr.write("{}: error: pattern returned multiple agents: {}\n".format(opts.command, pattern)) _stderr.write("Use -f or --force to force removal of multiple agents.\n") return 10 for agent in match: @@ -481,8 +478,7 @@ def list_remotes(opts): except TimeoutError: print("Certs timed out") try: - approved_certs = conn.server.vip.rpc.call(AUTH, - "get_authorization_approved").get(timeout=4) + approved_certs = conn.server.vip.rpc.call(AUTH, "get_authorization_approved").get(timeout=4) for value in approved_certs: output_view.append({"entry": value, "status": "APPROVED"}) except TimeoutError: @@ -514,9 +510,7 @@ def list_remotes(opts): output_view = [output for output in output_view if output["status"] == "PENDING"] elif opts.status is not None: - _stdout.write( - "Invalid parameter. Please use 'approved', 'denied', 'pending', or leave blank to list all.\n" - ) + _stdout.write("Invalid parameter. Please use 'approved', 'denied', 'pending', or leave blank to list all.\n") return if len(output_view) == 0: @@ -532,15 +526,14 @@ def list_remotes(opts): address_width = max(5, max(len(str(output["entry"]["address"])) for output in output_view)) status_width = max(5, max(len(str(output["status"])) for output in output_view)) fmt = "{:{}} {:{}} {:{}}\n" - _stderr.write( - fmt.format( - "USER_ID", - userid_width, - "ADDRESS", - address_width, - "STATUS", - status_width, - )) + _stderr.write(fmt.format( + "USER_ID", + userid_width, + "ADDRESS", + address_width, + "STATUS", + status_width, + )) fmt = "{:{}} {:{}} {:{}}\n" for output in output_view: _stdout.write( @@ -610,14 +603,12 @@ def update_health_cache(opts): t_now = datetime.now() do_update = True # Make sure we update if we don't have any health dicts, or if the cache has timed out. - if (health_cache_timeout_date is not None and t_now < health_cache_timeout_date - and health_cache): + if (health_cache_timeout_date is not None and t_now < health_cache_timeout_date and health_cache): do_update = False if do_update: health_cache.clear() - response = opts.connection.server.vip.rpc.call(PLATFORM_HEALTH, - "get_platform_health").get(timeout=4) + response = opts.connection.server.vip.rpc.call(PLATFORM_HEALTH, "get_platform_health").get(timeout=4) health_cache.update(response) health_cache_timeout_date = datetime.now() + timedelta(seconds=health_cache_timeout) @@ -638,10 +629,7 @@ def status_agents(opts): print(f"agent is {agent}") all_agents[uuid] = agent except KeyError: - all_agents[uuid] = AgentMeta(name=name, - uuid=uuid, - identity=identity, - agent_user=agent_user) + all_agents[uuid] = AgentMeta(name=name, uuid=uuid, identity=identity, agent_user=agent_user) status[uuid] = stat all_agents = list(all_agents.values()) @@ -1387,11 +1375,7 @@ def _show_filtered_agents(opts, field_name, field_callback, agents=None): _stdout.write(f"{jsonapi.dumps(json_obj, indent=2)}\n") -def _show_filtered_agents_status(opts, - status_callback, - health_callback, - priority_callback, - agents=None): +def _show_filtered_agents_status(opts, status_callback, health_callback, priority_callback, agents=None): """Provides generic way to filter and display agent information. The agents will be filtered by the provided opts.pattern and the @@ -1516,8 +1500,7 @@ def _show_filtered_agents_status(opts, } if cc.is_secure_mode(): json_obj[agent.vip_identity]["agent_user"] = ( - agent.agent_user - if json_obj[agent.vip_identity]["status"].startswith("running") else "") + agent.agent_user if json_obj[agent.vip_identity]["status"].startswith("running") else "") _stdout.write(f"{jsonapi.dumps(json_obj, indent=2)}\n") @@ -1640,8 +1623,7 @@ def edit_config(opts): # subprocess.PIPE subprocess.check_call([opts.editor, f.name]) except subprocess.CalledProcessError as e: - _stderr.write("Editor returned with code {}. Changes not committed.\n".format( - e.returncode)) + _stderr.write("Editor returned with code {}. Changes not committed.\n".format(e.returncode)) success = False if not success: @@ -2180,15 +2162,13 @@ def main(): "--name", dest="by_name", action="store_true", - help= - "filter/search by agent name. value passed should be quoted if it contains a regular expression", + help="filter/search by agent name. value passed should be quoted if it contains a regular expression", ) filterable.add_argument( "--tag", dest="by_tag", action="store_true", - help= - "filter/search by tag name. value passed should be quoted if it contains a regular expression", + help="filter/search by tag name. value passed should be quoted if it contains a regular expression", ) filterable.add_argument("--all-tagged", dest="by_all_tagged", @@ -2198,8 +2178,7 @@ def main(): "--uuid", dest="by_uuid", action="store_true", - help= - "filter/search by UUID (default). value passed should be quoted if it contains a regular expression", + help="filter/search by UUID (default). value passed should be quoted if it contains a regular expression", ) filterable.set_defaults(by_name=False, by_tag=False, by_all_tagged=False, by_uuid=False) parser = config.ArgumentParser( @@ -2276,6 +2255,7 @@ def add_parser(*args, **kwargs) -> argparse.ArgumentParser: add_install_agent_parser(add_parser) add_rpc_agent_parser(add_parser) + add_auth_parser(add_parser, filterable=filterable) add_authz_parser(add_parser, filterable=filterable) add_config_store_parser(add_parser) @@ -2299,10 +2279,7 @@ def add_parser(*args, **kwargs) -> argparse.ArgumentParser: peers = add_parser("peerlist", help="list the peers connected to the platform") peers.set_defaults(func=list_peers) - status = add_parser("status", - aliases=("list", ), - parents=[filterable], - help="show status of agents") + status = add_parser("status", aliases=("list", ), parents=[filterable], help="show status of agents") status.add_argument("pattern", nargs="*", help="UUID or name of agent") status.add_argument( "-n", @@ -2453,8 +2430,7 @@ def add_parser(*args, **kwargs) -> argparse.ArgumentParser: print_tb = exc.print_tb error = exc.message except AttributeError as exc: - _stderr.write("Invalid command: '{}' or command requires additional arguments\n".format( - opts.command)) + _stderr.write("Invalid command: '{}' or command requires additional arguments\n".format(opts.command)) parser.print_help() return 1 # raised during install if wheel not found. diff --git a/src/volttron/server/aip.py b/src/volttron/server/aip.py index b2f5310e7..cba080e29 100644 --- a/src/volttron/server/aip.py +++ b/src/volttron/server/aip.py @@ -236,8 +236,11 @@ def __call__(self, *args, **kwargs): class AIPplatform: """Manages the main workflow of receiving and sending agents.""" - def __init__(self, server_opts: ServerOptions, auth_service: AuthService | None, - credentials_store: CredentialsStore, **kwargs): + def __init__(self, + server_opts: ServerOptions, + auth_service: AuthService | None = None, + credentials_store: CredentialsStore | None = None, + **kwargs): self._server_opts = server_opts self._auth_service = auth_service self._credentials_store = credentials_store diff --git a/src/volttron/server/run_server.py b/src/volttron/server/run_server.py index 8da29b4db..ac1e24e38 100644 --- a/src/volttron/server/run_server.py +++ b/src/volttron/server/run_server.py @@ -273,10 +273,6 @@ def start_volttron_process(options: ServerOptions): address = "inproc://vip" pid_file = os.path.join(opts.volttron_home.as_posix(), "VOLTTRON_PID") try: - protected_topics = {} - proxy_router = None - proxy_router_task = None - _log.debug("********************************************************************") _log.debug("VOLTTRON PLATFORM RUNNING ON {} MESSAGEBUS".format(opts.messagebus)) _log.debug("********************************************************************") @@ -328,6 +324,7 @@ def start_volttron_process(options: ServerOptions): from volttron.types import MessageBus + # A message bus is required, if we don't have one installed then this will definitely fail. mb: MessageBus = service_repo.resolve(MessageBus) class StopHandler(MessageBusStopHandler): @@ -349,8 +346,6 @@ def message_bus_shutdown(self): assert mb.is_running() - # TODO Better make this so that it removes instances from this file or it will just be an - # ever increasing file depending on the number of instances it could get quite large. # The instance file is where we are going to record the instance and # its details according to if VOLTTRON_INSTANCES_PATH.is_file(): @@ -372,14 +367,13 @@ def message_bus_shutdown(self): this_instance = instances.get(opts.volttron_home.as_posix(), {}) this_instance["pid"] = os.getpid() this_instance["version"] = get_version() + # note vip_address is a list this_instance["address"] = opts.address this_instance["volttron-home"] = opts.volttron_home.as_posix() this_instance["start-args"] = sys.argv[1:] instances[opts.volttron_home.as_posix()] = this_instance - # protected_topics_file = os.path.join(opts.volttron_home, "protected_topics.json") - # _log.debug("protected topics file %s", protected_topics_file) external_address_file = os.path.join(opts.volttron_home, "external_address.json") _log.debug("external_address_file file %s", external_address_file) @@ -430,8 +424,6 @@ def message_bus_shutdown(self): _log.info("SIGINT received; shutting down") finally: sys.stderr.write("Shutting down.\n") - if proxy_router_task: - proxy_router.core.stop() _log.debug("Kill all service agent tasks") for task in spawned_greenlets: task.kill(block=False) diff --git a/src/volttron/services/control/control_service.py b/src/volttron/services/control/control_service.py index 2aa63062c..0e96100dd 100644 --- a/src/volttron/services/control/control_service.py +++ b/src/volttron/services/control/control_service.py @@ -185,12 +185,12 @@ def peerlist(self): peer_list = self.vip.peerlist().get(timeout=5) return peer_list - @RPC.export - def serverkey(self): - q = Query(self.core) - pk = q.query("serverkey").get(timeout=1) - del q - return pk + # @RPC.export + # def serverkey(self): + # q = Query(self.core) + # pk = q.query("serverkey").get(timeout=1) + # del q + # return pk @RPC.export def clear_status(self, clear_all=False): @@ -309,12 +309,9 @@ def remove_agent(self, uuid, remove_auth=True): "got {!r} from identity: {}".format(type(uuid).__name__, identity)) identity = self.agent_vip_identity(uuid) - # Because we are using send_vip we should pass frames that have - # bytes rather than - # strings. frames = [identity] - # Send message to router that agent is shutting down + # Send message to router that agent needs to shut down self.core.connection.send_vip("", "agentstop", args=frames) self._aip.remove_agent(uuid, remove_auth=remove_auth) @@ -344,28 +341,28 @@ def agent_vip_identity(self, uuid): # TODO: Have an accessor wrapper around this. return self._aip._uuid_vip_id_map[uuid] - @RPC.export - def get_all_agent_publickeys(self): - """ - RPC method to retrieve the public keys of all the agents installed - on the VOLTTRON instance. - - This method does not differentiate between running and not running - agents. - - .. note:: - - This method will only retrieve a publickey for an installed agents. - It is recommended that dynamic agents use the context of the - containing agent's publickey for connections to external instances. - - :return: mapping of identity to agent publickey - :rtype: dict - """ - result = {} - for vip_identity in self._aip._vip_id_uuid_map: - result[vip_identity] = self._aip.__get_agent_keystore__(vip_identity).public - return result + # @RPC.export + # def get_all_agent_publickeys(self): + # """ + # RPC method to retrieve the public keys of all the agents installed + # on the VOLTTRON instance. + # + # This method does not differentiate between running and not running + # agents. + # + # .. note:: + # + # This method will only retrieve a publickey for an installed agents. + # It is recommended that dynamic agents use the context of the + # containing agent's publickey for connections to external instances. + # + # :return: mapping of identity to agent publickey + # :rtype: dict + # """ + # result = {} + # for vip_identity in self._aip._vip_id_uuid_map: + # result[vip_identity] = self._aip.__get_agent_keystore__(vip_identity).public + # return result @RPC.export def identity_exists(self, identity): @@ -381,110 +378,110 @@ def identity_exists(self, identity): # with open("wheel.whl", 'wb') as fp: # fp.write(base64.b64decode(wheel['data'])) - @RPC.export - def install_agent_from_message_bus(self, - agent: str, - topic: str, - response_topic: str, - credentials: Credentials, - force: bool = False, - pre_release: bool = False, - agent_config: str = None): - """ - Install the agent through the rmq message bus. - """ - if isinstance(credentials, dict): - credentials = Credentials.from_dict(credentials) - peer = self.vip.rpc.context.vip_message.peer - protocol_request_size = 16 - protocol_message = None - protocol_headers = None - response_received = False - - def protocol_subscription(peer, sender, bus, topic, headers, message): - nonlocal protocol_message, protocol_headers, response_received - _log.debug(f"Received topic, message topic {topic}, {message}") - protocol_message = message - protocol_message = base64.b64decode(protocol_message.encode("utf-8")) - protocol_headers = headers - response_received = True - - #self._raise_error_if_identity_exists_without_force(vip_identity, force) - # if not agent.endswith(".whl"): - # # agent passed is package name to install from pypi. - # return self._aip.install_agent(agent, vip_identity, agent_config, force, pre_release) - - # Else it is a .whl file that needs to be transferred from client to server before calling aip.install_agent - tmpdir = None - try: - tmpdir = tempfile.mkdtemp() - path = os.path.join(tmpdir, os.path.basename(agent)) - store = open(path, "wb") - sha512 = hashlib.sha512() - - try: - request_checksum = base64.b64encode(jsonapi.dumps(["checksum"]).encode("utf-8")).decode("utf-8") - request_fetch = base64.b64encode(jsonapi.dumps(["fetch", - protocol_request_size]).encode("utf-8")).decode("utf-8") - - _log.debug(f"Server subscribing to {topic}") - self.vip.pubsub.subscribe(peer="pubsub", prefix=topic, callback=protocol_subscription).get(timeout=5) - gevent.sleep(5) - while True: - - _log.debug(f"Requesting data {request_fetch} sending to " - f"{response_topic}") - response_received = False - - # request a chunk of the file - self.vip.pubsub.publish("pubsub", topic=response_topic, message=request_fetch) - gevent.sleep(1) - # chunk binary representation of the bytes read from - # the other side of the connection - with gevent.Timeout(30): - _log.debug("Waiting for chunk") - while not response_received: - gevent.sleep(0.1) - - # Chunk will be bytes - chunk = protocol_message - _log.debug(f"chunk received is:\n{chunk}") - if chunk == b"complete": - _log.debug(f"File transfer complete!") - break - - sha512.update(chunk) - store.write(chunk) - - with gevent.Timeout(30): - _log.debug("Requesting checksum") - response_received = False - self.vip.pubsub.publish("pubsub", topic=response_topic, message=request_checksum).get(timeout=5) - - while not response_received: - gevent.sleep(0.1) - - checksum = protocol_message - assert checksum == sha512.digest() - - _log.debug("Outside of while loop in install agent service.") - - except AssertionError: - _log.warning("Checksum mismatch on received file") - raise - except gevent.Timeout: - _log.warning("Gevent timeout trying to receive data") - raise - finally: - store.close() - self.vip.pubsub.unsubscribe("pubsub", response_topic, protocol_subscription) - _log.debug("Unsubscribing on server") - - agent_uuid = self._aip.install_agent(agent, vip_identity, publickey, secretkey, agent_config, force, - pre_release) - return agent_uuid - finally: - shutil.rmtree(tmpdir, ignore_errors=True) + # @RPC.export + # def install_agent_from_message_bus(self, + # agent: str, + # topic: str, + # response_topic: str, + # credentials: Credentials, + # force: bool = False, + # pre_release: bool = False, + # agent_config: str = None): + # """ + # Install the agent through the rmq message bus. + # """ + # if isinstance(credentials, dict): + # credentials = Credentials.from_dict(credentials) + # peer = self.vip.rpc.context.vip_message.peer + # protocol_request_size = 16 + # protocol_message = None + # protocol_headers = None + # response_received = False + # + # def protocol_subscription(peer, sender, bus, topic, headers, message): + # nonlocal protocol_message, protocol_headers, response_received + # _log.debug(f"Received topic, message topic {topic}, {message}") + # protocol_message = message + # protocol_message = base64.b64decode(protocol_message.encode("utf-8")) + # protocol_headers = headers + # response_received = True + # + # #self._raise_error_if_identity_exists_without_force(vip_identity, force) + # # if not agent.endswith(".whl"): + # # # agent passed is package name to install from pypi. + # # return self._aip.install_agent(agent, vip_identity, agent_config, force, pre_release) + # + # # Else it is a .whl file that needs to be transferred from client to server before calling aip.install_agent + # tmpdir = None + # try: + # tmpdir = tempfile.mkdtemp() + # path = os.path.join(tmpdir, os.path.basename(agent)) + # store = open(path, "wb") + # sha512 = hashlib.sha512() + # + # try: + # request_checksum = base64.b64encode(jsonapi.dumps(["checksum"]).encode("utf-8")).decode("utf-8") + # request_fetch = base64.b64encode(jsonapi.dumps(["fetch", + # protocol_request_size]).encode("utf-8")).decode("utf-8") + # + # _log.debug(f"Server subscribing to {topic}") + # self.vip.pubsub.subscribe(peer="pubsub", prefix=topic, callback=protocol_subscription).get(timeout=5) + # gevent.sleep(5) + # while True: + # + # _log.debug(f"Requesting data {request_fetch} sending to " + # f"{response_topic}") + # response_received = False + # + # # request a chunk of the file + # self.vip.pubsub.publish("pubsub", topic=response_topic, message=request_fetch) + # gevent.sleep(1) + # # chunk binary representation of the bytes read from + # # the other side of the connection + # with gevent.Timeout(30): + # _log.debug("Waiting for chunk") + # while not response_received: + # gevent.sleep(0.1) + # + # # Chunk will be bytes + # chunk = protocol_message + # _log.debug(f"chunk received is:\n{chunk}") + # if chunk == b"complete": + # _log.debug(f"File transfer complete!") + # break + # + # sha512.update(chunk) + # store.write(chunk) + # + # with gevent.Timeout(30): + # _log.debug("Requesting checksum") + # response_received = False + # self.vip.pubsub.publish("pubsub", topic=response_topic, message=request_checksum).get(timeout=5) + # + # while not response_received: + # gevent.sleep(0.1) + # + # checksum = protocol_message + # assert checksum == sha512.digest() + # + # _log.debug("Outside of while loop in install agent service.") + # + # except AssertionError: + # _log.warning("Checksum mismatch on received file") + # raise + # except gevent.Timeout: + # _log.warning("Gevent timeout trying to receive data") + # raise + # finally: + # store.close() + # self.vip.pubsub.unsubscribe("pubsub", response_topic, protocol_subscription) + # _log.debug("Unsubscribing on server") + # + # agent_uuid = self._aip.install_agent(agent, vip_identity, publickey, secretkey, agent_config, force, + # pre_release) + # return agent_uuid + # finally: + # shutil.rmtree(tmpdir, ignore_errors=True) @RPC.export def install_agent(self, install_options: AgentInstallOptions | dict) -> str: diff --git a/src/volttron/types/__init__.py b/src/volttron/types/__init__.py index a0df3587e..aa1a2b851 100644 --- a/src/volttron/types/__init__.py +++ b/src/volttron/types/__init__.py @@ -196,7 +196,7 @@ class MessageBus(ABC): _stop_handler: MessageBusStopHandler @abstractmethod - def start(self, options: any): # ServerOptions): + def start(self): # ServerOptions): ... @abstractmethod diff --git a/src/volttron/types/auth/auth_credentials.py b/src/volttron/types/auth/auth_credentials.py index 903c6f4f7..dc051a505 100644 --- a/src/volttron/types/auth/auth_credentials.py +++ b/src/volttron/types/auth/auth_credentials.py @@ -143,7 +143,7 @@ def load_credentials_from_file(path: Path | str) -> Credentials: publickey=obj["publickey"], secretkey=obj["secretkey"]) else: - return Credentials.create(identity=identity) + return Credentials.create(identity=obj["identity"]) class CredentialsCreator(ABC): diff --git a/src/volttron/types/auth/auth_service.py b/src/volttron/types/auth/auth_service.py index 1abcd2946..9c478bbf5 100644 --- a/src/volttron/types/auth/auth_service.py +++ b/src/volttron/types/auth/auth_service.py @@ -59,8 +59,12 @@ def check_pubsub_authorization(self, *, identity: authz.Identity, topic_pattern: ... @abstractmethod - def create_or_merge_role(self, *, name: str, rpc_capabilities: Optional[authz.RPCCapabilities] = None, - pubsub_capabilities: Optional[authz.PubsubCapabilities] = None, **kwargs) -> bool: + def create_or_merge_role(self, + *, + name: str, + rpc_capabilities: Optional[authz.RPCCapabilities] = None, + pubsub_capabilities: Optional[authz.PubsubCapabilities] = None, + **kwargs) -> bool: ... @abstractmethod @@ -146,19 +150,19 @@ def remove_agent(self, *, identity: str, **kwargs) -> bool: ... @abstractmethod - def has_credentials_for(self, *, identity: str) -> bool: + def has_credentials_for(self, *, identity: Identity) -> bool: ... @abstractmethod - def add_credentials(self, *, credentials: Credentials): + def create_credentials(self, *, identity: Identity): ... @abstractmethod - def remove_credentials(self, *, credentials: Credentials): + def remove_credentials(self, *, identity: Identity): ... @abstractmethod - def is_credentials(self, *, identity: str) -> bool: + def is_credentials(self, *, identity: Identity) -> bool: ... # Authorization diff --git a/src/volttron/utils/context.py b/src/volttron/utils/context.py index f74293062..a766e48f7 100644 --- a/src/volttron/utils/context.py +++ b/src/volttron/utils/context.py @@ -44,8 +44,8 @@ class ClientContext: __volttron_home__: Optional[Path] = None __config__: dict = {} - __config_keys__ = ("vip-address", "bind-web-address", "instance-name", "message-bus", - "web-ssl-cert", "web-ssl-key", "web-secret-key", "secure-agent-users") + __config_keys__ = ("vip-address", "bind-web-address", "instance-name", "message-bus", "web-ssl-cert", "web-ssl-key", + "web-secret-key", "secure-agent-users") @classmethod def __load_config__(cls: "ClientContext"): @@ -155,9 +155,9 @@ def get_instance_name(cls): return instance_name @classmethod - def is_web_enabled(cls): - """Returns True if web enabled, False otherwise""" - if cls.get_config_param("bind-web-address"): + def is_auth_enabled(cls): + """Returns True if auth has been installed and is enabled.""" + if cls.get_config_param("auth-enabled"): return True return False @@ -169,12 +169,12 @@ def is_secure_mode(cls): secure_mode = secure_mode.upper() == "TRUE" return secure_mode - @classmethod - def get_agent_keys(cls, vip_id): - from volttron.utils.keystore import KeyStore - keystore_path = os.path.join(cls.get_volttron_home(), "agents", vip_id, "keystore.json") - keystore = KeyStore(keystore_path) - return keystore.public, keystore.secret + # @classmethod + # def get_agent_keys(cls, vip_id): + # from volttron.utils.keystore import KeyStore + # keystore_path = os.path.join(cls.get_volttron_home(), "agents", vip_id, "keystore.json") + # keystore = KeyStore(keystore_path) + # return keystore.public, keystore.secret @classmethod def get_tag_refresh_interval(cls):