14-dynsec-auth.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #!/usr/bin/env python3
  2. from mosq_test_helper import *
  3. import json
  4. import shutil
  5. def write_config(filename, port):
  6. with open(filename, 'w') as f:
  7. f.write("listener %d\n" % (port))
  8. f.write("allow_anonymous false\n")
  9. f.write("plugin ../../plugins/dynamic-security/mosquitto_dynamic_security.so\n")
  10. f.write("plugin_opt_config_file %d/dynamic-security.json\n" % (port))
  11. def command_check(sock, command_payload, expected_response):
  12. command_packet = mosq_test.gen_publish(topic="$CONTROL/dynamic-security/v1", qos=0, payload=json.dumps(command_payload))
  13. sock.send(command_packet)
  14. response = json.loads(mosq_test.read_publish(sock))
  15. if response != expected_response:
  16. print(expected_response)
  17. print(response)
  18. raise ValueError(response)
  19. port = mosq_test.get_port()
  20. conf_file = os.path.basename(__file__).replace('.py', '.conf')
  21. write_config(conf_file, port)
  22. add_client_command_with_id = { "commands": [{
  23. "command": "createClient", "username": "user_one",
  24. "password": "password", "clientid": "cid",
  25. "correlationData": "2" }]
  26. }
  27. add_client_response_with_id = {'responses': [{'command': 'createClient', 'correlationData': '2'}]}
  28. add_client_command_without_id = { "commands": [{
  29. "command": "createClient", "username": "user_two",
  30. "password": "asdfgh",
  31. "correlationData": "3" }]
  32. }
  33. add_client_response_without_id = {'responses': [{'command': 'createClient', 'correlationData': '3'}]}
  34. set_client_id_command = { "commands": [{
  35. "command": "setClientId", "username": "user_two", "clientid": "new-cid",
  36. "correlationData": "5" }]
  37. }
  38. set_client_id_response = {'responses': [{'command': 'setClientId', 'correlationData': '5'}]}
  39. # No password defined, this client should never be able to connect.
  40. add_client_command_without_pw = { "commands": [{
  41. "command": "createClient", "username": "user_three",
  42. "correlationData": "4" }]
  43. }
  44. add_client_response_without_pw = {'responses': [{'command': 'createClient', 'correlationData': '4'}]}
  45. rc = 1
  46. keepalive = 10
  47. connect_packet = mosq_test.gen_connect("ctrl-test", keepalive=keepalive, username="admin", password="admin")
  48. connack_packet = mosq_test.gen_connack(rc=0)
  49. mid = 2
  50. subscribe_packet = mosq_test.gen_subscribe(mid, "$CONTROL/dynamic-security/#", 1)
  51. suback_packet = mosq_test.gen_suback(mid, 1)
  52. # Success
  53. connect_packet_with_id1 = mosq_test.gen_connect("cid", keepalive=keepalive, username="user_one", password="password", proto_ver=5)
  54. connack_packet_with_id1 = mosq_test.gen_connack(rc=0, proto_ver=5)
  55. # Fail - bad client id
  56. connect_packet_with_id2 = mosq_test.gen_connect("bad-cid", keepalive=keepalive, username="user_one", password="password", proto_ver=5)
  57. connack_packet_with_id2 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  58. # Fail - bad password
  59. connect_packet_with_id3 = mosq_test.gen_connect("cid", keepalive=keepalive, username="user_one", password="ttt", proto_ver=5)
  60. connack_packet_with_id3 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  61. # Fail - no password
  62. connect_packet_with_id4 = mosq_test.gen_connect("cid", keepalive=keepalive, username="user_one", proto_ver=5)
  63. connack_packet_with_id4 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  64. # Success
  65. connect_packet_without_id1 = mosq_test.gen_connect("no-cid", keepalive=keepalive, username="user_two", password="asdfgh", proto_ver=5)
  66. connack_packet_without_id1 = mosq_test.gen_connack(rc=0, proto_ver=5)
  67. # Fail - bad password
  68. connect_packet_without_id2 = mosq_test.gen_connect("no-cid", keepalive=keepalive, username="user_two", password="pass", proto_ver=5)
  69. connack_packet_without_id2 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  70. # Fail - no password
  71. connect_packet_without_id3 = mosq_test.gen_connect("no-cid", keepalive=keepalive, username="user_two", proto_ver=5)
  72. connack_packet_without_id3 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  73. # Success
  74. connect_packet_set_id1 = mosq_test.gen_connect("new-cid", keepalive=keepalive, username="user_two", password="asdfgh", proto_ver=5)
  75. connack_packet_set_id1 = mosq_test.gen_connack(rc=0, proto_ver=5)
  76. # Fail - bad client id
  77. connect_packet_set_id2 = mosq_test.gen_connect("bad-cid", keepalive=keepalive, username="user_two", password="asdfgh", proto_ver=5)
  78. connack_packet_set_id2 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  79. # Fail - bad password
  80. connect_packet_without_pw1 = mosq_test.gen_connect("cid2", keepalive=keepalive, username="user_three", password="pass", proto_ver=5)
  81. connack_packet_without_pw1 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  82. # Fail - no password
  83. connect_packet_without_pw2 = mosq_test.gen_connect("cid2", keepalive=keepalive, username="user_three", proto_ver=5)
  84. connack_packet_without_pw2 = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  85. # Fail - no username
  86. connect_packet_without_un = mosq_test.gen_connect("cid3", keepalive=keepalive, proto_ver=5)
  87. connack_packet_without_un = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_NOT_AUTHORIZED, proto_ver=5, property_helper=False)
  88. try:
  89. os.mkdir(str(port))
  90. shutil.copyfile("dynamic-security-init.json", "%d/dynamic-security.json" % (port))
  91. except FileExistsError:
  92. pass
  93. broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
  94. try:
  95. sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=5, port=port)
  96. mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")
  97. # Add client
  98. command_check(sock, add_client_command_with_id, add_client_response_with_id)
  99. command_check(sock, add_client_command_without_id, add_client_response_without_id)
  100. command_check(sock, add_client_command_without_pw, add_client_response_without_pw)
  101. # Client with username, password, and client id
  102. csock = mosq_test.do_client_connect(connect_packet_with_id1, connack_packet_with_id1, timeout=5, port=port, connack_error="with id 1")
  103. csock.close()
  104. csock = mosq_test.do_client_connect(connect_packet_with_id2, connack_packet_with_id2, timeout=5, port=port, connack_error="with id 2")
  105. csock.close()
  106. csock = mosq_test.do_client_connect(connect_packet_with_id3, connack_packet_with_id3, timeout=5, port=port, connack_error="with id 3")
  107. csock.close()
  108. csock = mosq_test.do_client_connect(connect_packet_with_id4, connack_packet_with_id4, timeout=5, port=port, connack_error="with id 4")
  109. csock.close()
  110. # Client with just username and password
  111. csock = mosq_test.do_client_connect(connect_packet_without_id1, connack_packet_without_id1, timeout=5, port=port, connack_error="without id 1")
  112. csock.close()
  113. csock = mosq_test.do_client_connect(connect_packet_without_id2, connack_packet_without_id2, timeout=5, port=port, connack_error="without id 2")
  114. csock.close()
  115. csock = mosq_test.do_client_connect(connect_packet_without_id3, connack_packet_without_id3, timeout=5, port=port, connack_error="without id 3")
  116. csock.close()
  117. # Client with no password set
  118. csock = mosq_test.do_client_connect(connect_packet_without_pw1, connack_packet_without_pw1, timeout=5, port=port, connack_error="without pw 1")
  119. csock.close()
  120. csock = mosq_test.do_client_connect(connect_packet_without_pw2, connack_packet_without_pw2, timeout=5, port=port, connack_error="without pw 2")
  121. csock.close()
  122. # Add client id to "user_two"
  123. command_check(sock, set_client_id_command, set_client_id_response)
  124. csock = mosq_test.do_client_connect(connect_packet_set_id1, connack_packet_set_id1, timeout=5, port=port, connack_error="set id 1")
  125. csock.close()
  126. csock = mosq_test.do_client_connect(connect_packet_set_id2, connack_packet_set_id2, timeout=5, port=port, connack_error="set id 2")
  127. csock.close()
  128. # No username, anon disabled
  129. csock = mosq_test.do_client_connect(connect_packet_without_un, connack_packet_without_un, timeout=5, port=port, connack_error="without username")
  130. csock.close()
  131. rc = 0
  132. sock.close()
  133. except mosq_test.TestError:
  134. pass
  135. finally:
  136. os.remove(conf_file)
  137. try:
  138. os.remove(f"{port}/dynamic-security.json")
  139. except FileNotFoundError:
  140. pass
  141. os.rmdir(f"{port}")
  142. broker.terminate()
  143. broker.wait()
  144. (stdo, stde) = broker.communicate()
  145. if rc:
  146. print(stde.decode('utf-8'))
  147. exit(rc)