tcell_agent 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +4 -0
- data/README.md +43 -0
- data/Rakefile +7 -0
- data/bin/tcell_agent +171 -0
- data/config/initializers/authlogic_auth.rb +51 -0
- data/config/initializers/devise_auth.rb +167 -0
- data/config/initializers/init.rb +8 -0
- data/lib/tcell_agent.rb +33 -0
- data/lib/tcell_agent/agent.rb +79 -0
- data/lib/tcell_agent/agent/event_processor.rb +133 -0
- data/lib/tcell_agent/agent/policy_manager.rb +138 -0
- data/lib/tcell_agent/agent/policy_types.rb +42 -0
- data/lib/tcell_agent/agent/static_agent.rb +22 -0
- data/lib/tcell_agent/api.rb +101 -0
- data/lib/tcell_agent/appsensor.rb +42 -0
- data/lib/tcell_agent/appsensor/cmdi.rb +32 -0
- data/lib/tcell_agent/appsensor/path_traversal.rb +33 -0
- data/lib/tcell_agent/appsensor/sqli.rb +55 -0
- data/lib/tcell_agent/appsensor/xss.rb +40 -0
- data/lib/tcell_agent/authlogic.rb +26 -0
- data/lib/tcell_agent/configuration.rb +148 -0
- data/lib/tcell_agent/dataloss.rb +0 -0
- data/lib/tcell_agent/devise.rb +83 -0
- data/lib/tcell_agent/instrumentation.rb +44 -0
- data/lib/tcell_agent/logger.rb +46 -0
- data/lib/tcell_agent/policies/add_script_tag_policy.rb +47 -0
- data/lib/tcell_agent/policies/appsensor_policy.rb +76 -0
- data/lib/tcell_agent/policies/clickjacking_policy.rb +113 -0
- data/lib/tcell_agent/policies/content_security_policy.rb +119 -0
- data/lib/tcell_agent/policies/dataloss_policy.rb +175 -0
- data/lib/tcell_agent/policies/honeytokens_policy.rb +67 -0
- data/lib/tcell_agent/policies/http_redirect_policy.rb +84 -0
- data/lib/tcell_agent/policies/http_tx_policy.rb +60 -0
- data/lib/tcell_agent/policies/login_fraud_policy.rb +42 -0
- data/lib/tcell_agent/policies/secure_headers_policy.rb +64 -0
- data/lib/tcell_agent/rails.rb +146 -0
- data/lib/tcell_agent/rails/devise.rb +0 -0
- data/lib/tcell_agent/rails/dlp.rb +204 -0
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +69 -0
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +50 -0
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +53 -0
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +176 -0
- data/lib/tcell_agent/rails/routes.rb +130 -0
- data/lib/tcell_agent/rails/settings_reporter.rb +40 -0
- data/lib/tcell_agent/sensor_events/app_config.rb +16 -0
- data/lib/tcell_agent/sensor_events/app_sensor.rb +240 -0
- data/lib/tcell_agent/sensor_events/dlp.rb +58 -0
- data/lib/tcell_agent/sensor_events/honeytokens.rb +16 -0
- data/lib/tcell_agent/sensor_events/login_fraud.rb +43 -0
- data/lib/tcell_agent/sensor_events/metrics.rb +24 -0
- data/lib/tcell_agent/sensor_events/sensor.rb +85 -0
- data/lib/tcell_agent/sensor_events/server_agent.rb +101 -0
- data/lib/tcell_agent/sensor_events/util/redirect_utils.rb +22 -0
- data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +153 -0
- data/lib/tcell_agent/sensor_events/util/utils.rb +21 -0
- data/lib/tcell_agent/sinatra.rb +41 -0
- data/lib/tcell_agent/start_background_thread.rb +63 -0
- data/lib/tcell_agent/userinfo.rb +8 -0
- data/lib/tcell_agent/utils/queue_with_timeout.rb +60 -0
- data/lib/tcell_agent/version.rb +5 -0
- data/spec/controllers/application_controller.rb +12 -0
- data/spec/lib/tcell_agent/api/api_spec.rb +36 -0
- data/spec/lib/tcell_agent/appsensor_spec.rb +66 -0
- data/spec/lib/tcell_agent/policies/add_script_tag_policy_spec.rb +37 -0
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +40 -0
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +88 -0
- data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +62 -0
- data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/login_policy_spec.rb +42 -0
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +67 -0
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +187 -0
- data/spec/lib/tcell_agent/rails_spec.rb +57 -0
- data/spec/lib/tcell_agent/sensor_events/dlp_spec.rb +14 -0
- data/spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb +25 -0
- data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +57 -0
- data/spec/lib/tcell_agent_spec.rb +22 -0
- data/spec/resources/normal_config.json +13 -0
- data/spec/spec_helper.rb +4 -0
- data/tcell_agent.gemspec +29 -0
- metadata +249 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Policies
|
5
|
+
describe ContentSecurityPolicy 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 = ContentSecurityPolicy.fromJson(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(ContentSecurityPolicy.cspHeadersForType("csp")).to match_array(["Content-Security-Policy"])
|
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 = ContentSecurityPolicy.fromJson(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 ContentSecurityPolicy do
|
41
|
+
content_security_policy_json = {
|
42
|
+
"policy_id"=>"01a1",
|
43
|
+
"headers"=>[
|
44
|
+
{"name"=>"csp", "value"=>"value123\\nabc"}
|
45
|
+
]
|
46
|
+
}
|
47
|
+
csp_policy = ContentSecurityPolicy.fromJson(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 ContentSecurityPolicy 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 = ContentSecurityPolicy.fromJson(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
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module TCellAgent
|
5
|
+
module Policies
|
6
|
+
describe DataLossPolicy do
|
7
|
+
policy_json = {
|
8
|
+
"policy_id"=>"x1a1",
|
9
|
+
"data"=>{
|
10
|
+
"protections"=>[
|
11
|
+
{"table"=>"user",
|
12
|
+
"field"=>"ssn",
|
13
|
+
"actions"=>{
|
14
|
+
"body"=>["event","redact"],
|
15
|
+
"logs"=>["redact"]
|
16
|
+
}
|
17
|
+
}
|
18
|
+
]
|
19
|
+
}
|
20
|
+
}
|
21
|
+
policy = DataLossPolicy.fromJson(policy_json)
|
22
|
+
context "initialized with 3 items" do
|
23
|
+
it "returns true" do
|
24
|
+
expect(policy.get_actions_for("user","ssn")).to eq(["body_redact"].to_set)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
policy_json_two = {
|
28
|
+
"policy_id"=>"x1a1",
|
29
|
+
"data"=>{
|
30
|
+
"session_id_protection"=>{"body"=>["redact"], "log"=>["event"]}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
policy_two = DataLossPolicy.fromJson(policy_json_two)
|
34
|
+
context "check session_id_protections" do
|
35
|
+
it "gives the right actions" do
|
36
|
+
expect(policy_two.get_actions_for_session_id.body_redact).to eq(true)
|
37
|
+
expect(policy_two.get_actions_for_session_id.log_redact).to eq(nil)
|
38
|
+
expect(policy_two.get_actions_for_session_id.log_event).to eq(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
context "Request Options" do
|
42
|
+
it "Ignores non-global scoped policy" do
|
43
|
+
policy_json_requests = {
|
44
|
+
"policy_id"=>"x1a1",
|
45
|
+
"data"=>{
|
46
|
+
"request_protections"=>[
|
47
|
+
{
|
48
|
+
"context"=>"form",
|
49
|
+
"scope"=>"route",
|
50
|
+
"variable"=>"test123",
|
51
|
+
"options"=>{
|
52
|
+
"log"=>["redact"],
|
53
|
+
"body"=>["event"]
|
54
|
+
}
|
55
|
+
}
|
56
|
+
]
|
57
|
+
}
|
58
|
+
}
|
59
|
+
policy_three = DataLossPolicy.fromJson(policy_json_requests)
|
60
|
+
expect(policy_three.get_actions_for_request("form").keys).to eq([])
|
61
|
+
end
|
62
|
+
it "Reads in the policy" do
|
63
|
+
policy_json_requests = {
|
64
|
+
"policy_id"=>"x1a1",
|
65
|
+
"data"=>{
|
66
|
+
"request_protections"=>[
|
67
|
+
{
|
68
|
+
"context"=>"form",
|
69
|
+
"variable"=>"test123",
|
70
|
+
"options"=>{
|
71
|
+
"log"=>["redact"],
|
72
|
+
"body"=>["event"]
|
73
|
+
}
|
74
|
+
}
|
75
|
+
]
|
76
|
+
}
|
77
|
+
}
|
78
|
+
policy_three = DataLossPolicy.fromJson(policy_json_requests)
|
79
|
+
puts policy_three.request_filter_actions
|
80
|
+
expect(policy_three.get_actions_for_request("form").keys).to eq(["test123"])
|
81
|
+
expect(policy_three.get_actions_for_request("form")["test123"].log_redact).to eq(true)
|
82
|
+
expect(policy_three.get_actions_for_request("form")["test123"].body_redact).to eq(nil)
|
83
|
+
expect(policy_three.get_actions_for_request("form")["test123"].body_event).to eq(true)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Policies
|
5
|
+
describe HoneytokensPolicy do
|
6
|
+
policy_json = {
|
7
|
+
"policy_id"=>"x1a1",
|
8
|
+
"token_salt"=>"saltsaltsalt",
|
9
|
+
"tokens"=>[
|
10
|
+
{"type"=>"cred", "token"=>"TOKEN", "id"=>"ID001"}
|
11
|
+
]
|
12
|
+
}
|
13
|
+
policy = HoneytokensPolicy.fromJson(policy_json)
|
14
|
+
context "initialized with 3 items" do
|
15
|
+
it "returns true" do
|
16
|
+
expect(policy.policy_id).to eq("x1a1")
|
17
|
+
expect(policy.cred_tokens["TOKEN"]).to eq("ID001")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Policies
|
5
|
+
describe HttpRedirectPolicy do
|
6
|
+
http_redirect_plain = HttpRedirectPolicy.new
|
7
|
+
context "defaults" do
|
8
|
+
it "returns true" do
|
9
|
+
expect(http_redirect_plain.policy_id).to eq(nil)
|
10
|
+
expect(http_redirect_plain.enabled).to eq(false)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
http_redirect_policy_json = {
|
14
|
+
"policy_id"=>"x1a1",
|
15
|
+
"data"=>{
|
16
|
+
"enabled"=>true
|
17
|
+
}
|
18
|
+
}
|
19
|
+
http_redirect_from_json = HttpRedirectPolicy.fromJson(http_redirect_policy_json)
|
20
|
+
context "initialized with 3 items" do
|
21
|
+
it "returns true" do
|
22
|
+
expect(http_redirect_from_json.policy_id).to eq("x1a1")
|
23
|
+
expect(http_redirect_from_json.enabled).to eq(true)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
context "check url" do
|
27
|
+
it "see's other domain" do
|
28
|
+
result = http_redirect_from_json.check("test.google.com", "www.test.com")
|
29
|
+
expect(result).to eq(true)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
context "check url" do
|
33
|
+
it "wildcard domain false" do
|
34
|
+
http_redirect_from_json.whitelist = ["*.google.com"]
|
35
|
+
result = http_redirect_from_json.check("test.google.com", "www.test.com")
|
36
|
+
expect(result).to eq(false)
|
37
|
+
end
|
38
|
+
it "wildcard domain true" do
|
39
|
+
http_redirect_from_json.whitelist = ["*.google.com"]
|
40
|
+
result = http_redirect_from_json.check("test.google.net", "www.test.com")
|
41
|
+
expect(result).to eq(true)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
context "enforce url" do
|
45
|
+
it "domain enforce enabled false, block true" do
|
46
|
+
http_redirect_from_json.enabled = false
|
47
|
+
http_redirect_from_json.block = true
|
48
|
+
http_redirect_from_json.whitelist = ["*.google.com"]
|
49
|
+
result = http_redirect_from_json.enforce("https://test.google.com", "www.test.com", "/path/a", "GET", "1.1.1.1", 400)
|
50
|
+
expect(result).to eq(nil)
|
51
|
+
end
|
52
|
+
it "domain enforce enabled true, block true" do
|
53
|
+
http_redirect_from_json.enabled = true
|
54
|
+
http_redirect_from_json.block = true
|
55
|
+
http_redirect_from_json.whitelist = ["good.com"]
|
56
|
+
result = http_redirect_from_json.enforce("https://www.google.com/abc/def", "localhost", "/path/a", "GET", "1.1.1.1", 400)
|
57
|
+
expect(result).to eq("/")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Policies
|
5
|
+
describe HttpTxPolicy do
|
6
|
+
http_tx_policy_json = {
|
7
|
+
"policy_id"=>"01a1",
|
8
|
+
"types"=>{
|
9
|
+
"firehose"=>{"enabled"=>true}
|
10
|
+
}
|
11
|
+
}
|
12
|
+
http_tx_from_json = HttpTxPolicy.fromJson(http_tx_policy_json)
|
13
|
+
context "initialized with 3 items" do
|
14
|
+
it "returns true" do
|
15
|
+
expect(http_tx_from_json.policy_id).to eq("01a1")
|
16
|
+
expect(http_tx_from_json.firehose["enabled"]).to eq(true)
|
17
|
+
expect(http_tx_from_json.firehose["lite"]).to eq(false)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Policies
|
5
|
+
describe LoginFraudPolicy do
|
6
|
+
policy_json_empty = {
|
7
|
+
"policy_id"=>"01a1",
|
8
|
+
"data"=>{
|
9
|
+
"options"=>{}
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
policy_json_one = {
|
14
|
+
"policy_id"=>"01a1",
|
15
|
+
"data"=>{
|
16
|
+
"options"=>{
|
17
|
+
"login_failed_enabled"=>true,
|
18
|
+
"login_success_enabled"=>true
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
empty_policy = LoginFraudPolicy.fromJson(policy_json_empty)
|
24
|
+
context "test empty agent" do
|
25
|
+
it "enabled is false" do
|
26
|
+
expect(empty_policy.policy_id).to eq("01a1")
|
27
|
+
expect(empty_policy.login_failed_enabled).to eq(false)
|
28
|
+
expect(empty_policy.login_success_enabled).to eq(false)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
policy_one = LoginFraudPolicy.fromJson(policy_json_one)
|
33
|
+
context "enabled agent" do
|
34
|
+
it "enabled is true" do
|
35
|
+
expect(empty_policy.policy_id).to eq("01a1")
|
36
|
+
expect(policy_one.login_failed_enabled).to eq(true)
|
37
|
+
expect(policy_one.login_success_enabled).to eq(true)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,67 @@
|
|
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.fromJson(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.fromJson(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.fromJson(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.fromJson(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
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'rack'
|
4
|
+
|
5
|
+
module TCellAgent
|
6
|
+
module Instrumentation
|
7
|
+
module Rails
|
8
|
+
module Middleware
|
9
|
+
|
10
|
+
class MockRackApp
|
11
|
+
|
12
|
+
attr_reader :request_body
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@request_headers = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
@env = env
|
20
|
+
@request_body = env['rack.input'].read
|
21
|
+
rack_request = Rack::Request.new(env)
|
22
|
+
response_headers = {'Content-Type' => 'text/html'}
|
23
|
+
if (rack_request.params['rv'])
|
24
|
+
response_headers["Location"] = rack_request.params['rv']
|
25
|
+
end
|
26
|
+
[200, response_headers, ['OK']]
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](key)
|
30
|
+
@env[key]
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe HeadersMiddleware do
|
36
|
+
|
37
|
+
let(:app) { GlobalMiddleware.new(MockRackApp.new) }
|
38
|
+
subject { ContextMiddleware.new(described_class.new(app)) }
|
39
|
+
|
40
|
+
context "Redirect Middleware" do
|
41
|
+
let(:request) { Rack::MockRequest.new(subject) }
|
42
|
+
let(:agent) { ::TCellAgent::Agent.new(Process.pid) }
|
43
|
+
before(:each) do
|
44
|
+
TCellAgent.configuration = TCellAgent::Configuration.new
|
45
|
+
TCellAgent.configuration.read_config_from_file("spec/resources/normal_config.json")
|
46
|
+
agent.start
|
47
|
+
TCellAgent.thread_agent = agent
|
48
|
+
end
|
49
|
+
|
50
|
+
context "not enabled" do
|
51
|
+
it "passes through unchanged" do
|
52
|
+
agent.processPolicyJson({"http-redirect"=>{
|
53
|
+
"policy_id"=>"153ed270-7481-11e5-9194-95dad9b9dec3",
|
54
|
+
"data"=>{
|
55
|
+
"enabled"=>false,
|
56
|
+
"block"=>true,
|
57
|
+
"whitelist"=>[]
|
58
|
+
}
|
59
|
+
}}, cache=false)
|
60
|
+
tid_len = "78e596b7-e772-4caf-92eb-645fdbdec473".length + 1
|
61
|
+
response = request.get("/some/path?rv=https://www.google.com", 'CONTENT_TYPE' => 'text/html')
|
62
|
+
expect(response['Location']).to eq("https://www.google.com")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "doesn't block simple whitelist" do
|
67
|
+
it "passes through unchanged" do
|
68
|
+
agent.processPolicyJson({"http-redirect"=>{
|
69
|
+
"policy_id"=>"153ed270-7481-11e5-9194-95dad9b9dec3",
|
70
|
+
"data"=>{
|
71
|
+
"enabled"=>true,
|
72
|
+
"block"=>true,
|
73
|
+
"whitelist"=>["www.google.com"]
|
74
|
+
}
|
75
|
+
}}, cache=false)
|
76
|
+
|
77
|
+
tid_len = "78e596b7-e772-4caf-92eb-645fdbdec473".length + 1
|
78
|
+
response = request.get("/some/path?rv=https://www.google.com", 'CONTENT_TYPE' => 'text/html')
|
79
|
+
expect(response['Location']).to eq("https://www.google.com")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "doesn't block wildcard whitelist" do
|
84
|
+
it "passes through unchanged" do
|
85
|
+
agent.processPolicyJson({"http-redirect"=>{
|
86
|
+
"policy_id"=>"153ed270-7481-11e5-9194-95dad9b9dec3",
|
87
|
+
"data"=>{
|
88
|
+
"enabled"=>true,
|
89
|
+
"block"=>true,
|
90
|
+
"whitelist"=>["*.google.com"]
|
91
|
+
}
|
92
|
+
}}, cache=false)
|
93
|
+
|
94
|
+
tid_len = "78e596b7-e772-4caf-92eb-645fdbdec473".length + 1
|
95
|
+
response = request.get("/some/path?rv=https://www.google.com", 'CONTENT_TYPE' => 'text/html')
|
96
|
+
expect(response['Location']).to eq("https://www.google.com")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "DOES block wildcard whitelist" do
|
101
|
+
it "replaces the value with /" do
|
102
|
+
agent.processPolicyJson({"http-redirect"=>{
|
103
|
+
"policy_id"=>"153ed270-7481-11e5-9194-95dad9b9dec3",
|
104
|
+
"data"=>{
|
105
|
+
"enabled"=>true,
|
106
|
+
"block"=>true,
|
107
|
+
"whitelist"=>["*.google-test.com"]
|
108
|
+
}
|
109
|
+
}}, cache=false)
|
110
|
+
|
111
|
+
tid_len = "78e596b7-e772-4caf-92eb-645fdbdec473".length + 1
|
112
|
+
response = request.get("/some/path?rv=https://www.google.com", 'CONTENT_TYPE' => 'text/html')
|
113
|
+
expect(response['Location']).to eq("/")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
context "CSP Middleware" do
|
120
|
+
let(:request) { Rack::MockRequest.new(subject) }
|
121
|
+
let(:agent) { ::TCellAgent::Agent.new(Process.pid) }
|
122
|
+
|
123
|
+
before(:each) do
|
124
|
+
TCellAgent.configuration = TCellAgent::Configuration.new
|
125
|
+
TCellAgent.configuration.read_config_from_file("spec/resources/normal_config.json")
|
126
|
+
agent.start
|
127
|
+
TCellAgent.thread_agent = agent
|
128
|
+
end
|
129
|
+
|
130
|
+
context "Standard CSP Header" do
|
131
|
+
it "CSP Header is Added" do
|
132
|
+
agent.processPolicyJson({"csp-headers"=>{
|
133
|
+
"policy_id"=>"153ed270-7481-11e5-9194-95dad9b9dec3",
|
134
|
+
"headers"=>[{
|
135
|
+
"name"=>"Content-Security-Policy-Report-Only",
|
136
|
+
"value"=>"script-src 'unsafe-inline'",
|
137
|
+
"report-uri"=>"http://test.tcell.io/report"
|
138
|
+
}]
|
139
|
+
}}, cache=false)
|
140
|
+
tid_len = "78e596b7-e772-4caf-92eb-645fdbdec473".length + 1
|
141
|
+
response = request.get("/some/path", 'CONTENT_TYPE' => 'text/plain', 'action_dispatch.request_id'=>'35281717-247e-44e6-bd42-0fb1417e80d')
|
142
|
+
expect(response['Content-Security-Policy-Report-Only'][0..-tid_len]).to eq("script-src 'unsafe-inline'; report-uri http://test.tcell.io/report?tid=")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
# context "when called with a POST request" do
|
149
|
+
# context "with some particular data" do
|
150
|
+
# let(:request) { Rack::MockRequest.new(app) }
|
151
|
+
|
152
|
+
# it "passes the request through unchanged" do
|
153
|
+
|
154
|
+
# TCellAgent.configuration = TCellAgent::Configuration.new
|
155
|
+
# TCellAgent.configuration.read_config_from_file("spec/resources/normal_config.json")
|
156
|
+
|
157
|
+
# agent = ::TCellAgent::Agent.new(Process.pid)
|
158
|
+
# ::TCellAgent::AgentThread.setThread(agent)
|
159
|
+
# agent.start
|
160
|
+
# agent.processPolicyJson({"csp"=>{
|
161
|
+
# "policy_id"=>"153ed270-7481-11e5-9194-95dad9b9dec3",
|
162
|
+
# "headers"=>{
|
163
|
+
# "name"=>"Content-Security-Policy-Report-Only",
|
164
|
+
# "value"=>"script-src 'unsafe-inline'",
|
165
|
+
# "report-uri"=>"http://test.tcell.io/report"
|
166
|
+
# }
|
167
|
+
# }})
|
168
|
+
|
169
|
+
# #noop = Proc.new {[200, {}, ["hello"]]}
|
170
|
+
# #middleware = ActionDispatch::Static.new(noop, "/my_rails_app/public")
|
171
|
+
# #request = Rack::MockRequest.new(middleware)
|
172
|
+
# #puts request.get("/path_i_want_to_hit")
|
173
|
+
|
174
|
+
# puts request.get("/some/path", 'CONTENT_TYPE' => 'text/plain')
|
175
|
+
|
176
|
+
# # expect(app['CONTENT_TYPE']).to eq('text/plain')
|
177
|
+
# # expect(app.request_body).to eq(post_data)
|
178
|
+
|
179
|
+
# end
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|