moesif_rack 1.4.19 → 2.0.1
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/moesif_rack/app_config.rb +76 -113
- data/lib/moesif_rack/client_ip.rb +61 -102
- data/lib/moesif_rack/governance_rules.rb +480 -0
- data/lib/moesif_rack/moesif_helpers.rb +33 -6
- data/lib/moesif_rack/moesif_middleware.rb +159 -148
- data/lib/moesif_rack/regex_config_helper.rb +96 -104
- data/lib/moesif_rack/update_company.rb +44 -48
- data/lib/moesif_rack/update_user.rb +44 -48
- data/moesif_capture_outgoing/httplog/adapters/net_http.rb +18 -21
- data/moesif_capture_outgoing/httplog/http_log.rb +57 -107
- data/moesif_capture_outgoing/httplog.rb +2 -2
- data/test/config_example.json +1473 -0
- data/test/govrule_example.json +20 -0
- data/test/test_governance_rules.rb +213 -0
- data/test/{moesif_rack_test.rb → test_moesif_rack.rb} +18 -16
- metadata +30 -6
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"_id": "647e8bd1b80b4f10945463c9",
|
3
|
+
"type": "user",
|
4
|
+
"block": true,
|
5
|
+
"name": "test",
|
6
|
+
"appliedTo": "matching",
|
7
|
+
"appliedToUnidentified": false,
|
8
|
+
"regex_config": [],
|
9
|
+
"cohorts": [{ "id": "647e8bbbed26fe10468dfe55", "type": "user" }],
|
10
|
+
"state": 2,
|
11
|
+
"response": {
|
12
|
+
"status": 100,
|
13
|
+
"headers": { "test": "{{1}}" },
|
14
|
+
"body": { "test": "{{0}}" }
|
15
|
+
},
|
16
|
+
"variables": [
|
17
|
+
{ "name": "0", "path": "cohort_names" },
|
18
|
+
{ "name": "1", "path": "first_seen_time" }
|
19
|
+
]
|
20
|
+
}
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'moesif_api'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
require 'net/http'
|
5
|
+
require_relative '../lib/moesif_rack/app_config'
|
6
|
+
require_relative '../lib/moesif_rack'
|
7
|
+
require_relative '../lib/moesif_rack/governance_rules'
|
8
|
+
|
9
|
+
class GovernanceRulesTest < Test::Unit::TestCase
|
10
|
+
self.test_order = :defined
|
11
|
+
def setup
|
12
|
+
return if @already_setup
|
13
|
+
@goverance_rule_manager = GovernanceRules.new(true)
|
14
|
+
@api_client = MoesifApi::MoesifAPIClient.new('Your Moesif Application Id')
|
15
|
+
@goverance_rule_manager.load_rules(@api_client.api)
|
16
|
+
@already_setup = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_get_applicable_regex_rules
|
20
|
+
request_fields = {
|
21
|
+
'request.verb' => 'GET',
|
22
|
+
'request.ip_address' => '125.2.3.2',
|
23
|
+
'request.route' => "",
|
24
|
+
'request.body.operationName' => "operator name"
|
25
|
+
}
|
26
|
+
request_body = {
|
27
|
+
"subject" => "should_block"
|
28
|
+
}
|
29
|
+
|
30
|
+
applicable_rules = @goverance_rule_manager.get_applicable_regex_rules(request_fields, request_body)
|
31
|
+
print "\nFound #{applicable_rules.length} applicable rule for regex only rules-------\n"
|
32
|
+
print applicable_rules.to_s
|
33
|
+
print "\n-------------\n"
|
34
|
+
assert(applicable_rules.length === 1, "expect to get at least one regex rule")
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def test_get_applicable_user_rules_for_unidentified_user
|
39
|
+
request_fields = {
|
40
|
+
'request.route' => "test/no_italy",
|
41
|
+
}
|
42
|
+
request_body = {
|
43
|
+
"subject" => "should_block"
|
44
|
+
}
|
45
|
+
applicable_rules = @goverance_rule_manager.get_applicable_user_rules_for_unidentified_user(request_fields, request_body)
|
46
|
+
print "\nFound #{applicable_rules.length} applicable rule for anonymous user-------\n"
|
47
|
+
print applicable_rules.to_s
|
48
|
+
print "\n-------------\n"
|
49
|
+
assert(applicable_rules.length === 1, "expect to get 1 unidentified user rules")
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_get_applicable_user_rules_for_matching
|
53
|
+
request_fields = {
|
54
|
+
'request.route' => "test/no_italy",
|
55
|
+
}
|
56
|
+
request_body = {
|
57
|
+
"subject" => "should_block"
|
58
|
+
}
|
59
|
+
user_id = 'rome1'
|
60
|
+
|
61
|
+
#for user id matched rules it depends on getting from config_rules_values
|
62
|
+
#for that particular user id.
|
63
|
+
# for this test case I will use this rule as fake input
|
64
|
+
#https://www.moesif.com/wrap/app/88:210-660:387/governance-rule/64a783a3e7d62b036d16006e
|
65
|
+
config_user_rules_values = [
|
66
|
+
{
|
67
|
+
"rules" => "64a783a3e7d62b036d16006e",
|
68
|
+
"values" => {
|
69
|
+
"0" => "rome",
|
70
|
+
"1" => "some value for 1",
|
71
|
+
"2" => "some value for 2",
|
72
|
+
}
|
73
|
+
}
|
74
|
+
]
|
75
|
+
|
76
|
+
applicable_rules = @goverance_rule_manager.get_applicable_user_rules(request_fields, request_body, config_user_rules_values)
|
77
|
+
print "\nFound #{applicable_rules.length} applicable rule for identified user based on event and config user rule values-------\n"
|
78
|
+
print applicable_rules.to_s
|
79
|
+
print "\n-------------\n"
|
80
|
+
assert(applicable_rules.length === 1, "expect 1 rules")
|
81
|
+
|
82
|
+
fake_response = {
|
83
|
+
status: 200,
|
84
|
+
headers: {
|
85
|
+
"original-header" => "should be preserved"
|
86
|
+
},
|
87
|
+
body: {
|
88
|
+
"foo_bar" => "if not blocked this would show"
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
new_response = @goverance_rule_manager.apply_rules_list(applicable_rules, fake_response, config_user_rules_values);
|
93
|
+
print "new resposne is: \n"
|
94
|
+
print new_response.to_s
|
95
|
+
print "\n------------------\n"
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def test_get_applicable_user_rules_in_cohort_but_rule_is_apply_to_not_in_cohort
|
100
|
+
request_fields = {
|
101
|
+
'request.route' => "hello/canada",
|
102
|
+
}
|
103
|
+
request_body = {
|
104
|
+
"from_location" => "canada"
|
105
|
+
}
|
106
|
+
user_id = 'vancouver1'
|
107
|
+
|
108
|
+
# https://www.moesif.com/wrap/app/88:210-660:387/governance-rule/64a783a43660b60f7c766a06
|
109
|
+
config_user_rules_values = [
|
110
|
+
{
|
111
|
+
"rules" => "64a783a43660b60f7c766a06",
|
112
|
+
"values" => {
|
113
|
+
"0" => "city",
|
114
|
+
"1" => "some value for 1",
|
115
|
+
"2" => "some value for 2",
|
116
|
+
}
|
117
|
+
}
|
118
|
+
]
|
119
|
+
|
120
|
+
applicable_rules = @goverance_rule_manager.get_applicable_user_rules(request_fields, request_body, config_user_rules_values)
|
121
|
+
print "\nFound #{applicable_rules.length} applicable rule for identified user in cohort rule rule apply to not in cohort-------\n"
|
122
|
+
print applicable_rules.to_s
|
123
|
+
print "\n-------------\n"
|
124
|
+
assert(applicable_rules.length === 0, "expect 0 rules, since user is in cohort, the rule is apply to users not in cohort")
|
125
|
+
|
126
|
+
fake_response = {
|
127
|
+
status: 200,
|
128
|
+
headers: {
|
129
|
+
"original-header" => "should be preserved"
|
130
|
+
},
|
131
|
+
body: {
|
132
|
+
"foo_bar" => "if not blocked this would show"
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
new_response = @goverance_rule_manager.apply_rules_list(applicable_rules, fake_response, config_user_rules_values);
|
137
|
+
print "new response is: \n"
|
138
|
+
print new_response.to_s
|
139
|
+
print "\n------------------\n"
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def test_get_applicable_user_not_in_any_cohort_but_regex_matched
|
144
|
+
request_fields = {
|
145
|
+
'request.route' => "hello/canada",
|
146
|
+
}
|
147
|
+
request_body = {
|
148
|
+
"from_location" => "canada"
|
149
|
+
}
|
150
|
+
user_id = 'some_random_user'
|
151
|
+
|
152
|
+
# since user didn't match any cohort, the config_user_rule_values is nil
|
153
|
+
config_user_rules_values = nil;
|
154
|
+
|
155
|
+
applicable_rules = @goverance_rule_manager.get_applicable_user_rules(request_fields, request_body, config_user_rules_values)
|
156
|
+
print "\nFound #{applicable_rules.length} applicable rule for identified user no in any cohort, but rule apply to not in cohort-------\n"
|
157
|
+
print applicable_rules.to_json
|
158
|
+
print "\n-------------\n"
|
159
|
+
assert(applicable_rules.length === 1, "expect 1 rules, since user is not in cohort, there is a apply to not in cohort rule with same regex maching")
|
160
|
+
|
161
|
+
fake_response = {
|
162
|
+
status: 200,
|
163
|
+
headers: {
|
164
|
+
"original-header" => "should be preserved"
|
165
|
+
},
|
166
|
+
body: {
|
167
|
+
"foo_bar" => "if not blocked this would show"
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
new_response = @goverance_rule_manager.apply_rules_list(applicable_rules, fake_response, config_user_rules_values)
|
172
|
+
print "new resposne is: \n"
|
173
|
+
print new_response.to_json
|
174
|
+
print "\n------------------\n"
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def test_apply_multiple_rules
|
179
|
+
# this should match regex from one rule
|
180
|
+
request_fields = {
|
181
|
+
'request.route' => "hello/canada",
|
182
|
+
}
|
183
|
+
# this should match regex from another rule
|
184
|
+
request_body = {
|
185
|
+
"from_location" => "cairo"
|
186
|
+
}
|
187
|
+
|
188
|
+
# since user didn't match any cohort, the config_user_rule_values is nil
|
189
|
+
config_user_rules_values = nil;
|
190
|
+
|
191
|
+
applicable_rules = @goverance_rule_manager.get_applicable_user_rules(request_fields, request_body, config_user_rules_values)
|
192
|
+
print "\nFound #{applicable_rules.length} applicable rule for in cohort rule rule apply to not in cohort-------\n"
|
193
|
+
print applicable_rules.to_json
|
194
|
+
print "\n-------------\n"
|
195
|
+
assert(applicable_rules.length === 2, "expect 2 rules, since user is not in cohort, regex should match 2 rules")
|
196
|
+
|
197
|
+
fake_response = {
|
198
|
+
status: 200,
|
199
|
+
headers: {
|
200
|
+
"original-header" => "should be preserved"
|
201
|
+
},
|
202
|
+
body: {
|
203
|
+
"foo_bar" => "if not blocked this would show"
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
new_response = @goverance_rule_manager.apply_rules_list(applicable_rules, fake_response, config_user_rules_values)
|
208
|
+
print "new resposne is: \n"
|
209
|
+
print new_response.to_json
|
210
|
+
print "\n------------------\n"
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
@@ -45,6 +45,7 @@ class MoesifRackTest < Test::Unit::TestCase
|
|
45
45
|
event_model
|
46
46
|
}
|
47
47
|
}
|
48
|
+
|
48
49
|
@moesif_rack_app = MoesifRack::MoesifMiddleware.new(@app, @options)
|
49
50
|
@app_config = AppConfig.new(true)
|
50
51
|
end
|
@@ -72,9 +73,9 @@ class MoesifRackTest < Test::Unit::TestCase
|
|
72
73
|
campaign_model = {"utm_source" => "Newsletter",
|
73
74
|
"utm_medium" => "Email"}
|
74
75
|
|
75
|
-
user_model = { "user_id" => "12345",
|
76
|
+
user_model = { "user_id" => "12345",
|
76
77
|
"company_id" => "67890",
|
77
|
-
"modified_time" => Time.now.utc.iso8601,
|
78
|
+
"modified_time" => Time.now.utc.iso8601,
|
78
79
|
"metadata" => metadata,
|
79
80
|
"campaign" => campaign_model}
|
80
81
|
|
@@ -91,14 +92,14 @@ class MoesifRackTest < Test::Unit::TestCase
|
|
91
92
|
|
92
93
|
user_models = []
|
93
94
|
|
94
|
-
user_model_A = { "user_id" => "12345",
|
95
|
+
user_model_A = { "user_id" => "12345",
|
95
96
|
"company_id" => "67890",
|
96
|
-
"modified_time" => Time.now.utc.iso8601,
|
97
|
+
"modified_time" => Time.now.utc.iso8601,
|
97
98
|
"metadata" => metadata }
|
98
|
-
|
99
|
+
|
99
100
|
user_model_B = { "user_id" => "1234",
|
100
|
-
"company_id" => "6789",
|
101
|
-
"modified_time" => Time.now.utc.iso8601,
|
101
|
+
"company_id" => "6789",
|
102
|
+
"modified_time" => Time.now.utc.iso8601,
|
102
103
|
"metadata" => metadata }
|
103
104
|
|
104
105
|
user_models << user_model_A << user_model_B
|
@@ -116,9 +117,10 @@ class MoesifRackTest < Test::Unit::TestCase
|
|
116
117
|
def test_get_config
|
117
118
|
@api_client = MoesifApi::MoesifAPIClient.new(@options['application_id'])
|
118
119
|
@api_controller = @api_client.api
|
119
|
-
@
|
120
|
-
@
|
121
|
-
|
120
|
+
@app_config.get_config(@api_controller)
|
121
|
+
@sampling_percentage = @app_config.get_sampling_percentage(nil, nil, nil)
|
122
|
+
assert_instance_of Hash, @app_config.config
|
123
|
+
print "app config from test " + @app_config.config.to_s
|
122
124
|
assert_operator 100, :>=, @sampling_percentage
|
123
125
|
end
|
124
126
|
|
@@ -132,8 +134,8 @@ class MoesifRackTest < Test::Unit::TestCase
|
|
132
134
|
campaign_model = {"utm_source" => "Adwords",
|
133
135
|
"utm_medium" => "Twitter"}
|
134
136
|
|
135
|
-
company_model = { "company_id" => "12345",
|
136
|
-
"company_domain" => "acmeinc.com",
|
137
|
+
company_model = { "company_id" => "12345",
|
138
|
+
"company_domain" => "acmeinc.com",
|
137
139
|
"metadata" => metadata,
|
138
140
|
"campaign" => campaign_model }
|
139
141
|
|
@@ -151,11 +153,11 @@ class MoesifRackTest < Test::Unit::TestCase
|
|
151
153
|
company_models = []
|
152
154
|
|
153
155
|
company_model_A = { "company_id" => "12345",
|
154
|
-
"company_domain" => "nowhere.com",
|
156
|
+
"company_domain" => "nowhere.com",
|
155
157
|
"metadata" => metadata }
|
156
|
-
|
158
|
+
|
157
159
|
company_model_B = { "company_id" => "1234",
|
158
|
-
"company_domain" => "acmeinc.com",
|
160
|
+
"company_domain" => "acmeinc.com",
|
159
161
|
"metadata" => metadata }
|
160
162
|
|
161
163
|
company_models << company_model_A << company_model_B
|
@@ -163,4 +165,4 @@ class MoesifRackTest < Test::Unit::TestCase
|
|
163
165
|
assert_equal response, nil
|
164
166
|
end
|
165
167
|
|
166
|
-
end
|
168
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moesif_rack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Moesif, Inc
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-07-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: test-unit
|
@@ -37,14 +37,34 @@ dependencies:
|
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 2.0.1
|
41
41
|
type: :runtime
|
42
42
|
prerelease: false
|
43
43
|
version_requirements: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 2.0.1
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rack
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.8
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 2.0.0
|
58
|
+
type: :runtime
|
59
|
+
prerelease: false
|
60
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - "~>"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 3.0.8
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 2.0.0
|
48
68
|
description: Rack/Rails middleware to log API calls to Moesif API analytics and monitoring
|
49
69
|
email: xing@moesif.com
|
50
70
|
executables: []
|
@@ -56,6 +76,7 @@ files:
|
|
56
76
|
- lib/moesif_rack.rb
|
57
77
|
- lib/moesif_rack/app_config.rb
|
58
78
|
- lib/moesif_rack/client_ip.rb
|
79
|
+
- lib/moesif_rack/governance_rules.rb
|
59
80
|
- lib/moesif_rack/moesif_helpers.rb
|
60
81
|
- lib/moesif_rack/moesif_middleware.rb
|
61
82
|
- lib/moesif_rack/regex_config_helper.rb
|
@@ -64,7 +85,10 @@ files:
|
|
64
85
|
- moesif_capture_outgoing/httplog.rb
|
65
86
|
- moesif_capture_outgoing/httplog/adapters/net_http.rb
|
66
87
|
- moesif_capture_outgoing/httplog/http_log.rb
|
67
|
-
- test/
|
88
|
+
- test/config_example.json
|
89
|
+
- test/govrule_example.json
|
90
|
+
- test/test_governance_rules.rb
|
91
|
+
- test/test_moesif_rack.rb
|
68
92
|
homepage: https://moesif.com
|
69
93
|
licenses:
|
70
94
|
- Apache-2.0
|
@@ -84,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
108
|
requirements:
|
85
109
|
- - ">="
|
86
110
|
- !ruby/object:Gem::Version
|
87
|
-
version: '2.
|
111
|
+
version: '2.6'
|
88
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
113
|
requirements:
|
90
114
|
- - ">="
|