contrast-agent 6.15.3 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
  3. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +1 -1
  4. data/ext/cs__assess_module/cs__assess_module.c +0 -19
  5. data/ext/cs__assess_test/cs__assess_tests.c +1 -1
  6. data/ext/cs__common/cs__common.c +17 -18
  7. data/ext/cs__common/cs__common.h +7 -11
  8. data/ext/cs__contrast_patch/cs__contrast_patch.c +16 -24
  9. data/ext/extconf_common.rb +79 -0
  10. data/lib/contrast/agent/assess/policy/policy.rb +1 -1
  11. data/lib/contrast/agent/assess/policy/source_method.rb +1 -0
  12. data/lib/contrast/agent/deadzone/policy/policy.rb +1 -1
  13. data/lib/contrast/agent/patching/policy/policy.rb +2 -2
  14. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +3 -0
  15. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli.rb +1 -1
  16. data/lib/contrast/agent/reporting/reporter.rb +19 -4
  17. data/lib/contrast/agent/reporting/reporting_events/agent_effective_config.rb +32 -0
  18. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +7 -0
  19. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +3 -1
  20. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +11 -7
  21. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +15 -7
  22. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +4 -2
  23. data/lib/contrast/agent/reporting/reporting_workers/application_server_worker.rb +3 -0
  24. data/lib/contrast/agent/reporting/reporting_workers/reporter_heartbeat.rb +3 -0
  25. data/lib/contrast/agent/reporting/reporting_workers/server_settings_worker.rb +3 -0
  26. data/lib/contrast/agent/telemetry/base.rb +37 -12
  27. data/lib/contrast/agent/telemetry/client.rb +1 -3
  28. data/lib/contrast/agent/telemetry/telemetry.rb +0 -7
  29. data/lib/contrast/agent/thread/thread_watcher.rb +2 -2
  30. data/lib/contrast/agent/version.rb +1 -1
  31. data/lib/contrast/components/agent.rb +1 -1
  32. data/lib/contrast/components/api.rb +3 -3
  33. data/lib/contrast/components/app_context.rb +1 -1
  34. data/lib/contrast/components/assess.rb +1 -1
  35. data/lib/contrast/components/assess_rules.rb +2 -2
  36. data/lib/contrast/components/base.rb +3 -3
  37. data/lib/contrast/components/config/sources.rb +12 -9
  38. data/lib/contrast/components/config.rb +2 -2
  39. data/lib/contrast/components/protect.rb +2 -2
  40. data/lib/contrast/components/sampling.rb +7 -5
  41. data/lib/contrast/components/settings.rb +1 -1
  42. data/lib/contrast/config/certification_configuration.rb +1 -1
  43. data/lib/contrast/config/configuration_files.rb +47 -0
  44. data/lib/contrast/config/diagnostics/command_line.rb +24 -0
  45. data/lib/contrast/config/{config.rb → diagnostics/config.rb} +21 -6
  46. data/lib/contrast/config/diagnostics/contrast_ui.rb +24 -0
  47. data/lib/contrast/config/diagnostics/effective_config.rb +28 -0
  48. data/lib/contrast/config/diagnostics/effective_config_value.rb +14 -0
  49. data/lib/contrast/config/diagnostics/environment_variables.rb +51 -0
  50. data/lib/contrast/config/{diagnostics.rb → diagnostics/monitor.rb} +10 -10
  51. data/lib/contrast/config/diagnostics/source_config_value.rb +51 -0
  52. data/lib/contrast/config/diagnostics/tools.rb +188 -0
  53. data/lib/contrast/config/diagnostics/user_configuration_file.rb +44 -0
  54. data/lib/contrast/config/request_audit_configuration.rb +1 -1
  55. data/lib/contrast/config/server_configuration.rb +1 -1
  56. data/lib/contrast/configuration.rb +90 -57
  57. data/lib/contrast/utils/hash_utils.rb +43 -0
  58. data/lib/contrast/utils/json.rb +46 -0
  59. data/lib/contrast/utils/middleware_utils.rb +4 -4
  60. data/lib/contrast/utils/net_http_base.rb +75 -26
  61. data/lib/contrast/utils/object_share.rb +3 -3
  62. data/lib/contrast.rb +0 -16
  63. data/ruby-agent.gemspec +4 -8
  64. metadata +40 -25
  65. data/lib/contrast/config/diagnostics_tools.rb +0 -99
  66. data/lib/contrast/config/effective_config.rb +0 -131
  67. data/lib/contrast/config/effective_config_value.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb55239bd37c7b0d2c3adc47d2e47ff25e331694b9be68522a29f8e4ce8c1220
