#!/usr/bin/env python3 from mosq_test_helper import * import json import os import shutil def write_config(filename, ports): with open(filename, 'w') as f: f.write(f"global_plugin {mosq_test.get_build_root()}/plugins/dynamic-security/mosquitto_dynamic_security.so\n") f.write(f"plugin_opt_config_file {ports[0]}/dynamic-security.json\n") f.write("allow_anonymous false\n") f.write(f"listener {ports[0]}\n") f.write(f"listener {ports[1]}\n") f.write(f"certfile {ssl_dir}/server.crt\n") f.write(f"keyfile {ssl_dir}/server.key\n") def ctrl_dynsec_cmd(args, ports, response=None, input=None): opts = ["-u", "admin", "-P", "newadmin",] if response is None: opts += [ "-p", str(ports[0]), "-q", "1" ] else: opts += ["-p", str(ports[1])] opts += ["--cafile", f"{ssl_dir}/all-ca.crt"] proc = subprocess.run([mosq_test.get_build_root()+"/apps/mosquitto_ctrl/mosquitto_ctrl"] + opts + ["dynsec"] + args, env=env, capture_output=True, encoding='utf-8', timeout=2, input=input) if response is not None: if proc.stdout != response: print(len(proc.stdout)) print(len(response)) raise ValueError(proc.stdout) if proc.returncode != 0: raise ValueError(args) def ctrl_dynsec_file_cmd(args, ports, response=None): opts = ["-f", f"{ports[0]}/dynamic-security.json"] proc = subprocess.run([mosq_test.get_build_root()+"/apps/mosquitto_ctrl/mosquitto_ctrl"] + opts + ["dynsec"] + args, env=env, capture_output=True, encoding='utf-8') if response is not None: if proc.stdout != response: raise ValueError(proc.stdout) if proc.returncode != 0: raise ValueError(args) ports = mosq_test.get_port(2) conf_file = os.path.basename(__file__).replace('.py', '.conf') write_config(conf_file, ports) env = mosq_test.env_add_ld_library_path() if not os.path.exists(str(ports[0])): os.mkdir(str(ports[0])) # Generate initial dynsec file ctrl_dynsec_cmd(["init", f"{ports[0]}/dynamic-security.json", "admin", "admin"], ports) try: # If we're root, set file ownership to "nobody", because that is the user # the broker will change to. os.chown(f"{ports[0]}/dynamic-security.json", 65534, 65534) except PermissionError: pass ctrl_dynsec_file_cmd(["help"], ports) # get the help, don't check the response though ctrl_dynsec_file_cmd(["setClientPassword", "admin", "newadmin", "-i", "10000"], ports) ctrl_dynsec_file_cmd(["setClientPassword", "admin", "newadmin"], ports) # Then start broker broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=ports[0], nolog=True) try: rc = 1 # Set default access to opposite of normal ctrl_dynsec_cmd(["setDefaultACLAccess", "publishClientSend", "allow"], ports) ctrl_dynsec_cmd(["setDefaultACLAccess", "publishClientReceive", "deny"], ports) ctrl_dynsec_cmd(["setDefaultACLAccess", "subscribe", "allow"], ports) ctrl_dynsec_cmd(["setDefaultACLAccess", "unsubscribe", "deny"], ports) # Verify ctrl_dynsec_cmd(["getDefaultACLAccess"], ports, response="publishClientSend : allow\npublishClientReceive : deny\nsubscribe : allow\nunsubscribe : deny\n") # Create clients ctrl_dynsec_cmd(["createClient", "username1", "-p", "password1"], ports) # password, no client id ctrl_dynsec_cmd(["createClient", "username2", "-p", "password2", "-c", "clientid2"], ports) # password and client id ctrl_dynsec_cmd(["createClient", "username3"], ports, input="pw\npw\n") # password, no client id ctrl_dynsec_cmd(["createClient", "username4"], ports, input="\n\n") # password, no client id ctrl_dynsec_cmd(["createClient", "username5"], ports, input="not\nmatching\n") # List clients ctrl_dynsec_cmd(["listClients"], ports, response="admin\nusername1\nusername2\nusername3\nusername4\n") ctrl_dynsec_cmd(["listClients", "1"], ports, response="admin\n") # with count ctrl_dynsec_cmd(["listClients", "1", "1"], ports, response="username1\n") # with count, offset # Create groups ctrl_dynsec_cmd(["createGroup", "group1"], ports) ctrl_dynsec_cmd(["createGroup", "group2"], ports) ctrl_dynsec_cmd(["createGroup", "group3"], ports) #List groups ctrl_dynsec_cmd(["listGroups"], ports, response="group1\ngroup2\ngroup3\n") ctrl_dynsec_cmd(["listGroups", "1"], ports, response="group1\n") ctrl_dynsec_cmd(["listGroups", "1", "1"], ports, response="group2\n") # Add client to group ctrl_dynsec_cmd(["addGroupClient", "group1", "username1", "10"], ports) # Get anonymous group ctrl_dynsec_cmd(["getAnonymousGroup"], ports, response="\n") # Set anon as anonymous group ctrl_dynsec_cmd(["setAnonymousGroup", "group2"], ports) # Verify ctrl_dynsec_cmd(["getAnonymousGroup"], ports, response="group2\n") # Create roles ctrl_dynsec_cmd(["createRole", "role1"], ports) ctrl_dynsec_cmd(["createRole", "role2"], ports) ctrl_dynsec_cmd(["createRole", "role3"], ports) #Delete a role: deleteRole ctrl_dynsec_cmd(["deleteRole", "role3"], ports) # repeat with count, offset # Add a role to a client ctrl_dynsec_cmd(["addClientRole", "username1", "role1", "20"], ports) # Add a role to a group ctrl_dynsec_cmd(["addGroupRole", "group1", "role2", "15"], ports) ctrl_dynsec_cmd(["getGroup", "group1"], ports) # repeat with count, offset # Add ACLs ctrl_dynsec_cmd(["addRoleACL", "role1", "publishClientSend", "#", "allow", "1"], ports) ctrl_dynsec_cmd(["addRoleACL", "role1", "publishClientReceive", "#", "allow", "2"], ports) ctrl_dynsec_cmd(["addRoleACL", "role1", "subscribeLiteral", "#", "allow", "1"], ports) ctrl_dynsec_cmd(["addRoleACL", "role1", "subscribePattern", "#", "allow", "2"], ports) ctrl_dynsec_cmd(["addRoleACL", "role1", "unsubscribeLiteral", "#", "deny", "1"], ports) ctrl_dynsec_cmd(["addRoleACL", "role1", "unsubscribePattern", "#", "deny", "2"], ports) ctrl_dynsec_cmd(["addRoleACL", "role2", "publishClientSend", "#", "allow", "3"], ports) ctrl_dynsec_cmd(["addRoleACL", "role2", "publishClientReceive", "#", "allow"], ports) # List roles ctrl_dynsec_cmd(["listRoles"], ports, response="admin\nrole1\nrole2\n") ctrl_dynsec_cmd(["listRoles", "1"], ports, response="admin\n") ctrl_dynsec_cmd(["listRoles", "1", "1"], ports, response="role1\n") # Get role ctrl_dynsec_cmd(["getRole", "role1"], ports, response="Rolename: role1\nACLs: publishClientSend : allow : # (priority: 1)\n publishClientReceive : allow : # (priority: 2)\n subscribeLiteral : allow : # (priority: 1)\n subscribePattern : allow : # (priority: 2)\n unsubscribeLiteral : deny : # (priority: 1)\n unsubscribePattern : deny : # (priority: 2)\n") # Get client ctrl_dynsec_cmd(["getClient", "username1"], ports, response="Username: username1\nClientid:\nRoles: role1 (priority: 20)\nGroups: group1 (priority: 10)\n") # Disable client ctrl_dynsec_cmd(["disableClient", "username1"], ports) # Verify client ctrl_dynsec_cmd(["getClient", "username1"], ports, response="Username: username1\nClientid:\nDisabled: true\nRoles: role1 (priority: 20)\nGroups: group1 (priority: 10)\n") # Set clientid ctrl_dynsec_cmd(["setClientID", "username1", "fixed-id"], ports) # Verify client ctrl_dynsec_cmd(["getClient", "username1"], ports, response="Username: username1\nClientid: fixed-id\nDisabled: true\nRoles: role1 (priority: 20)\nGroups: group1 (priority: 10)\n") # Clear clientid ctrl_dynsec_cmd(["setClientID", "username1"], ports) # Enable client ctrl_dynsec_cmd(["enableClient", "username1"], ports) # Verify client ctrl_dynsec_cmd(["getClient", "username1"], ports, response="Username: username1\nClientid:\nRoles: role1 (priority: 20)\nGroups: group1 (priority: 10)\n") # Set client password ctrl_dynsec_cmd(["setClientPassword", "username1", "new-password"], ports) ctrl_dynsec_cmd(["setClientPassword", "username1"], ports, input="not\nmatch\n") # Remove an ACL ctrl_dynsec_cmd(["removeRoleACL", "role1", "publishClientReceive", "#"], ports) ctrl_dynsec_cmd(["getRole", "role1"], ports, response="Rolename: role1\nACLs: publishClientSend : allow : # (priority: 1)\n subscribeLiteral : allow : # (priority: 1)\n subscribePattern : allow : # (priority: 2)\n unsubscribeLiteral : deny : # (priority: 1)\n unsubscribePattern : deny : # (priority: 2)\n") ctrl_dynsec_cmd(["removeRoleACL", "role1", "publishClientSend", "#"], ports) ctrl_dynsec_cmd(["getRole", "role1"], ports, response="Rolename: role1\nACLs: subscribeLiteral : allow : # (priority: 1)\n subscribePattern : allow : # (priority: 2)\n unsubscribeLiteral : deny : # (priority: 1)\n unsubscribePattern : deny : # (priority: 2)\n") ctrl_dynsec_cmd(["removeRoleACL", "role1", "subscribeLiteral", "#"], ports) ctrl_dynsec_cmd(["removeRoleACL", "role1", "subscribePattern", "#"], ports) ctrl_dynsec_cmd(["removeRoleACL", "role1", "unsubscribeLiteral", "#"], ports) ctrl_dynsec_cmd(["removeRoleACL", "role1", "unsubscribePattern", "#"], ports) ctrl_dynsec_cmd(["getRole", "role1"], ports, response="Rolename: role1\n") # Remove a Role ctrl_dynsec_cmd(["deleteRole", "role2"], ports) # Remove client from a group ctrl_dynsec_cmd(["removeGroupClient", "group1", "username1"], ports) # Remove role from a group ctrl_dynsec_cmd(["removeGroupRole", "group1", "role2"], ports) # Delete group ctrl_dynsec_cmd(["deleteGroup", "group1"], ports) ctrl_dynsec_cmd(["removeClientRole", "username1", "role1"], ports) # Delete client ctrl_dynsec_cmd(["deleteClient", "username1"], ports) rc = 0 except mosq_test.TestError: pass finally: os.remove(conf_file) try: os.remove(f"{ports[0]}/dynamic-security.json") pass except FileNotFoundError: pass shutil.rmtree(f"{ports[0]}") broker.terminate() if mosq_test.wait_for_subprocess(broker): print("broker not terminated") if rc == 0: rc=1 exit(rc)