diff --git a/asadm.py b/asadm.py index a492120a..aa43aaba 100755 --- a/asadm.py +++ b/asadm.py @@ -79,6 +79,7 @@ def __init__( ssl_context=None, only_connect_seed=False, execute_only_mode=False, + privileged_mode=False, timeout=5, ): # indicates shell created successfully and connected to cluster/collectinfo/logfile @@ -165,7 +166,10 @@ def __init__( self.set_default_prompt() self.intro = "" - if not execute_only_mode: + if execute_only_mode: + if privileged_mode: + self.ctrl.do_enable([]) + else: self.intro += str(self.ctrl.cluster) + "\n" cluster_visibility_error_nodes = ( self.ctrl.cluster.get_visibility_error_nodes() @@ -636,6 +640,7 @@ def main(): ssl_context=ssl_context, only_connect_seed=cli_args.single_node, execute_only_mode=execute_only_mode, + privileged_mode=cli_args.enable, timeout=cli_args.timeout, ) diff --git a/lib/live_cluster/client/types.py b/lib/live_cluster/client/types.py index 5f7dc287..8582e9cb 100644 --- a/lib/live_cluster/client/types.py +++ b/lib/live_cluster/client/types.py @@ -47,10 +47,13 @@ class ASPrivilege(IntEnum): USER_ADMIN = 0 SYS_ADMIN = 1 DATA_ADMIN = 2 + UDF_ADMIN = 3 + SINDEX_ADMIN = 4 READ = 10 READ_WRITE = 11 READ_WRITE_UDF = 12 WRITE = 13 + TRUNCATE = 14 ERROR = 255 @classmethod @@ -62,10 +65,13 @@ def str_to_enum(cls, privilege_str): "user-admin": cls.USER_ADMIN, "sys-admin": cls.SYS_ADMIN, "data-admin": cls.DATA_ADMIN, + "udf-admin": cls.UDF_ADMIN, + "sindex-admin": cls.SINDEX_ADMIN, "read": cls.READ, "read-write": cls.READ_WRITE, "read-write-udf": cls.READ_WRITE_UDF, "write": cls.WRITE, + "truncate": cls.TRUNCATE, } if privilege_str in str_to_enum_map: @@ -78,6 +84,8 @@ def is_global_only_scope(self): self == ASPrivilege.DATA_ADMIN or self == ASPrivilege.SYS_ADMIN or self == ASPrivilege.USER_ADMIN + or self == ASPrivilege.UDF_ADMIN + or self == ASPrivilege.SINDEX_ADMIN ) def __str__(self): diff --git a/lib/utils/conf.py b/lib/utils/conf.py index 4659cff2..156be728 100644 --- a/lib/utils/conf.py +++ b/lib/utils/conf.py @@ -78,6 +78,7 @@ def __init__(self, adict): "asinfo-mode": False, "collectinfo": False, "execute": False, + "enable": False, "log-analyser": False, "log-path": "", "pmap": False, @@ -123,6 +124,7 @@ def __init__(self, adict): "asinfo-mode": { "type" : "boolean" }, "collectinfo": { "type" : "boolean" }, "execute": { "type" : "boolean" }, + "enable": { "type" : "boolean" }, "log-analyser": { "type" : "boolean" }, "log-path" : { "type" : "string" } }, @@ -467,6 +469,10 @@ def print_config_help(): " The input value is either string of ';' separated asadm \n" " commands or path of file which has asadm commands (ends with ';')." ) + print( + " --enable Run commands in privileged mode. Must be used with the\n" + " --execute option. Not allowed in interactive mode." + ) print(" -o --out-file Path of file to write output of -e command[s].") print(" --no-color Disable colored output.") print( @@ -494,8 +500,7 @@ def print_config_file_option(): print("----------------------------------\n") print("[cluster]") print( - " -h, --host=HOST\n" - ' HOST is "[:][:],..." \n' + ' -h, --host=HOST HOST is "[:][:],..." \n' " Server seed hostnames or IP addresses. The tlsname is \n" " only used when connecting with a secure TLS enabled \n" " server. Default: localhost:3000\n" @@ -505,20 +510,15 @@ def print_config_file_option(): " 192.168.1.10:cert1:3000,192.168.1.20:cert2:3000" ) print( - " --services-alternate \n" - " Enable use of services-alternate instead of services in\n" + " --services-alternate Enable use of services-alternate instead of services in\n" " info request during cluster tending" ) + print(" -p, --port=PORT Server default port. Default: 3000") print( - " -p, --port=PORT \n" " Server default port. Default: 3000" - ) - print( - " -U, --user=USER \n" - " User name used to authenticate with cluster. Default: none" + " -U, --user=USER User name used to authenticate with cluster. Default: none" ) print( - " -P, --password\n" - " Password used to authenticate with cluster. Default: none\n" + " -P, --password Password used to authenticate with cluster. Default: none\n" " User will be prompted on command line if -P specified and no\n" " password is given." ) @@ -532,21 +532,13 @@ def print_config_file_option(): print( " --tls-enable Enable TLS on connections. By default TLS is disabled." ) - # Deprecated - # print(" --tls-encrypt-only Disable TLS certificate verification.\n") print( " -t --tls-name=name Default TLS name of host to verify for TLS connection,\n" " if not specified in host string. It is required if tls-enable\n" " is set." ) - print( - " --tls-cafile=path\n" - " Path to a trusted CA certificate file." - ) - print( - " --tls-capath=path\n" - " Path to a directory of trusted CA certificates." - ) + print(" --tls-cafile=path Path to a trusted CA certificate file.") + print(" --tls-capath=path Path to a directory of trusted CA certificates.") print( " --tls-protocols=TLS_PROTOCOLS\n" " Set the TLS protocol selection criteria. This format\n" @@ -564,9 +556,8 @@ def print_config_file_option(): " html" ) print( - " --tls-keyfile=path\n" - " Path to the key for mutual authentication (if\n" - " Aerospike Cluster is supporting it)." + " --tls-keyfile=path Path to the key for mutual authentication (if Aerospike\n" + " Cluster is supporting it)." ) print( " --tls-keyfile-password=password\n" @@ -580,8 +571,7 @@ def print_config_file_option(): " password is given." ) print( - " --tls-certfile=path\n" - " Path to the chain file for mutual authentication (if\n" + " --tls-certfile=path Path to the chain file for mutual authentication (if\n" " Aerospike Cluster is supporting it)." ) print( @@ -616,6 +606,10 @@ def print_config_file_option(): " --timeout=value Set timeout value in seconds for node level operations. \n" " TLS connection does not support timeout. Default: 5 seconds" ) + print( + " --enable Run commands in privileged mode. Must be used with the\n" + " --execute option. Not allowed in interactive mode." + ) def config_file_help(): @@ -664,6 +658,7 @@ def get_cli_args(): add_fn("-V", "--version", action="store_true") add_fn("-E", "--help", action="store_true") add_fn("-e", "--execute") + add_fn("--enable", action="store_true") add_fn("-o", "--out-file") add_fn("-c", "--collectinfo", action="store_true") add_fn("-l", "--log-analyser", action="store_true") diff --git a/pkg/astools.conf b/pkg/astools.conf index f35275f1..67fa7a90 100644 --- a/pkg/astools.conf +++ b/pkg/astools.conf @@ -94,6 +94,7 @@ # services-alumni = true # services-alternate = false # timeout = 5 +# enable = true [asadm_secure] # services-alternate = true diff --git a/test/unit/live_cluster/client/test_info.py b/test/unit/live_cluster/client/test_info.py index 625e4e15..90bf26d1 100644 --- a/test/unit/live_cluster/client/test_info.py +++ b/test/unit/live_cluster/client/test_info.py @@ -39,18 +39,24 @@ def test_str_to_enum(self): def test_is_global_only_scope(self): self.assertTrue(ASPrivilege.is_global_only_scope(ASPrivilege.DATA_ADMIN)) self.assertTrue(ASPrivilege.is_global_only_scope(ASPrivilege.SYS_ADMIN)) + self.assertTrue(ASPrivilege.is_global_only_scope(ASPrivilege.UDF_ADMIN)) self.assertTrue(ASPrivilege.is_global_only_scope(ASPrivilege.USER_ADMIN)) + self.assertTrue(ASPrivilege.is_global_only_scope(ASPrivilege.SINDEX_ADMIN)) self.assertFalse(ASPrivilege.is_global_only_scope(ASPrivilege.READ)) self.assertFalse(ASPrivilege.is_global_only_scope(ASPrivilege.READ_WRITE_UDF)) self.assertFalse(ASPrivilege.is_global_only_scope(ASPrivilege.READ_WRITE)) + self.assertFalse(ASPrivilege.is_global_only_scope(ASPrivilege.TRUNCATE)) def test__str__(self): self.assertEqual(str(ASPrivilege.SYS_ADMIN), "sys-admin") self.assertEqual(str(ASPrivilege.DATA_ADMIN), "data-admin") self.assertEqual(str(ASPrivilege.USER_ADMIN), "user-admin") + self.assertEqual(str(ASPrivilege.UDF_ADMIN), "udf-admin") + self.assertEqual(str(ASPrivilege.SINDEX_ADMIN), "sindex-admin") self.assertEqual(str(ASPrivilege.READ_WRITE_UDF), "read-write-udf") self.assertEqual(str(ASPrivilege.READ), "read") self.assertEqual(str(ASPrivilege.WRITE), "write") + self.assertEqual(str(ASPrivilege.TRUNCATE), "truncate") class ASResponseTest(unittest.TestCase):