4
- data.tar.gz: 41a5a677403dd10c0dcd67673b32e32aa8f8ad04a82d963891f95ceaa25b46a1
3
+ metadata.gz: 81222798666699f86b31b925d531d2ee2229eb7934582d2a502cc61de3ca4e0b
4
+ data.tar.gz: 7dd4d41a58600b7d57b5f57cf95c42bd2f6d198f5f1906e93751e33c09efa3e0
5
5
  SHA512:
6
- metadata.gz: 94aaa0a8ed0b9fb08fb5c206bee3695cd1cc1f3a8b7752fa8c52abfb563a4e58fac60162ab13c4f06ceb785532ae1a76b93dcc8f348e99d29b112b265a88051b
7
- data.tar.gz: 658421a2a8558bac001eb707340f0bc763012d06b9fdcfe1137fb3ceff6f53966d7cc9af9bced07f08411b5e44af1ad5c4f5805b54abaae0ad71dcc81011fbb9
6
+ metadata.gz: 02e5d3aa6b342e8c4277ad6cefde65819aed6f6b4a1079cfe7528fcce236ec702aa8a63fc756c403c0df6e3ef38d5d25dc9f1c6e5c450d272122d699b6fd9872
7
+ data.tar.gz: 9cc83b5f69edeea949784ae766be7e02c1d589e58b2af5b5c1bd7975dcee1450d294bc7de647f60a9a3f18a1ea05a43bfe452a52d4760ed1b1cfcb0a7339a6ab
@@ -62,7 +62,7 @@ VALUE rb_fiber_yield_hook(int argc, const VALUE *argv) {
62
62
  return rb_fiber_yield_original(argc, argv);
63
63
  }
64
64
 
