contrast-agent 6.12.0 → 6.14.0
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.
- checksums.yaml +4 -4
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +39 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/config/validate.rb +140 -0
- data/lib/contrast/config/yaml_file.rb +129 -0
- data/lib/contrast/tasks/config.rb +7 -118
- data/lib/contrast/utils/middleware_utils.rb +4 -0
- data/resources/assess/policy.json +26 -0
- data/ruby-agent.gemspec +3 -2
- metadata +15 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 577b0810f45b302615af1f151ebb6b772d76c0bccd460057022f5fbadf065d73
|
4
|
+
data.tar.gz: f3e882dd5e3d7e63e4cf09f37733acd02ad3b70b2d195b8a9377175cfe1b4330
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 168ea3d43d19acbe29a80b9b244a91c29b0f7c091137b7a0575edd39f763ec013e1402bc1337c167e8147738428813b7d1010e92a8e102aa3b72570685d73605
|
7
|
+
data.tar.gz: ddbf43ffe314bfd53c19687dc7bfc549a1b5374a43ede461a73487519ef263672f6dc7fe449140159c5e26587a55052b132242c20b1673d2dbed3d882340f157
|
@@ -7,9 +7,13 @@ module Contrast
|
|
7
7
|
module Policy
|
8
8
|
module TriggerValidation
|
9
9
|
# Validator used to assert a REDOS finding is actually vulnerable
|
10
|
-
# before serializing that finding as a
|
10
|
+
# before serializing that finding as a Event to report to the TeamServer.
|
11
11
|
module REDOSValidator
|
12
12
|
RULE_NAME = 'redos'
|
13
|
+
# If Regexp is set to Float::Infinite this is the maximum number it will receive
|
14
|
+
POSITIVE_INFINITY = 18_446_744_073.709553
|
15
|
+
# We are checking and for negative infinity (-1.0/0.0 )
|
16
|
+
NEGATIVE_INFINITY = -POSITIVE_INFINITY
|
13
17
|
|
14
18
|
class << self
|
15
19
|
def valid? _patcher, object, _ret, args
|
@@ -49,8 +53,42 @@ module Contrast
|
|
49
53
|
|
50
54
|
# Use #match? because it doesn't fill out global variables
|
51
55
|
# in the way match or =~ do.
|
56
|
+
#
|
57
|
+
# Since ruby 3.2.0 the Regexp now have a timeout option. we need to check and see if the timeout
|
58
|
+
# is set. If so we can assume that the regexp is safe.
|
59
|
+
# puts "SAFE #{regexp_timeout_safe?(regexp)}"
|
60
|
+
return false if regexp_timeout_safe?(regexp)
|
61
|
+
|
62
|
+
# report only if pattern is bad:
|
52
63
|
VULNERABLE_PATTERN.match?(regexp.source)
|
53
64
|
end
|
65
|
+
|
66
|
+
# Check and see if a regexp is with safely set Timeout or not.
|
67
|
+
#
|
68
|
+
# @param regexp [Regexp]
|
69
|
+
# @return [Boolean]
|
70
|
+
def regexp_timeout_safe? regexp
|
71
|
+
return false if RUBY_VERSION < '3.2.0'
|
72
|
+
# Global
|
73
|
+
return false if Regexp.timeout.nil? || regexp_infinite?(Regexp)
|
74
|
+
|
75
|
+
# Local
|
76
|
+
return false if regexp.cs__is_a?(Regexp) && !(regexp.timeout.nil? || regexp_infinite?(regexp))
|
77
|
+
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Check and see if the set timeout is set to infinity:
|
84
|
+
#
|
85
|
+
# @param regexp[Regexp] Instance or class
|
86
|
+
# @return[Boolean]
|
87
|
+
def regexp_infinite? regexp
|
88
|
+
return false unless regexp.timeout == POSITIVE_INFINITY || regexp.timeout == NEGATIVE_INFINITY
|
89
|
+
|
90
|
+
true
|
91
|
+
end
|
54
92
|
end
|
55
93
|
end
|
56
94
|
end
|
@@ -0,0 +1,140 @@
|
|
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 'yaml'
|
5
|
+
require 'contrast/configuration'
|
6
|
+
require 'contrast/agent/reporting/reporter'
|
7
|
+
require 'base64'
|
8
|
+
|
9
|
+
module Contrast
|
10
|
+
module Config
|
11
|
+
# Helper module with methods to validate the existing yaml file.
|
12
|
+
module Validate
|
13
|
+
# rubocop:disable Rails/Output
|
14
|
+
SKIP_LOG = %w[service_key api_key].cs__freeze
|
15
|
+
REQUIRED = %i[url api_key service_key user_name].cs__freeze
|
16
|
+
PASS = " \u{2705} "
|
17
|
+
FAIL = " \u{274C} "
|
18
|
+
REQUIRED_HEADERS = %i[server_type server_name server_path app_language app_name].cs__freeze
|
19
|
+
|
20
|
+
def validate_file
|
21
|
+
puts("\u{1F9EA} Validating Agent Configuration...\n")
|
22
|
+
Contrast::Config.validate_config
|
23
|
+
puts('done...')
|
24
|
+
puts("Validating Contrast Reporter Headers...\n")
|
25
|
+
reporter = Contrast::Config.validate_headers
|
26
|
+
puts('done...')
|
27
|
+
puts("Testing Reporter Client Connection...\n")
|
28
|
+
Contrast::Config.test_connection(reporter) if reporter
|
29
|
+
puts('Validation complete')
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate_config
|
33
|
+
config = Contrast::Configuration.new
|
34
|
+
abort("Unable to Build Config #{ FAIL }") unless config
|
35
|
+
missing = []
|
36
|
+
|
37
|
+
api_hash = config.api.to_contrast_hash
|
38
|
+
|
39
|
+
api_hash.each_key do |key|
|
40
|
+
value = mask_keys(api_hash, key)
|
41
|
+
if value.is_a?(Contrast::Config::ApiProxyConfiguration)
|
42
|
+
Contrast::Config.validate_proxy(value)
|
43
|
+
elsif value.is_a?(Contrast::Config::CertificationConfiguration)
|
44
|
+
Contrast::Config.validate_cert(value)
|
45
|
+
next
|
46
|
+
elsif value.is_a?(Contrast::Config::RequestAuditConfiguration)
|
47
|
+
Contrast::Config.validate_audit(value)
|
48
|
+
next
|
49
|
+
elsif value.nil? && REQUIRED.include?(key.to_sym)
|
50
|
+
missing << key
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return if missing.empty?
|
54
|
+
|
55
|
+
abort("Validation failed: Missing required API configuration values: #{ missing.join(', ') } #{ FAIL }")
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_proxy config
|
59
|
+
puts(" Proxy Enabled: #{ config.enable }")
|
60
|
+
return unless config.enable
|
61
|
+
|
62
|
+
mark = config.url.nil? ? FAIL : PASS
|
63
|
+
puts(" Proxy URL: #{ config.url } #{ mark }")
|
64
|
+
abort('Proxy Enabled but no Proxy URL given') unless config.url
|
65
|
+
end
|
66
|
+
|
67
|
+
def validate_cert config
|
68
|
+
puts(" Certification Enabled: #{ config.enable }")
|
69
|
+
return unless config.enable
|
70
|
+
|
71
|
+
mark = config.ca_file.nil? ? FAIL : PASS
|
72
|
+
puts(" CA File: #{ config.ca_file } #{ mark }")
|
73
|
+
abort('CA file path not provided') unless config.ca_file
|
74
|
+
mark = config.cert_file.nil? ? FAIL : PASS
|
75
|
+
puts(" Cert File: #{ config.cert_file } #{ mark }")
|
76
|
+
abort('Cert file path not provided') unless config.cert_file
|
77
|
+
mark = config.key_file.nil? ? FAIL : PASS
|
78
|
+
puts(" Key File: #{ config.key_file } #{ mark }")
|
79
|
+
abort('Key file path not provided') unless config.key_file
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate_audit config
|
83
|
+
puts(" Request Audit Enabled: #{ config.enable }")
|
84
|
+
return unless config.enable
|
85
|
+
|
86
|
+
config.cs__class::CONFIG_VALUES.each do |value_name|
|
87
|
+
puts(" #{ value_name }::#{ config.send(value_name.to_sym) }")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def init_reporter
|
92
|
+
Contrast::Agent::Reporter.new
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_headers
|
96
|
+
missing = []
|
97
|
+
reporter = init_reporter
|
98
|
+
reporter_headers = reporter.client.headers.to_contrast_hash
|
99
|
+
REQUIRED_HEADERS.each do |key|
|
100
|
+
value = decode_header(reporter_headers, key)
|
101
|
+
missing << key if value.nil?
|
102
|
+
end
|
103
|
+
unless missing.empty?
|
104
|
+
abort("Validation failed: Missing required header values: #{ missing.join(', ') } #{ FAIL }")
|
105
|
+
end
|
106
|
+
reporter
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_connection reporter
|
110
|
+
puts(" Connection failed #{ FAIL }") unless reporter
|
111
|
+
connection = reporter.connection
|
112
|
+
abort("Failed to Initialize Connection please check error logs for details #{ FAIL } ") unless connection
|
113
|
+
abort('Failed to Start Client please check error logs for details') unless reporter.client.startup!(connection)
|
114
|
+
last_response = reporter.client.response_handler.last_response_code
|
115
|
+
if last_response.include?('40')
|
116
|
+
puts(" Last response code: #{ last_response } #{ FAIL }")
|
117
|
+
abort("Failed to Initialize Connection please check error logs for details #{ FAIL } ")
|
118
|
+
elsif connection
|
119
|
+
puts(" Last response code: #{ last_response } #{ PASS }")
|
120
|
+
puts(" Connection successful #{ PASS }") if connection
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def mask_keys hash, key
|
125
|
+
value = hash[key]
|
126
|
+
redacted_value = Contrast::Configuration::REDACTED if SKIP_LOG.include?(key.to_s)
|
127
|
+
puts(" #{ key }::#{ redacted_value || value }") unless value.is_a?(Contrast::Config::BaseConfiguration)
|
128
|
+
value
|
129
|
+
end
|
130
|
+
|
131
|
+
def decode_header hash, key
|
132
|
+
value = hash[key]
|
133
|
+
decoded_header = Base64.strict_decode64(value)
|
134
|
+
puts(" #{ key }::#{ key == :app_language ? value : decoded_header }")
|
135
|
+
value
|
136
|
+
end
|
137
|
+
# rubocop:enable Rails/Output
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,129 @@
|
|
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 'fileutils'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module Contrast
|
8
|
+
module Config
|
9
|
+
# Helper module with methods to find active configuration file used by the agent or create it.\
|
10
|
+
# This file is used before the agent start so methods added here must not be dependent on Agent
|
11
|
+
# instrumentation.
|
12
|
+
module YamlFile
|
13
|
+
CONFIG_FILE_NAME = 'contrast_security'
|
14
|
+
EXT = { yml: 'yml', yaml: 'yaml' }.freeze # rubocop:disable Security/Object/Freeze
|
15
|
+
|
16
|
+
POSSIBLE_TARGET_PATHS = %w[
|
17
|
+
./
|
18
|
+
./config/
|
19
|
+
/etc/contrast/ruby/
|
20
|
+
/etc/contrast/
|
21
|
+
/etc/
|
22
|
+
].freeze # rubocop:disable Security/Object/Freeze
|
23
|
+
|
24
|
+
HEADER = "# +-------------------------------------------------------------------------+\n" \
|
25
|
+
"# This Contrast Security configuration is Auto-generated by rake task.\n" \
|
26
|
+
"# To List all available rake task use 'rake -T'. \n" \
|
27
|
+
"#\n" \
|
28
|
+
"# Please enter valid api information, for the Ruby Agent to be able to\n" \
|
29
|
+
"# connect to Contrast UI. You can validate your config file by running: \n" \
|
30
|
+
"# 'bundle exec rake contrast:config:validate' \n" \
|
31
|
+
"#\n" \
|
32
|
+
"# To find your organization keys please follow this documentation:\n" \
|
33
|
+
"# https://docs.contrastsecurity.com/en/find-the-agent-keys.html\n" \
|
34
|
+
"# +-------------------------------------------------------------------------+\n"
|
35
|
+
|
36
|
+
FOOTER = "\n# For more information visit the full Ruby agent configuration guide:\n" \
|
37
|
+
'# https://docs.contrastsecurity.com/en/ruby-configuration.html'
|
38
|
+
|
39
|
+
COMMENT = "#agent:\n" \
|
40
|
+
"# logger:\n" \
|
41
|
+
"# level: WARN\n" \
|
42
|
+
"# path: contrast_agent.log\n" \
|
43
|
+
"#server:\n" \
|
44
|
+
"# name: Server name\n" \
|
45
|
+
"#application:\n" \
|
46
|
+
"# name: Application name\n" \
|
47
|
+
"# code: Application name\n" \
|
48
|
+
"# group: Application group\n" \
|
49
|
+
"# session_metadata: Application metadata used for creation of Session ID\n" \
|
50
|
+
"# version: Application version\n"
|
51
|
+
|
52
|
+
DEFAULT_CONFIG = {
|
53
|
+
'api' => {
|
54
|
+
'url' => 'https://app.contrastsecurity.com',
|
55
|
+
'api_key' => 'contrast_user',
|
56
|
+
'service_key' => 'demo',
|
57
|
+
'user_name' => 'demo'
|
58
|
+
}
|
59
|
+
}.freeze # rubocop:disable Security/Object/Freeze
|
60
|
+
|
61
|
+
class << self
|
62
|
+
# Checks all accessible by the agent path for active configuration created.
|
63
|
+
#
|
64
|
+
# @return [Boolean]
|
65
|
+
def created?
|
66
|
+
return true if File.exist?(Contrast::Config::YamlFile.target_path)
|
67
|
+
return true unless find!.empty?
|
68
|
+
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
72
|
+
# Finds active configuration used.
|
73
|
+
#
|
74
|
+
# @return [String] path of the config file.
|
75
|
+
def find!
|
76
|
+
found = ''
|
77
|
+
paths = POSSIBLE_TARGET_PATHS.dup
|
78
|
+
paths << ENV['CONTRAST_CONFIG_PATH'] if ENV['CONTRAST_CONFIG_PATH']
|
79
|
+
paths.each do |path|
|
80
|
+
EXT.each_value do |extension|
|
81
|
+
effective_config = "#{ path }#{ file_name }.#{ extension }"
|
82
|
+
found = effective_config if File.exist?(effective_config)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
found
|
86
|
+
end
|
87
|
+
|
88
|
+
# Create new config file to the default destination.
|
89
|
+
#
|
90
|
+
def create
|
91
|
+
# rubocop:disable Rails/Output
|
92
|
+
puts("\u{1F48E} Generating: Contrast Configuration file.")
|
93
|
+
if Contrast::Config::YamlFile.created?
|
94
|
+
puts("\u{2705} Configuration file already exists: #{ Contrast::Config::YamlFile.find! }")
|
95
|
+
else
|
96
|
+
File.open(Contrast::Config::YamlFile.target_path, 'w') do |file|
|
97
|
+
file.write(HEADER)
|
98
|
+
file.write(YAML.dump(DEFAULT_CONFIG).gsub('---', ' '))
|
99
|
+
file.write(COMMENT)
|
100
|
+
file.write(FOOTER)
|
101
|
+
file.close
|
102
|
+
end
|
103
|
+
|
104
|
+
puts("\u{2728} Created! path #{ Contrast::Config::YamlFile.target_path }\n")
|
105
|
+
puts("\nOpen the file and enter your Contrast Security api keys or set them via environment variables.\n")
|
106
|
+
puts('Visit our documentation for more details: ' \
|
107
|
+
'https://docs.contrastsecurity.com/en/ruby-configuration.html')
|
108
|
+
end
|
109
|
+
rescue StandardError => e
|
110
|
+
puts("\u{2757} WARNING configuration could not be created due to error: '#{ e }'. " \
|
111
|
+
"Try created in manually by running 'bundle exec rake contrast:config:create'.")
|
112
|
+
# rubocop:enable Rails/Output
|
113
|
+
end
|
114
|
+
|
115
|
+
def target_path
|
116
|
+
File.join(execution_directory, "#{ file_name }.#{ EXT[:yml] }")
|
117
|
+
end
|
118
|
+
|
119
|
+
def execution_directory
|
120
|
+
Dir.pwd
|
121
|
+
end
|
122
|
+
|
123
|
+
def file_name
|
124
|
+
ENV['CONTRAST_YAML_FILE_TEST_CREATE_CONFIG_FILE_NAME_VALUE'] || CONFIG_FILE_NAME
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -1,47 +1,22 @@
|
|
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 '
|
5
|
-
require 'contrast/
|
6
|
-
require 'contrast/agent/reporting/reporter'
|
4
|
+
require 'contrast/config/yaml_file'
|
5
|
+
require 'contrast/config/validate'
|
7
6
|
|
8
7
|
module Contrast
|
9
8
|
# A Rake task to generate a contrast_security.yaml file with some basic settings
|
10
9
|
module Config
|
11
10
|
extend Rake::DSL
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
'api_key' => 'Enter your Contrast api key',
|
16
|
-
'service_key' => 'Enter your Contrast service key',
|
17
|
-
'user_name' => 'Enter your Contrast user name'
|
18
|
-
},
|
19
|
-
'agent' => {
|
20
|
-
'logger' => {
|
21
|
-
'level' => 'ERROR',
|
22
|
-
'path' => 'contrast_agent.log'
|
23
|
-
}
|
24
|
-
}
|
25
|
-
}.cs__freeze
|
26
|
-
|
27
|
-
SKIP_LOG = %w[service_key api_key].cs__freeze
|
28
|
-
REQUIRED = %i[url api_key service_key user_name].cs__freeze
|
11
|
+
# The file create methods are required in the gemspec. Some of the Agent functions are not
|
12
|
+
# available there. To be safe the validate mechanics are extracted in different module.
|
13
|
+
extend Contrast::Config::Validate
|
29
14
|
|
30
15
|
namespace :contrast do
|
31
16
|
namespace :config do
|
32
17
|
desc 'Create a contrast_security.yaml in the applications root directory'
|
33
18
|
task :create do
|
34
|
-
|
35
|
-
target_path = File.join(execution_directory, 'contrast_security.yaml')
|
36
|
-
if File.exist?(target_path)
|
37
|
-
puts 'WARNING: contrast_security.yaml already exists'
|
38
|
-
else
|
39
|
-
File.write(target_path, YAML.dump(DEFAULT_CONFIG))
|
40
|
-
|
41
|
-
puts "Created contrast_security.yaml at #{ target_path }"
|
42
|
-
puts 'Open the file and enter your Contrast Security api keys or set them via environment variables'
|
43
|
-
puts 'Visit our documentation site for more details: https://docs.contrastsecurity.com/installation-rubyconfig.html'
|
44
|
-
end
|
19
|
+
Contrast::Config::YamlFile.create
|
45
20
|
end
|
46
21
|
end
|
47
22
|
end
|
@@ -50,94 +25,8 @@ module Contrast
|
|
50
25
|
namespace :config do
|
51
26
|
desc 'Validate the provided Contrast configuration and confirm connectivity'
|
52
27
|
task validate: :environment do
|
53
|
-
|
54
|
-
Contrast::Config.validate_config
|
55
|
-
puts '...done!'
|
56
|
-
puts 'Validating Contrast Reporter Headers...'
|
57
|
-
reporter = Contrast::Config.validate_headers
|
58
|
-
puts '...done!'
|
59
|
-
puts 'Testing Reporter Client Connection...'
|
60
|
-
Contrast::Config.test_connection(reporter) if reporter
|
61
|
-
puts '...done!'
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.validate_config
|
66
|
-
config = Contrast::Configuration.new
|
67
|
-
abort('Unable to Build Config') unless config
|
68
|
-
missing = []
|
69
|
-
|
70
|
-
api_hash = config.api.to_contrast_hash
|
71
|
-
|
72
|
-
api_hash.each_key do |key|
|
73
|
-
value = mask_keys(api_hash, key)
|
74
|
-
if value.is_a?(Contrast::Config::ApiProxyConfiguration)
|
75
|
-
Contrast::Config.validate_proxy(value)
|
76
|
-
elsif value.is_a?(Contrast::Config::CertificationConfiguration)
|
77
|
-
Contrast::Config.validate_cert(value)
|
78
|
-
next
|
79
|
-
elsif value.is_a?(Contrast::Config::RequestAuditConfiguration)
|
80
|
-
Contrast::Config.validate_audit(value)
|
81
|
-
next
|
82
|
-
elsif value.nil? && REQUIRED.includes?(key.to_sym)
|
83
|
-
missing << key
|
84
|
-
end
|
85
|
-
end
|
86
|
-
abort("Missing required API configuration values: #{ missing.join(', ') }") unless missing.empty?
|
87
|
-
end
|
88
|
-
|
89
|
-
def self.validate_proxy config
|
90
|
-
puts("Proxy Enabled: #{ config.enable }")
|
91
|
-
return unless config.enable
|
92
|
-
|
93
|
-
puts("Proxy URL: #{ config.url }")
|
94
|
-
abort('Proxy Enabled but no Proxy URL given') unless config.url
|
95
|
-
end
|
96
|
-
|
97
|
-
def self.validate_cert config
|
98
|
-
puts("Certification Enabled: #{ config.enable }")
|
99
|
-
return unless config.enable
|
100
|
-
|
101
|
-
puts("CA File: #{ config.ca_file }")
|
102
|
-
abort('CA file path not provided') unless config.ca_file
|
103
|
-
puts("Cert File: #{ config.cert_file }")
|
104
|
-
abort('Cert file path not provided') unless config.cert_file
|
105
|
-
puts("Key File: #{ config.key_file }")
|
106
|
-
abort('Key file path not provided') unless config.key_file
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.validate_audit config
|
110
|
-
puts("Request Audit Enabled: #{ config.enable }")
|
111
|
-
return unless config.enable
|
112
|
-
|
113
|
-
config.each do |k, v|
|
114
|
-
puts("#{ k }::#{ v }")
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def self.validate_headers
|
119
|
-
missing = []
|
120
|
-
reporter = Contrast::Agent::Reporter.new
|
121
|
-
reporter_headers = reporter.client.headers.to_contrast_hash
|
122
|
-
reporter_headers.each_key do |key|
|
123
|
-
value = mask_keys(reporter_headers, key)
|
124
|
-
missing << key if value.nil?
|
28
|
+
validate_file
|
125
29
|
end
|
126
|
-
abort("Missing required header values: #{ missing.join(', ') }") unless missing.empty?
|
127
|
-
reporter
|
128
|
-
end
|
129
|
-
|
130
|
-
def self.test_connection reporter
|
131
|
-
connection = reporter.connection
|
132
|
-
abort('Failed to Initialize Connection please check error logs for details') unless connection
|
133
|
-
abort('Failed to Start Client please check error logs for details') unless reporter.client.startup!(connection)
|
134
|
-
end
|
135
|
-
|
136
|
-
def self.mask_keys hash, key
|
137
|
-
value = hash[key]
|
138
|
-
redacted_value = Contrast::Configuration::REDACTED if SKIP_LOG.include?(key.to_s)
|
139
|
-
puts("#{ key }::#{ redacted_value || value }") unless value.is_a?(Contrast::Config::BaseConfiguration)
|
140
|
-
value
|
141
30
|
end
|
142
31
|
end
|
143
32
|
end
|
@@ -1,6 +1,8 @@
|
|
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 'contrast/config/yaml_file'
|
5
|
+
|
4
6
|
module Contrast
|
5
7
|
module Utils
|
6
8
|
# helper methods for Contrast::Agent::Middleware
|
@@ -16,6 +18,8 @@ module Contrast
|
|
16
18
|
"April #{ LANGUAGE_DEPRECATION_YEAR }. Please contact Customer Support prior if you require continued support."
|
17
19
|
|
18
20
|
def setup_agent
|
21
|
+
# Generate new config file if one is not already created:
|
22
|
+
Contrast::Config::YamlFile.create unless Contrast::Config::YamlFile.created?
|
19
23
|
::Contrast::SETTINGS.reset_state
|
20
24
|
|
21
25
|
inform_deprecations
|
@@ -932,6 +932,22 @@
|
|
932
932
|
"source":"O",
|
933
933
|
"target":"R",
|
934
934
|
"action":"SPLAT"
|
935
|
+
}, {
|
936
|
+
"class_name":"IO",
|
937
|
+
"method_name":"to_path",
|
938
|
+
"instance_method": true,
|
939
|
+
"method_visibility": "public",
|
940
|
+
"source":"O",
|
941
|
+
"target":"R",
|
942
|
+
"action":"SPLAT"
|
943
|
+
}, {
|
944
|
+
"class_name":"IO",
|
945
|
+
"method_name":"path",
|
946
|
+
"instance_method": true,
|
947
|
+
"method_visibility": "public",
|
948
|
+
"source":"O",
|
949
|
+
"target":"R",
|
950
|
+
"action":"SPLAT"
|
935
951
|
}, {
|
936
952
|
"class_name": "ActiveModel::AttributeAssignment",
|
937
953
|
"method_name": "assign_attributes",
|
@@ -1177,6 +1193,16 @@
|
|
1177
1193
|
"action": "BUFFER",
|
1178
1194
|
"patch_method": "buffer_keep_splat"
|
1179
1195
|
},
|
1196
|
+
{
|
1197
|
+
"class_name": "IO::Buffer",
|
1198
|
+
"instance_method": true,
|
1199
|
+
"method_visibility": "public",
|
1200
|
+
"method_name": "read",
|
1201
|
+
"source":"P0,O",
|
1202
|
+
"target":"O",
|
1203
|
+
"action": "BUFFER",
|
1204
|
+
"patch_method": "buffer_keep_splat"
|
1205
|
+
},
|
1180
1206
|
{
|
1181
1207
|
"class_name": "ERB",
|
1182
1208
|
"method_name": "result",
|
data/ruby-agent.gemspec
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require_relative './lib/contrast/agent/version'
|
5
|
+
require_relative './lib/contrast/config/yaml_file'
|
5
6
|
|
6
7
|
lib = File.expand_path('lib', __dir__)
|
7
8
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
@@ -178,14 +179,14 @@ Gem::Specification.new do |spec|
|
|
178
179
|
'Testing and Protection.'
|
179
180
|
spec.homepage = 'https://www.contrastsecurity.com'
|
180
181
|
spec.license = 'CONTRAST SECURITY (see license file)'
|
181
|
-
spec.required_ruby_version = ['>= 2.7.0', '< 3.
|
182
|
+
spec.required_ruby_version = ['>= 2.7.0', '< 3.3.0']
|
182
183
|
|
183
184
|
spec.bindir = 'exe'
|
184
185
|
# Keep cs__common first, it handles funchook.h right now.
|
185
186
|
spec.extensions = Dir['ext/cs__common/extconf.rb', 'ext/**/extconf.rb']
|
186
187
|
spec.require_paths = ['lib']
|
187
188
|
|
188
|
-
unless
|
189
|
+
unless Contrast::Config::YamlFile.created?
|
189
190
|
spec.post_install_message = 'To generate the required contrast_security.yaml file you can run: '\
|
190
191
|
'bundle exec rake contrast:config:create'
|
191
192
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contrast-agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- galen.palmer@contrastsecurity.com
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: exe
|
15
15
|
cert_chain: []
|
16
|
-
date: 2023-01-
|
16
|
+
date: 2023-01-26 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: bundler
|
@@ -684,22 +684,22 @@ email:
|
|
684
684
|
executables: []
|
685
685
|
extensions:
|
686
686
|
- ext/cs__common/extconf.rb
|
687
|
-
- ext/cs__assess_module/extconf.rb
|
688
|
-
- ext/cs__scope/extconf.rb
|
689
|
-
- ext/cs__assess_string_interpolation/extconf.rb
|
690
|
-
- ext/cs__assess_kernel/extconf.rb
|
691
687
|
- ext/cs__assess_basic_object/extconf.rb
|
692
|
-
- ext/cs__assess_test/extconf.rb
|
693
|
-
- ext/cs__assess_yield_track/extconf.rb
|
694
688
|
- ext/cs__assess_hash/extconf.rb
|
689
|
+
- ext/cs__assess_kernel/extconf.rb
|
690
|
+
- ext/cs__assess_string_interpolation/extconf.rb
|
691
|
+
- ext/cs__contrast_patch/extconf.rb
|
695
692
|
- ext/cs__assess_string/extconf.rb
|
693
|
+
- ext/cs__assess_regexp/extconf.rb
|
696
694
|
- ext/cs__tests/extconf.rb
|
695
|
+
- ext/cs__assess_module/extconf.rb
|
696
|
+
- ext/cs__assess_yield_track/extconf.rb
|
697
697
|
- ext/cs__assess_fiber_track/extconf.rb
|
698
|
-
- ext/
|
699
|
-
- ext/
|
698
|
+
- ext/cs__scope/extconf.rb
|
699
|
+
- ext/cs__assess_test/extconf.rb
|
700
700
|
- ext/cs__os_information/extconf.rb
|
701
701
|
- ext/cs__assess_marshal_module/extconf.rb
|
702
|
-
- ext/
|
702
|
+
- ext/cs__assess_array/extconf.rb
|
703
703
|
extra_rdoc_files: []
|
704
704
|
files:
|
705
705
|
- ".clang-format"
|
@@ -1234,6 +1234,8 @@ files:
|
|
1234
1234
|
- lib/contrast/config/protect_rules_configuration.rb
|
1235
1235
|
- lib/contrast/config/request_audit_configuration.rb
|
1236
1236
|
- lib/contrast/config/server_configuration.rb
|
1237
|
+
- lib/contrast/config/validate.rb
|
1238
|
+
- lib/contrast/config/yaml_file.rb
|
1237
1239
|
- lib/contrast/configuration.rb
|
1238
1240
|
- lib/contrast/extension/assess.rb
|
1239
1241
|
- lib/contrast/extension/assess/array.rb
|
@@ -1337,8 +1339,7 @@ metadata:
|
|
1337
1339
|
support_uri: https://support.contrastsecurity.com
|
1338
1340
|
trouble_shooting_uri: https://support.contrastsecurity.com/hc/en-us/search?utf8=%E2%9C%93&query=Ruby
|
1339
1341
|
wiki_uri: https://docs.contrastsecurity.com/
|
1340
|
-
post_install_message:
|
1341
|
-
run: bundle exec rake contrast:config:create'
|
1342
|
+
post_install_message:
|
1342
1343
|
rdoc_options: []
|
1343
1344
|
require_paths:
|
1344
1345
|
- lib
|
@@ -1349,7 +1350,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
1349
1350
|
version: 2.7.0
|
1350
1351
|
- - "<"
|
1351
1352
|
- !ruby/object:Gem::Version
|
1352
|
-
version: 3.
|
1353
|
+
version: 3.3.0
|
1353
1354
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
1354
1355
|
requirements:
|
1355
1356
|
- - ">="
|