tcell_agent 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Readme.txt +7 -0
- data/bin/tcell_agent +6 -2
- data/lib/tcell_agent.rb +0 -3
- data/lib/tcell_agent/agent/event_processor.rb +1 -4
- data/lib/tcell_agent/agent/policy_manager.rb +5 -8
- data/lib/tcell_agent/agent/policy_types.rb +1 -7
- data/lib/tcell_agent/agent/static_agent.rb +2 -2
- data/lib/tcell_agent/api.rb +7 -9
- data/lib/tcell_agent/configuration.rb +42 -6
- data/lib/tcell_agent/policies/rust_policies.rb +33 -8
- data/lib/tcell_agent/rails/js_agent_insert.rb +17 -18
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +18 -59
- data/lib/tcell_agent/rails/tcell_body_proxy.rb +10 -6
- data/lib/tcell_agent/rust/libtcellagent-0.19.5.dylib +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-0.11.1.so → libtcellagent-0.19.5.so} +0 -0
- data/lib/tcell_agent/rust/tcellagent-0.19.5.dll +0 -0
- data/lib/tcell_agent/rust/whisperer.rb +165 -39
- data/lib/tcell_agent/sensor_events/patches.rb +2 -0
- data/lib/tcell_agent/sinatra.rb +17 -14
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/agent/policy_manager_spec.rb +17 -0
- data/spec/lib/tcell_agent/api/api_spec.rb +10 -7
- data/spec/lib/tcell_agent/cmdi_spec.rb +91 -80
- data/spec/lib/tcell_agent/instrumentation_spec.rb +20 -0
- data/spec/lib/tcell_agent/patches_spec.rb +33 -15
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +150 -99
- data/spec/lib/tcell_agent/policies/command_injection_policy_spec.rb +13 -1
- data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +12 -0
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +2 -39
- data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +6 -2
- data/spec/lib/tcell_agent/rails_spec.rb +0 -31
- data/spec/lib/tcell_agent/rust/whisperer_spec.rb +234 -120
- data/tcell_agent.gemspec +1 -1
- metadata +21 -40
- data/lib/tcell_agent/policies/clickjacking_policy.rb +0 -114
- data/lib/tcell_agent/policies/content_security_policy.rb +0 -166
- data/lib/tcell_agent/policies/secure_headers_policy.rb +0 -67
- data/lib/tcell_agent/rust/libtcellagent-0.11.1.dylib +0 -0
- data/lib/tcell_agent/rust/tcellagent-0.11.1.dll +0 -0
- data/spec/apps/rails-3.2/config/tcell_agent.config +0 -15
- data/spec/apps/rails-3.2/log/development.log +0 -0
- data/spec/apps/rails-3.2/log/test.log +0 -12
- data/spec/apps/rails-4.1/log/test.log +0 -0
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +0 -71
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +0 -130
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +0 -67
- data/spec/lib/tcell_agent_spec.rb +0 -22
@@ -1,67 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# See the file "LICENSE" for the full license governing this code.
|
3
|
-
require 'tcell_agent/policies/policy'
|
4
|
-
|
5
|
-
|
6
|
-
module TCellAgent
|
7
|
-
module Policies
|
8
|
-
class SecureHeadersPolicy < Policy
|
9
|
-
class SecurityHeader
|
10
|
-
@@approved_headers = [
|
11
|
-
"strict-transport-security",
|
12
|
-
"x-frame-options",
|
13
|
-
"x-xss-protection",
|
14
|
-
"x-content-type-options",
|
15
|
-
"x-permitted-cross-domain-policies",
|
16
|
-
"x-download-options"
|
17
|
-
]
|
18
|
-
attr_accessor :name
|
19
|
-
attr_accessor :value
|
20
|
-
def initialize(name, value)
|
21
|
-
if !(name && value)
|
22
|
-
raise "Name and value were not set"
|
23
|
-
end
|
24
|
-
if !@@approved_headers.include?(name.downcase)
|
25
|
-
raise "Name was not included in approved_headers"
|
26
|
-
end
|
27
|
-
if value != value.gsub(/[^\p{L}\w\d\-_\ :\/,;.'\*"%?@#=$]/,'')
|
28
|
-
raise "Value is not valid"
|
29
|
-
end
|
30
|
-
self.name = name
|
31
|
-
self.value = value
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
attr_accessor :headers
|
36
|
-
attr_accessor :policy_id
|
37
|
-
|
38
|
-
def self.from_json(policy_json)
|
39
|
-
if (!policy_json)
|
40
|
-
return nil
|
41
|
-
end
|
42
|
-
security_headers_policy = SecureHeadersPolicy.new
|
43
|
-
if policy_json.has_key?("policy_id")
|
44
|
-
security_headers_policy.policy_id = policy_json["policy_id"]
|
45
|
-
else
|
46
|
-
raise "Policy ID missing"
|
47
|
-
end
|
48
|
-
security_headers = []
|
49
|
-
if policy_json.has_key?("headers")
|
50
|
-
headers = policy_json["headers"]
|
51
|
-
headers.each do |header|
|
52
|
-
if header.has_key?("name") && header.has_key?("value")
|
53
|
-
begin
|
54
|
-
security_header = SecurityHeader.new(header["name"], header["value"])
|
55
|
-
security_headers.push(security_header)
|
56
|
-
rescue StandardError => secure_header_exception
|
57
|
-
TCellAgent.logger.debug("Could not load secure header:" + secure_header_exception.message)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
security_headers_policy.headers = security_headers
|
63
|
-
return security_headers_policy
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
Binary file
|
Binary file
|
@@ -1,15 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"version":1,
|
3
|
-
"applications":
|
4
|
-
[
|
5
|
-
{
|
6
|
-
"name":"<name>",
|
7
|
-
"api_key":"<apikey>",
|
8
|
-
"fetch_policies_from_tcell":false,
|
9
|
-
"tcell_input_url":"https://localhost/",
|
10
|
-
"preload_policy_filename":"config/tcell_preload.json",
|
11
|
-
"logging_options":{"enabled":true, "level":"DEBUG"}
|
12
|
-
}
|
13
|
-
]
|
14
|
-
}
|
15
|
-
|
File without changes
|
@@ -1,12 +0,0 @@
|
|
1
|
-
Connecting to database specified by DATABASE_URL
|
2
|
-
Connecting to database specified by DATABASE_URL
|
3
|
-
Connecting to database specified by DATABASE_URL
|
4
|
-
Connecting to database specified by DATABASE_URL
|
5
|
-
Connecting to database specified by DATABASE_URL
|
6
|
-
Connecting to database specified by DATABASE_URL
|
7
|
-
Connecting to database specified by DATABASE_URL
|
8
|
-
Connecting to database specified by DATABASE_URL
|
9
|
-
Connecting to database specified by DATABASE_URL
|
10
|
-
Connecting to database specified by DATABASE_URL
|
11
|
-
Connecting to database specified by DATABASE_URL
|
12
|
-
Connecting to database specified by DATABASE_URL
|
File without changes
|
@@ -1,71 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module TCellAgent
|
4
|
-
module Policies
|
5
|
-
describe ClickjackingPolicy do
|
6
|
-
content_security_policy_json = {
|
7
|
-
'policy_id' => '00a1',
|
8
|
-
'headers' => [
|
9
|
-
{ 'name' => 'csp', 'value' => 'csp header value' }
|
10
|
-
]
|
11
|
-
}
|
12
|
-
csp_from_json = ClickjackingPolicy.from_json(content_security_policy_json)
|
13
|
-
context 'initialized with 3 items' do
|
14
|
-
it 'returns true' do
|
15
|
-
expect(csp_from_json.policy_id).to eq('00a1')
|
16
|
-
expect(csp_from_json.headers[0].type).to eq('csp')
|
17
|
-
expect(csp_from_json.headers[0].value).to eq('csp header value')
|
18
|
-
end
|
19
|
-
end
|
20
|
-
context 'headers match up appropriately' do
|
21
|
-
it 'returns content-security-policy headers' do
|
22
|
-
expect(ClickjackingPolicy.cspHeadersForType('csp')).to match_array(['Content-Security-Policy']) # ,"X-Content-Security-Policy","X-WebKit-CSP"])
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
describe ContentSecurityPolicy do
|
27
|
-
content_security_policy_json = {
|
28
|
-
'policy_id' => '01a1',
|
29
|
-
'headers' => [
|
30
|
-
{ 'name' => 'csp-header-is-bad', 'value' => 'csp header value' }
|
31
|
-
]
|
32
|
-
}
|
33
|
-
csp_policy = ClickjackingPolicy.from_json(content_security_policy_json)
|
34
|
-
context 'csp header example, invalid header' do
|
35
|
-
it 'returns false' do
|
36
|
-
expect(csp_policy.headers.length).to eq(0)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
describe ClickjackingPolicy do
|
41
|
-
content_security_policy_json = {
|
42
|
-
'policy_id' => '01a1',
|
43
|
-
'headers' => [
|
44
|
-
{ 'name' => 'csp', 'value' => 'value123\\nabc' }
|
45
|
-
]
|
46
|
-
}
|
47
|
-
csp_policy = ClickjackingPolicy.from_json(content_security_policy_json)
|
48
|
-
context 'secure header, value is bad' do
|
49
|
-
it 'returns false' do
|
50
|
-
expect(csp_policy.headers.length).to eq(0)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
describe ClickjackingPolicy do
|
55
|
-
content_security_policy_json = {
|
56
|
-
'policy_id' => '01a1',
|
57
|
-
'headers' => [
|
58
|
-
{ 'name' => 'csp', 'value' => 'value normal', 'report-uri' => 'https://example.com/abcdde' }
|
59
|
-
]
|
60
|
-
}
|
61
|
-
csp_policy = ClickjackingPolicy.from_json(content_security_policy_json)
|
62
|
-
context 'secure header, report-uri seperate' do
|
63
|
-
it 'returns false' do
|
64
|
-
expect(csp_policy.headers.length).to eq(1)
|
65
|
-
expect(csp_policy.headers[0].value).to eq('value normal; report-uri https://example.com/abcdde')
|
66
|
-
expect(csp_policy.headers[0].value('1', '2', '3')).to eq('value normal; report-uri https://example.com/abcdde?tid=1&sid=2&uid=3')
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,130 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module TCellAgent
|
4
|
-
module Policies
|
5
|
-
describe ContentSecurityPolicy do
|
6
|
-
context 'test empty agent' do
|
7
|
-
it 'enabled is false' do
|
8
|
-
policy_json_empty = {
|
9
|
-
'policy_id' => '01a1',
|
10
|
-
'data' => {
|
11
|
-
'options' => {
|
12
|
-
|
13
|
-
}
|
14
|
-
}
|
15
|
-
}
|
16
|
-
|
17
|
-
empty_policy = ContentSecurityPolicy.from_json(policy_json_empty)
|
18
|
-
|
19
|
-
expect(empty_policy.policy_id).to eq('01a1')
|
20
|
-
expect(empty_policy.js_agent_api_key).to eq(nil)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'tests xss is true and enabled true' do
|
25
|
-
it 'returns true' do
|
26
|
-
policy_json_one = {
|
27
|
-
'policy_id' => '01a1',
|
28
|
-
'data' => {
|
29
|
-
'options' => {
|
30
|
-
'js_agent_api_key' => '000-000-1'
|
31
|
-
}
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
from_json = ContentSecurityPolicy.from_json(policy_json_one)
|
36
|
-
|
37
|
-
expect(from_json.policy_id).to eq('01a1')
|
38
|
-
expect(from_json.js_agent_api_key).to eq('000-000-1')
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context 'initialized with 3 items' do
|
43
|
-
it 'returns true' do
|
44
|
-
content_security_policy_json = {
|
45
|
-
'policy_id' => '00a1',
|
46
|
-
'headers' => [
|
47
|
-
{ 'name' => 'csp', 'value' => 'csp header value' }
|
48
|
-
]
|
49
|
-
}
|
50
|
-
|
51
|
-
csp_from_json = ContentSecurityPolicy.from_json(content_security_policy_json)
|
52
|
-
|
53
|
-
expect(csp_from_json.policy_id).to eq('00a1')
|
54
|
-
expect(csp_from_json.headers[0].type).to eq('csp')
|
55
|
-
expect(csp_from_json.headers[0].value).to eq('csp header value')
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'headers match up appropriately' do
|
60
|
-
it 'returns content-security-policy headers' do
|
61
|
-
expect(ContentSecurityPolicy.cspHeadersForType('csp')).to match_array(['Content-Security-Policy'])
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'csp header example, invalid header' do
|
66
|
-
it 'returns false' do
|
67
|
-
content_security_policy_json = {
|
68
|
-
'policy_id' => '01a1',
|
69
|
-
'headers' => [
|
70
|
-
{ 'name' => 'csp-header-is-bad', 'value' => 'csp header value' }
|
71
|
-
]
|
72
|
-
}
|
73
|
-
|
74
|
-
csp_policy = ContentSecurityPolicy.from_json(content_security_policy_json)
|
75
|
-
|
76
|
-
expect(csp_policy.headers.length).to eq(0)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'secure header, value is bad' do
|
81
|
-
it 'returns false' do
|
82
|
-
content_security_policy_json = {
|
83
|
-
'policy_id' => '01a1',
|
84
|
-
'headers' => [
|
85
|
-
{ 'name' => 'csp', 'value' => 'value123\\nabc' }
|
86
|
-
]
|
87
|
-
}
|
88
|
-
csp_policy = ContentSecurityPolicy.from_json(content_security_policy_json)
|
89
|
-
expect(csp_policy.headers.length).to eq(0)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context 'secure header, report-uri seperate' do
|
94
|
-
it 'returns false' do
|
95
|
-
content_security_policy_json = {
|
96
|
-
'policy_id' => '01a1',
|
97
|
-
'headers' => [
|
98
|
-
{ 'name' => 'csp', 'value' => 'value normal', 'report-uri' => 'https://example.com/abcdde' }
|
99
|
-
]
|
100
|
-
}
|
101
|
-
|
102
|
-
csp_policy = ContentSecurityPolicy.from_json(content_security_policy_json)
|
103
|
-
|
104
|
-
expect(csp_policy.headers.length).to eq(1)
|
105
|
-
expect(csp_policy.headers[0].value).to eq('value normal; report-uri https://example.com/abcdde?c=-815891691')
|
106
|
-
expect(csp_policy.headers[0].value('1', '2', '3')).to eq('value normal; report-uri https://example.com/abcdde?tid=1&sid=3&rid=2&c=1777384531')
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'default js_agent_url' do
|
111
|
-
it 'should have the configuration set to the default js_agent_url value' do
|
112
|
-
expect(TCellAgent.configuration.js_agent_url).to eq('https://jsagent.tcell.io/tcellagent.min.js')
|
113
|
-
|
114
|
-
content_security_policy_json = {
|
115
|
-
'policy_id' => '01a1',
|
116
|
-
'headers' => [
|
117
|
-
{ 'name' => 'csp', 'value' => "script-src 'unsafe-inline' 'unsafe-eval' 'self' https://api.tcell.io/" }
|
118
|
-
]
|
119
|
-
}
|
120
|
-
|
121
|
-
csp_policy = ContentSecurityPolicy.from_json(content_security_policy_json)
|
122
|
-
|
123
|
-
expect(csp_policy.headers.length).to eq(1)
|
124
|
-
expect(csp_policy.headers[0].value).to eq("script-src 'unsafe-inline' 'unsafe-eval' 'self' https://api.tcell.io/")
|
125
|
-
expect(TCellAgent.configuration.js_agent_url).to eq('https://jsagent.tcell.io/tcellagent.min.js')
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module TCellAgent
|
4
|
-
module Policies
|
5
|
-
describe SecureHeadersPolicy do
|
6
|
-
secure_headers_policy_json = {
|
7
|
-
'policy_id' => '01a1',
|
8
|
-
'headers' => [
|
9
|
-
{ 'name' => 'x-permitted-cross-domain-policies', 'value' => 'value123' }
|
10
|
-
]
|
11
|
-
}
|
12
|
-
secure_headers_policy = SecureHeadersPolicy.from_json(secure_headers_policy_json)
|
13
|
-
context 'secure header example' do
|
14
|
-
it 'returns true' do
|
15
|
-
expect(secure_headers_policy.headers[0].name).to eq('x-permitted-cross-domain-policies')
|
16
|
-
expect(secure_headers_policy.headers[0].value).to eq('value123')
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
describe SecureHeadersPolicy do
|
21
|
-
secure_headers_policy_json = {
|
22
|
-
'policy_id' => '01a1',
|
23
|
-
'headers' => [
|
24
|
-
{ 'name' => 'x-frame-options', 'value' => 'DENY' },
|
25
|
-
{ 'name' => 'x-xss-protection', 'value' => '1; mode=block' }
|
26
|
-
]
|
27
|
-
}
|
28
|
-
secure_headers_policy = SecureHeadersPolicy.from_json(secure_headers_policy_json)
|
29
|
-
context 'secure headers (2) example' do
|
30
|
-
it 'returns true' do
|
31
|
-
expect(secure_headers_policy.headers[0].name).to eq('x-frame-options')
|
32
|
-
expect(secure_headers_policy.headers[0].value).to eq('DENY')
|
33
|
-
expect(secure_headers_policy.headers[1].name).to eq('x-xss-protection')
|
34
|
-
expect(secure_headers_policy.headers[1].value).to eq('1; mode=block')
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
describe SecureHeadersPolicy do
|
39
|
-
secure_headers_policy_json = {
|
40
|
-
'policy_id' => '01a1',
|
41
|
-
'headers' => [
|
42
|
-
{ 'name' => 'bad-header', 'value' => 'value123' }
|
43
|
-
]
|
44
|
-
}
|
45
|
-
secure_headers_policy = SecureHeadersPolicy.from_json(secure_headers_policy_json)
|
46
|
-
context 'secure header example, invalid header' do
|
47
|
-
it 'returns false' do
|
48
|
-
expect(secure_headers_policy.headers.length).to eq(0)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
describe SecureHeadersPolicy do
|
53
|
-
secure_headers_policy_json = {
|
54
|
-
'policy_id' => '01a1',
|
55
|
-
'headers' => [
|
56
|
-
{ 'name' => 'x-permitted-cross-domain-policies', 'value' => 'value123\\nabc' }
|
57
|
-
]
|
58
|
-
}
|
59
|
-
secure_headers_policy = SecureHeadersPolicy.from_json(secure_headers_policy_json)
|
60
|
-
context 'secure header, value is bad' do
|
61
|
-
it 'returns false' do
|
62
|
-
expect(secure_headers_policy.headers.length).to eq(0)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module TCellAgent
|
4
|
-
describe Agent do
|
5
|
-
context 'Agent Read File' do
|
6
|
-
agent_worker = Agent.new(0)
|
7
|
-
it 'Reads in a policy file' do
|
8
|
-
policy_file_json = {
|
9
|
-
'csp-headers' => {
|
10
|
-
'policy_id' => '00a1',
|
11
|
-
'headers' => [
|
12
|
-
{ 'name' => 'csp', 'value' => 'csp loaded header' }
|
13
|
-
]
|
14
|
-
}
|
15
|
-
}
|
16
|
-
agent_worker.processPolicyJson(policy_file_json)
|
17
|
-
expect(agent_worker.policies[TCellAgent::PolicyTypes::CSP].headers[0].type).to eq('csp')
|
18
|
-
expect(agent_worker.policies[TCellAgent::PolicyTypes::CSP].headers[0].value).to eq('csp loaded header')
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|