privileges(refactor): consolidate individual sys op privileges (#11549)

This commit is contained in:
david-leifker 2024-10-07 15:36:13 -05:00 committed by GitHub
parent 7bdb7bbab2
commit 5ad15a7b99
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 63 additions and 34 deletions

View File

@ -191,16 +191,18 @@ These privileges are for DataHub operators to access & manage the administrative
#### System Management
| Platform Privileges | Description |
|-----------------------------------------------|------------------------------------------------------------------------|
| Restore Indices API[^1] | Allow actor to use the Restore Indices API. | |
| Get Timeseries index sizes API[^1] | Allow actor to use the get Timeseries indices size API. |
| Truncate timeseries aspect index size API[^1] | Allow actor to use the API to truncate a timeseries index. |
| Get ES task status API[^1] | Allow actor to use the get task status API for an ElasticSearch task. |
| Enable/Disable Writeability API[^1] | Allow actor to enable or disable GMS writeability for data migrations. |
| Apply Retention API[^1] | Allow actor to apply retention using the API. |
| Analytics API access[^1] | Allow actor to use API read access to raw analytics data. |
| Manage System Operations | Allow actor to manage system operation controls. |
| Platform Privileges | Description |
|-----------------------------------------------|----------------------------------------------------------------------------------------------------------|
| Restore Indices API[^1] | Allow actor to use the Restore Indices API. | |
| Get Timeseries index sizes API[^1] | Allow actor to use the get Timeseries indices size API. |
| Truncate timeseries aspect index size API[^1] | Allow actor to use the API to truncate a timeseries index. |
| Get ES task status API[^1] | Allow actor to use the get task status API for an ElasticSearch task. |
| Enable/Disable Writeability API[^1] | Allow actor to enable or disable GMS writeability for data migrations. |
| Apply Retention API[^1] | Allow actor to apply retention using the API. |
| Analytics API access[^1] | Allow actor to use API read access to raw analytics data. |
| Explain ElasticSearch Query API[^1] | Allow actor to use the Operations API explain endpoint. |
| Produce Platform Event API[^1] | Allow actor to produce Platform Events using the API. |
| Manage System Operations | Allow actor to manage system operation controls. This setting includes all System Management privileges. |
[^1]: Only active if REST_API_AUTHORIZATION_ENABLED is true
[^2]: DataHub Cloud only
@ -262,16 +264,6 @@ These privileges are to view & modify any entity within DataHub.
[^1]: Only active if REST_API_AUTHORIZATION_ENABLED is true
[^2]: DataHub Cloud only
#### System Management
| System Privileges | Description |
|-------------------------------------|--------------------------------------------------------------------------------------------|
| Explain ElasticSearch Query API[^1] | Allow actor to use the Operations API explain endpoint. |
| Produce Platform Event API[^1] | Allow actor to produce Platform Events using the API. |
[^1]: Only active if REST_API_AUTHORIZATION_ENABLED is true
[^2]: DataHub Cloud only
### Specific Entity-level Privileges
These privileges are not generalizable.

View File

@ -31,6 +31,8 @@ This file documents any backwards-incompatible changes in DataHub and assists pe
### Other Notable Changes
- #11549 - Manage Operations Privilege is extended from throttle control to all system management and operations APIs.
## 0.14.1
### Breaking Changes

View File

@ -24,6 +24,7 @@ import static com.linkedin.metadata.authorization.ApiOperation.UPDATE;
import static com.linkedin.metadata.authorization.Disjunctive.DENY_ACCESS;
import static com.linkedin.metadata.authorization.PoliciesConfig.API_ENTITY_PRIVILEGE_MAP;
import static com.linkedin.metadata.authorization.PoliciesConfig.API_PRIVILEGE_MAP;
import static com.linkedin.metadata.authorization.PoliciesConfig.MANAGE_SYSTEM_OPERATIONS_PRIVILEGE;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
@ -304,6 +305,30 @@ public class AuthUtil {
return isAPIAuthorized(session, Disjunctive.disjoint(privilege), (EntitySpec) null);
}
/**
* Allow specific privilege OR MANAGE_SYSTEM_OPERATIONS_PRIVILEGE
*
* @param session authorization session
* @param privilege specific privilege
* @return authorized status
*/
public static boolean isAPIOperationsAuthorized(
@Nonnull final AuthorizationSession session,
@Nonnull final PoliciesConfig.Privilege privilege) {
return isAPIAuthorized(
session,
Disjunctive.disjoint(privilege, MANAGE_SYSTEM_OPERATIONS_PRIVILEGE),
(EntitySpec) null);
}
public static boolean isAPIOperationsAuthorized(
@Nonnull final AuthorizationSession session,
@Nonnull final PoliciesConfig.Privilege privilege,
@Nullable final EntitySpec resource) {
return isAPIAuthorized(
session, Disjunctive.disjoint(privilege, MANAGE_SYSTEM_OPERATIONS_PRIVILEGE), resource);
}
private static boolean isAPIAuthorized(
@Nonnull final AuthorizationSession session,
@Nonnull final Disjunctive<Conjunctive<PoliciesConfig.Privilege>> privileges,

View File

@ -154,7 +154,8 @@ public class OperationsController {
authentication,
true);
if (!AuthUtil.isAPIAuthorized(opContext, PoliciesConfig.GET_TIMESERIES_INDEX_SIZES_PRIVILEGE)) {
if (!AuthUtil.isAPIOperationsAuthorized(
opContext, PoliciesConfig.GET_TIMESERIES_INDEX_SIZES_PRIVILEGE)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(String.format(actorUrnStr + " is not authorized to get timeseries index sizes"));
}
@ -255,7 +256,7 @@ public class OperationsController {
}
});
if (!AuthUtil.isAPIAuthorized(opContext, PoliciesConfig.ES_EXPLAIN_QUERY_PRIVILEGE)) {
if (!AuthUtil.isAPIOperationsAuthorized(opContext, PoliciesConfig.ES_EXPLAIN_QUERY_PRIVILEGE)) {
log.error("{} is not authorized to get explain queries", actorUrnStr);
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
}
@ -363,7 +364,7 @@ public class OperationsController {
}
});
if (!AuthUtil.isAPIAuthorized(opContext, PoliciesConfig.ES_EXPLAIN_QUERY_PRIVILEGE)) {
if (!AuthUtil.isAPIOperationsAuthorized(opContext, PoliciesConfig.ES_EXPLAIN_QUERY_PRIVILEGE)) {
log.error("{} is not authorized to get explain queries", actorUrnStr);
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
}
@ -449,7 +450,7 @@ public class OperationsController {
authentication,
true);
if (!AuthUtil.isAPIAuthorized(opContext, PoliciesConfig.RESTORE_INDICES_PRIVILEGE)) {
if (!AuthUtil.isAPIOperationsAuthorized(opContext, PoliciesConfig.RESTORE_INDICES_PRIVILEGE)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
@ -492,7 +493,7 @@ public class OperationsController {
authentication,
true);
if (!AuthUtil.isAPIAuthorized(opContext, PoliciesConfig.RESTORE_INDICES_PRIVILEGE)) {
if (!AuthUtil.isAPIOperationsAuthorized(opContext, PoliciesConfig.RESTORE_INDICES_PRIVILEGE)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}

View File

@ -3,6 +3,7 @@ package com.linkedin.metadata.resources.entity;
import static com.datahub.authorization.AuthUtil.isAPIAuthorized;
import static com.datahub.authorization.AuthUtil.isAPIAuthorizedEntityUrns;
import static com.datahub.authorization.AuthUtil.isAPIAuthorizedUrns;
import static com.datahub.authorization.AuthUtil.isAPIOperationsAuthorized;
import static com.linkedin.metadata.authorization.ApiGroup.COUNTS;
import static com.linkedin.metadata.authorization.ApiGroup.ENTITY;
import static com.linkedin.metadata.authorization.ApiGroup.TIMESERIES;
@ -372,7 +373,7 @@ public class AspectResource extends CollectionResourceTaskTemplate<String, Versi
systemOperationContext, RequestContext.builder().buildRestli(authentication.getActor().toUrnStr(),
getContext(), ACTION_RESTORE_INDICES), _authorizer, authentication, true);
if (!isAPIAuthorized(
if (!isAPIOperationsAuthorized(
opContext,
PoliciesConfig.RESTORE_INDICES_PRIVILEGE)) {
throw new RestLiServiceException(

View File

@ -1058,7 +1058,7 @@ public class EntityResource extends CollectionResourceTaskTemplate<String, Entit
systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(),
"setWriteable"), authorizer, auth, true);
if (!isAPIAuthorized(
if (!isAPIOperationsAuthorized(
opContext,
PoliciesConfig.SET_WRITEABLE_PRIVILEGE)) {
throw new RestLiServiceException(
@ -1168,7 +1168,7 @@ public class EntityResource extends CollectionResourceTaskTemplate<String, Entit
systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(),
ACTION_APPLY_RETENTION, resourceSpec.getType()), authorizer, auth, true);
if (!isAPIAuthorized(
if (!isAPIOperationsAuthorized(
opContext,
PoliciesConfig.APPLY_RETENTION_PRIVILEGE,
resourceSpec)) {

View File

@ -1,6 +1,7 @@
package com.linkedin.metadata.resources.operations;
import static com.datahub.authorization.AuthUtil.isAPIAuthorized;
import static com.datahub.authorization.AuthUtil.isAPIOperationsAuthorized;
import static com.linkedin.metadata.resources.restli.RestliConstants.*;
import static com.linkedin.metadata.utils.CriterionUtils.buildCriterion;
@ -136,7 +137,7 @@ public class OperationsResource extends CollectionResourceTaskTemplate<String, V
systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(),
ACTION_GET_ES_TASK_STATUS), _authorizer, auth, true);
if (!isAPIAuthorized(
if (!isAPIOperationsAuthorized(
opContext,
PoliciesConfig.GET_ES_TASK_STATUS_PRIVILEGE)) {
throw new RestLiServiceException(
@ -199,7 +200,7 @@ public class OperationsResource extends CollectionResourceTaskTemplate<String, V
systemOperationContext, RequestContext.builder().buildRestli(auth.getActor().toUrnStr(), getContext(),
ACTION_GET_INDEX_SIZES, List.of()), _authorizer, auth, true);
if (!isAPIAuthorized(
if (!isAPIOperationsAuthorized(
opContext,
PoliciesConfig.GET_TIMESERIES_INDEX_SIZES_PRIVILEGE)) {
throw new RestLiServiceException(

View File

@ -1,6 +1,7 @@
package com.linkedin.metadata.resources.platform;
import static com.datahub.authorization.AuthUtil.isAPIAuthorized;
import static com.datahub.authorization.AuthUtil.isAPIOperationsAuthorized;
import com.datahub.authentication.Authentication;
import com.datahub.authentication.AuthenticationContext;
@ -63,7 +64,7 @@ public class PlatformResource extends CollectionResourceTaskTemplate<String, Ent
ACTION_PRODUCE_PLATFORM_EVENT), _authorizer,
auth, true);
if (!isAPIAuthorized(
if (!isAPIOperationsAuthorized(
opContext,
PoliciesConfig.PRODUCE_PLATFORM_EVENT_PRIVILEGE)) {
throw new RestLiServiceException(

View File

@ -183,7 +183,7 @@ public class PoliciesConfig {
Privilege.of(
"MANAGE_SYSTEM_OPERATIONS",
"Manage System Operations",
"Allow access to system operations APIs and controls.");
"Allow access to all system operations/management APIs and controls.");
public static final List<Privilege> PLATFORM_PRIVILEGES =
ImmutableList.of(
@ -877,13 +877,19 @@ public class PoliciesConfig {
.put(ApiOperation.CREATE, DENY_ACCESS)
.put(
ApiOperation.READ,
Disjunctive.disjoint(VIEW_ANALYTICS_PRIVILEGE, GET_ANALYTICS_PRIVILEGE))
Disjunctive.disjoint(
VIEW_ANALYTICS_PRIVILEGE,
GET_ANALYTICS_PRIVILEGE,
MANAGE_SYSTEM_OPERATIONS_PRIVILEGE))
.put(ApiOperation.UPDATE, DENY_ACCESS)
.put(ApiOperation.DELETE, DENY_ACCESS)
.put(
ApiOperation.EXISTS,
Disjunctive.disjoint(
VIEW_ANALYTICS_PRIVILEGE, GET_ANALYTICS_PRIVILEGE, SEARCH_PRIVILEGE))
VIEW_ANALYTICS_PRIVILEGE,
GET_ANALYTICS_PRIVILEGE,
SEARCH_PRIVILEGE,
MANAGE_SYSTEM_OPERATIONS_PRIVILEGE))
.build())
.put(
ApiGroup.TIMESERIES,