diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/charts/ChartResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/charts/ChartResource.java index e041f8cab54..1325cfa398d 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/charts/ChartResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/charts/ChartResource.java @@ -327,7 +327,11 @@ public class ChartResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Chart chart = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(chart).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(chart).getEntityReference(), + dao.getOriginalOwner(chart), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/dashboards/DashboardResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/dashboards/DashboardResource.java index 1add603f0f8..7cc1da2f75a 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/dashboards/DashboardResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/dashboards/DashboardResource.java @@ -334,7 +334,11 @@ public class DashboardResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Dashboard dashboard = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(dashboard).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(dashboard).getEntityReference(), + dao.getOwnerReference(dashboard), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/DatabaseResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/DatabaseResource.java index cb3f2039797..071dd75dec3 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/DatabaseResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/DatabaseResource.java @@ -341,7 +341,11 @@ public class DatabaseResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Database database = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(database).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(database).getEntityReference(), + dao.getOriginalOwner(database), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/TableResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/TableResource.java index c8f72d11214..c0b99152291 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/TableResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/databases/TableResource.java @@ -364,7 +364,11 @@ public class TableResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Table table = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(table).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(table).getEntityReference(), + dao.getOriginalOwner(table), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java index b786afc2bd1..6d6f97e8bf1 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryResource.java @@ -331,7 +331,11 @@ public class GlossaryResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Glossary glossary = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(glossary).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(glossary).getEntityReference(), + dao.getOwnerReference(glossary), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); addHref(uriInfo, response.getEntity()); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResource.java index 12398e2755c..1ee4be189fd 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/glossary/GlossaryTermResource.java @@ -368,7 +368,11 @@ public class GlossaryTermResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); GlossaryTerm term = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(term).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(term).getEntityReference(), + dao.getOriginalOwner(term), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); addHref(uriInfo, response.getEntity()); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/locations/LocationResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/locations/LocationResource.java index c926e14414f..d3791dea9dd 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/locations/LocationResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/locations/LocationResource.java @@ -401,7 +401,11 @@ public class LocationResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Location location = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(location).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(location).getEntityReference(), + dao.getOwnerReference(location), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/mlmodels/MlModelResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/mlmodels/MlModelResource.java index ed27cf7218e..7229ccdc942 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/mlmodels/MlModelResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/mlmodels/MlModelResource.java @@ -272,7 +272,11 @@ public class MlModelResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); MlModel mlModel = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(mlModel).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(mlModel).getEntityReference(), + dao.getOwnerReference(mlModel), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/operations/AirflowPipelineResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/operations/AirflowPipelineResource.java index 4067085c148..4bba5544698 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/operations/AirflowPipelineResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/operations/AirflowPipelineResource.java @@ -370,7 +370,11 @@ public class AirflowPipelineResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); AirflowPipeline airflowPipeline = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(airflowPipeline).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(airflowPipeline).getEntityReference(), + dao.getOriginalOwner(airflowPipeline), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/pipelines/PipelineResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/pipelines/PipelineResource.java index e054ae1f573..72cd2b68ecb 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/pipelines/PipelineResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/pipelines/PipelineResource.java @@ -334,7 +334,11 @@ public class PipelineResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Pipeline pipeline = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(pipeline).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(pipeline).getEntityReference(), + dao.getOwnerReference(pipeline), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java index 02eaba7b14b..a050a235886 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java @@ -307,8 +307,8 @@ public class TeamResource { public Response createOrUpdateTeam( @Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid CreateTeam ct) throws IOException, ParseException { - SecurityUtil.checkAdminOrBotRole(authorizer, securityContext); Team team = getTeam(ct, securityContext); + SecurityUtil.checkAdminOrBotOrOwner(authorizer, securityContext, dao.getOriginalOwner(team)); RestUtil.PutResponse response = dao.createOrUpdate(uriInfo, team); addHref(uriInfo, response.getEntity()); return response.toResponse(); @@ -339,7 +339,11 @@ public class TeamResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELDS); Team team = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(team).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(team).getEntityReference(), + dao.getOriginalOwner(team), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); addHref(uriInfo, response.getEntity()); @@ -370,6 +374,7 @@ public class TeamResource { .withDescription(ct.getDescription()) .withDisplayName(ct.getDisplayName()) .withProfile(ct.getProfile()) + .withOwner(ct.getOwner()) .withUpdatedBy(securityContext.getUserPrincipal().getName()) .withUpdatedAt(System.currentTimeMillis()) .withUsers(dao.getEntityReferences(ct.getUsers())) diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/topics/TopicResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/topics/TopicResource.java index 5e072ca80b2..11dd560a404 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/topics/TopicResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/topics/TopicResource.java @@ -332,7 +332,11 @@ public class TopicResource { Fields fields = new Fields(ALLOWED_FIELDS, FIELD_OWNER); Topic topic = dao.get(uriInfo, id, fields); SecurityUtil.checkAdminRoleOrPermissions( - authorizer, securityContext, dao.getEntityInterface(topic).getEntityReference(), patch); + authorizer, + securityContext, + dao.getEntityInterface(topic).getEntityReference(), + dao.getOwnerReference(topic), + patch); PatchResponse response = dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/DefaultAuthorizer.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/DefaultAuthorizer.java index df137e59e60..29f4a8f23df 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/DefaultAuthorizer.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/DefaultAuthorizer.java @@ -127,9 +127,12 @@ public class DefaultAuthorizer implements Authorizer { @Override public boolean hasPermissions(AuthenticationContext ctx, EntityReference owner) { validateAuthenticationContext(ctx); - // To encourage users to claim or update changes to tables when a non-owner or un-claimed datasets. + // Since we have roles and operations. An Admin could enable updateDescription, tags, ownership permissions to + // a role and assign that to the users who can update the entities. With this we can look at the owner as a strict + // requirement to manage entities. So if owner is null we will not allow users to update entities. They can get a + // role that allows them to update the entity. if (owner == null) { - return true; + return false; } try { User user = getUserFromAuthenticationContext(ctx); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/SecurityUtil.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/SecurityUtil.java index 5ce98822cba..029f0d7f13f 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/SecurityUtil.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/SecurityUtil.java @@ -103,11 +103,17 @@ public final class SecurityUtil { * metadata operations that can be derived from JSON patch. */ public static void checkAdminRoleOrPermissions( - Authorizer authorizer, SecurityContext securityContext, EntityReference entityReference, JsonPatch patch) { + Authorizer authorizer, + SecurityContext securityContext, + EntityReference entityReference, + EntityReference ownerReference, + JsonPatch patch) { Principal principal = securityContext.getUserPrincipal(); AuthenticationContext authenticationCtx = SecurityUtil.getAuthenticationContext(principal); - if (authorizer.isAdmin(authenticationCtx) || authorizer.isBot(authenticationCtx)) { + if (authorizer.isAdmin(authenticationCtx) + || authorizer.isBot(authenticationCtx) + || authorizer.hasPermissions(authenticationCtx, ownerReference)) { return; } diff --git a/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json b/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json index 1c7b8e74586..ca7dc597de5 100644 --- a/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json +++ b/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json @@ -29,12 +29,22 @@ "default": null }, "defaultRoles": { - "description": "Roles to be assigned to all users that are part of this team.", + "description": "Roles to be assigned to all users that are part of this team.", "type": "array", "items": { "$ref": "../../type/basic.json#/definitions/uuid" }, "default": null + }, + "owner": { + "description": "Owner of this team. ", + "$ref": "../../type/entityReference.json", + "default": null + }, + "joinable": { + "description": "This field describes if the users can join a team without any permission. By default this is set to True.", + "type": "boolean", + "default": "true" } }, "required": ["name"], diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json b/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json index 7fdf7236bf6..dfc561490be 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json @@ -56,6 +56,11 @@ "description": "List of entities owned by the team.", "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" }, + "owner": { + "description": "Owner of this team. ", + "$ref": "../../type/entityReference.json", + "default": null + }, "changeDescription": { "description": "Change that lead to this version of the entity.", "$ref": "../../type/entityHistory.json#/definitions/changeDescription" diff --git a/ingestion-core/src/metadata/_version.py b/ingestion-core/src/metadata/_version.py index 9cb1f9a7012..6fbbe18a170 100644 --- a/ingestion-core/src/metadata/_version.py +++ b/ingestion-core/src/metadata/_version.py @@ -7,5 +7,5 @@ Provides metadata version information. from incremental import Version -__version__ = Version("metadata", 0, 9, 0, dev=0) +__version__ = Version("metadata", 0, 9, 0, dev=1) __all__ = ["__version__"]