ree_lib 1.3.13 → 1.3.14
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/Gemfile.lock +1 -1
- data/lib/ree_lib/packages/ree_audit/README.md +12 -10
- data/lib/ree_lib/packages/ree_roda/spec/ree_roda/plugins/ree_routes_audit_spec.rb +17 -0
- data/lib/ree_lib/packages/ree_routes/package/ree_routes/dsl.rb +8 -0
- data/lib/ree_lib/packages/ree_routes/package/ree_routes/route.rb +11 -5
- data/lib/ree_lib/packages/ree_routes/spec/ree_routes/dsl_spec.rb +11 -1
- data/lib/ree_lib/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2ebed252b6557db13e60268884fd6b1a0f405f256d28aaf18953764886ab6cb0
|
|
4
|
+
data.tar.gz: e6328fda6013213c588f834b5a0782c271c76686b8303a0f458cfac5e926c80d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06ad16d1ca9361397b0e324d8ab0d9a3a064337831384f45616dd500efb88367c84be252537d203e07ec08cb109e8f976980ff39ac2de315f96938a21edc697e
|
|
7
|
+
data.tar.gz: fa3b6b910f9855585af6f0e985720db3773d7483779f65d3907badc16711e5bfdd159abcfcd8135466a5a2c57a75645da44c79ba532e0bcd9bf777d50aa7bdd5
|
data/Gemfile.lock
CHANGED
|
@@ -54,11 +54,12 @@ through `ree_logger`.
|
|
|
54
54
|
|
|
55
55
|
## What gets audited
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
Nothing is audited until the route says so:
|
|
58
58
|
|
|
59
59
|
```ruby
|
|
60
60
|
get "api/v1/admin/users" do
|
|
61
|
-
visibility :internal
|
|
61
|
+
visibility :internal
|
|
62
|
+
audit true # recorded
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
get "api/v1/admin/health" do
|
|
@@ -66,19 +67,20 @@ get "api/v1/admin/health" do
|
|
|
66
67
|
audit false # deliberately silent
|
|
67
68
|
end
|
|
68
69
|
|
|
69
|
-
get "api/v1/exports" do
|
|
70
|
-
audit true # public route reaching into someone else's data
|
|
71
|
-
end
|
|
72
|
-
|
|
73
70
|
get "api/v1/organizations/:id/balance" do
|
|
74
71
|
audit :on_annotation # the owner calls it too — see below
|
|
75
72
|
end
|
|
76
73
|
```
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
`visibility`
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
The flag is declared at the route and nowhere else. Deriving it from
|
|
76
|
+
`visibility` would work just as well and read far worse: whether a call lands in
|
|
77
|
+
the access trail is exactly the kind of fact a reader must see where the route
|
|
78
|
+
is written, not infer from a flag that means something else.
|
|
79
|
+
|
|
80
|
+
Forgetting it is not possible where it matters: like `visibility`, `audit` is
|
|
81
|
+
mandatory on admin paths — a route whose path carries an `admin` segment fails
|
|
82
|
+
at boot until it declares one. So the audited set cannot drift away from the set
|
|
83
|
+
of routes that reach client data.
|
|
82
84
|
|
|
83
85
|
### `audit :on_annotation`
|
|
84
86
|
|
|
@@ -99,6 +99,14 @@ RSpec.describe "ree_routes audit" do
|
|
|
99
99
|
summary "Internal route"
|
|
100
100
|
sections "Admin"
|
|
101
101
|
visibility :internal
|
|
102
|
+
audit true
|
|
103
|
+
action :ok_cmd, **opts
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
get "api/internal_undeclared" do
|
|
107
|
+
summary "Internal route that never mentions audit"
|
|
108
|
+
sections "Admin"
|
|
109
|
+
visibility :internal
|
|
102
110
|
action :ok_cmd, **opts
|
|
103
111
|
end
|
|
104
112
|
|
|
@@ -148,6 +156,7 @@ RSpec.describe "ree_routes audit" do
|
|
|
148
156
|
summary "Internal route refusing access"
|
|
149
157
|
sections "Admin"
|
|
150
158
|
visibility :internal
|
|
159
|
+
audit true
|
|
151
160
|
action :denied_cmd, **opts
|
|
152
161
|
end
|
|
153
162
|
|
|
@@ -155,6 +164,7 @@ RSpec.describe "ree_routes audit" do
|
|
|
155
164
|
summary "Internal route blowing up"
|
|
156
165
|
sections "Admin"
|
|
157
166
|
visibility :internal
|
|
167
|
+
audit true
|
|
158
168
|
action :boom_cmd, **opts
|
|
159
169
|
end
|
|
160
170
|
end
|
|
@@ -274,6 +284,13 @@ RSpec.describe "ree_routes audit" do
|
|
|
274
284
|
expect(event.accessor).to eq({user: "visitor"})
|
|
275
285
|
end
|
|
276
286
|
|
|
287
|
+
it "leaves an internal route that never declared audit out of the trail" do
|
|
288
|
+
get "api/internal_undeclared"
|
|
289
|
+
|
|
290
|
+
expect(last_response.status).to eq(200)
|
|
291
|
+
expect(test_sink.events).to be_empty
|
|
292
|
+
end
|
|
293
|
+
|
|
277
294
|
it "leaves a silenced internal route out of the trail" do
|
|
278
295
|
get "api/internal_silenced"
|
|
279
296
|
|
|
@@ -97,6 +97,14 @@ module ReeRoutes
|
|
|
97
97
|
)
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
+
if !builder.get_route.audit_declared? && admin_path?(path)
|
|
101
|
+
raise ArgumentError.new(
|
|
102
|
+
"admin route #{path} must declare audit explicitly: " \
|
|
103
|
+
"`audit true` to record the call in the access trail, " \
|
|
104
|
+
"or `audit false` if the route touches nothing worth recording"
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
|
|
100
108
|
route = builder.get_route
|
|
101
109
|
|
|
102
110
|
@dsl.link(route.action.name, from: route.action.package_name)
|
|
@@ -16,12 +16,18 @@ class ReeRoutes::Route
|
|
|
16
16
|
!public?
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
19
|
+
# Auditing is declared at the route and nowhere else. Deriving it from
|
|
20
|
+
# `visibility` would work just as well and read far worse: whether a call
|
|
21
|
+
# lands in the access trail is exactly the kind of fact that must be visible
|
|
22
|
+
# where the route is written, not inferred from a flag that means something
|
|
23
|
+
# else. `audit` is mandatory on admin paths (see DSL#define_route), so the
|
|
24
|
+
# audited set still cannot drift away from the routes that touch client data.
|
|
23
25
|
def audited?
|
|
24
|
-
@audit
|
|
26
|
+
@audit == true || @audit == :on_annotation
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def audit_declared?
|
|
30
|
+
!@audit.nil?
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
# `audit :on_annotation` — a public route that the client calls for its own
|
|
@@ -76,7 +76,14 @@ RSpec.describe ReeRoutes::DSL, type: [:autoclean] do
|
|
|
76
76
|
default_warden_scope :user
|
|
77
77
|
|
|
78
78
|
get "internal_default" do
|
|
79
|
-
summary "Internal route
|
|
79
|
+
summary "Internal route that says it is audited"
|
|
80
|
+
action :cmd, from: :ree_routes_test
|
|
81
|
+
visibility :internal
|
|
82
|
+
audit true
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
get "internal_undeclared" do
|
|
86
|
+
summary "Internal route that never mentions audit"
|
|
80
87
|
action :cmd, from: :ree_routes_test
|
|
81
88
|
visibility :internal
|
|
82
89
|
end
|
|
@@ -137,7 +144,10 @@ RSpec.describe ReeRoutes::DSL, type: [:autoclean] do
|
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
expect(routes["internal_default"].audited?).to eq(true)
|
|
147
|
+
expect(routes["internal_undeclared"].audited?).to eq(false)
|
|
148
|
+
expect(routes["internal_undeclared"].audit_declared?).to eq(false)
|
|
140
149
|
expect(routes["internal_silenced"].audited?).to eq(false)
|
|
150
|
+
expect(routes["internal_silenced"].audit_declared?).to eq(true)
|
|
141
151
|
expect(routes["public_default"].audited?).to eq(false)
|
|
142
152
|
expect(routes["public_audited"].audited?).to eq(true)
|
|
143
153
|
expect(routes["public_on_annotation"].audited?).to eq(true)
|
data/lib/ree_lib/version.rb
CHANGED