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,21 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'cgi'
|
5
|
+
require 'uri'
|
6
|
+
require 'openssl'
|
7
|
+
|
8
|
+
module TCellAgent
|
9
|
+
module SensorEvents
|
10
|
+
module Util
|
11
|
+
def self.jhash(str)
|
12
|
+
str.each_char.reduce(0) do |result, char|
|
13
|
+
[((result << 5) - result) + char.ord].pack('L').unpack('l').first
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def self.calculateRouteId(method, path, params=nil)
|
17
|
+
jhash("#{method}|#{path}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'sinatra'
|
5
|
+
require 'tcell_agent/agent'
|
6
|
+
require 'tcell_agent/instrumentation'
|
7
|
+
|
8
|
+
module TCellAgent
|
9
|
+
class Sinatra::Response
|
10
|
+
include Sinatra
|
11
|
+
alias_method :original_finish, :finish
|
12
|
+
def finish
|
13
|
+
status, headers, response = original_finish
|
14
|
+
|
15
|
+
TCellAgent::Instrumentation.safe_block("Setting CSP Headers") {
|
16
|
+
content_security_policy = TCellAgent.policy(TCellAgent::PolicyTypes::CSP)
|
17
|
+
if content_security_policy
|
18
|
+
content_security_policy.each(
|
19
|
+
nil,
|
20
|
+
nil,
|
21
|
+
nil) do | header_pair |
|
22
|
+
headers[header_pair["name"]] = header_pair["value"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
TCellAgent::Instrumentation.safe_block("Setting Secure Headers") {
|
28
|
+
secure_headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::SecureHeaders)
|
29
|
+
if secure_headers_policy
|
30
|
+
secure_headers_policy.headers.each do | secure_header |
|
31
|
+
headers[secure_header.name] = secure_header.value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
}
|
35
|
+
|
36
|
+
[status, headers, response]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'tcell_agent/logger'
|
4
|
+
require 'tcell_agent/agent'
|
5
|
+
require 'tcell_agent/configuration'
|
6
|
+
|
7
|
+
agent = ::TCellAgent::Agent.new(Process.pid)
|
8
|
+
TCellAgent.thread_agent = agent
|
9
|
+
|
10
|
+
# creates a fork and pipes a string from parent to child
|
11
|
+
if File.basename($0) != 'rake'
|
12
|
+
if (File.basename($0) == 'rails' &&
|
13
|
+
((defined?(Thin) && (Rack::Handler.default == Rack::Handler::Thin)) ||
|
14
|
+
(defined?(WEBrick) && (Rack::Handler.default == Rack::Handler::WEBrick))))
|
15
|
+
TCellAgent.logger.debug("Initializing background thread: Thin")
|
16
|
+
begin
|
17
|
+
TCellAgent.thread_agent = agent
|
18
|
+
agent.start
|
19
|
+
rescue Exception => e
|
20
|
+
TCellAgent.logger.error("Could not start worker.", e.message)
|
21
|
+
end
|
22
|
+
elsif defined?(Puma) && defined?(Puma.cli_config) && Puma.cli_config.options[:workers] > 1
|
23
|
+
agent.start_event_processor(false)
|
24
|
+
# preload app
|
25
|
+
TCellAgent.logger.debug("Initializing background thread: Puma Preload")
|
26
|
+
puma_worker_start = Proc.new do
|
27
|
+
begin
|
28
|
+
agent = TCellAgent::Agent.new(Process.pid)
|
29
|
+
TCellAgent.thread_agent = agent
|
30
|
+
agent.start
|
31
|
+
rescue Exception => e
|
32
|
+
TCellAgent.logger.error("Could not start worker.", e.message)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
Puma.cli_config.options[:before_worker_boot].push(puma_worker_start)
|
36
|
+
elsif defined?(Unicorn) && Unicorn::HttpServer::LISTENERS.length == 0
|
37
|
+
agent.start_event_processor(false)
|
38
|
+
TCellAgent.logger.debug("Initializing background thread: Unicorn Preload")
|
39
|
+
class Unicorn::HttpServer
|
40
|
+
alias old_init_worker_process init_worker_process
|
41
|
+
def init_worker_process(work)
|
42
|
+
begin
|
43
|
+
agent = TCellAgent::Agent.new(Process.pid)
|
44
|
+
TCellAgent.thread_agent = agent
|
45
|
+
agent.start
|
46
|
+
rescue Exception => e
|
47
|
+
TCellAgent.logger.error("Could not start worker.", e.message)
|
48
|
+
end
|
49
|
+
return old_init_worker_process(work)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
else
|
53
|
+
TCellAgent.logger.debug("Initializing background thread (no-preload).")
|
54
|
+
begin
|
55
|
+
TCellAgent.thread_agent = agent
|
56
|
+
agent.start
|
57
|
+
rescue Exception => e
|
58
|
+
TCellAgent.logger.error("Could not start worker.", e.message)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require "tcell_agent/logger"
|
4
|
+
require 'thread'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
module TCellAgent
|
8
|
+
class QueueWithTimeout
|
9
|
+
def initialize
|
10
|
+
@mutex = Mutex.new
|
11
|
+
@queue = []
|
12
|
+
@response_time_table = {}
|
13
|
+
@recieved = ConditionVariable.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def <<(x)
|
17
|
+
@mutex.synchronize do
|
18
|
+
@queue << x
|
19
|
+
@recieved.signal
|
20
|
+
end
|
21
|
+
end
|
22
|
+
def add_response_time(route_id, response_time)
|
23
|
+
@mutex.synchronize do
|
24
|
+
if (route_id == nil || route_id == "")
|
25
|
+
route_id = "?"
|
26
|
+
end
|
27
|
+
@response_time_table[route_id] = @response_time_table.fetch(route_id,{})
|
28
|
+
@response_time_table[route_id]["c"] = @response_time_table[route_id].fetch("c",0) + 1
|
29
|
+
@response_time_table[route_id]["mx"] = [@response_time_table[route_id].fetch("mx",0), response_time].max
|
30
|
+
@response_time_table[route_id]["mn"] = [@response_time_table[route_id].fetch("mn",response_time), response_time].min
|
31
|
+
@response_time_table[route_id]["t"] = ((@response_time_table[route_id].fetch("t",0)*(@response_time_table[route_id]["c"]-1)) + response_time) / @response_time_table[route_id]["c"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
def length
|
35
|
+
return @queue.length
|
36
|
+
end
|
37
|
+
def get_response_time_table
|
38
|
+
return @response_time_table
|
39
|
+
end
|
40
|
+
def reset_response_time_table
|
41
|
+
@mutex.synchronize do
|
42
|
+
@response_time_table = {}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
def pop(non_block = false)
|
46
|
+
pop_with_timeout(non_block ? 0 : nil)
|
47
|
+
end
|
48
|
+
|
49
|
+
def pop_with_timeout(timeout = nil)
|
50
|
+
@mutex.synchronize do
|
51
|
+
if @queue.empty?
|
52
|
+
@recieved.wait(@mutex, timeout) if timeout != 0
|
53
|
+
#if we're still empty after the timeout, raise exception
|
54
|
+
raise ThreadError, "queue empty" if @queue.empty?
|
55
|
+
end
|
56
|
+
@queue.shift
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
describe 'GET /' do
|
2
|
+
context 'Get homepage' do
|
3
|
+
it 'Adds CSP Headers' do
|
4
|
+
|
5
|
+
user = create(:user)
|
6
|
+
|
7
|
+
post :create, session: { email: user.email, password: 'invalid' }
|
8
|
+
|
9
|
+
expect(response).to render_template(:new)
|
10
|
+
expect(flash[:notice]).to match(/^Email and password do not match/)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'addressable/template'
|
3
|
+
|
4
|
+
|
5
|
+
module TCellAgent
|
6
|
+
class TCellApi
|
7
|
+
describe "successful POST on /user/create" do
|
8
|
+
it "should redirect to dashboard" do
|
9
|
+
tapi = TCellApi.new
|
10
|
+
TCellAgent.configuration.app_id = "test-appid"
|
11
|
+
TCellAgent.configuration.api_key = "test-apikey"
|
12
|
+
|
13
|
+
def checkreq(req)
|
14
|
+
return '{"result":{"csp-headers":{"app_id":"testapp-Becwu","policy_id":' \
|
15
|
+
'"acf60560-4e76-11e5-874c-7d71d425b275","headers":[{"name":"Content-Security-Policy-Report-Only",' \
|
16
|
+
'"value":"font-src \'none\'; script-src \'self\'; reflected-xss block; ' \
|
17
|
+
'style-src \'self\'; connect-src' \
|
18
|
+
' \'none\'" ,"report-uri":"http://localhost:3000/csp/cab5e750e66d614bd46fd07a7078db1e74b4f427b2a135b2c96eca684a642707"}]}}}'
|
19
|
+
end
|
20
|
+
uri_template =
|
21
|
+
Addressable::Template.new "https://api.tcell.io/api/v1/app/{app}/update"
|
22
|
+
stub_request(:any, uri_template).
|
23
|
+
to_return(lambda { |request| {
|
24
|
+
:body => checkreq(request), :status => 200,
|
25
|
+
:headers => { 'Content-Tyoe' => 'application/json' }
|
26
|
+
} })
|
27
|
+
|
28
|
+
# to_return(:body => resbody,
|
29
|
+
result = tapi.pollAPI
|
30
|
+
TCellAgent.configuration.app_id = nil
|
31
|
+
TCellAgent.configuration.api_key = nil
|
32
|
+
expect(result["csp-headers"]["app_id"]).to eq("testapp-Becwu")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
describe AppSensor do
|
5
|
+
|
6
|
+
context "Safe String" do
|
7
|
+
it "Tests Generally Safe Strings" do
|
8
|
+
expect(AppSensor.generallySafe("abc def")).to eq(true)
|
9
|
+
expect(AppSensor.generallySafe("abc d\">ef")).to eq(false)
|
10
|
+
expect(AppSensor.generallySafe("abc \0>ef")).to eq(false)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
context "XSS Detection Test" do
|
14
|
+
it "Tests Standard XSS Probes" do
|
15
|
+
expect(AppSensor.isXss("abc def")).to eq(false)
|
16
|
+
expect(AppSensor.isXss("O'Reilly")).to eq(false)
|
17
|
+
|
18
|
+
expect(AppSensor.isXss("abc\"><script>")).to eq(true)
|
19
|
+
expect(AppSensor.isXss("<script>")).to eq(true)
|
20
|
+
expect(AppSensor.isXss("O'><img src='x' onerror='alert(1)'>Reilly")).to eq(true)
|
21
|
+
expect(AppSensor.isXss("O'><img/src='x' onerror='alert(1)'>Reilly")).to eq(true)
|
22
|
+
expect(AppSensor.isXss("\"><script>alert(/XSSPOSED/);</script>")).to eq(true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
context "SQLi Detection Test" do
|
26
|
+
it "Tests Standard XSS Probes" do
|
27
|
+
expect(AppSensor.isSqli("abc def")).to eq(false)
|
28
|
+
expect(AppSensor.isSqli("555--")).to eq(false)
|
29
|
+
expect(AppSensor.isSqli("555--666")).to eq(false)
|
30
|
+
expect(AppSensor.isSqli("I should order by friday")).to eq(false)
|
31
|
+
expect(AppSensor.isSqli('b<img src="a"><script>alert(1)</script>')).to eq(false)
|
32
|
+
|
33
|
+
expect(AppSensor.isSqli("a\" OR \"5\"= \"5")).to eq(true)
|
34
|
+
expect(AppSensor.isSqli("a' OR '5'= '5")).to eq(true)
|
35
|
+
expect(AppSensor.isSqli("a';--")).to eq(true)
|
36
|
+
expect(AppSensor.isSqli("a'--")).to eq(true)
|
37
|
+
#expect(AppSensor.isSqli("4 OR 3=3--")).to eq(true)
|
38
|
+
expect(AppSensor.isSqli("10 OrDeR By 10--")).to eq(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
context "Cmd Injection Test" do
|
42
|
+
it "Tests for null character" do
|
43
|
+
expect(AppSensor.isCmdi("bob.txt echo 'hi'")).to eq(false)
|
44
|
+
expect(AppSensor.isCmdi("bob.txt; echo 'hi'")).to eq(true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
context "Path Traversal Test" do
|
48
|
+
it "Tests for path traversal" do
|
49
|
+
expect(AppSensor.isPathTraversal("bob.txt echo 'hi'")).to eq(false)
|
50
|
+
expect(AppSensor.isPathTraversal("3/.5")).to eq(false)
|
51
|
+
expect(AppSensor.isPathTraversal("../../../test.config")).to eq(true)
|
52
|
+
expect(AppSensor.isPathTraversal("/etc/passwd")).to eq(true)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
context "String Characters Test" do
|
56
|
+
it "Tests for null character" do
|
57
|
+
expect(AppSensor.containsReturnChars("abc def")).to eq(false)
|
58
|
+
expect(AppSensor.containsReturnChars("abc\x0adef")).to eq(true)
|
59
|
+
expect(AppSensor.containsReturnChars("abc\x0a\x0ddef")).to eq(true)
|
60
|
+
expect(AppSensor.containsReturnChars("abc\x0ddef")).to eq(true)
|
61
|
+
expect(AppSensor.containsReturnChars("abc\x00 def")).to eq(false)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Policies
|
5
|
+
describe AddScriptTagPolicy do
|
6
|
+
policy_json_empty = {
|
7
|
+
"policy_id"=>"01a1",
|
8
|
+
"data"=>{
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
policy_json_one = {
|
13
|
+
"policy_id"=>"01a1",
|
14
|
+
"data"=>{
|
15
|
+
"js_agent_api_key"=>"000-000-1"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
empty_policy = AddScriptTagPolicy.fromJson(policy_json_empty)
|
20
|
+
context "test empty agent" do
|
21
|
+
it "enabled is false" do
|
22
|
+
expect(empty_policy.policy_id).to eq("01a1")
|
23
|
+
expect(empty_policy.enabled).to eq(false)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
from_json = AddScriptTagPolicy.fromJson(policy_json_one)
|
28
|
+
context "tests xss is true and enabled true" do
|
29
|
+
it "returns true" do
|
30
|
+
expect(from_json.policy_id).to eq("01a1")
|
31
|
+
expect(from_json.enabled).to eq(true)
|
32
|
+
expect(from_json.js_agent_api_key).to eq("000-000-1")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Policies
|
5
|
+
describe AppSensorPolicy 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
|
+
"xss"=>true
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
empty_policy = AppSensorPolicy.fromJson(policy_json_empty)
|
23
|
+
context "test empty agent" do
|
24
|
+
it "enabled is false" do
|
25
|
+
expect(empty_policy.policy_id).to eq("01a1")
|
26
|
+
expect(empty_policy.enabled).to eq(false)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
from_json = AppSensorPolicy.fromJson(policy_json_one)
|
31
|
+
context "tests xss is true and enabled true" do
|
32
|
+
it "returns true" do
|
33
|
+
expect(from_json.policy_id).to eq("01a1")
|
34
|
+
expect(from_json.enabled).to eq(true)
|
35
|
+
expect(from_json.option_enabled?("xss")).to eq(true)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,71 @@
|
|
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.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(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.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 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.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 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.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
|