holado 0.2.8__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of holado might be problematic. Click here for more details.

Files changed (110) hide show
  1. holado/common/handlers/undefined.py +7 -1
  2. {holado-0.2.8.dist-info → holado-0.4.0.dist-info}/METADATA +4 -1
  3. {holado-0.2.8.dist-info → holado-0.4.0.dist-info}/RECORD +108 -101
  4. holado_ais/ais/ais_messages.py +97 -6
  5. holado_ais/tests/behave/steps/ais/ais_manager_steps.py +1 -1
  6. holado_ais/tests/behave/steps/ais/ais_messages_steps.py +45 -6
  7. holado_binary/ipc/bit_series.py +3 -3
  8. holado_binary/tests/behave/steps/ipc/binary_steps.py +1 -1
  9. holado_binary/tests/behave/steps/ipc/bit_series_steps.py +4 -3
  10. holado_context/tests/behave/steps/private/common/context_steps.py +1 -1
  11. holado_core/common/resource/persisted_data_manager.py +13 -16
  12. holado_core/common/resource/resource_manager.py +10 -10
  13. holado_core/common/tables/converters/table_converter.py +47 -9
  14. holado_core/common/tables/table_manager.py +6 -7
  15. holado_core/common/tables/table_with_header.py +6 -0
  16. holado_core/tests/behave/steps/common/common_steps.py +2 -1
  17. holado_core/tests/behave/steps/common/config_steps.py +1 -1
  18. holado_core/tests/behave/steps/common/resource_steps.py +1 -1
  19. holado_core/tests/behave/steps/common/tables_steps.py +18 -2
  20. holado_data/data/generator/generator_manager.py +39 -0
  21. holado_data/tests/behave/steps/data/generator_steps.py +1 -1
  22. holado_data/tests/behave/steps/tools/utils_steps.py +1 -2
  23. holado_db/tests/behave/steps/tools/db/db_client_steps.py +1 -1
  24. holado_db/tests/behave/steps/tools/db/postgresql_client_steps.py +1 -1
  25. holado_db/tests/behave/steps/tools/db/sqlite_client_steps.py +1 -1
  26. holado_db/tools/db/clients/base/db_client.py +81 -28
  27. holado_db/tools/db/clients/postgresql/postgresql_client.py +17 -7
  28. holado_db/tools/db/query/base/query_builder.py +58 -7
  29. holado_db/tools/db/query/pypika/pypika_query_builder.py +73 -21
  30. holado_docker/tests/behave/steps/tools/docker_steps.py +1 -1
  31. holado_grpc/tests/behave/steps/api/grpc_client_steps.py +1 -1
  32. holado_grpc/tests/behave/steps/private/api/grpc_steps.py +1 -1
  33. holado_json/tests/behave/steps/ipc/json_steps.py +1 -1
  34. holado_keycloak/tests/behave/steps/tools/keycloak_client_steps.py +1 -1
  35. holado_multitask/tests/behave/steps/multiprocessing_steps.py +1 -1
  36. holado_multitask/tests/behave/steps/multithreading_steps.py +1 -1
  37. holado_protobuf/ipc/protobuf/types/google/protobuf.py +1 -1
  38. holado_protobuf/tests/behave/steps/ipc/protobuf_steps.py +1 -1
  39. holado_python/common/tools/datetime.py +31 -12
  40. holado_python/standard_library/socket/blocking_socket.py +37 -24
  41. holado_python/standard_library/socket/message_socket.py +11 -3
  42. holado_python/standard_library/socket/non_blocking_socket.py +24 -24
  43. holado_python/standard_library/socket/socket.py +132 -19
  44. holado_python/standard_library/ssl/resources/certificates/NOTES.txt +1 -1
  45. holado_python/standard_library/ssl/resources/certificates/rootCACert.pem +24 -0
  46. holado_python/standard_library/ssl/resources/certificates/tcpbin.crt +21 -0
  47. holado_python/standard_library/ssl/resources/certificates/tcpbin.key +28 -0
  48. holado_python/standard_library/ssl/ssl.py +138 -21
  49. holado_python/tests/behave/steps/convert_steps.py +1 -1
  50. holado_python/tests/behave/steps/iterable_steps.py +1 -1
  51. holado_python/tests/behave/steps/standard_library/csv_steps.py +1 -1
  52. holado_python/tests/behave/steps/standard_library/datetime_steps.py +1 -1
  53. holado_python/tests/behave/steps/standard_library/hashlib_steps.py +2 -2
  54. holado_python/tests/behave/steps/standard_library/multiprocessing_steps.py +1 -1
  55. holado_python/tests/behave/steps/standard_library/queue_steps.py +1 -1
  56. holado_python/tests/behave/steps/standard_library/socket_steps.py +132 -18
  57. holado_python/tests/behave/steps/standard_library/ssl_steps.py +87 -16
  58. holado_rabbitmq/tests/behave/steps/tools/rabbitmq_client_steps.py +48 -20
  59. holado_rabbitmq/tests/behave/steps/tools/rabbitmq_server_steps.py +1 -1
  60. holado_rabbitmq/tools/rabbitmq/rabbitmq_client.py +19 -13
  61. holado_rabbitmq/tools/rabbitmq/rabbitmq_manager.py +2 -29
  62. holado_redis/tests/behave/steps/tools/redis_client_steps.py +1 -1
  63. holado_rest/api/rest/rest_client.py +18 -1
  64. holado_rest/api/rest/rest_manager.py +5 -0
  65. holado_rest/tests/behave/steps/api/rest_client_steps.py +52 -11
  66. holado_rest/tests/behave/steps/private/api/rest_steps.py +1 -1
  67. holado_s3/tests/behave/steps/private/tools/s3_steps.py +1 -1
  68. holado_s3/tests/behave/steps/tools/s3_client_steps.py +1 -1
  69. holado_s3/tests/behave/steps/tools/s3_server_steps.py +1 -1
  70. holado_scripting/tests/behave/steps/common/tools/variable_convert_steps.py +3 -2
  71. holado_scripting/tests/behave/steps/common/tools/variable_new_steps.py +1 -1
  72. holado_scripting/tests/behave/steps/common/tools/variable_steps.py +1 -1
  73. holado_scripting/tests/behave/steps/common/tools/variable_verify_steps.py +1 -1
  74. holado_scripting/tests/behave/steps/scenario/function_steps.py +1 -1
  75. holado_scripting/tests/behave/steps/scenario/if_steps.py +1 -1
  76. holado_scripting/tests/behave/steps/scenario/loop_steps.py +1 -1
  77. holado_sftp/tests/behave/steps/private/tools/sftp_steps.py +1 -1
  78. holado_sftp/tests/behave/steps/tools/sftp_client_steps.py +1 -1
  79. holado_sftp/tests/behave/steps/tools/sftp_server_steps.py +1 -1
  80. holado_swagger/tests/behave/steps/swagger_hub/mockserver_steps.py +1 -1
  81. holado_system/system/command/command.py +14 -9
  82. holado_system/tests/behave/steps/system/commands_steps.py +1 -1
  83. holado_system/tests/behave/steps/system/file_steps.py +1 -1
  84. holado_system/tests/behave/steps/system/system_steps.py +1 -1
  85. holado_test/scenario/step_tools.py +1 -1
  86. holado_test/scenario/tester_tools.py +6 -3
  87. holado_test/tests/behave/steps/scenario/exception_steps.py +1 -1
  88. holado_test/tests/behave/steps/scenario/scenario_steps.py +1 -1
  89. holado_test/tests/behave/steps/scenario/tester_steps.py +4 -4
  90. holado_value/common/tables/converters/value_table_converter.py +52 -8
  91. holado_value/common/tables/value_table_manager.py +0 -10
  92. holado_ws/tests/behave/steps/api/web_service_steps.py +1 -1
  93. holado_yaml/tests/behave/steps/yaml_steps.py +1 -1
  94. holado_yaml/yaml/yaml_manager.py +2 -2
  95. test_holado/features/NonReg/common/tables/table.feature +30 -24
  96. test_holado/features/NonReg/holado_ais/ais_message-bitarray_to_nmea.feature +1 -1
  97. test_holado/features/NonReg/holado_python/standard_library/socket/local_echo_server/socket_reset.feature +191 -0
  98. test_holado/features/NonReg/holado_python/standard_library/{socket_with_ssl.feature → socket/local_echo_server/socket_with_tls_and_verify.feature} +53 -30
  99. test_holado/features/NonReg/holado_python/standard_library/socket/local_echo_server/socket_with_tls_without_verify.feature +299 -0
  100. test_holado/features/NonReg/holado_python/standard_library/{socket.feature → socket/local_echo_server/socket_without_tls.feature} +2 -2
  101. test_holado/features/NonReg/holado_python/standard_library/socket/tcpbin.com/socket_with_mtls.feature +214 -0
  102. test_holado/features/NonReg/holado_python/standard_library/socket/tcpbin.com/socket_with_tls.feature +184 -0
  103. test_holado/features/NonReg/holado_python/standard_library/socket/tcpbin.com/socket_without_tls.feature +169 -0
  104. test_holado/features/NonReg/tools/RabbitMQ.feature +9 -9
  105. test_holado/features/NonReg/tools/RabbitMQ_steps.feature +8 -8
  106. test_holado/logging.conf +5 -3
  107. holado_core/common/transport/__init__.py +0 -0
  108. holado_core/common/transport/crc.py +0 -40
  109. {holado-0.2.8.dist-info → holado-0.4.0.dist-info}/WHEEL +0 -0
  110. {holado-0.2.8.dist-info → holado-0.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,24 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIID7jCCAtagAwIBAgIJAJNpPsX/1B+fMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
3
+ VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDzAN
4
+ BgNVBAoMBnRjcGJpbjEMMAoGA1UECwwDb3BzMRMwEQYDVQQDDAp0Y3BiaW4uY29t
5
+ MSMwIQYJKoZIhvcNAQkBFhRoYXJyeWJhZ2RpQGdtYWlsLmNvbTAeFw0xOTA1MDUw
6
+ NjI3NTlaFw0yOTA1MDIwNjI3NTlaMIGLMQswCQYDVQQGEwJVUzELMAkGA1UECAwC
7
+ Q0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBnRjcGJpbjEMMAoG
8
+ A1UECwwDb3BzMRMwEQYDVQQDDAp0Y3BiaW4uY29tMSMwIQYJKoZIhvcNAQkBFhRo
9
+ YXJyeWJhZ2RpQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
10
+ ggEBAK0LTwoX+/d/QKJuIuvUw2gUBGwjeX8DM3OqagcmZutlq9VfSW1pkzNhCpFU
11
+ 1JQh/bJ3P97VTZn75H2zL4BQnAXaPSRoi0wOFsoEhzbIOAFELPq2TMoY9lvOLO9n
12
+ 4yt4Pz7AbFLhPDeltqb91S/18hN1YmVTDEuMCz4OGnJOf5NbmuVwmjMcDWiOwmjp
13
+ dBYlwCMn/TRB3wUPSwafLef9EIJfm4uL0ruH3Rlhj8Lktt0YTvrA7M6URMcgFqYG
14
+ wNNsYa9X88Js1nxlryvTputbVf6zL35S7CvTGc6fft/pfdSAu2KcmOd+C0dew1GI
15
+ daM9tqTiqi6Tg+IA2t4eaA3tR2MCAwEAAaNTMFEwHQYDVR0OBBYEFOLuMowBSAZf
16
+ V5v82LmlaIIOvU/DMB8GA1UdIwQYMBaAFOLuMowBSAZfV5v82LmlaIIOvU/DMA8G
17
+ A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEj3o18u8FQDrQu89Etk
18
+ 4sQgiZxtQ0C3OglCXP9kRGSBt8Ymd/2bmpGK2TsEpACkfpJLaFRVPek2302YQ8mc
19
+ oj63wPTDYx1P/BSH+dPvDUXI9SePXcrFAPq9YemteQHE+WZ/PFe0wAq1ehziWgqQ
20
+ OiMb1wydDbaRZF6jPPMW7cHCiUYceLBRO0ZTe9CsUPYw6A78QZnO6P7Cuc1SwkNv
21
+ uejCGTfv5HP72/Jm24ifAMOoWXALmvIIAnOVTwpPEX2nEnr9H1S8Psi3+mqkGyC1
22
+ RQXprzHkflCKHxjiNfNguHeC3x6l0LGWEShcemyDWCsTgCYNX6RMTWWcug3Vb/70
23
+ BSs=
24
+ -----END CERTIFICATE-----
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDZTCCAk2gAwIBAgIBKjANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMCVVMx
3
+ CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZ0
4
+ Y3BiaW4xDDAKBgNVBAsMA29wczETMBEGA1UEAwwKdGNwYmluLmNvbTEjMCEGCSqG
5
+ SIb3DQEJARYUaGFycnliYWdkaUBnbWFpbC5jb20wHhcNMjUwNTI4MTMxODIwWhcN
6
+ MjUwNTI5MTMxODIwWjAcMRowGAYDVQQDDBF0Y3BiaW4uY29tLWNsaWVudDCCASIw
7
+ DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANvo9G/86es6qoCHTum0RAoqAAiY
8
+ qnOCLgXmamgfQgbfYoBIkNTBBVzsZyoZIY4QuuO8E07VmbrnH23czCSAO5akPb7D
9
+ teotATqDf4My0Ybht62nLoxhHBb9jrzSgv4+04gy/W6wu5diyfeY8BNopHkUkmEN
10
+ WhmGkP9s9npUGaEfEeasuiB1JMkAEOWnw+kHqE3Us+4Av4Mht6srswst3B90WCIV
11
+ Rry48gRJS4qZoAk1dwZHIcYSOfMJ8Pu69wS1qjRwRPLc3dfnUs2E3dAx1FDxDBkK
12
+ eQ73VUm64A5AXLYRk3PvgPwbcgerkLAnYAb5o8YJmyufGXKQNhmZxcCt+t0CAwEA
13
+ AaNCMEAwHQYDVR0OBBYEFDgjXXI6juiInalFSZEZM6BcEW9UMB8GA1UdIwQYMBaA
14
+ FOLuMowBSAZfV5v82LmlaIIOvU/DMA0GCSqGSIb3DQEBCwUAA4IBAQAu6SJ3OT6D
15
+ fhjfg4wRMHZVsaYSF6Kwe0RNt6izRkv5MUGi6Ew0SK1Mm+qxE51G3aaVCE4G+P1e
16
+ ACOiBL55saWDJtdng2VTKhUsFxIk2c/t+tuh7ttV7i0yGbaLGDP0N2FveBhKj/5d
17
+ SaPpAQvZ1rFhXpUU1jQr+xi5pP/iOPH02O8A8VgHyGebDVXs8iWMHjozOrRhgQVJ
18
+ YAl5lyYs+aj199p9ixwY3RPPWbUcggvAipv9bu6uEEIWMOMMERM2P7yFYaWJBcw5
19
+ A/Uqu2bBLmOu9/qmlEj2uQfTeVhnoT/bZBfmPcrL64tHjw7G5u0WuooPNTI23z28
20
+ 3ttcr+fDbDR4
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDb6PRv/OnrOqqA
3
+ h07ptEQKKgAImKpzgi4F5mpoH0IG32KASJDUwQVc7GcqGSGOELrjvBNO1Zm65x9t
4
+ 3MwkgDuWpD2+w7XqLQE6g3+DMtGG4betpy6MYRwW/Y680oL+PtOIMv1usLuXYsn3
5
+ mPATaKR5FJJhDVoZhpD/bPZ6VBmhHxHmrLogdSTJABDlp8PpB6hN1LPuAL+DIber
6
+ K7MLLdwfdFgiFUa8uPIESUuKmaAJNXcGRyHGEjnzCfD7uvcEtao0cETy3N3X51LN
7
+ hN3QMdRQ8QwZCnkO91VJuuAOQFy2EZNz74D8G3IHq5CwJ2AG+aPGCZsrnxlykDYZ
8
+ mcXArfrdAgMBAAECggEAe76UfcfloTY752M8ZonHl6iWqD+v+puQZkWILtsX/mIJ
9
+ PYKX7QBIkkd8rdXCafzEDY4xlzTe8qtHpjyOqyN1ZIk7LXNXlFSK0nBYem1INgwh
10
+ nZfru5aRheZcQah7ibG0unlm3riYdtFiMO9geKtzkaafz/kBcEemo/SepatZWK3m
11
+ DQX6okkpHh04GZNIO52K2QCaYpmj14fXIi2p5M4+KD+gmYbXhkmzNdcjz2l/wkqo
12
+ SziZf31nzuoHd6FuQ6vAsmXU/m6jW7Nll0wsxTm5Ynw5SoIrAbreJJmSSD8o2Shj
13
+ mvzWlurk1SgOhtoHP+AaVAn454x/Fn7+8u0f5ptNyQKBgQDvKc/3etCi22ntlgQM
14
+ dIwxbUPnmSvwejpMPOq3kMGTQWUJcKFinbPC28s/lJGzVjMsH5VisjiprCt3TXGN
15
+ XwmLNaUycWN3po9HyLSndAjHWM4aQ3yTOFKfLFEDUhKi8Dxy995KmHhgSSHd65qM
16
+ PvnPhITZWfKLkItCOmNEULxE8wKBgQDrZCji91ztgNyN3MHDGN2o854lAvWc1l6s
17
+ 4L8ZwU/RCNYyvMkdhadASzLwVC44q/6txGjTHGjnJPdkzV2u+WsPVWG2uCaD9PV1
18
+ 3L8wyG9sJ2YoJE5QcAQ+1J+rRN3fluzSKFiQNDpf7C5YqCPvk7C7lXFllGHM6FmF
19
+ hoYbyIb07wKBgQDKaF+qulViz0FqIwFQLT8NAcVrd7W5MyitpwyayLcbUkgZYioj
20
+ lQYzDuOH7swUtApg+GXsfpr39k9fC7rjg6BHIeKqu04MUHmIrjM+WTSoyd68WYtP
21
+ 6WX7cn0py0ccgScXwfFuvnV6P8qaz7Afq5iuaSAp9zcPqQhCx7mFcrKzwwKBgQCo
22
+ VH3woNgxd59BS4a8j8GjmmOTMCSYPayCkE3Yiyca4ujaa6qek/9guOX6exh6qnR7
23
+ qyMTJRPXh9XqnfnKsM5grrwrwFC6uKf32x5WMl+LxjkFp8DhQNmoXMC554uK4xED
24
+ 0JpUtSSxh+I0wDjCkKkn29y1uYCe2eF63RJ2N9ZavQKBgQCbHI/bMIZw/fsaijg3
25
+ 676mpQqFPiQdXTogw8UWzZBAvP6eQOnqQ9aw4tJt6OZWnwCDMwXrEYk3H8qisZl7
26
+ ou63o5t8bTrU4C6e1VIQ1XuQM4FEpx6/TFwBG2FXkgzGHUpHlR9+woxqvmQgfsiW
27
+ tEJ/TZv7bU6s9FRLTzMspp+tIA==
28
+ -----END PRIVATE KEY-----
@@ -13,13 +13,15 @@
13
13
 
14
14
  import logging
15
15
  import ssl
16
- from holado_core.common.exceptions.functional_exception import FunctionalException
17
16
  from holado_core.common.tools.tools import Tools
18
17
  from holado_json.ipc.json import set_object_attributes_with_json_dict
19
18
  from holado_core.common.exceptions.technical_exception import TechnicalException
20
19
  import os
21
20
  import copy
22
21
  from ssl import Purpose
22
+ from holado_system.system.command.command import Command, CommandStates
23
+ from holado.common.context.session_context import SessionContext
24
+ import json
23
25
 
24
26
  logger = logging.getLogger(__name__)
25
27
 
@@ -32,37 +34,67 @@ class SslManager(object):
32
34
  """
33
35
 
34
36
  @classmethod
35
- def new_ssl_context(cls, server_side=False, flat_kwargs=None):
37
+ def __get_path_manager(cls):
38
+ return SessionContext.instance().path_manager
39
+
40
+ @classmethod
41
+ def new_ssl_context(cls, server_side=False, ssl_kwargs=None, context_kwargs=None):
36
42
  res = None
37
43
 
38
- if flat_kwargs is None:
39
- flat_kwargs = {}
40
- kwargs = copy.copy(flat_kwargs)
44
+ if ssl_kwargs is None:
45
+ ssl_kwargs = {}
46
+ kwargs = copy.copy(ssl_kwargs)
41
47
 
42
48
  try:
43
49
  activate_ssl = kwargs.pop('activate', True)
44
50
  if activate_ssl:
51
+ if Tools.has_sub_kwargs(kwargs, 'create_default_context.'):
52
+ create_default_context_kwargs = Tools.pop_sub_kwargs(kwargs, 'create_default_context.')
53
+ else:
54
+ create_default_context_kwargs = {}
55
+
45
56
  purpose = Purpose.CLIENT_AUTH if server_side else Purpose.SERVER_AUTH
46
- res = ssl.create_default_context(purpose=purpose)
57
+ res = ssl.create_default_context(purpose=purpose, **create_default_context_kwargs)
58
+
59
+ # res.set_default_verify_paths()
47
60
 
48
- if Tools.has_sub_kwargs(kwargs, 'context.'):
49
- context_kwargs = Tools.pop_sub_kwargs(kwargs, 'context.')
61
+ if context_kwargs:
62
+ c_kwargs = copy.copy(context_kwargs)
50
63
 
51
- ciphers = context_kwargs.pop('ciphers', None)
64
+ ciphers = c_kwargs.pop('ciphers', None)
52
65
  if ciphers is not None:
66
+ if ciphers == 'OPENSSL_CIPHERS':
67
+ ciphers = SslManager.get_openssl_ciphers()
68
+ logger.debug(f"Using openssl ciphers: {ciphers}")
53
69
  res.set_ciphers(ciphers)
54
- if Tools.has_sub_kwargs(context_kwargs, 'load_cert_chain.'):
55
- load_cert_chain_kwargs = Tools.pop_sub_kwargs(context_kwargs, 'load_cert_chain.')
70
+ if Tools.has_sub_kwargs(c_kwargs, 'load_cert_chain.'):
71
+ load_cert_chain_kwargs = Tools.pop_sub_kwargs(c_kwargs, 'load_cert_chain.')
56
72
  res.load_cert_chain(**load_cert_chain_kwargs)
57
- if Tools.has_sub_kwargs(context_kwargs, 'load_verify_locations.'):
58
- load_verify_locations_kwargs = Tools.pop_sub_kwargs(context_kwargs, 'load_verify_locations.')
73
+ if Tools.has_sub_kwargs(c_kwargs, 'load_verify_locations.'):
74
+ load_verify_locations_kwargs = Tools.pop_sub_kwargs(c_kwargs, 'load_verify_locations.')
59
75
  res.load_verify_locations(**load_verify_locations_kwargs)
60
76
 
61
- # Set context attributes with remaining kwargs
62
- if len(context_kwargs) > 0:
63
- set_object_attributes_with_json_dict(res, context_kwargs)
77
+ # Set context attributes with remaining c_kwargs
78
+ if len(c_kwargs) > 0:
79
+ set_object_attributes_with_json_dict(res, c_kwargs)
80
+
81
+ logger.debug(f"Default verify paths: {ssl.get_default_verify_paths()})")
82
+ dvp = ssl.get_default_verify_paths()
83
+ if res.verify_mode != ssl.CERT_NONE and dvp.cafile is None and 'create_default_context.cafile' not in ssl_kwargs and 'load_verify_locations.cafile' not in context_kwargs:
84
+ msg_list = [f"No CA file is defined, it is not possible to verify certificates.",
85
+ f"Most common solutions:",
86
+ f" - Configure to not verify certificates, by adding/setting in table: | 'ssl.context.verify_mode' | ssl.CERT_NONE |",
87
+ f" - Be sure OpenSSL default CA file exists on system (configured path: '{dvp.openssl_cafile}'). Example of command (on Ubuntu): sudo ln -s /etc/ssl/certs/ca-certificates.crt {dvp.openssl_cafile}",
88
+ f" - Configure a CA file at context creation, by adding/setting in table: | 'ssl.create_default_context.cafile' | <path to CA file> |",
89
+ f" - Configure a CA file after context creation, by adding/setting in table: | 'ssl.context.load_verify_locations.cafile' | <path to CA file> |",
90
+ f"Note: step 'Given CACERTS_PATH = CA certs file path (from certifi package)' can be used to get the path to CA file coming with 'certifi' package that is supposed to be installed when using ssl module",
91
+ ]
92
+ raise TechnicalException("\n".join(msg_list))
93
+ logger.debug(f"Loaded CA certificates: {res.get_ca_certs()})")
94
+ logger.debug(f"Loaded ciphers: {res.get_ciphers()})")
95
+
64
96
  except Exception as exc:
65
- msg = f"Failed to create SSL context with parameters {flat_kwargs}: {exc}"
97
+ msg = f"Failed to create SSL context with parameters ({ssl_kwargs}, {context_kwargs}): {exc}"
66
98
  logger.error(msg)
67
99
  raise TechnicalException(msg) from exc
68
100
 
@@ -73,9 +105,94 @@ class SslManager(object):
73
105
  return res
74
106
 
75
107
  @classmethod
76
- def get_localhost_certificate(cls):
108
+ def get_openssl_ciphers(cls):
109
+ import subprocess
110
+ output = subprocess.run(["openssl", "ciphers"], capture_output=True).stdout
111
+ output_str = output.decode("utf-8")
112
+ return output_str.strip().split("\n")[0]
113
+
114
+ @classmethod
115
+ def get_default_certificates(cls):
116
+ dvp = ssl.get_default_verify_paths()
117
+ if not os.path.exists(dvp.cafile):
118
+ raise TechnicalException(f"openssl CA file '{dvp.cafile}' doesn't exist. Example of resolution command (on Ubuntu): sudo ln -s /etc/ssl/certs/ca-certificates.crt {dvp.cafile}")
119
+ return (dvp.cafile, dvp.capath)
120
+
121
+ @classmethod
122
+ def get_certifi_ca_certs_file_path(cls):
123
+ import certifi
124
+ return certifi.where()
125
+
126
+ # @classmethod
127
+ # def get_localhost_certificate(cls):
128
+ # here = os.path.abspath(os.path.dirname(__file__))
129
+ # certfile_path = os.path.join(here, 'resources', 'certificates', 'localhost.crt')
130
+ # keyfile_path = os.path.join(here, 'resources', 'certificates', 'localhost.key')
131
+ # return (certfile_path, keyfile_path)
132
+
133
+ @classmethod
134
+ def get_tcpbin_certificates(cls):
77
135
  here = os.path.abspath(os.path.dirname(__file__))
78
- certfile_path = os.path.join(here, 'resources', 'certificates', 'localhost.crt')
79
- keyfile_path = os.path.join(here, 'resources', 'certificates', 'localhost.key')
80
- return (certfile_path, keyfile_path)
136
+ certfile_path = os.path.join(here, 'resources', 'certificates', 'tcpbin.crt')
137
+ keyfile_path = os.path.join(here, 'resources', 'certificates', 'tcpbin.key')
138
+ ca_certfile_path = os.path.join(here, 'resources', 'certificates', 'rootCACert.pem')
139
+
140
+ cls.ensure_tcpbin_certificates_are_valid(certfile_path, keyfile_path)
141
+
142
+ return (certfile_path, keyfile_path, ca_certfile_path)
143
+
144
+ @classmethod
145
+ def ensure_tcpbin_certificates_are_valid(cls, public_key_path, private_key_path, duration_seconds=600):
146
+ cls.__get_path_manager().makedirs(public_key_path)
147
+ cls.__get_path_manager().makedirs(private_key_path)
148
+
149
+ # Verify if certificate has expired
150
+ do_generate_certificates = True
151
+ if os.path.exists(public_key_path):
152
+ cmd = f"openssl x509 -checkend {duration_seconds} -noout -in '{public_key_path}'"
153
+ command = Command(cmd, do_log_output=True, do_raise_on_stderr=False, executable="/bin/bash")
154
+ command.start()
155
+ command.join()
156
+ if command.state is CommandStates.Success:
157
+ do_generate_certificates = False
158
+ elif command.return_code == 1:
159
+ do_generate_certificates = True
160
+ else:
161
+ raise TechnicalException(f"Error while executing openssl command [{cmd}]: error code={command.return_code} ; stdout: [{command.stdout}] ; stderr: [{command.stderr}]")
162
+
163
+ # Generate new certificates if needed
164
+ if do_generate_certificates:
165
+ cmd = f"curl -s https://tcpbin.com/api/client-cert"
166
+ command = Command(cmd, do_log_output=True, do_raise_on_stderr=False, executable="/bin/bash")
167
+ command.start()
168
+ command.join()
169
+ if command.state is not CommandStates.Success:
170
+ raise TechnicalException(f"Error while executing command [{cmd}] : [{command.stderr}]")
171
+
172
+ data = json.loads(command.stdout)
173
+ with open(public_key_path, 'wt') as fout:
174
+ fout.write(data['cert'])
175
+ with open(private_key_path, 'wt') as fout:
176
+ fout.write(data['key'])
177
+
178
+ @classmethod
179
+ def generate_new_self_signed_key_files(cls, public_key_path, private_key_path, openssl_args):
180
+ cls.__get_path_manager().makedirs(public_key_path)
181
+ cls.__get_path_manager().makedirs(private_key_path)
182
+
183
+ cmd = f"openssl req -out '{public_key_path}' -keyout '{private_key_path}' {openssl_args}"
184
+ command = Command(cmd, do_log_output=True, do_raise_on_stderr=False, executable="/bin/bash")
185
+ command.start()
186
+ command.join()
187
+
188
+ if command.state is not CommandStates.Success:
189
+ raise TechnicalException(f"Error while executing openssl command [{cmd}] : [{command.stderr}]")
190
+
191
+ @classmethod
192
+ def generate_new_self_signed_key_files_for_localhost(cls, public_key_path, private_key_path, algorithm='rsa:2048'):
193
+ SslManager.generate_new_self_signed_key_files(
194
+ public_key_path, private_key_path,
195
+ f"-x509 -newkey {algorithm} -noenc -sha256 -subj '/CN=localhost' -extensions EXT \
196
+ -config <( printf \"[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth\")"
197
+ )
81
198
 
@@ -15,7 +15,7 @@
15
15
 
16
16
  from holado_test.scenario.step_tools import StepTools
17
17
  from holado.common.context.session_context import SessionContext
18
- from holado_test.behave.behave import *
18
+ from holado_test.behave.behave import * # @UnusedWildImport
19
19
  import logging
20
20
  from holado_core.common.tools.string_tools import StrTools
21
21
 
@@ -15,7 +15,7 @@
15
15
 
16
16
  from holado_test.scenario.step_tools import StepTools
17
17
  from holado.common.context.session_context import SessionContext
18
- from holado_test.behave.behave import *
18
+ from holado_test.behave.behave import * # @UnusedWildImport
19
19
  import logging
20
20
  from holado_core.common.exceptions.verify_exception import VerifyException
21
21
  from holado_core.common.tools.converters.converter import Converter
@@ -15,7 +15,7 @@
15
15
 
16
16
  from holado_test.scenario.step_tools import StepTools
17
17
  from holado.common.context.session_context import SessionContext
18
- from holado_test.behave.behave import *
18
+ from holado_test.behave.behave import * # @UnusedWildImport
19
19
  from holado_test.behave.behave import render_step_table
20
20
  import logging
21
21
  from holado_test.behave.scenario.behave_step_tools import BehaveStepTools
@@ -15,7 +15,7 @@
15
15
 
16
16
  from holado_test.scenario.step_tools import StepTools
17
17
  from holado.common.context.session_context import SessionContext
18
- from holado_test.behave.behave import *
18
+ from holado_test.behave.behave import * # @UnusedWildImport
19
19
  from datetime import datetime, timedelta
20
20
  from holado_python.common.tools.datetime import DateTime, DurationUnit
21
21
  import logging
@@ -15,7 +15,7 @@
15
15
 
16
16
  from holado_test.scenario.step_tools import StepTools
17
17
  from holado.common.context.session_context import SessionContext
18
- from holado_test.behave.behave import *
18
+ from holado_test.behave.behave import * # @UnusedWildImport
19
19
  import logging
20
20
  from holado_core.common.exceptions.verify_exception import VerifyException
21
21
  from holado_core.common.tools.converters.converter import Converter
@@ -40,7 +40,7 @@ def __get_variable_manager():
40
40
  def step_impl(context, var_name, code_size, content, prefix):
41
41
  """Return a code computed with content as input.
42
42
  Dynamic part of the code is computed with blake2b hash algorithm.
43
- If code_size (minus length of prefix if defined) is not a multiple of 2, it is rounded to the multiple of 2 juste below.
43
+ If code_size (minus length of prefix if defined) is not a multiple of 2, it is rounded to the multiple of 2 just below.
44
44
  """
45
45
  var_name = StepTools.evaluate_variable_name(var_name)
46
46
  code_size = StepTools.evaluate_scenario_parameter(code_size)
@@ -13,7 +13,7 @@
13
13
  #################################################
14
14
 
15
15
 
16
- from holado_test.behave.behave import *
16
+ from holado_test.behave.behave import * # @UnusedWildImport
17
17
  from holado.common.context.session_context import SessionContext
18
18
  from holado_test.scenario.step_tools import StepTools
19
19
  import logging
@@ -13,7 +13,7 @@
13
13
  #################################################
14
14
 
15
15
 
16
- from holado_test.behave.behave import *
16
+ from holado_test.behave.behave import * # @UnusedWildImport
17
17
  from holado.common.context.session_context import SessionContext
18
18
  from holado_test.scenario.step_tools import StepTools
19
19
  import logging
@@ -15,14 +15,14 @@
15
15
 
16
16
  from holado_test.scenario.step_tools import StepTools
17
17
  from holado.common.context.session_context import SessionContext
18
- from holado_test.behave.behave import *
18
+ from holado_test.behave.behave import * # @UnusedWildImport
19
19
  import logging
20
20
  from holado_test.behave.scenario.behave_step_tools import BehaveStepTools
21
21
  from holado_value.common.tables.converters.value_table_converter import ValueTableConverter
22
22
  from holado_python.standard_library.socket.blocking_socket import TCPBlockingSocketClient
23
23
  from holado_python.standard_library.socket.echo_server import EchoTCPBlockingSocketServer
24
24
  from holado_python.standard_library.socket.message_socket import MessageTCPNonBlockingSocketClient, MessageTCPBlockingSocketClient
25
- from holado_core.common.handlers.wait import WaitEndChange
25
+ from holado_core.common.handlers.wait import WaitEndChange, WaitChange
26
26
  from holado_core.common.exceptions.functional_exception import FunctionalException
27
27
  from holado_python.standard_library.socket.non_blocking_socket import TCPNonBlockingSocketClient
28
28
 
@@ -85,7 +85,9 @@ def step_impl(context, var_name):
85
85
 
86
86
  @Step(r"start \(socket client: (?P<server_varname>{Variable})\)")
87
87
  def step_impl(context, server_varname):
88
- """Start a non blocking socket client.
88
+ """Start a socket client.
89
+ It starts a thread listening incoming data.
90
+ This step is needed for non blocking socket clients to manage incoming data.
89
91
  Note: current implementation uses 'start' method parameters default values.
90
92
  """
91
93
  server = StepTools.evaluate_scenario_parameter(server_varname)
@@ -173,6 +175,89 @@ def step_impl(context, var_name, socket_varname):
173
175
 
174
176
  __get_variable_manager().register_variable(var_name, res)
175
177
 
178
+ @Step(r"(?P<var_name>{Variable}) = received data \(socket: (?P<socket_varname>{Variable})\)")
179
+ def step_impl(context, var_name, socket_varname):
180
+ """Get currently received data
181
+ This step works only with clients that are started, so that listening thread is started.
182
+ """
183
+ var_name = StepTools.evaluate_variable_name(var_name)
184
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
185
+
186
+ res = sock.received_data
187
+
188
+ __get_variable_manager().register_variable(var_name, res)
189
+
190
+ @Step(r"(?P<var_name>{Variable}) = size of received data \(socket: (?P<socket_varname>{Variable})\)")
191
+ def step_impl(context, var_name, socket_varname):
192
+ """Get received messages without removing from socket
193
+ """
194
+ var_name = StepTools.evaluate_variable_name(var_name)
195
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
196
+
197
+ res = sock.received_data_size
198
+
199
+ __get_variable_manager().register_variable(var_name, res)
200
+
201
+ @Step(r"socket (?P<socket_varname>{Variable}) doesn't receive any data(?: \((?:timeout: (?P<timeout_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
202
+ def step_impl(context, socket_varname, timeout_sec, polling_sec):
203
+ """Wait and verify socket doesn't receive any data
204
+ """
205
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
206
+ timeout_sec = StepTools.evaluate_scenario_parameter(timeout_sec)
207
+ polling_sec = StepTools.evaluate_scenario_parameter(polling_sec)
208
+
209
+ if timeout_sec is None:
210
+ timeout_sec = 10
211
+
212
+ wait = WaitChange(f"Verify no data is received (socket: {sock})",
213
+ lambda: sock.received_data_size,
214
+ timeout_seconds=timeout_sec, polling_seconds=polling_sec)
215
+ wait.without_raise_on_timeout()
216
+ data_size = wait.execute()
217
+ if data_size > 0:
218
+ raise FunctionalException(f"[{sock.name}] Socket has received data of size {data_size}")
219
+
220
+ @Step(r"await socket (?P<socket_varname>{Variable}) receives a data(?: \((?:timeout: (?P<timeout_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
221
+ def step_impl(context, socket_varname, timeout_sec, polling_sec):
222
+ """Wait socket receives at least one data
223
+ """
224
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
225
+ timeout_sec = StepTools.evaluate_scenario_parameter(timeout_sec)
226
+ polling_sec = StepTools.evaluate_scenario_parameter(polling_sec)
227
+
228
+ if timeout_sec is None:
229
+ timeout_sec = 10
230
+
231
+ wait = WaitChange(f"Wait data reception (socket: {sock})",
232
+ lambda: sock.received_data_size,
233
+ timeout_seconds=timeout_sec, polling_seconds=polling_sec)
234
+ wait.without_raise_on_timeout()
235
+ data_size = wait.execute()
236
+ if data_size == 0:
237
+ raise FunctionalException(f"[{sock.name}] No data was received (timeout: {wait.timeout} seconds)")
238
+
239
+ @Step(r"await socket (?P<socket_varname>{Variable}) receives data(?: \((?:first timeout: (?P<first_timeout_sec>{Float}) s)?(?: ; )?(?:window: (?P<window_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
240
+ def step_impl(context, socket_varname, first_timeout_sec, window_sec, polling_sec):
241
+ """Wait socket stop to receive data
242
+ """
243
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
244
+ first_timeout_sec = StepTools.evaluate_scenario_parameter(first_timeout_sec)
245
+ window_sec = StepTools.evaluate_scenario_parameter(window_sec)
246
+ polling_sec = StepTools.evaluate_scenario_parameter(polling_sec)
247
+
248
+ wait = WaitEndChange(f"Wait end of data reception (socket: {sock})",
249
+ lambda: sock.received_data_size,
250
+ first_timeout_seconds=first_timeout_sec, window_seconds=window_sec, polling_seconds=polling_sec)
251
+ wait.without_raise_on_timeout()
252
+ data_size = wait.execute()
253
+ if data_size == 0:
254
+ raise FunctionalException(f"[{sock.name}] No data was received (timeout: {wait.timeout} seconds)")
255
+
256
+ @Given(r"reset stored received data in socket (?P<socket_varname>{Variable})")
257
+ def step_impl(context, socket_varname):
258
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
259
+ sock.reset_received_data()
260
+
176
261
 
177
262
 
178
263
  # For client and servers managing messages
@@ -232,39 +317,68 @@ def step_impl(context, var_name, socket_varname):
232
317
 
233
318
  __get_variable_manager().register_variable(var_name, res)
234
319
 
235
- @Step(r"wait socket (?P<socket_varname>{Variable}) stops to receive data(?: \((?:first timeout: (?P<first_timeout_sec>{Float}) s)?(?: ; )?(?:window: (?P<window_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
236
- def step_impl(context, socket_varname, first_timeout_sec, window_sec, polling_sec):
237
- """Get received messages without removing from socket
320
+ @Step(r"socket (?P<socket_varname>{Variable}) doesn't receive any message(?: \((?:timeout: (?P<timeout_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
321
+ def step_impl(context, socket_varname, timeout_sec, polling_sec):
322
+ """Wait and verify socket doesn't receive any message
238
323
  """
239
324
  sock = StepTools.evaluate_scenario_parameter(socket_varname)
325
+ timeout_sec = StepTools.evaluate_scenario_parameter(timeout_sec)
326
+ polling_sec = StepTools.evaluate_scenario_parameter(polling_sec)
327
+
328
+ if timeout_sec is None:
329
+ timeout_sec = 10
330
+
331
+ wait = WaitChange(f"Wait end of message reception (socket: {sock})",
332
+ lambda: sock.nb_messages,
333
+ timeout_seconds=timeout_sec, polling_seconds=polling_sec)
334
+ wait.without_raise_on_timeout()
335
+ nb_messages = wait.execute()
336
+ if nb_messages > 0:
337
+ raise FunctionalException(f"[{sock.name}] Socket has received {nb_messages} messages (timeout: {wait.timeout} seconds)")
338
+
339
+ @Step(r"await socket (?P<socket_varname>{Variable}) receives (?:(?P<no_str>no) )?messages(?: \((?:first timeout: (?P<first_timeout_sec>{Float}) s)?(?: ; )?(?:window: (?P<window_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
340
+ def step_impl(context, socket_varname, no_str, first_timeout_sec, window_sec, polling_sec):
341
+ """Wait until socket receives messages or no messages.
342
+ Wait during max first_timeout_sec duration for a first message, then, and after each new message, wait during max window_sec duration for a new message.
343
+ If no message is received during first_timeout_sec duration, an error is raised only if messages are waited (ie 'no ' is not added when calling step).
344
+ """
345
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
346
+ no_messages = no_str is not None
240
347
  first_timeout_sec = StepTools.evaluate_scenario_parameter(first_timeout_sec)
241
348
  window_sec = StepTools.evaluate_scenario_parameter(window_sec)
242
349
  polling_sec = StepTools.evaluate_scenario_parameter(polling_sec)
243
350
 
244
- wait = WaitEndChange(f"Wait end of data reception (socket: {sock})",
245
- lambda: sock.received_data_size,
351
+ wait = WaitEndChange(f"Wait until socket receives {no_str if no_str is not None else ''}messages (socket: {sock})",
352
+ lambda: sock.nb_messages,
246
353
  first_timeout_seconds=first_timeout_sec, window_seconds=window_sec, polling_seconds=polling_sec)
247
354
  wait.without_raise_on_timeout()
248
- data_size = wait.execute()
249
- if data_size == 0:
250
- raise FunctionalException(f"[{sock.name}] No data was received (timeout: {wait.timeout} seconds)")
355
+ nb_messages = wait.execute()
356
+ if not no_messages and nb_messages == 0:
357
+ raise FunctionalException(f"[{sock.name}] No message was received (timeout: {wait.timeout} seconds)")
251
358
 
252
- @Step(r"wait socket (?P<socket_varname>{Variable}) stops to receive messages(?: \((?:first timeout: (?P<first_timeout_sec>{Float}) s)?(?: ; )?(?:window: (?P<window_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
253
- def step_impl(context, socket_varname, first_timeout_sec, window_sec, polling_sec):
359
+ @Step(r"await socket (?P<socket_varname>{Variable}) receives a message(?: \((?:timeout: (?P<timeout_sec>{Float}) s)?(?: ; )?(?:polling: (?P<polling_sec>{Float}) s)?\))?")
360
+ def step_impl(context, socket_varname, timeout_sec, polling_sec):
254
361
  """Get received messages without removing from socket
255
362
  """
256
363
  sock = StepTools.evaluate_scenario_parameter(socket_varname)
257
- first_timeout_sec = StepTools.evaluate_scenario_parameter(first_timeout_sec)
258
- window_sec = StepTools.evaluate_scenario_parameter(window_sec)
364
+ timeout_sec = StepTools.evaluate_scenario_parameter(timeout_sec)
259
365
  polling_sec = StepTools.evaluate_scenario_parameter(polling_sec)
260
366
 
261
- wait = WaitEndChange(f"Wait end of message reception (socket: {sock})",
262
- lambda: sock.nb_messages,
263
- first_timeout_seconds=first_timeout_sec, window_seconds=window_sec, polling_seconds=polling_sec)
367
+ if timeout_sec is None:
368
+ timeout_sec = 10
369
+
370
+ wait = WaitChange(f"Wait a message reception (socket: {sock})",
371
+ lambda: sock.nb_messages,
372
+ timeout_seconds=timeout_sec, polling_seconds=polling_sec)
264
373
  wait.without_raise_on_timeout()
265
374
  nb_messages = wait.execute()
266
375
  if nb_messages == 0:
267
376
  raise FunctionalException(f"[{sock.name}] No message was received (timeout: {wait.timeout} seconds)")
268
377
 
378
+ @Given(r"reset stored received messages in socket (?P<socket_varname>{Variable})")
379
+ def step_impl(context, socket_varname):
380
+ sock = StepTools.evaluate_scenario_parameter(socket_varname)
381
+ sock.reset_received_messages()
382
+
269
383
 
270
384