65
- int install_fiber_hooks() {
65
+ int install_fiber_hooks(void) {
66
66
  rb_fiber_new_original = rb_fiber_new;
67
67
  patch_via_funchook(&rb_fiber_new_original, &rb_fiber_new_hook);
68
68
 
@@ -28,6 +28,6 @@ VALUE rb_fiber_new_hook(VALUE (*func)(ANYARGS), VALUE obj);
28
28
 
29
29
  VALUE rb_fiber_yield_hook(int argc, const VALUE *argv);
30
30
 
31
- static int install_fiber_hooks();
31
+ static int install_fiber_hooks(void);
32
32
 
33
33
  void Init_cs__assess_fiber_track(void);
@@ -115,23 +115,4 @@ void Init_cs__assess_module(void) {
115
115
 
116
116
  contrast_register_patch("Module", "module_eval",
117
117
  contrast_assess_module_module_eval);
118
- /*
119
- * We patch these for better ancestors handling, and only for older ruby
120
- * versions.
121
- */
122
- // if (rb_ver_below_three()) {
123
- /*
124
- * `included` is a private method. We should make it public, patch it,
125
- * and make our new method public
126
- */
127
- // contrast_register_patch("Module", "included",
128
- // contrast_assess_module_included);
129
- /*
130
- * The `prepend` patch may actually be the issue, if we're not properly
131
- * passing along the call/context. It could be that my attempt to fix
132
- * `included` left this section unreachable.
133
- */
134
- // contrast_register_patch("Module", "prepend",
135
- // contrast_assess_module_prepend);
136
- // }
137
118
  }
@@ -1,4 +1,4 @@
1
- #include "../cs__common/cs__common.h";
1
+ #include "../cs__common/cs__common.h"
2
2
  #include "ruby.h"
3
3
  #include <ruby/re.h>
4
4
 
@@ -28,8 +28,12 @@ void patch_via_funchook(void *original_function, void *hook_function) {
28
28
 
29
29
  void *funchook_lib_handle;
30
30
  void *funchook_reference, *(*funchook_create)(void);
31
+ /* This variables are used to load the funchook dylib */
32
+ #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
33
+ #pragma GCC diagnostic push
31
34
  int prepareResult, (*funchook_prepare)(void *, void **, void *);
32
35
  int installResult, (*funchook_install)(void *, int);
36
+ #pragma GCC diagnostic pop
33
37
 
34
38
  funchook_lib_handle =
35
39
  dlopen(StringValueCStr(funchook_path), RTLD_NOW | RTLD_GLOBAL);
@@ -55,7 +59,7 @@ void contrast_alias_method(const VALUE target, const char *to,
55
59
  ID2SYM(rb_intern(to)), ID2SYM(rb_intern(from)));
56
60
  }
57
61
 
58
- VALUE contrast_patcher() {
62
+ VALUE contrast_patcher(void) {
59
63
  return patcher;
60
64
  }
61
65
 
@@ -102,7 +106,7 @@ VALUE contrast_check_and_register_instance_patch(const char *module_name,
102
106
  VALUE(c_fn)(const int, VALUE *,
103
107
  const VALUE)) {
104
108
 
105
- VALUE object, method, is_prepended, patch_type;
109
+ VALUE object, method, is_prepended;
106
110
  /* check if method is prepended */
107
111
  object = rb_const_get(rb_cObject, rb_intern(module_name));
108
112
  method = ID2SYM(rb_intern(method_name));
@@ -119,7 +123,7 @@ VALUE contrast_check_and_register_instance_patch(const char *module_name,
119
123
  }
120
124
  }
121
125
 
122
- static VALUE
126
+ VALUE
123
127
  _contrast_register_patch(const char *module_name, const char *method_name,
124
128
  VALUE(c_fn)(const int, VALUE *, const VALUE),
125
129
  patch_impl patch) {
@@ -175,13 +179,6 @@ _contrast_register_patch(const char *module_name, const char *method_name,
175
179
  return SYM2ID(underlying_method_name);
176
180
  }
177
181
 
178
- int rb_ver_below_three() {
179
- int ruby_version =
180
- FIX2INT(rb_funcall(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")),
181
- rb_intern("to_i"), 0));
182
- return ruby_version < 3;
183
- }
184
-
185
182
  /* used for direct check on object: String.cs__prepended? *args */
186
183
  extern VALUE contrast_check_prepended(VALUE self, VALUE method_name,
187
184
  VALUE is_instance) {
@@ -200,17 +197,18 @@ extern VALUE contrast_lookout_prepended(VALUE self, VALUE object_name,
200
197
  return result;
201
198
  }
202
199
 
203
- static VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
200
+ VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
204
201
  VALUE is_instance) {
205
- VALUE entry, ancestors, object_idx, entry_methods;
202
+ VALUE entry, ancestors, entry_methods;
206
203
  VALUE result = Qfalse;
207
- int i;
208
- int y;
204
+ VALUE object_idx = Qnil;
205
+ long y;
206
+ unsigned long i;
209
207
 
210
208
  /* get self ancestors */
211
209
  ancestors = rb_mod_ancestors(object);
212
210
  /* get the size of the array */
213
- int length = RARRAY_LEN(ancestors);
211
+ unsigned long length = RARRAY_LEN(ancestors);
214
212
  /* Locate self in ancestors: */
215
213
  for (i = 0; i < length; ++i) {
216
214
  entry = rb_ary_entry(ancestors, i);
@@ -226,14 +224,14 @@ static VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
226
224
  for (i = 0; i < object_idx; ++i) {
227
225
  entry = rb_ary_entry(ancestors, i);
228
226
  if (is_instance == Qtrue) {
229
- entry_methods = rb_class_instance_methods(1, entry, entry);
227
+ entry_methods = rb_class_instance_methods(1UL, &entry, entry);
230
228
  } else {
231
- entry_methods = rb_obj_singleton_methods(1, entry, entry);
229
+ entry_methods = rb_obj_singleton_methods(1UL, &entry, entry);
232
230
  }
233
231
 
234
232
  /* Loop through the instance/singleton methods of the prepended modules
235
233
  */
236
- int entry_methods_length = RARRAY_LEN(entry_methods);
234
+ long entry_methods_length = RARRAY_LEN(entry_methods);
237
235
  for (y = 0; y <= entry_methods_length; ++y) {
238
236
  if (rb_ary_entry(entry_methods, y) == method_name) {
239
237
  result = Qtrue;
@@ -244,6 +242,7 @@ static VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
244
242
  break;
245
243
  }
246
244
  }
245
+
247
246
  return result;
248
247
  }
249
248
 
@@ -10,6 +10,9 @@ typedef enum {
10
10
  IMPL_PREPEND_SINGLETON,
11
11
  } patch_impl;
12
12
 
13
+ /* the unused variable warning is triggered for gcc only */
14
+ #pragma GCC diagnostic ignored "-Wunused-variable"
15
+ #pragma GCC diagnostic push
13
16
  static VALUE cs__send_method;
14
17
  static VALUE cs__alias_method_sym;
15
18
 
@@ -34,14 +37,7 @@ static VALUE rb_sym_alias_instance;
34
37
  static VALUE rb_sym_alias_singleton;
35
38
  static VALUE rb_sym_prepend_instance;
36
39
  static VALUE rb_sym_prepend_singleton;
37
-
38
- /*
39
- * Check if ruby version is < 3.0.0.
40
- * We are using this for handling ancestors of included modules.
41
- * Since this is fixed after Ruby 3.0.0 we should remove this after
42
- * dropping support for older versions, as no longer needed.
43
- */
44
- int rb_ver_below_three();
40
+ #pragma GCC diagnostic pop
45
41
 
46
42
  void patch_via_funchook(void *original_function, void *hook_function);
47
43
 
@@ -73,11 +69,11 @@ VALUE contrast_register_prepend_patch(const char *module_name,
73
69
  VALUE(c_fn)(const int, VALUE *,
74
70
  const VALUE));
75
71
 
76
- static VALUE _contrast_register_patch(const char *module_name, const char *method_name,
72
+ VALUE _contrast_register_patch(const char *module_name, const char *method_name,
77
73
  VALUE(c_fn)(const int, VALUE *, const VALUE),
78
74
  patch_impl patch_impl);
79
75
 
80
- static VALUE _contrast_check_prepended(VALUE self, VALUE method_name, VALUE is_instance);
76
+ VALUE _contrast_check_prepended(VALUE self, VALUE method_name, VALUE is_instance);
81
77
 
82
78
  extern VALUE contrast_check_prepended(VALUE self, VALUE method_name, VALUE is_instance);
83
79
 
@@ -90,7 +86,7 @@ VALUE contrast_check_and_register_instance_patch(const char *module_name,
90
86
  VALUE(c_fn)(const int, VALUE *,
91
87
  const VALUE));
92
88
 
93
- VALUE contrast_patcher();
89
+ VALUE contrast_patcher(void);
94
90
 
95
91
  void Init_cs__common(void);
96
92
 
@@ -97,8 +97,6 @@ VALUE rescue_func(VALUE arg1) {
97
97
  */
98
98
  exception = rb_errinfo();
99
99
  rb_exc_raise(exception);
100
-
101
- return Qnil;
102
100
  }
103
101
 
104
102
  /**
@@ -109,17 +107,18 @@ VALUE rescue_func(VALUE arg1) {
109
107
  *
110
108
  **/
111
109
  VALUE contrast_patch_call_ensure(const VALUE *args) {
112
- // we do not need to ensure that post patch is called if no error was thrown
110
+ /* we do not need to ensure that post patch is called if no error was thrown */
113
111
  if (!RTEST(rb_errinfo())) {
114
112
  return Qnil;
115
113
  }
116
114
 
117
115
  int argc;
118
- VALUE object, preshift, method_policy, method;
116
+ VALUE object, preshift, method_policy;
119
117
  VALUE *argv;
118
+ /* VALUE method; */
120
119
 
121
120
  object = args[0];
122
- method = args[1];
121
+ /* method = args[1]; */
123
122
  argc = NUM2INT(args[2]);
124
123
  argv = (VALUE *)args[3];
125
124
  method_policy = args[4];
@@ -137,8 +136,8 @@ VALUE ensure_wrapper(const VALUE *args) {
137
136
  original_args = (VALUE)args[1];
138
137
  ensure_args = (VALUE)args[2];
139
138
 
140
- // this ensure if being treated as a rescue due to issues surrounding
141
- // Kernel#throw
139
+ /* this ensure if being treated as a rescue due to issues surrounding
140
+ Kernel#throw */
142
141
  return rb_ensure(original_method, original_args, contrast_patch_call_ensure,
143
142
  (VALUE)ensure_args);
144
143
  }
@@ -154,7 +153,7 @@ VALUE contrast_call_super(const VALUE *args) {
154
153
 
155
154
  VALUE contrast_run_patches(const VALUE *wrapped_args) {
156
155
  VALUE impl, method, method_policy, object, original_args, original_ret,
157
- preshift, transformed_ret;
156
+ preshift;
158
157
  int argc;
159
158
  VALUE *argv;
160
159
  VALUE ensure_args[6];
@@ -257,9 +256,15 @@ VALUE contrast_ensure_function(const VALUE method_policy) {
257
256
 
258
257
  VALUE contrast_patch_dispatch(const int argc, const VALUE *argv,
259
258
  const patch_impl impl, const VALUE object) {
259
+ /*
260
+ * Silence the known variable unused warning detected by compiler.
261
+ * Since this Variable is set by cases and we check if it is set or not.
262
+ * To disalbe this remove the -Wno-maybe-uninitialized flag.
263
+ */
264
+
260
265
  VALUE cs__method, known, method, method_policy;
261
266
  VALUE original_args[4];
262
- int do_contrast, nested_scope;
267
+ long do_contrast, nested_scope;
263
268
 
264
269
  /* Do Contrast analysis, unless our subsequent checks tell us no. */
265
270
  do_contrast = 1;
@@ -369,6 +374,8 @@ call_original:
369
374
  case IMPL_PREPEND_SINGLETON:
370
375
  return contrast_call_super(original_args);
371
376
  };
377
+
378
+ return Qfalse;
372
379
  }
373
380
 
374
381
  VALUE contrast_alias_instance_patch(const int argc, const VALUE *argv,
@@ -490,21 +497,6 @@ VALUE contrast_patch_prepend(const VALUE self, const VALUE originalModule,
490
497
  }
491
498
  rb_prepend_module(originalModule, module);
492
499
 
493
- if (rb_ver_below_three()) {
494
- VALUE module_at;
495
- VALUE rb_incl_in_mod_ary =
496
- rb_funcall(originalModule, rb_intern("included_in"), 0);
497
- if (RB_TYPE_P(rb_incl_in_mod_ary, T_ARRAY)) {
498
- int i = 0;
499
- int size = RARRAY_LEN(rb_incl_in_mod_ary);
500
- for (i = 0; i < size; ++i) {
501
- module_at = rb_ary_entry(rb_incl_in_mod_ary, i);
502
- if (RB_TYPE_P(module_at, T_MODULE)) {
503
- rb_include_module(module_at, module);
504
- }
505
- }
506
- }
507
- }
508
500
  return Qtrue;
509
501
  }
510
502
 
@@ -2,18 +2,97 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'mkmf'
5
+ require 'rbconfig'
5
6
  require_relative '../lib/contrast/agent/version'
6
7
 
8
+ # The mkmf.rb file uses all passed flags from Ruby configuration (RbConfig::CONFIG) on
9
+ # Ruby build time. Problem with Clang and GCC is that it do not keep up with c89 and finds
10
+ # error on including <ryby.h> as not allowing inline variables.
11
+ #
12
+ # Ruby inlining is a C99 feature that is allowed to be used, because the Ruby configure script
13
+ # can work around the absence of the inline feature with a simple #define:
14
+ #
15
+ # ifndef __cplusplus
16
+ # define inline
17
+ # endif
18
+ #
19
+ # There is difference between using c89 and gnu89, as the latter is extended version of the
20
+ # 1989 standard allowing features like // comments for example. This makes the use of the
21
+ # gnu not favorable since it will skip some checks and would make wholes in the c89 standard
22
+ # support.
23
+ #
24
+ # We can directly append the CFLAGS we need with ENV variable used to create the makefile.
25
+ # MAKEFILE_CONFIG is extension of the RbConfig::CONFIG used to build the Ruby itself.
26
+ # So if we try to run c89 on clang it will brake because of detecting errors from external
27
+ # library used - Ruby itself build with different standard as it seems. This means the
28
+ # Ruby must be compiled beforehand with the compiler forced to C89.
29
+ #
30
+ # This makes the C dialect of choice to be gnu89 with strict pedantic warnings reported as errors,
31
+ # and making the compiler configurable by flags:
32
+ STANDARD_FLAGS = '-std=gnu89'
33
+ CLANG = 'clang'
34
+
35
+ # TODO: RUBY-999999 Add -pedantic flag, remove all warning flags and see to it that as many as possible become obsolete.
36
+ # Note: Adding -pedantic could raise <ruby.h> warnings, and we are not in control of that code.
37
+ # e.g. error: '_Bool' is a C99 extension [-Werror,-Wc99-extensions] ; empty macros and etc.
38
+ #
39
+ # -Wno-int-conversion => Passing VALUEs as function args but required as unsigned long parameters.
40
+ # -Werror => report all warnings as errors
41
+ # -Wshorten-64-to-32 => is recognized by clang but not in gcc.
42
+ # Use alternative if viable. [Wno-narrowing]
43
+ # -Wno-maybe-uninitialized is used by clang but not gcc
44
+ #
45
+ # Note: Clang supports old style function definition e.g. void func () {}
46
+ # but the gcc is not.
47
+ # make sure to add parameters type => void func (void) {}.
48
+ # All Changes must be tested against both clang and gcc.
49
+ WARNING_FLAGS = %w[
50
+ -Wno-language-extension-token -Wno-incompatible-function-pointer-types
51
+ -Wno-declaration-after-statement -Wno-variadic-macros -Wno-int-conversion
52
+ -Wno-incompatible-pointer-types -Wno-narrowing
53
+ ].freeze # rubocop:disable Security/Object/Freeze
54
+
55
+ # Flags that are only recognized by gcc:
56
+ GCC_FLAGS = %w[-Wno-maybe-uninitialized].freeze # rubocop:disable Security/Object/Freeze
57
+
58
+ # Extend $CFLAGS passed directly to compiler in ruby mkmf
59
+ def extend_cflags
60
+ $CFLAGS += " #{ [STANDARD_FLAGS, WARNING_FLAGS].flatten.join(' ') }"
61
+ # Extend with GCC specific flags:
62
+ unless RbConfig::MAKEFILE_CONFIG['CC'].downcase.include?(CLANG) ||
63
+ RbConfig::MAKEFILE_CONFIG['CPP'].downcase.include?(CLANG) ||
64
+ RbConfig::CONFIG['CC'].downcase.include?(CLANG)
65
+
66
+ $CFLAGS += " #{ GCC_FLAGS.flatten.join(' ') }"
67
+ end
68
+ end
69
+
7
70
  def make!
8
71
  create_makefile("#{ $TO_MAKE }/#{ $TO_MAKE }")
9
72
  end
10
73
 
74
+ # -----------------------------------------------------------------------
75
+ # | MOVING CODE BELLOW THIS SECTION MAY BRAKE MAKEFILE. ORDER MATTERS! |
76
+ # ----------------------------------------------------------------------
77
+
11
78
  def ext_path
12
79
  # __dir__ is relative to the file you're reading.
13
80
  # this file you're reading is presently within $APP_ROOT/ext/.
14
81
  __dir__
15
82
  end
16
83
 
84
+ # We need to first build funchook which relies on ext_path method. This enables the require of
85
+ # funchook.h file. Then we can pass CFLAGS and extend makefile flags and invoke make!
17
86
  require_relative './build_funchook'
18
87
 
88
+ # Extended flags are mainly tested with clang and gcc. Experience with other compilers may vary.
89
+ # To that end if something brakes on client side we must have a mechanism to go back to previous
90
+ # non strict gnu89 standard and be able to maintain the build.
91
+ # We can disable newly added changes with this setting CONTRAST_USE_C89=false.
92
+ extend_cflags unless ENV['CONTRAST__USE_GNU89'] == 'false'
93
+
94
+ # use same C compiler if set.
95
+ RbConfig::CONFIG['CC'] = RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
96
+
97
+ # Generate Makefile.
19
98
  make!
@@ -58,7 +58,7 @@ module Contrast
58
58
  # can skip policy loading.
59
59
  return if disabled_globally?
60
60
 
61
- policy_data = JSON.parse(string)
61
+ policy_data = Contrast::Utils::Json.parse(string)
62
62
 
63
63
  policy_data[SOURCES_KEY].each do |source_hash|
64
64
  source = Contrast::Agent::Assess::Policy::SourceNode.new(source_hash)
@@ -91,6 +91,7 @@ module Contrast
91
91
  process_source(source_node, value, source_data, source_type, source_name, *args)
92
92
  end
93
93
  end
94
+ nil
94
95
  rescue StandardError => e
95
96
  logger.warn('Unable to apply source', e, node_id: source_node.id)
96
97
  end
@@ -28,7 +28,7 @@ module Contrast
28
28
  end
29
29
 
30
30
  def from_hash_string string
31
- policy_data = JSON.parse(string)
31
+ policy_data = Contrast::Utils::Json.parse(string)
32
32
 
33
33
  policy_data[DEADZONES_KEY].each do |deadzone_hash|
34
34
  add_node(node_type.new(deadzone_hash))
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'json'
4
+ require 'contrast/utils/json'
5
5
  require 'singleton'
6
6
 
7
7
  require 'contrast'
@@ -71,7 +71,7 @@ module Contrast
71
71
  # it, so in that case, we can skip policy loading.
72
72
  return if disabled_globally?
73
73
 
74
- policy_data = JSON.parse(string)
74
+ policy_data = Contrast::Utils::Json.parse(string)
75
75
 
76
76
  policy_data[RULES_KEY].each do |rule_hash|
77
77
  rule_hash[TRIGGERS_KEY].each do |trigger_hash|
@@ -26,11 +26,14 @@ module Contrast
26
26
  # Thread that will process all the InputAnalysisResults that have a score level of WORTHWATCHING and
27
27
  # sends results to TeamServer
28
28
  def start_thread!
29
+ return unless attempt_to_start?
29
30
  return if running?
30
31
 
31
32
  @_thread = Contrast::Agent::Thread.new do
32
33
  logger.info('[WorthWatchingAnalyzer] Starting thread.')
33
34
  loop do
35
+ break unless attempt_to_start?
36
+
34
37
  sleep(REPORT_INTERVAL_SECOND)
35
38
  next if queue.empty?
36
39
 
@@ -94,7 +94,7 @@ module Contrast
94
94
  #
95
95
  # @return [Boolean]
96
96
  def json? string
97
- return true if JSON.parse(string)
97
+ return true if Contrast::Utils::Json.parse(string)
98
98
  rescue StandardError
99
99
  false
100
100
  end
@@ -10,10 +10,12 @@ require 'contrast/agent/telemetry/exception'
10
10
  module Contrast
11
11
  module Agent
12
12
  # This module will hold everything essential to reporting to TeamServer
13
- class Reporter < WorkerThread
13
+ class Reporter < WorkerThread # rubocop:disable Metrics/ClassLength
14
14
  include Contrast::Components::Logger::InstanceMethods
15
15
  include Contrast::Utils::ObjectShare
16
16
 
17
+ # How many tries to reconnect the Reporter should make.
18
+ RETRY_ATTEMPTS = 10
17
19
  MAX_QUEUE_SIZE = 1000
18
20
 
19
21
  class << self
@@ -35,13 +37,17 @@ module Contrast
35
37
  end
36
38
 
37
39
  def start_thread!
40
+ return unless attempt_to_start?
38
41
  return if running?
39
42
 
43
+ @connection_attempts = 0
44
+
40
45
  client.startup!(connection)
41
46
  @_thread = Contrast::Agent::Thread.new do
42
47
  logger.debug('[Reporter] Starting background Reporter thread.')
43
48
  loop do
44
49
  next unless connected?
50
+ break unless attempt_to_start?
45
51
 
46
52
  process_event(queue.pop)
47
53
  rescue StandardError => e
@@ -124,10 +130,19 @@ module Contrast
124
130
  #
125
131
  # @return [Boolean]
126
132
  def connected?
127
- return true if client && connection
133
+ if client && connection
134
+ # Try to resend startup messages now with connection:
135
+ client.startup!(connection) unless client.status.startup_messages_sent?
136
+ return true
137
+ end
128
138
 
129
- logger.debug('[Reporter] No client/connection; sleeping...', client: client, connection: connection)
130
- sleep(5)
139
+ logger.debug('[Reporter] No client/connection; sleeping...')
140
+ @connection_attempts += 1
141
+ if @connection_attempts >= RETRY_ATTEMPTS
142
+ logger.debug('[Reporter] shutting down..')
143
+ Contrast::AGENT.disable!
144
+ end
145
+ sleep(5) unless Contrast::AGENT.disabled?
131
146
  false
132
147
  end
133
148
 
@@ -0,0 +1,32 @@
1
+ # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/agent/reporting/reporting_events/reporting_event'
5
+ require 'contrast/config'
6
+
7
+ module Contrast
8
+ module Agent
9
+ module Reporting
10
+ # AgentStartup Event which sends the agent data to TeamServer on the startup of a server or process,
11
+ # used to create a new Server entity there.
12
+ class AgentEffectiveConfig < Contrast::Agent::Reporting::ReportingEvent
13
+ # @param diagnostics [Contrast::Agent::DiagnosticsConfig::Diagnostics] current diagnostics
14
+ def initialize diagnostics
15
+ @event_method = :PUT
16
+ @event_endpoint = Contrast::Agent::Reporting::Endpoints.effective_config
17
+ @event_type = :effective_config
18
+ @diagnostics = diagnostics
19
+ super()
20
+ end
21
+
22
+ def file_name
23
+ 'agent-effective-config'
24
+ end
25
+
26
+ def to_controlled_hash
27
+ @diagnostics.to_controlled_hash
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -83,6 +83,13 @@ module Contrast
83
83
  end
84
84
  end
85
85
 
86
+ # @return [String, nil]
87
+ def effective_config
88
+ with_rescue do
89
+ "#{ application_endpoint }/effective-config".cs__freeze
90
+ end
91
+ end
92
+
86
93
  private
87
94
 
88
95
  # Returns the URL needed to connect to endpoints in TeamServer required for application related information.
@@ -11,7 +11,7 @@ module Contrast
11
11
  # This class will build the required headers for agent reporting to TS
12
12
  class Headers
13
13
  attr_reader :app_name, :api_key, :agent_version, :app_language, :app_path, :app_version, :authorization,
14
- :server_name, :server_path, :server_type, :content_type, :encoding, :compression
14
+ :server_name, :server_path, :server_type, :content_type, :encoding, :compression, :session_id
15
15
 
16
16
  include Contrast::Utils::ObjectShare
17
17
  ENCODING = 'base64'
@@ -29,6 +29,7 @@ module Contrast
29
29
  @server_name = Base64.strict_encode64(Contrast::APP_CONTEXT.server_name)
30
30
  @server_path = Base64.strict_encode64(Contrast::APP_CONTEXT.server_path)
31
31
  @server_type = Base64.strict_encode64(Contrast::APP_CONTEXT.server_type)
32
+ @session_id = Contrast::CONFIG.session_id
32
33
  @content_type = CONTENT_TYPE
33
34
  @encoding = ENCODING
34
35
  @compression = COMPRESSION
@@ -46,6 +47,7 @@ module Contrast
46
47
  server_name: @server_name,
47
48
  server_path: @server_path,
48
49
  server_type: @server_type,
50
+ 'Session-ID': @session_id,
49
51
  content_type: @content_type,
50
52
  encoding: @encoding,
51
53
  compression: @compression