Commit 27c9862
[Write restricted SOs] Allow creation, update, delete and transfer ownership (elastic#224411)
Closes elastic#221753
----
> [!IMPORTANT]
> To support requirements, this feature is restricted to SO types that
are `multiple` and `multiple-isolated` namespace types only.
----
## Summary
Summarize your PR. If it involves visual changes include a screenshot or
gif.
- **Change Ownership Endpoints**: Adds server-side logic, client
methods, and repository support to transfer object ownership.
- **Extended Create Options** : Allow specifying `accessMode:
'read_only'` when creating an object.
- **Security & Authorization**: Integrates with the security extension
to enforce owner-based restrictions.
- **Mappings & Migrations**: Elasticsearch mappings and migrations
updated to persist `accessControl`.
- **Tests**: New FTR integration tests and a dedicated test plugin for
read-only object scenarios.
## Ownership-Based Authorization Logic
All ownership checks are now centralized in
`SavedObjectsAccessControlService.enforceAccessControl(operation,
args…)`.
The general flow is:
1. **Load existing object** to read its `accessControl` metadata.
2. **Determine required privilege** based on the operation:
- `create`
- `read`
- `modify` (covers both update & delete)
- `changeOwnership`
3. **If** `object.accessControl.accessMode === 'read_only'`, **also
enforce** `user === object.accessControl.owner`.
4. **Always** verify the caller holds the corresponding privilege.
| Operation | Privilege Key | Read-Only Constraint | Notes |
|-----------------------|-----------------------|---------------------------------|----------------------------------------------------------|
| **Create** | `create` | Must supply `accessControl.owner` |
`accessControl.accessMode` passed in create options |
| **Read** | `read` | N/A | Falls back to standard read privileges |
| **Modify** (update/delete) | `modify` | Caller must be the current
owner or admin | Single hook for both update & delete |
| **Change Ownership** | `changeOwnership` | Caller must be the current
owner or admin| Performs a preflight multi-get, then bulk-updates owner
based on result |
## Assumptions
1. Update operations will not support changing accessControl metadata.
2. Updates (and in turn upserts) will also not allow objects to be
created as write restricted types. We throw an error and ask the
consumer to use `create` instead.
3. Bulk Delete operations will behave as expected with the new changes.
Superusers/owners can bulk delete objects. Non-owners cannot bulk delete
objects that are in write restricted mode. (Assuming that they otherwise
have the permission to do so)
4. Bulk delete with `force` option works the same way.
## Expected behavior of SOR operations
All operations in the SOR on accessControl types follow the same rules.
After the existing RBAC rules for these operations, for a user to be
granted permission to perform an action on an SO Type supporting access
control, they must be superuser or owner of the object.
1. Create
Objects supporting access control will be created with the accessControl
metadata as follows:
`owner`: User profile ID of creating user
`accessMode`: `read_only` | `default` based on the incoming option
If objects supporting access control are created with no access control
metadata, then they are created just as they are today - no change to
how that object type will function.
2. Read
No changes to read. Must have RBAC granted access for SOs.
3. Update
Update operations will not support changing accessControl metadata.
Updates (and in turn upserts) will also not allow objects to be created
as write restricted types. We throw an error and ask the consumer to use
`create` instead. Updates are restricted by the access control rules
stated above
4. Delete
Delete operations will be allowed/disallowed based on the rules above.
6. Bulk update
Objects supporting access control but not owned by the current user
(unless superuser) will not be updated in this operation.
7. Bulk delete
Bulk delete (with and without the force option) work the same way. If an
object in the payload is of a type supporting access control, then the
rules will be the same. We will allow delete only if the user is a
superuser or owner of said object - all other instances will be
rejected.
8. Delete by namespace
Delete by namespace is a workaround for bulk deleting all objects in a
space. This function isn't exposed on the SO client but rather used on
the repository which is used by the SpacesClient to be able to delete
_all_ objects in a space. For users with a role granting this
permission, we will continue to allow them to do so even if there are
objects owned by others in that space. This is product decision based on
the Editor role being granted this privilege and if removed, would be
considered a breaking change that's out of the scope of this project.
Misc:
Saved objects like dashboards that are shareable across spaces have the
same rules assigned to them. A user cannot update/delete a dashboard in
a space where they might have RBAC access but don't own said dashboard.
## How to test
Since there's no associated UI changes in this PR, you can use the test
`read only objects` plugin to test behavior of the different flows.
Start the plugin in the integration test as:
```
node scripts/functional_tests_server --config x-pack/platform/test/spaces_api_integration/read_only_objects/config.ts
```
Once done, you can open Kibana on `localhost:5620` and set up a simple
user with this role: `kibana_savedobjects_editor`. For your tests you
can use three users:
1. elastic:changeme `superuser`
2. test_user:changeme `non-superuser`
3. The user just created above with role `kibana_savedobjects_editor`
With each of these users, you can try the following calls in Dev Tools
1. Create a read only object / non-read only
```
POST kbn:/read_only_objects/create
{"isReadOnly": true} // switch to false if creating regular SO type
```
Creates and responds with an object owned by the creating user. Using
the ID in the response, you can now perform the different operations and
verify how access control works
You can run
```
GET kbn:/read_only_objects/<ID>
```
at any time to see the current shape of the object including the access
control metadata
2. Updates - Run this as admin/owner/non-owner to test and verify the
different responses
```
PUT kbn:/read_only_objects/update
{
"objectId": "<ID FROM CREATE>",
"type": "read_only_type"
}
```
3. Delete - Run this as admin/owner/non-owner to test and verify the
different responses
```
DELETE kbn:/read_only_objects/<ID FROM CREATE>
```
4. Bulk delete - Run this as admin/owner/non-owner to test and verify
the different responses
```
POST kbn:/read_only_objects/bulk_delete
{
"objects": [
{
"id": "<ID1>",
"type": "read_only_type"
},
{
"id": "<ID2>",
"type": "read_only_type"
},
// ...
]
}
```
5. Bulk delete with force - same as above with force option
```
POST kbn:/read_only_objects/bulk_delete
{
"force": true,
"objects": [
{
"id": "<ID1>",
"type": "read_only_type"
},
{
"id": "<ID2>",
"type": "read_only_type"
},
// ...
]
}
```
## Note for reviewers:
- There are a lot of changes owned by the core team. Although most of
the authz and ownership changes are in the security extension owned by
Kibana platform security, surfacing these APIs to the SO client touches
a lot of interfaces owned by core.
### Follow up tasks
We have a few different follow up tasks documented on
elastic#230991
### Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.
- [x]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
### Identify risks
Risk matrix attached on parent PR:
elastic#224552 (comment)
---------
Co-authored-by: Elastic Machine <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: kibanamachine <[email protected]>
Co-authored-by: Aleh Zasypkin <[email protected]>
Co-authored-by: Christiane (Tina) Heiligers <[email protected]>
Co-authored-by: “jeramysoucy” <[email protected]>1 parent 3bacb47 commit 27c9862
File tree
67 files changed
+5112
-133
lines changed- .buildkite
- .github
- src/core/packages/saved-objects
- api-server-internal/src
- lib
- apis
- helpers
- internals
- utils
- utils
- mocks
- test_helpers
- api-server-mocks/src
- api-server
- src
- apis
- base-server-internal/src
- validation
- common
- src
- server
- src
- extensions
- x-pack/platform
- test
- spaces_api_integration
- common/plugins/read_only_objects_test_plugin
- server
- read_only_objects
- apis/spaces
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
67 files changed
+5112
-133
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
334 | 334 | | |
335 | 335 | | |
336 | 336 | | |
| 337 | + | |
337 | 338 | | |
338 | 339 | | |
339 | 340 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1081 | 1081 | | |
1082 | 1082 | | |
1083 | 1083 | | |
| 1084 | + | |
1084 | 1085 | | |
1085 | 1086 | | |
1086 | 1087 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
817 | 817 | | |
818 | 818 | | |
819 | 819 | | |
| 820 | + | |
820 | 821 | | |
821 | 822 | | |
822 | 823 | | |
| |||
Lines changed: 243 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
23 | 26 | | |
24 | 27 | | |
25 | 28 | | |
| |||
58 | 61 | | |
59 | 62 | | |
60 | 63 | | |
| 64 | + | |
61 | 65 | | |
62 | 66 | | |
63 | 67 | | |
| |||
1086 | 1090 | | |
1087 | 1091 | | |
1088 | 1092 | | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
| 1278 | + | |
| 1279 | + | |
| 1280 | + | |
| 1281 | + | |
| 1282 | + | |
| 1283 | + | |
| 1284 | + | |
| 1285 | + | |
| 1286 | + | |
| 1287 | + | |
| 1288 | + | |
| 1289 | + | |
| 1290 | + | |
| 1291 | + | |
| 1292 | + | |
| 1293 | + | |
| 1294 | + | |
| 1295 | + | |
| 1296 | + | |
| 1297 | + | |
| 1298 | + | |
| 1299 | + | |
| 1300 | + | |
| 1301 | + | |
| 1302 | + | |
| 1303 | + | |
| 1304 | + | |
| 1305 | + | |
| 1306 | + | |
| 1307 | + | |
| 1308 | + | |
| 1309 | + | |
| 1310 | + | |
| 1311 | + | |
| 1312 | + | |
| 1313 | + | |
| 1314 | + | |
| 1315 | + | |
| 1316 | + | |
| 1317 | + | |
| 1318 | + | |
| 1319 | + | |
| 1320 | + | |
| 1321 | + | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
1089 | 1331 | | |
1090 | 1332 | | |
1091 | 1333 | | |
0 commit comments